]> git.lizzy.rs Git - Crafter.git/blob - mods/mob/api/movement.lua
Implement first prototype of pathfinding
[Crafter.git] / mods / mob / api / movement.lua
1 --
2 mobs.create_movement_functions = function(def,mob_register)
3         --makes the mob swim
4         mob_register.swim = function(self,dtime)
5                 local pos = self.object:get_pos()
6                 pos.y = pos.y + 0.3
7                 local node = minetest.get_node(pos).name
8                 self.swimming = false
9                 if node == "main:water" or node =="main:waterflow" then
10                         local vel = self.object:getvelocity()
11                         local goal = 3
12                         local acceleration = vector.new(0,goal-vel.y,0)
13                         --jump out of the water
14                         if (vel.x == 0 and self.direction.x ~= 0) or (vel.z == 0 and self.direction.z ~= 0) then
15                                 self.object:set_velocity(vector.new(vel.x,5,vel.z))
16                         --else swim
17                         else
18                                 self.object:add_velocity(acceleration)
19                         end
20                         self.swimming = true
21                 end
22         end
23
24         local get_group = minetest.get_item_group
25         local get_node = minetest.get_node
26         mob_register.hurt_inside = function(self,dtime)
27                 if self.hp > 0 and self.hurt_inside_timer <= 0 then
28                         local pos = self.object:get_pos()
29                         local hurty = get_group(get_node(pos).name, "hurt_inside")
30                         if hurty > 0 then
31                                 self.object:punch(self.object, 2, 
32                                         {
33                                         full_punch_interval=1.5,
34                                         damage_groups = {damage=hurty},
35                                 })
36                         end
37                 else
38                         self.hurt_inside_timer = self.hurt_inside_timer - dtime
39                 end
40         end
41
42         --This makes the mob walk at a certain speed and jump
43         if def.movement_type == "walk" then
44                 mob_register.move = function(self,dtime,moveresult)
45                         self.manage_jump_timer(self,dtime)
46                         self.timer = self.timer - dtime
47
48                         --jump
49                         self.jump(self,moveresult)
50                         
51                         --swim
52                         self.swim(self,dtime)
53                         
54                         --print(self.timer)
55                         --direction state change
56                         if self.timer <= 0 and not self.following == true then
57                                 --print("changing direction")
58                                 self.timer = math.random(2,7)
59                                 self.direction = vector.new(math.random()*math.random(-1,1),0,math.random()*math.random(-1,1))
60                                 --local yaw = self.object:get_yaw() + dtime
61                                 self.speed = math.random(0,self.max_speed)
62                                 --self.object:set_yaw(yaw)
63                         end
64
65                         self.hurt_inside(self,dtime)
66
67                         local currentvel = self.object:get_velocity()
68                         local goal = vector.multiply(self.direction,self.speed)
69                         local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
70                         acceleration = vector.multiply(acceleration, 0.05)
71                         self.object:add_velocity(acceleration)
72                 end
73                 mob_register.jump = function(self,moveresult)
74                         if moveresult and moveresult.touching_ground and self.direction then
75                                 local pos = self.object:get_pos()
76                                 pos.y = pos.y+0.1
77
78                                 if self.path_data and table.getn(self.path_data) > 0 then
79                                         --smart jump
80                                         local y = math.floor(pos.y+0.5)
81                                         local vel = self.object:get_velocity()
82                                         if y < self.path_data[1].y then
83                                                 self.object:set_velocity(vector.new(vel.x,5,vel.z))
84                                         elseif self.path_data[2] and y < self.path_data[2].y then
85                                                 self.object:set_velocity(vector.new(vel.x,5,vel.z))
86                                         elseif self.path_data[3] and y < self.path_data[3].y then
87                                                 self.object:set_velocity(vector.new(vel.x,5,vel.z))
88                                         elseif ((vel.x == 0 and self.direction.x ~= 0) or (vel.z == 0 and self.direction.z ~= 0)) then
89                                                 self.object:set_velocity(vector.new(vel.x,5,vel.z))
90                                         end
91                                 else
92                                         --assume collisionbox is even x and z
93                                         local modifier = self.object:get_properties().collisionbox[4]*3
94                                         
95
96                                         local pos2 = vector.add(vector.multiply(self.direction,modifier),pos)
97
98                                         local ray = minetest.raycast(pos, pos2, false, false)
99                                         
100                                         local pointed_thing
101
102                                         if ray then
103                                                 pointed_thing = ray:next()
104                                         end
105                                                 
106                                         if pointed_thing then
107                                                 if minetest.get_nodedef(minetest.get_node(pointed_thing.under).name, "walkable") then
108                                                         --print("jump")
109                                                         local vel = self.object:get_velocity()
110                                                         --self.jump_timer = 1+math.random()
111                                                         self.object:set_velocity(vector.new(vel.x,5,vel.z))
112                                                 else
113                                                         --print("velocity check")
114                                                         local vel = self.object:get_velocity()
115                                                         if (vel.x == 0 and self.direction.x ~= 0) or (vel.z == 0 and self.direction.z ~= 0) then
116                                                                 self.object:set_velocity(vector.new(vel.x,5,vel.z))
117                                                         end
118                                                 end
119                                         else
120                                                 --print("velcheck 2")
121                                                 local vel = self.object:get_velocity()
122                                                 if (vel.x == 0 and self.direction.x ~= 0) or (vel.z == 0 and self.direction.z ~= 0) then
123                                                         self.object:set_velocity(vector.new(vel.x,5,vel.z))
124                                                 end
125                                         end
126                                 end
127                         end
128                 end
129         elseif def.movement_type == "jump" then
130                 mob_register.move = function(self,dtime,moveresult)
131                         self.manage_jump_timer(self,dtime)
132                         self.timer = self.timer - dtime
133                         
134                         --jump
135                         self.jump(self,moveresult)
136                         
137                         --swim
138                         self.swim(self,dtime)
139                         
140                         --print(self.timer)
141                         --direction state change
142                         if self.timer <= 0 and not self.following == true then
143                                 --print("changing direction")
144                                 self.timer = math.random(2,7)
145                                 self.direction = vector.new(math.random()*math.random(-1,1),0,math.random()*math.random(-1,1))
146                                 --local yaw = self.object:get_yaw() + dtime
147                                 self.speed = math.random(0,self.max_speed)
148                                 --self.object:set_yaw(yaw)
149                         end
150
151                         self.hurt_inside(self,dtime)    
152                         
153                         local currentvel = self.object:get_velocity()
154                         if currentvel.y ~= 0 then
155                                 local goal = vector.multiply(self.direction,self.speed)
156                                 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
157                                 acceleration = vector.multiply(acceleration, 0.05)
158                                 self.object:add_velocity(acceleration)
159                         end
160                 end
161                 
162                 mob_register.jump = function(self,moveresult)
163                         if moveresult and moveresult.touching_ground and self.direction then
164                                 if self.jump_timer <= 0 then
165                                         if self.make_jump_noise then
166                                                 minetest.sound_play("slime_splat", {object=self.object, gain = 1.0, max_hear_distance = 10,pitch = math.random(80,100)/100})
167                                         end
168                                         local vel = self.object:get_velocity()
169                                         self.object:set_velocity(vector.new(vel.x,5,vel.z))
170                                         if self.following == true then
171                                                 self.jump_timer = 0.5
172                                         else
173                                                 self.jump_timer = 1+math.random()
174                                         end
175                                 else
176                                         self.object:set_velocity(vector.new(0,0,0))
177                                 end
178                         end
179                 end
180         end
181         
182         if def.pathfinds then
183                 mob_register.pathfinding = function(self,dtime)
184                         if self.following and self.following_pos then
185                                 self.pathfinding_timer = self.pathfinding_timer + dtime
186                                 if self.pathfinding_timer > 1 then
187                                         self.pathfinding_timer = 0
188
189                                         local path = minetest.find_path(self.object:get_pos(),self.following_pos,self.view_distance*2,1,1,"A*_noprefetch")
190
191                                         if path and (not self.path_data or (self.path_data and table.getn(self.path_data) < 3)) then
192                                                 self.path_data = path
193                                         end
194
195                                         if self.path_data then
196                                                 for index,pos_data in pairs(self.path_data) do
197                                                         --print(dump(pos_data))
198                                                         minetest.add_particle({
199                                                                 pos = pos_data,
200                                                                 velocity = {x=0, y=0, z=0},
201                                                                 acceleration = {x=0, y=0, z=0},
202                                                                 expirationtime = 1,
203                                                                 size = 1,
204                                                                 texture = "dirt.png",
205                                                         })
206                                                 end
207                                         end
208                                 end
209                         end
210                         local selfpos = self.object:get_pos()
211                         local pos1 = vector.new(selfpos.x,0,selfpos.z)
212                         if self.path_data and table.getn(self.path_data) > 0 and vector.distance(pos1,vector.new(self.path_data[1].x,0,self.path_data[1].z)) < 1 then
213                                 --shift whole list down
214                                 for i = 2,table.getn(self.path_data) do
215                                         self.path_data[i-1] = self.path_data[i]
216                                 end
217                                 self.path_data[table.getn(self.path_data)] = nil
218                         end
219                 end
220         end
221         
222         return(mob_register)
223 end
224