]> git.lizzy.rs Git - Crafter.git/blob - mods/mob/api/interaction.lua
Add in damage color texture modifier to mob api
[Crafter.git] / mods / mob / api / interaction.lua
1 --
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
8                         if wear then
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})
12                                 end
13                                 puncher:set_wielded_item(itemstack)
14                         end
15                 end
16         end
17
18         --critical effect particles
19         mob_register.do_critical_particles = function(pos)
20                 minetest.add_particlespawner({
21                         amount = 40,
22                         time = 0.001,
23                         minpos = pos,
24                         maxpos = pos,
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},
29                         minexptime = 1.1,
30                         maxexptime = 1.5,
31                         minsize = 1,
32                         maxsize = 2,
33                         collisiondetection = false,
34                         vertical = false,
35                         texture = "critical.png",
36                 })
37         end
38         
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()
46                                 
47                                 local dir = vector.direction(pos,pos2)
48                                 dir.y = 0
49                                 
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())
53                                 end
54                                 
55                                 local velocity = vector.multiply(dir,1.1)
56                                 
57                                 local vel1 = vector.multiply(velocity, -1)
58                                 local vel2 = velocity
59                                 self.object:add_velocity(vel1)
60                                 
61                                 if object:is_player() then
62                                         object:add_player_velocity(vel2)
63                                 else
64                                         object:add_velocity(vel2)
65                                 end
66                         end
67                 end
68         end
69         if def.takes_fall_damage == nil or def.takes_fall_damage == true then
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, 
77                                                 {
78                                                 full_punch_interval=1.5,
79                                                 damage_groups = {damage=damage},
80                                                 })
81                                 end
82                         end
83                         self.oldvel = vel
84                 end
85         end
86
87         --this controls what happens when the mob gets punched
88         mob_register.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
89                 local hp = self.hp
90                 local vel = self.object:get_velocity()
91                 local hurt = tool_capabilities.damage_groups.damage
92                 
93                 if not hurt then
94                         hurt = 1
95                 end
96                 
97                 local critical = false
98                 
99                 --criticals
100                 local pos = self.object:get_pos()
101                 if puncher:is_player() then
102                         local puncher_vel = puncher:get_player_velocity().y
103                         if puncher_vel < 0 then
104                                 hurt = hurt * 1.5
105                                 critical = true
106                         end
107                 end
108                 
109                 local hp = hp-hurt
110
111                 if (self.punched_timer <= 0 and hp > 1) and not self.dead then
112                         self.object:set_texture_mod("^[colorize:"..self.damage_color..":130")
113                         self.hurt_color_timer = 0.25
114                         if puncher ~= self.object then
115                                 self.punched_timer = 0.8
116                                 if self.attacked_hostile then
117                                         self.hostile = true
118                                         self.hostile_timer = 20
119                                         if self.group_attack == true then
120                                                 for _,object in ipairs(minetest.get_objects_inside_radius(pos, self.view_distance)) do
121                                                         if not object:is_player() and object:get_luaentity() and object:get_luaentity().mobname == self.mobname then
122                                                                 object:get_luaentity().hostile = true
123                                                                 object:get_luaentity().hostile_timer = 20
124                                                         end
125                                                 end
126                                         end
127                                 end
128                         end
129                         
130                         --critical effect
131                         if critical == true then
132                                 self.do_critical_particles(pos)
133                                 minetest.sound_play("critical", {object=self.object, gain = 0.1, max_hear_distance = 10,pitch = math.random(80,100)/100})
134                         end
135                         minetest.sound_play(self.hurt_sound, {object=self.object, gain = 1.0, max_hear_distance = 10,pitch = math.random(100,140)/100})
136                         
137                         self.hp = hp
138                         
139                         self.direction = vector.multiply(dir,-1)
140                         dir = vector.multiply(dir,10)
141                         if vel.y <= 0 then
142                                 dir.y = 4
143                         else
144                                 dir.y = 0
145                         end
146                         
147                         
148                         self.object:add_velocity(dir)
149                         self.add_sword_wear(self, puncher, time_from_last_punch, tool_capabilities, dir)
150                 elseif (self.punched_timer <= 0 and self.death_animation_timer == 0) then
151                         self.object:set_texture_mod("^[colorize:"..self.damage_color..":130")
152                         self.hurt_color_timer = 0.25
153                         if puncher ~= self.object then
154                                 self.punched_timer = 0.8
155                                 if self.attacked_hostile then
156                                         self.hostile = true
157                                         self.hostile_timer = 20
158                                         if self.group_attack == true then
159                                                 for _,object in ipairs(minetest.get_objects_inside_radius(pos, self.view_distance)) do
160                                                         if not object:is_player() and object:get_luaentity() and object:get_luaentity().mobname == self.mobname then
161                                                                 object:get_luaentity().hostile = true
162                                                                 object:get_luaentity().hostile_timer = 20
163                                                         end
164                                                 end
165                                         end
166                                 end
167                         end
168                         self.death_animation_timer = 1
169                         self.dead = true
170                         
171                         --critical effect
172                         if critical == true then
173                                 self.do_critical_particles(pos)
174                                 minetest.sound_play("critical", {object=self.object, gain = 0.1, max_hear_distance = 10,pitch = math.random(80,100)/100})
175                         end
176                         minetest.sound_play(self.die_sound, {object=self.object, gain = 1.0, max_hear_distance = 10,pitch = math.random(80,100)/100})
177                         self.add_sword_wear(self, puncher, time_from_last_punch, tool_capabilities, dir)
178                 end
179         end
180
181         --this is what happens when a mob dies
182         mob_register.on_death = function(self, killer)
183                 local pos = self.object:get_pos()
184                 --pos.y = pos.y + 0.4
185                 minetest.sound_play("mob_die", {pos = pos, gain = 1.0})
186                 minetest.add_particlespawner({
187                         amount = 40,
188                         time = 0.001,
189                         minpos = pos,
190                         maxpos = pos,
191                         minvel = vector.new(-5,-5,-5),
192                         maxvel = vector.new(5,5,5),
193                         minacc = {x=0, y=0, z=0},
194                         maxacc = {x=0, y=0, z=0},
195                         minexptime = 1.1,
196                         maxexptime = 1.5,
197                         minsize = 1,
198                         maxsize = 2,
199                         collisiondetection = false,
200                         vertical = false,
201                         texture = "smoke.png",
202                 })
203                 
204                 --only throw items if registered
205                 if self.item_drop then
206                         --detect if multiple items are going to be added
207                         if self.item_max then
208                                 local data_item_amount = math.random(self.item_minimum, self.item_max)
209                                 for i = 1 ,data_item_amount do
210                                         minetest.throw_item(pos,self.item_drop)
211                                 end
212                         else
213                                 minetest.throw_item(pos,self.item_drop)
214                         end
215                 end
216                         
217                 global_mob_amount = global_mob_amount - 1
218                 print("Mobs Died. Current Mobs: "..global_mob_amount)
219                 
220                 self.object:remove()
221         end
222         
223         --the pig will look for and at players
224         mob_register.look_around = function(self,dtime)
225                 local pos = self.object:get_pos()
226                 
227                 if self.die_in_light and self.die_in_light_level and self.die_in_light == true then
228                         local light_level = minetest.get_node_light(pos)
229                         if light_level then
230                                 if (self.die_in_light == true and light_level > self.die_in_light_level) then
231                                         local damage = self.hp
232                                         self.object:punch(self.object, 2, 
233                                                 {
234                                                 full_punch_interval=1.5,
235                                                 damage_groups = {damage=damage},
236                                         })
237                                 end
238                         end
239                 end
240                 
241                 --STARE O_O
242                 --and follow!
243                 self.following = false
244                 local player_found = false
245
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
251                                 
252                                 player_found = true
253                                 
254                                 if self.head_bone then
255                                         self.move_head(self,pos2,dtime)
256                                 end
257                                 
258                                 --print(self.hostile)
259                                 if self.hostile == true then
260                                         local distance = vector.distance(pos,pos2)
261                                         
262                                         --punch the player
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
267                                                                 self.punch_timer = 1
268                                                                 object:punch(self.object, 2, 
269                                                                         {
270                                                                         full_punch_interval=1.5,
271                                                                         damage_groups = {fleshy=2},
272                                                                 },vector.direction(pos,pos2))
273                                                         end
274                                                 end
275                                         elseif self.attack_type == "explode" then
276                                                 --mob will not explode if it cannot see you
277                                                 if distance <  self.explosion_radius and minetest.line_of_sight(vector.new(pos.x,pos.y+self.object:get_properties().collisionbox[5],pos.z), pos2) then
278                                                         
279                                                         if not self.tnt_timer then
280                                                                 minetest.sound_play("tnt_ignite", {object = self.object, gain = 1.0,})
281                                                                 self.tnt_timer = self.explosion_time
282                                                                 self.tnt_tick_timer  = 0.2
283                                                                 self.tnt_mod_state = 1
284                                                                 self.object:set_texture_mod("^[colorize:white:130")
285                                                         end
286                                                 end
287                                         elseif self.attack_type == "projectile" then
288                                                 if not self.projectile_timer then
289                                                         self.projectile_timer = self.projectile_timer_cooldown
290                                                 end
291                                                 if self.projectile_timer <= 0 then
292                                                         self.projectile_timer = self.projectile_timer_cooldown
293                                                         
294                                                         local obj = minetest.add_entity(pos, self.projectile_type)
295                                                         if obj then
296                                                                 local dir = vector.multiply(vector.direction(pos,pos2), 50)
297                                                                 obj:set_velocity(dir)
298                                                                 obj:get_luaentity().timer = 2
299                                                         end
300                                                 end
301                                         end
302                                         self.direction = vector.direction(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z))
303                                         self.speed = self.max_speed
304                                         self.following = true
305                                 end
306                                 --only look at one player
307                                 break
308                         end
309                 end
310                 --stare straight if not found
311                 if player_found == false then
312                         self.move_head(self,nil,dtime)
313                         if self.manage_hostile_timer then
314                                 self.manage_hostile_timer(self,dtime)
315                         end
316                 end
317         end
318         
319         return(mob_register)
320 end