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