morde.lua 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. local SCALE = 500
  2. mobs.register_mob("nssm:morde", {
  3. type = "monster",
  4. description = "Morde",
  5. hp_max = 47*SCALE,
  6. hp_min = 37*SCALE,
  7. collisionbox = {-0.4, -0.1, -0.4, 0.4, 1.6, 0.4},
  8. visual = "mesh",
  9. rotate= 270,
  10. mesh = "morde.x",
  11. textures = {{"morde.png"}},
  12. visual_size = {x=8, y=8},
  13. makes_footstep_sound = true,
  14. view_range = 20,
  15. walk_velocity = 0.5,
  16. reach =3.0,
  17. run_velocity = 3.5,
  18. damage = 6*SCALE,
  19. jump = true,
  20. sounds = {
  21. random = "morde",
  22. attack = "morde",
  23. },
  24. drops = {
  25. {name = "default:flint", chance = 1, min = 2, max = 4},
  26. {name = "default:obsidian_shard", chance = 3, min = 1, max = 1},
  27. },
  28. armor = 60,
  29. drawtype = "front",
  30. water_damage = 0,
  31. fear_height = 4,
  32. floats = 1,
  33. lava_damage = 0,
  34. light_damage = 0,
  35. group_attack=true,
  36. attack_animals=true,
  37. knock_back=1,
  38. blood_texture="morparticle.png",
  39. stepheight=1.1,
  40. on_rightclick = nil,
  41. attack_type = "dogfight",
  42. animation = {
  43. speed_normal = 15,
  44. speed_run = 25,
  45. stand_start = 10,
  46. stand_end = 40,
  47. walk_start = 50,
  48. walk_end = 90,
  49. run_start = 100,
  50. run_end = 120,
  51. punch_start = 130,
  52. punch_end = 160,
  53. },
  54. custom_attack = function(self)
  55. self.morde_timer = (self.morde_timer or os.time())
  56. if (os.time() - self.morde_timer) > 1 then
  57. self.morde_timer = os.time()
  58. local s = self.object:get_pos()
  59. local p = self.attack:get_pos()
  60. mobs.set_animation(self, "punch")
  61. self.health = self.health + (self.damage*2)
  62. local m = 3
  63. if minetest.line_of_sight({x = p.x, y = p.y +1.5, z = p.z}, {x = s.x, y = s.y +1.5, z = s.z}) == true then
  64. -- play attack sound
  65. if self.sounds.attack then
  66. minetest.sound_play(self.sounds.attack, {
  67. object = self.object,
  68. max_hear_distance = self.sounds.distance
  69. })
  70. end
  71. -- punch player
  72. self.attack:punch(self.object, 1.0, {
  73. full_punch_interval=1.0,
  74. damage_groups = {snappy=self.damage}
  75. }, nil)
  76. minetest.add_particlespawner({
  77. amount = 6, --amount
  78. time = 1, --time
  79. minpos = {x=p.x-0.5, y=p.y-0.5, z=p.z-0.5}, --minpos
  80. maxpos = {x=p.x+0.5, y=p.y+0.5, z=p.z+0.5}, --maxpos
  81. minvel = {x=(s.x-p.x)*m, y=(s.y-p.y+1)*m, z=(s.z-p.z)*m}, --minvel
  82. maxvel = {x=(s.x-p.x)*m, y=(s.y-p.y+1)*m, z=(s.z-p.z)*m}, --maxvel
  83. minacc = {x=s.x-p.x, y=s.y-p.y+1, z=s.z-p.z}, --minacc
  84. maxacc = {x=s.x-p.x, y=s.y-p.y+1, z=s.z-p.z}, --maxacc
  85. minexptime = 0.2, --minexptime
  86. maxexptime = 0.3, --maxexptime
  87. minsize = 2, --minsize
  88. maxsize = 3, --maxsize
  89. collisiondetection = false, --collisiondetection
  90. texture = "morparticle.png", --texture
  91. })
  92. end
  93. end
  94. end,
  95. on_die = function(self)
  96. local pos = self.object:get_pos()
  97. minetest.add_entity(pos, "nssm:mortick")
  98. end,
  99. })
  100. mobs.register_egg("nssm:morde", "Morde", "default_obsidian.png", 1)
  101. minetest.register_entity("nssm:mortick", {
  102. textures = {"mortick.png"},
  103. hp_min = 10000,
  104. hp_max = 10000,
  105. armor = 1,
  106. visual = "mesh",
  107. mesh = "mortick.x",
  108. visual_size = {x=3, y=3},
  109. pointable = false,
  110. -- Thus much damage is a nuisance if the player is healthy, but can quickly
  111. -- overwhelm them if they become so damaged that passive healing can no longer
  112. -- keep up.
  113. damage = 1*SCALE,
  114. on_step = function(self, dtime)
  115. self.mortick_timer = self.mortick_timer or os.time()
  116. self.timer = (self.timer or 0) + dtime
  117. self.timer2 = (self.timer2 or 0) + dtime
  118. if self.timer2 >= 1 then
  119. self.timer2 = 0
  120. local s = self.object:get_pos()
  121. local s1 = vector.round({x=s.x, y = s.y, z = s.z})
  122. -- The mortick dies when he finds himself in the water.
  123. -- It has to be *really* water (group level 3).
  124. local name = minetest.get_node(s1).name
  125. if minetest.get_item_group(name, "water") == 3 then
  126. self.object:remove()
  127. return
  128. end
  129. -- Find player to attack, if we don't have a target named already.
  130. if not self.attack or self.attack == "" then
  131. -- Chose target for the first time, once only.
  132. local objects = minetest.get_objects_inside_radius(s, 8)
  133. for _, obj in ipairs(objects) do
  134. if obj:is_player() and not gdac.player_is_admin(obj) then
  135. -- Note: this is player's name! Do not store player reference.
  136. self.attack = obj:get_player_name()
  137. break
  138. end
  139. end
  140. end
  141. end
  142. -- If found a player follow him.
  143. if self.attack and self.attack ~= "" then
  144. local target = minetest.get_player_by_name(self.attack)
  145. if target then
  146. local cur_hp = target:get_hp()
  147. -- Attach to target if not currently attached.
  148. if not self.object:get_attach() or (self.target_hp or 0) ~= cur_hp then
  149. self.target_hp = cur_hp
  150. if cur_hp > 0 then
  151. -- Attach to back.
  152. self.object:set_attach(target, "", {x=0, y=9, z=-4}, {x=0, y=90, z=0})
  153. else
  154. -- Attach to front.
  155. self.object:set_attach(target, "", {x=0, y=4, z=-3}, {x=90, y=0, z=90})
  156. end
  157. end
  158. -- Damage player every ten seconds:
  159. if self.timer > 10 then
  160. self.timer = 0
  161. utility.damage_player(target, "poison", self.damage)
  162. end
  163. end
  164. end
  165. end
  166. })