]> git.lizzy.rs Git - Crafter.git/blob - mods/mob/init.lua
Make it so you cannot spam hit mobs
[Crafter.git] / mods / mob / init.lua
1 --this is where mobs are defined
2
3 --this is going to be used to set an active mob limit
4 global_mob_table = {}
5
6
7 local path = minetest.get_modpath(minetest.get_current_modname())
8
9 dofile(path.."/spawning.lua")
10 dofile(path.."/items.lua")
11
12
13 --these are helpers to create entities
14 mob = {}
15
16 dofile(path.."/head_code.lua")
17 dofile(path.."/movement_code.lua")
18 dofile(path.."/data_handling_code.lua")
19 dofile(path.."/interaction_code.lua")
20
21 mob.initial_properties = {
22         hp_max = 1,
23         physical = true,
24         collide_with_objects = false,
25         collisionbox = {-0.37, -0.4, -0.37, 0.37, 0.5, 0.37},
26         visual = "mesh",
27         visual_size = {x = 3, y = 3},
28         mesh = "pig.x",
29         textures = {
30                 "body.png","leg.png","leg.png","leg.png","leg.png"
31         },
32         is_visible = true,
33         pointable = true,
34         automatic_face_movement_dir = 0.0,
35         automatic_face_movement_max_rotation_per_sec = 300,
36 }
37 mob.hp = 5
38 mob.speed = 5
39
40 mob.mob = true
41 mob.hostile = false
42 mob.timer = 0
43 mob.state = 0
44 mob.hunger = 200
45 mob.view_distance = 20
46
47 mob.punch_timer = 0
48 mob.punched_timer = 0
49 ----------------------------------
50
51
52
53 mob.on_death = function(self, killer)
54         local pos = self.object:getpos()
55         pos.y = pos.y + 0.4
56         minetest.sound_play("mob_die", {pos = pos, gain = 1.0})
57         minetest.add_particlespawner({
58                 amount = 40,
59                 time = 0.001,
60                 minpos = pos,
61                 maxpos = pos,
62                 minvel = vector.new(-5,-5,-5),
63                 maxvel = vector.new(5,5,5),
64                 minacc = {x=0, y=0, z=0},
65                 maxacc = {x=0, y=0, z=0},
66                 minexptime = 1.1,
67                 maxexptime = 1.5,
68                 minsize = 1,
69                 maxsize = 2,
70                 collisiondetection = false,
71                 vertical = false,
72                 texture = "smoke.png",
73         })
74         local obj = minetest.add_item(pos,"mob:raw_porkchop")
75         self.child:get_luaentity().parent = nil
76 end
77
78 --repel from players
79 mob.push = function(self)
80         local pos = self.object:getpos()
81         local radius = 1
82         for _,object in ipairs(minetest.get_objects_inside_radius(pos, radius)) do
83                 if object:is_player() or object:get_luaentity().mob == true then
84                         local player_pos = object:getpos()
85                         pos.y = 0
86                         player_pos.y = 0
87                         
88                         local currentvel = self.object:getvelocity()
89                         local vel = vector.subtract(pos, player_pos)
90                         vel = vector.normalize(vel)
91                         local distance = vector.distance(pos,player_pos)
92                         distance = (radius-distance)*10
93                         vel = vector.multiply(vel,distance)
94                         local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
95                         
96                         
97                         self.object:add_velocity(acceleration)
98                         
99                         acceleration = vector.multiply(acceleration, 5)
100                         object:add_player_velocity(acceleration)
101                 end
102         end
103 end
104
105
106 --makes the mob swim
107 mob.swim = function(self)
108         local pos = self.object:getpos()
109         pos.y = pos.y + 0.7
110         local node = minetest.get_node(pos).name
111         local vel = self.object:getvelocity()
112         local goal = 3
113         local acceleration = vector.new(0,goal-vel.y,0)
114         self.swimming = false
115         
116         if node == "main:water" or node =="main:waterflow" then
117                 self.swimming = true
118                 self.object:add_velocity(acceleration)
119         end
120 end
121
122 --sets the mob animation and speed
123 mob.set_animation = function(self)
124         local distance = vector.distance(vector.new(0,0,0), self.object:getvelocity())
125         self.object:set_animation_frame_speed(distance*5)
126 end
127
128
129
130
131
132 mob.look_around = function(self)
133         local pos = self.object:get_pos()
134         
135         --this is where the mob is actually looking
136         local eye_ray = self.raycast_look(self,dtime)
137         --this is below where the mob is pointed, checks if ledge
138         --[[ --work on this later
139         local ledge_ray = self.look_below(self)
140                 
141         local is_a_drop = true
142         --check if there's a drop
143         if ledge_ray then
144                 for pointed_thing in ledge_ray do
145                         if pointed_thing then
146                                 local pos2 = pointed_thing.under
147                                 local distance = math.floor(vector.subtract(pos2,pos).y-self.object:get_properties().collisionbox[2]+0.5+0.5)
148                                 if distance >= -3 then
149                                         is_a_drop = false
150                                 end
151                         end
152                 end
153         end
154         --turn around
155         if is_a_drop == true then
156                 self.direction = vector.multiply(self.direction, -1)
157                 print("turning around")
158         end
159         ]]--
160         
161         --a mob will check if it needs to jump
162         if eye_ray then
163                 for pointed_thing in eye_ray do
164                         local pos = self.object:get_pos()
165                         local pos2 = pointed_thing.under
166                         local walkable = minetest.registered_nodes[minetest.get_node(pos2).name].walkable
167                         if walkable then
168                                 if vector.distance(pos,pos2) < 1 then
169                                         self.jump(self)
170                                         break
171                                 end
172                         end
173                 end
174         end
175         
176         
177         --STARE O_O
178         --and follow!
179         self.following = false
180         local player_found = false
181         for _,object in ipairs(minetest.get_objects_inside_radius(pos, 6)) do
182                 if object:is_player() and player_found == false then
183                         --print("test")
184                         player_found = true
185                         --look at player's camera
186                         local pos2 = object:get_pos()
187                         pos2.y = pos2.y + 1.625
188                         
189                         local found_player = self.move_head(self,pos2)
190                         
191                         if found_player == true then
192                                 self.direction = vector.direction(pos,pos2)
193                                 local distance = vector.distance(pos,pos2)-2
194                                 if distance < 0 then
195                                         distance = 0
196                                 end
197                                 
198                                 --punch the player
199                                 if distance < 0.5 and self.punch_timer <= 0 and object:get_hp() > 0 then
200                                         self.punch_timer = 1
201                                         object:punch(self.object, 2, 
202                                                 {
203                                                 full_punch_interval=1.5,
204                                                 damage_groups = {fleshy=2},
205                                         },vector.direction(pos,pos2))
206                                 elseif distance < 0.5 and object:get_hp() <= 0 then
207                                         --make the head spin "victory dance"
208                                         if self.child then
209                                                 if not self.head_spin then
210                                                         self.head_spin = 180
211                                                 end
212                                                 self.child:set_attach(self.object, "", vector.new(2.4,1.2,0), vector.new(self.head_spin,0,0))
213                                                 self.child:set_animation({x=90,y=90}, 15, 0, true)
214                                                 self.head_spin = self.head_spin + 5
215                                                 if self.head_spin > 360 then
216                                                         self.head_spin = 0
217                                                 end
218                                         end
219                                 end
220                                 self.speed = distance * 2
221                                 self.following = true
222                                 break
223                         end
224                 end
225         end
226         
227         
228         
229         --stare straight if not found
230         if player_found == false then
231                 self.move_head(self,nil)
232         end
233         
234 end
235 --this is the info on the mob
236 mob.debug_nametag = function(self,dtime)
237         --we're doing this to the child because the nametage breaks the
238         --animation on the mob's body
239         if self.child then
240                 --we add in items we want to see in this list
241                 local debug_items = {"hunger","timer","punch_timer"}
242                 local text = ""
243                 for _,item in pairs(debug_items) do
244                         if self[item] then
245                                 text = text..item..": "..self[item].."\n"
246                         end
247                 end
248                 self.child:set_nametag_attributes({
249                 color = "white",
250                 text = text
251                 })
252         end
253 end
254
255 --this depletes the mobs hunger
256 mob.do_hunger = function(self,dtime)
257         self.hunger = self.hunger - dtime
258 end
259
260 --this sets the state of the mob
261 mob.set_state = function(self,dtime)
262         self.do_hunger(self,dtime)
263 end
264
265 mob.on_step = function(self, dtime)
266         self.set_state(self,dtime)
267         self.move(self,dtime)
268         self.set_animation(self)
269         self.look_around(self)
270         self.manage_punch_timer(self,dtime)
271         mob.debug_nametag(self,dtime)
272 end
273
274 minetest.register_entity("mob:pig", mob)
275
276
277
278
279
280 ------------------------------------------------------------------------the head
281
282 local head = {}
283 head.initial_properties = {
284         hp_max = 1,
285         physical = false,
286         collide_with_objects = false,
287         collisionbox = {0, 0, 0, 0, 0, 0},
288         visual = "mesh",
289         visual_size = {x = 1.1, y = 1.1},
290         mesh = "pig_head.x",
291         textures = {
292                 "head.png","nose.png"
293         },
294         is_visible = true,
295         pointable = false,
296         --automatic_face_movement_dir = 0.0,
297         --automatic_face_movement_max_rotation_per_sec = 600,
298 }
299
300 --remove the head if no body
301 head.on_step = function(self, dtime)
302         if self.parent == nil then
303                 self.object:remove()
304         end
305 end
306 minetest.register_entity("mob:head", head)