1 --this is where mobs are defined
3 --this is going to be used to set an active mob limit
7 local path = minetest.get_modpath(minetest.get_current_modname())
9 dofile(path.."/spawning.lua")
10 dofile(path.."/items.lua")
13 --these are helpers to create entities
16 dofile(path.."/head_code.lua")
17 dofile(path.."/movement_code.lua")
18 dofile(path.."/data_handling_code.lua")
20 mob.initial_properties = {
23 collide_with_objects = false,
24 collisionbox = {-0.37, -0.4, -0.37, 0.37, 0.5, 0.37},
26 visual_size = {x = 3, y = 3},
29 "body.png","leg.png","leg.png","leg.png","leg.png"
33 automatic_face_movement_dir = 0.0,
34 automatic_face_movement_max_rotation_per_sec = 300,
44 mob.view_distance = 20
46 ----------------------------------
49 mob.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
50 local hurt = tool_capabilities.damage_groups.fleshy
54 local hp = self.object:get_hp()
55 self.object:set_hp(hp-hurt)
57 minetest.sound_play("hurt", {object=self.object, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
61 mob.on_death = function(self, killer)
62 local pos = self.object:getpos()
64 minetest.sound_play("mob_die", {pos = pos, gain = 1.0})
65 minetest.add_particlespawner({
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},
78 collisiondetection = false,
80 texture = "smoke.png",
82 local obj = minetest.add_item(pos,"mob:raw_porkchop")
83 self.child:get_luaentity().parent = nil
87 mob.push = function(self)
88 local pos = self.object:getpos()
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()
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)
105 self.object:add_velocity(acceleration)
107 acceleration = vector.multiply(acceleration, 5)
108 object:add_player_velocity(acceleration)
115 mob.swim = function(self)
116 local pos = self.object:getpos()
118 local node = minetest.get_node(pos).name
119 local vel = self.object:getvelocity()
121 local acceleration = vector.new(0,goal-vel.y,0)
122 self.swimming = false
124 if node == "main:water" or node =="main:waterflow" then
126 self.object:add_velocity(acceleration)
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)
140 mob.look_around = function(self)
141 local pos = self.object:get_pos()
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)
149 local is_a_drop = true
150 --check if there's a drop
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
163 if is_a_drop == true then
164 self.direction = vector.multiply(self.direction, -1)
165 print("turning around")
169 --a mob will check if it needs to jump
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
176 if vector.distance(pos,pos2) < 1 then
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
193 --look at player's camera
194 local pos2 = object:get_pos()
195 pos2.y = pos2.y + 1.625
197 local found_player = self.move_head(self,pos2)
199 if found_player == true then
200 self.direction = vector.direction(pos,pos2)
201 local distance = vector.distance(pos,pos2)-2
205 self.speed = distance
206 self.following = true
214 --stare straight if not found
215 if player_found == false then
216 self.move_head(self,nil)
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
225 --we add in items we want to see in this list
226 local debug_items = {"hunger","timer","yaw"}
228 for _,item in pairs(debug_items) do
230 text = text..item..": "..self[item].."\n"
233 self.child:set_nametag_attributes({
240 --this depletes the mobs hunger
241 mob.do_hunger = function(self,dtime)
242 self.hunger = self.hunger - dtime
245 --this sets the state of the mob
246 mob.set_state = function(self,dtime)
247 self.do_hunger(self,dtime)
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)
258 minetest.register_entity("mob:pig", mob)
264 ------------------------------------------------------------------------the head
267 head.initial_properties = {
270 collide_with_objects = false,
271 collisionbox = {0, 0, 0, 0, 0, 0},
273 visual_size = {x = 1.1, y = 1.1},
276 "head.png","nose.png"
280 --automatic_face_movement_dir = 0.0,
281 --automatic_face_movement_max_rotation_per_sec = 600,
284 --remove the head if no body
285 head.on_step = function(self, dtime)
286 if self.parent == nil then
290 minetest.register_entity("mob:head", head)