init.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. --[[
  2. Mobs Balrog - Adds balrogs.
  3. Copyright © 2018-2019 Hamlet <hamlatmesehub@riseup.net>
  4. Authors of source code:
  5. -----------------------
  6. (LOTT-specific-mod)
  7. Original Author(s):
  8. PilzAdam (WTFPL)
  9. https://github.com/PilzAdam/mobs
  10. Modifications By:
  11. Copyright (C) 2016 TenPlus1 (MIT)
  12. https://github.com/tenplus1/mobs_redo
  13. BrandonReese (LGPL v2.1)
  14. https://github.com/Bremaweb/adventuretest
  15. LOTT Modifications By:
  16. Amaz (LGPL v2.1)
  17. lumidify (LGPL v2.1)
  18. fishyWET (LGPL v2.1)
  19. https://github.com/minetest-LOTR/Lord-of-the-Test/
  20. This program is free software; you can redistribute it and/or modify
  21. it under the terms of the Lesser GNU General Public License as published
  22. by the Free Software Foundation; either version 2.1 of the License, or
  23. (at your option) any later version.
  24. This program is distributed in the hope that it will be useful,
  25. but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. GNU General Public License for more details.
  28. You should have received a copy of the GNU General Public License
  29. along with this program; if not, write to the Free Software
  30. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  31. MA 02110-1301, USA.
  32. ]]--
  33. local function flood_flame(pos, _, newnode)
  34. -- Play flame extinguish sound if liquid is not an 'igniter'
  35. if minetest.get_item_group(newnode.name, "igniter") == 0 then
  36. minetest.sound_play("fire_extinguish_flame",
  37. {pos = pos, max_hear_distance = 16, gain = 0.15}, true)
  38. end
  39. -- Remove the flame
  40. return false
  41. end
  42. local fire_node = {
  43. drawtype = "firelike",
  44. tiles = {{
  45. name = "fire_basic_flame_animated.png",
  46. animation = {
  47. type = "vertical_frames",
  48. aspect_w = 16,
  49. aspect_h = 16,
  50. length = 1
  51. }}
  52. },
  53. inventory_image = "fire_basic_flame.png",
  54. paramtype = "light",
  55. light_source = 13,
  56. walkable = false,
  57. buildable_to = true,
  58. sunlight_propagates = true,
  59. floodable = true,
  60. is_air = true,
  61. damage_per_second = 6,
  62. groups = {igniter = 2, dig_immediate = 3, },
  63. drop = "",
  64. on_flood = flood_flame
  65. }
  66. local flame_fire_node = table.copy(fire_node)
  67. flame_fire_node.description = S("Balrog Fire")
  68. flame_fire_node.groups.not_in_creative_inventory = 1
  69. flame_fire_node.on_timer = function(pos)
  70. if not minetest.find_node_near(pos, 1, {"group:flammable"}) then
  71. minetest.remove_node(pos)
  72. return
  73. end
  74. -- Restart timer
  75. return true
  76. end
  77. flame_fire_node.on_construct = function(pos)
  78. minetest.get_node_timer(pos):start(math.random(2, 7))
  79. end
  80. minetest.register_node("mobs_balrog:flame", flame_fire_node)
  81. -- Used for localization
  82. local S = minetest.get_translator("mobs_balrog")
  83. --
  84. -- Balrog's spawn settings
  85. --
  86. local MAX_LIGHT = tonumber(minetest.settings:get("mobs_balrog_max_light"))
  87. if (MAX_LIGHT == nil) then
  88. MAX_LIGHT = 14
  89. end
  90. local MIN_LIGHT = tonumber(minetest.settings:get("mobs_balrog_min_light"))
  91. if (MIN_LIGHT == nil) then
  92. MIN_LIGHT = 0
  93. end
  94. local INTERVAL = tonumber(minetest.settings:get("mobs_balrog_interval"))
  95. if (INTERVAL == nil) then
  96. INTERVAL = 60
  97. end
  98. local CHANCE = tonumber(minetest.settings:get("mobs_balrog_chance"))
  99. if (CHANCE == nil) then
  100. CHANCE = 500000
  101. end
  102. local MAX_NUMBER = tonumber(minetest.settings:get("mobs_balrog_aoc"))
  103. if (MAX_NUMBER == nil) then
  104. MAX_NUMBER = 1
  105. end
  106. local MIN_HEIGHT = tonumber(minetest.settings:get("mobs_balrog_min_height"))
  107. if (MIN_HEIGHT == nil) then
  108. MIN_HEIGHT = -30912
  109. end
  110. local MAX_HEIGHT = tonumber(minetest.settings:get("mobs_balrog_max_height"))
  111. if (MAX_HEIGHT == nil) then
  112. MAX_HEIGHT = -1800
  113. end
  114. --
  115. -- Balrog's attributes
  116. --
  117. local MIN_HP = tonumber(minetest.settings:get("mobs_balrog_min_hp"))
  118. if (MIN_HP == nil) then
  119. MIN_HP = 200
  120. end
  121. local MAX_HP = tonumber(minetest.settings:get("mobs_balrog_max_hp"))
  122. if (MAX_HP == nil) then
  123. MAX_HP = 600
  124. end
  125. local WALK_CHANCE = tonumber(minetest.settings:get("mobs_balrog_walk_chance"))
  126. if (WALK_CHANCE == nil) then
  127. WALK_CHANCE = 50
  128. end
  129. local VIEW_RANGE = tonumber(minetest.settings:get("mobs_balrog_view_range"))
  130. if (VIEW_RANGE == nil) then
  131. VIEW_RANGE = 32
  132. end
  133. local DAMAGE = tonumber(minetest.settings:get("mobs_balrog_damage"))
  134. if (DAMAGE == nil) then
  135. DAMAGE = 20
  136. end
  137. local PATH_FINDER = tonumber(minetest.settings:get("mobs_balrog_pathfinding"))
  138. if (PATH_FINDER == nil) then
  139. PATH_FINDER = 1
  140. end
  141. --
  142. -- Balrog entity
  143. --
  144. mobs:register_mob("mobs_balrog:balrog", {
  145. nametag = "",
  146. type = "monster",
  147. hp_min = MIN_HP,
  148. hp_max = MAX_HP,
  149. armor = 100,
  150. walk_velocity = 3.5,
  151. run_velocity = 5.2,
  152. walk_chance = WALK_CHANCE,
  153. jump_height = 16,
  154. stepheight = 2.2,
  155. view_range = VIEW_RANGE,
  156. damage = DAMAGE,
  157. knock_back = false,
  158. fear_height = 0,
  159. fall_damage = 0,
  160. water_damage = 7,
  161. lava_damage = 0,
  162. light_damage = 0,
  163. suffocation = false,
  164. floats = 0,
  165. reach = 5,
  166. glow = 5,
  167. attack_animals = true,
  168. group_attack = true,
  169. attack_type = "dogfight",
  170. blood_amount = 0,
  171. pathfinding = PATH_FINDER,
  172. makes_footstep_sound = true,
  173. sounds = {
  174. war_cry = "mobs_balrog_howl",
  175. death = "mobs_balrog_howl",
  176. attack = "mobs_balrog_stone_death"
  177. },
  178. drops = {
  179. {name = "mobs_balrog:balrog_whip", chance = 1, min = 0, max = 1},
  180. {name = "default:lava_source", chance = 3, min = 0, max = 20},
  181. {name = "slimes:lava_goo_block", chance = 3, min = 0, max = 3},
  182. {name = "lavastuff:pick", chance = 3, min = 0, max = 2},
  183. {name = "lavastuff:axe", chance = 3, min = 0, max = 2},
  184. {name = "lavastuff:sword", chance = 3, min = 0, max = 2},
  185. {name = "bucket:bucket_lava", chance = 3, min = 0, max = 2},
  186. {name = "lavastuff:sword", chance = 3, min = 0, max = 2},
  187. {name = "slimes:lava_slime", chance = 3, min = 0, max = 2},
  188. {name = "lavastuff:shield", chance = 3, min = 0, max = 1},
  189. {name = "lavastuff:leggings", chance = 3, min = 0, max = 1},
  190. {name = "lavastuff:helmet", chance = 3, min = 0, max = 1},
  191. {name = "lavastuff:boots", chance = 3, min = 0, max = 1},
  192. {name = "lavastuff:chestplate", chance = 3, min = 0, max = 1},
  193. {name = "mobs_balrog:balrog", chance = 25, min = 0, max = 1},
  194. {name = "nether:lavacrust", chance = 3, min = 0, max = 15},
  195. {name = "default:diamond", chance = 3, min = 0, max = 13},
  196. {name = "lavastuff:lava_in_a_bottle", chance = 3, min = 0, max = 1},
  197. {name = "bweapons_magic_pack:tome_fireball", chance = 3, min = 0, max = 1},
  198. {name = "draconis:dracolilly_fire", chance = 3, min = 0, max = 1},
  199. {name = "fire:permanent_flame", chance = 3, min = 0, max = 15},
  200. {name = "lavastuff:chestplate", chance = 3, min = 0, max = 1},
  201. {name = "mobs_creatures:fire_imp", chance = 15, min = 0, max = 1},
  202. {name = "torch_bomb:mega_torch_bomb", chance = 3, min = 0, max = 1},
  203. {name = "df_underworld_items:slade_block", chance = 20, min = 0, max = 30},
  204. },
  205. visual = "mesh",
  206. visual_size = {x = 2, y = 2},
  207. collisionbox = {-0.8, -2.0, -0.8, 0.8, 2.5, 0.8},
  208. textures = {"mobs_balrog_balrog.png"},
  209. mesh = "mobs_balrog.b3d",
  210. rotate = 180,
  211. animation = {
  212. stand_start = 0,
  213. stand_end = 240,
  214. walk_start = 240,
  215. walk_end = 300,
  216. walk_speed = 30,
  217. run_speed = 45,
  218. punch_start = 300,
  219. punch_end = 380,
  220. punch_speed = 45,
  221. },
  222. -- custom_attack = function( self , to_attack )
  223. -- local sp_attack_chance = 20
  224. -- if not self then return end
  225. -- if not self.attack then return true end
  226. -- local s_pos = self.object:get_pos()
  227. -- local a_pos = to_attack
  228. -- if math.random( 1 , sp_attack_chance ) ~= 1 then return true end
  229. -- -- use whip to cast fire
  230. -- local dir = vector.direction(s_pos, a_pos)
  231. -- local pos = s_pos
  232. -- for i = 1, 20 do
  233. -- local new_pos = {
  234. -- x = pos.x + (dir.x * i),
  235. -- y = pos.y + (dir.y * i),
  236. -- z = pos.z + (dir.z * i),
  237. -- }
  238. -- if minetest.get_node(new_pos).name == "air" then
  239. -- minetest.set_node(new_pos, {name = "mobs_balrog:flame"})
  240. -- end
  241. -- end
  242. -- -- if target is in balrog fire, push them towards the balrog
  243. -- if minetest.get_node(a_pos).name == "mobs_balrog:flame" then
  244. -- to_attack:add_velocity(6*vector.normalize(vector.direction(a_pos, s_pos)))
  245. -- end
  246. -- return true
  247. -- end,
  248. do_custom = function(self)
  249. local sp_attack_chance = 20
  250. if not self then return false end
  251. if not self.attack then return true end
  252. local s_pos = self.object:get_pos()
  253. local a_pos = self.attack:get_pos()
  254. if math.random( 1 , sp_attack_chance ) ~= 1 then return true end
  255. -- use whip to cast fire
  256. local dir = vector.direction(s_pos, a_pos)
  257. local pos = vector.add(s_pos,vector.new(0,.7,0))
  258. for i = 1, 300 do
  259. local new_pos = {
  260. x = pos.x + (dir.x * i),
  261. y = pos.y + (dir.y * i),
  262. z = pos.z + (dir.z * i),
  263. }
  264. if minetest.get_node(new_pos).name == "air" then
  265. minetest.set_node(new_pos, {name = "mobs_balrog:flame"})
  266. end
  267. end
  268. -- if target is in balrog fire, push them towards the balrog
  269. if minetest.get_node(a_pos).name == "mobs_balrog:flame" then
  270. --vector.multiply(vector.normalize(vector.subtract(destination, source)), speed) -- thx Warr1024!!!!
  271. local velocity = math.random (3, 17)
  272. self.attack:add_velocity(vector.multiply(vector.normalize(vector.subtract(s_pos, a_pos)), velocity) )
  273. end
  274. return true
  275. end,
  276. on_die = function(self, pos)
  277. self.object:remove()
  278. minetest.after(0.1, function()
  279. -- This has been taken from ../tnt/init.lua @243
  280. minetest.add_particlespawner({
  281. amount = 128,
  282. time = 0.1,
  283. minpos = vector.subtract(pos, 10 / 2),
  284. maxpos = vector.add(pos, 10 / 2),
  285. minvel = {x = -3, y = 0, z = -3},
  286. maxvel = {x = 3, y = 5, z = 3},
  287. minacc = {x = 0, y = -10, z = 0},
  288. maxacc = {x = 0, y = -10, z = 0},
  289. minexptime = 0.8,
  290. maxexptime = 2.0,
  291. minsize = 10 * 0.66,
  292. maxsize = 10 * 2,
  293. texture = "fire_basic_flame.png",
  294. collisiondetection = true,
  295. })
  296. tnt.boom(pos, {
  297. name = "Balrog's Blast",
  298. radius = 16,
  299. damage_radius = 16,
  300. disable_drops = true,
  301. ignore_protection = false,
  302. ignore_on_blast = false,
  303. tiles = {""},
  304. })
  305. end)
  306. end,
  307. })
  308. --
  309. -- Balrog's whip
  310. --
  311. minetest.register_tool("mobs_balrog:balrog_whip", {
  312. description = minetest.colorize("orange", S("Balrog Whip")) ..
  313. minetest.get_background_escape_sequence("darkred"),
  314. inventory_image = "mobs_balrog_balrog_whip.png^[transform3",
  315. on_use = function(itemstack, user, pointed_thing)
  316. if pointed_thing.type == "nothing" then
  317. local dir = user:get_look_dir()
  318. local add_vector = vector.new( 0 , .5 , 0 )
  319. local pos = vector.add(user:get_pos() , add_vector)
  320. for i = 1, 15 do
  321. local new_pos = {
  322. x = pos.x + (dir.x * i),
  323. y = pos.y + (dir.y * i),
  324. z = pos.z + (dir.z * i),
  325. }
  326. if minetest.get_node(new_pos).name == "air" then
  327. minetest.set_node(new_pos, {name = "mobs_balrog:flame"})
  328. end
  329. end
  330. if not minetest.setting_getbool("creative_mode") then
  331. itemstack:add_wear(65535/600)
  332. return itemstack
  333. end
  334. elseif pointed_thing.type == "object" then
  335. local obj = pointed_thing.ref
  336. minetest.add_particlespawner({
  337. amount = 40,
  338. time = 6,
  339. minpos = {x = -1, y = -1, z = -1},
  340. maxpos = {x = 1, y = 1, z = 1},
  341. minvel = {x = -2, y = -2, z = -2},
  342. maxvel = {x = 2, y = 2, z = 2},
  343. minacc = {x = -1, y = -1, z = -1},
  344. maxacc = {x = 1, y = 1, z = 1},
  345. minexptime = 1,
  346. maxexptime = 2,
  347. minsize = 1,
  348. maxsize = 3,
  349. attached = obj,
  350. vertical = false,
  351. -- ^ vertical: if true faces player using y axis only
  352. texture = "fire_basic_flame.png",
  353. })
  354. obj:punch(user, 1, itemstack:get_tool_capabilities())
  355. for i = 1, 5 do
  356. minetest.after(i, function()
  357. if obj and user and itemstack then
  358. obj:punch(user, 1, itemstack:get_tool_capabilities())
  359. end
  360. end)
  361. end
  362. if not minetest.setting_getbool("creative_mode") then
  363. itemstack:add_wear(65535/499)
  364. return itemstack
  365. end
  366. elseif pointed_thing.type == "node" then
  367. local pos = user:get_pos()
  368. local radius = 5
  369. for x = -radius, radius do
  370. for z = -radius, radius do
  371. for y = 10, -10, -1 do
  372. local new_pos = {
  373. x = pos.x + x,
  374. y = pos.y + y,
  375. z = pos.z + z,
  376. }
  377. local node = minetest.get_node(new_pos)
  378. local nodeu = minetest.get_node({x = new_pos.x, y = new_pos.y - 1, z = new_pos.z})
  379. local value = x * x + z * z
  380. if value <= radius * radius + 1
  381. and node.name == "air" and nodeu.name ~= "air" and vector.distance(user:get_pos(),new_pos) > 3 then
  382. minetest.set_node(new_pos, {name = "mobs_balrog:flame"})
  383. break
  384. end
  385. end
  386. end
  387. end
  388. if not minetest.setting_getbool("creative_mode") then
  389. itemstack:add_wear(65535/49)
  390. return itemstack
  391. end
  392. end
  393. end,
  394. tool_capabilities = {
  395. full_punch_interval = 0.25,
  396. max_drop_level=2,
  397. groupcaps={
  398. snappy={times={[1]=1.60, [2]=1.30, [3]=0.90}, uses=50, maxlevel=3},
  399. },
  400. damage_groups = {fleshy=5},
  401. },
  402. })
  403. --
  404. -- Barlog's spawner
  405. --
  406. mobs:spawn({name = "mobs_balrog:balrog",
  407. nodes = {"df_underworld_items:slade"},
  408. max_light = MAX_LIGHT,
  409. min_light = MIN_LIGHT,
  410. interval = INTERVAL,
  411. chance = CHANCE,
  412. active_object_count = MAX_NUMBER,
  413. min_height = MIN_HEIGHT,
  414. max_height = MAX_HEIGHT,
  415. })
  416. mobs:register_egg("mobs_balrog:balrog",
  417. "Balrog",
  418. "default_lava.png", -- the texture displayed for the egg in inventory
  419. 1, -- egg image in front of your texture (1 = yes, 0 = no)
  420. false -- if set to true this stops spawn egg appearing in creative
  421. )
  422. mobs:alias_mob("mobs:balrog", "mobs_balrog:balrog")
  423. --
  424. -- Minetest engine debug logging
  425. --
  426. if (minetest.settings:get("debug_log_level") == nil)
  427. or (minetest.settings:get("debug_log_level") == "action")
  428. or (minetest.settings:get("debug_log_level") == "info")
  429. or (minetest.settings:get("debug_log_level") == "verbose")
  430. then
  431. minetest.log("action", "[Mod] Mobs Balrog [v0.4.0] loaded.")
  432. end