2 mobs.create_interaction_functions = function(def,mob_register)
3 --the sword wear mechanic
4 mob_register.add_sword_wear = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
5 if puncher:is_player() then
6 local itemstack = puncher:get_wielded_item()
7 local wear = itemstack:get_definition().mob_hit_wear
9 itemstack:add_wear(wear)
10 if itemstack:get_name() == "" then
11 minetest.sound_play("tool_break",{to_player = puncher:get_player_name(),gain=0.4})
13 puncher:set_wielded_item(itemstack)
18 --critical effect particles
19 mob_register.do_critical_particles = function(pos)
20 minetest.add_particlespawner({
25 minvel = vector.new(-2,-2,-2),
26 maxvel = vector.new(2,8,2),
27 minacc = {x=0, y=4, z=0},
28 maxacc = {x=0, y=12, z=0},
33 collisiondetection = false,
35 texture = "critical.png",
39 mob_register.collision_detection = function(self)
40 local pos = self.object:get_pos()
41 --do collision detection from the base of the mob
42 pos.y = pos.y - self.object:get_properties().collisionbox[2]
43 for _,object in ipairs(minetest.get_objects_inside_radius(pos, self.collision_boundary)) do
44 if object:is_player() or object:get_luaentity().mob == true then
45 local pos2 = object:get_pos()
47 local dir = vector.direction(pos,pos2)
50 --eliminate mob being stuck in corners
51 if dir.x == 0 and dir.z == 0 then
52 dir = vector.new(math.random(-1,1)*math.random(),0,math.random(-1,1)*math.random())
55 local velocity = vector.multiply(dir,1.1)
57 vel1 = vector.multiply(velocity, -1)
59 self.object:add_velocity(vel1)
61 if object:is_player() then
62 object:add_player_velocity(vel2)
64 object:add_velocity(vel2)
70 mob_register.fall_damage = function(self)
71 local vel = self.object:get_velocity()
72 if vel and self.oldvel then
73 if self.oldvel.y < -7 and vel.y == 0 then
74 local damage = math.abs(self.oldvel.y + 7)
75 damage = math.floor(damage/1.5)
76 self.object:punch(self.object, 2,
78 full_punch_interval=1.5,
79 damage_groups = {damage=damage},
86 --this controls what happens when the mob gets punched
87 mob_register.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
89 local vel = self.object:get_velocity()
90 local hurt = tool_capabilities.damage_groups.damage
96 local critical = false
99 local pos = self.object:get_pos()
100 if puncher:is_player() then
101 local puncher_vel = puncher:get_player_velocity().y
102 if puncher_vel < 0 then
110 print(self.punched_timer)
112 if (self.punched_timer <= 0 and hp > 1) and not self.dead then
113 self.object:set_texture_mod("^[colorize:red:130")
114 self.hurt_color_timer = 0.25
115 if puncher ~= self.object then
116 self.punched_timer = 0.8
117 if self.attacked_hostile then
119 self.hostile_timer = 20
120 if self.group_attack == true then
121 for _,object in ipairs(minetest.get_objects_inside_radius(pos, self.view_distance)) do
122 if not object:is_player() and object:get_luaentity() and object:get_luaentity().mobname == self.mobname then
123 object:get_luaentity().hostile = true
124 object:get_luaentity().hostile_timer = 20
132 if critical == true then
133 self.do_critical_particles(pos)
134 minetest.sound_play("critical", {object=self.object, gain = 0.1, max_hear_distance = 10,pitch = math.random(80,100)/100})
136 minetest.sound_play(self.hurt_sound, {object=self.object, gain = 1.0, max_hear_distance = 10,pitch = math.random(100,140)/100})
140 self.direction = vector.multiply(dir,-1)
141 dir = vector.multiply(dir,10)
149 self.object:add_velocity(dir)
150 self.add_sword_wear(self, puncher, time_from_last_punch, tool_capabilities, dir)
151 elseif (self.punched_timer <= 0 and self.death_animation_timer == 0) then
152 self.object:set_texture_mod("^[colorize:red:130")
153 self.hurt_color_timer = 0.25
154 if puncher ~= self.object then
155 self.punched_timer = 0.8
156 if self.attacked_hostile then
158 self.hostile_timer = 20
159 if self.group_attack == true then
160 for _,object in ipairs(minetest.get_objects_inside_radius(pos, self.view_distance)) do
161 if not object:is_player() and object:get_luaentity() and object:get_luaentity().mobname == self.mobname then
162 object:get_luaentity().hostile = true
163 object:get_luaentity().hostile_timer = 20
169 self.death_animation_timer = 1
173 if critical == true then
174 self.do_critical_particles(pos)
175 minetest.sound_play("critical", {object=self.object, gain = 0.1, max_hear_distance = 10,pitch = math.random(80,100)/100})
177 minetest.sound_play(self.die_sound, {object=self.object, gain = 1.0, max_hear_distance = 10,pitch = math.random(80,100)/100})
178 self.add_sword_wear(self, puncher, time_from_last_punch, tool_capabilities, dir)
182 --this is what happens when a mob dies
183 mob_register.on_death = function(self, killer)
184 local pos = self.object:get_pos()
185 --pos.y = pos.y + 0.4
186 minetest.sound_play("mob_die", {pos = pos, gain = 1.0})
187 minetest.add_particlespawner({
192 minvel = vector.new(-5,-5,-5),
193 maxvel = vector.new(5,5,5),
194 minacc = {x=0, y=0, z=0},
195 maxacc = {x=0, y=0, z=0},
200 collisiondetection = false,
202 texture = "smoke.png",
205 --only throw items if registered
206 if self.item_drop then
207 --detect if multiple items are going to be added
208 if self.item_amount and self.item_minumum then
209 local data_item_amount = math.random(self.item_minimum, self.item_amount)
210 for i = self.item_minimum,data_item_amount do
211 minetest.throw_item(pos,self.item_drop)
214 minetest.throw_item(pos,self.item_drop)
218 global_mob_amount = global_mob_amount - 1
219 print("Mobs Died. Current Mobs: "..global_mob_amount)
224 --the pig will look for and at players
225 mob_register.look_around = function(self,dtime)
226 local pos = self.object:get_pos()
228 if self.die_in_light and self.die_in_light_level and self.die_in_light == true then
229 local light_level = minetest.get_node_light(pos)
231 if (self.die_in_light == true and light_level > self.die_in_light_level) then
232 local damage = self.hp
233 self.object:punch(self.object, 2,
235 full_punch_interval=1.5,
236 damage_groups = {damage=damage},
244 self.following = false
245 local player_found = false
246 for _,object in ipairs(minetest.get_objects_inside_radius(pos, self.view_distance)) do
247 if object:is_player() and player_found == false and object:get_hp() > 0 then
248 --look at player's camera
249 local pos2 = object:get_pos()
250 pos2.y = pos2.y + 1.625
254 if self.head_bone then
255 self.move_head(self,pos2,dtime)
259 if self.hostile == true then
260 local distance = vector.distance(pos,pos2)
263 if self.attack_type == "punch" then
264 if distance < 2.5 and self.punch_timer <= 0 and object:get_hp() > 0 then
265 local line_of_sight = minetest.line_of_sight(pos, pos2)
266 if line_of_sight == true then
268 object:punch(self.object, 2,
270 full_punch_interval=1.5,
271 damage_groups = {fleshy=2},
272 },vector.direction(pos,pos2))
275 elseif self.attack_type == "explode" then
276 if distance < self.explosion_radius then
278 if not self.tnt_timer then
279 minetest.sound_play("tnt_ignite", {object = self.object, gain = 1.0,})
280 self.tnt_timer = self.explosion_time
281 self.tnt_tick_timer = 0.2
282 self.tnt_mod_state = 1
283 self.object:set_texture_mod("^[colorize:white:130")
286 elseif self.attack_type == "projectile" then
287 if not self.projectile_timer then
288 self.projectile_timer = self.projectile_timer_cooldown
290 if self.projectile_timer <= 0 then
291 self.projectile_timer = self.projectile_timer_cooldown
293 local obj = minetest.add_entity(pos, self.projectile_type)
295 local dir = vector.multiply(vector.direction(pos,pos2), 50)
296 obj:set_velocity(dir)
297 obj:get_luaentity().timer = 2
301 self.direction = vector.direction(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z))
302 self.speed = self.max_speed
303 self.following = true
305 --only look at one player
309 --stare straight if not found
310 if player_found == false then
311 --self.move_head(self,nil,dtime)
312 if self.manage_hostile_timer then
313 self.manage_hostile_timer(self,dtime)