-- =================================================================== local sprite_collision = { -0.50 , -0.50 , -0.50 , 0.50 , 0.50 , 0.50 } -- =================================================================== unified_foods.register_sprite = function (basename, image, vsize) local cbox = sprite_collision if vsize == nil then vsize = 1 else cbox = ocutil.clone_table (sprite_collision) for ii=1,#cbox do cbox [ii] = cbox [ii] * vsize end end local param = { visual = "sprite" , visual_size = { x=vsize, y=vsize } , textures = {} , collisionbox = cbox , on_punch = function (self, hitter) self.object:remove() if hitter and hitter:is_player() then local inv = hitter:get_inventory() local node = "food:" .. basename if inv and inv:room_for_item ("main", node) then inv:add_item ("main", node) end end end , } param.textures = { image, image } minetest.register_entity (":ufsprites:" .. basename, param) end -- =================================================================== local do_env_damage = function (self) local pos = self.object:getpos() local n = minetest.env:get_node(pos) if self.light_damage and self.light_damage ~= 0 and pos.y>0 and minetest.env:get_node_light(pos) and minetest.env:get_node_light(pos) > 4 -- and minetest.env:get_timeofday() > 0.2 -- and minetest.env:get_timeofday() < 0.8 then self.object:set_hp (self.object:get_hp()-self.light_damage) if self.object:get_hp() < 1 then self.object:remove() return end end if self.water_damage and self.water_damage ~= 0 and minetest.get_item_group(n.name, "water") ~= 0 then self.object:set_hp(self.object:get_hp()-self.water_damage) if self.object:get_hp() == 0 then self.object:remove() return end end if self.lava_damage and self.lava_damage ~= 0 and minetest.get_item_group(n.name, "lava") ~= 0 then self.object:set_hp(self.object:get_hp()-self.lava_damage) if self.object:get_hp() == 0 then self.object:remove() return end end end -- =================================================================== unified_foods.register_mob = function (basename, image, vsize) local cbox = sprite_collision if vsize == nil then vsize = 1 else cbox = ocutil.clone_table (sprite_collision) for ii=1,#cbox do cbox [ii] = cbox [ii] * vsize end end local param = { visual = "sprite" , visual_size = { x=vsize, y=vsize } , textures = {} , collisionbox = cbox , on_punch = function (self, hitter) self.object:remove() if hitter and hitter:is_player() then local inv = hitter:get_inventory() local node = "food:" .. basename if inv and inv:room_for_item ("main", node) then inv:add_item ("main", node) end end end , makes_footstep_sound = false , type = "animal" , hp_max = 1 , armor = 1 , walk_velocity = 1 , run_velocity = 2 , view_range = 5 , damage = 1 , water_damage = 1 , lava_damage = 5 , light_damage = 0 , light_resistant = true , drops = {} , state = "stand" , v_start = false, old_y = nil, lifetimer = 600, tamed = false, physical = true , jump = true , timer = 0 , env_damage_timer = 0, -- only if state = "attack" attack = {player=nil, dist=nil}, -- =================================================================== set_velocity = function(self, v) local yaw = self.object:getyaw() if self.drawtype == "side" then yaw = yaw+(math.pi/2) end local x = math.sin(yaw) * -v local z = math.cos(yaw) * v self.object:setvelocity({x=x, y=self.object:getvelocity().y, z=z}) end, -- =================================================================== get_velocity = function(self) local v = self.object:getvelocity() return (v.x^2 + v.z^2)^(0.5) end, -- =================================================================== set_animation = function(self, type) end , -- =================================================================== on_step = function(self, dtime) if skydoom_special then local pos = self.object:getpos() if pos.y < 1.5 then self.object:remove() return "" end end -- RJK: Future change: if false then if coderfood_disable_mobs then self.object:remove() return end end if self.type == "monster" and codermobs_disable_monsters then self.object:remove() return end -- RJK: Future change: -- self.lifetimer = self.lifetimer - dtime if self.lifetimer <= 0 and not self.tamed then local player_count = 0 for _,obj in ipairs(minetest.env:get_objects_inside_radius(self.object:getpos(), 20)) do if obj:is_player() then player_count = player_count+1 end end -- RJK: Future change: if false then if player_count == 0 and self.state ~= "attack" then self.object:remove() return end end end if self.object:getvelocity().y > 0.1 then local yaw = self.object:getyaw() if self.drawtype == "side" then yaw = yaw+(math.pi/2) end local x = math.sin(yaw) * -2 local z = math.cos(yaw) * 2 self.object:setacceleration({x=x, y=-10, z=z}) else self.object:setacceleration({x=0, y=-10, z=0}) end if self.disable_fall_damage and self.object:getvelocity().y == 0 then if not self.old_y then self.old_y = self.object:getpos().y else local d = self.old_y - self.object:getpos().y if d > 5 then local damage = d-5 self.object:set_hp(self.object:get_hp()-damage) if self.object:get_hp() == 0 then self.object:remove() end end self.old_y = self.object:getpos().y end end self.timer = self.timer+dtime if self.state ~= "attack" then if self.timer < 1 then return end self.timer = 0 end if self.sounds and self.sounds.random and math.random(1, 100) <= 1 then minetest.sound_play(self.sounds.random, {object = self.object}) end self.env_damage_timer = self.env_damage_timer + dtime if self.state == "attack" and self.env_damage_timer > 1 then self.env_damage_timer = 0 do_env_damage(self) elseif self.state ~= "attack" then do_env_damage(self) end if self.type == "monster" and minetest.setting_getbool("enable_damage") then for _,player in pairs(minetest.get_connected_players()) do local s = self.object:getpos() local p = player:getpos() local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 if dist < self.view_range then if self.attack.dist then if self.attack.dist < dist then self.state = "attack" self.attack.player = player self.attack.dist = dist end else self.state = "attack" self.attack.player = player self.attack.dist = dist end end end end if self.follow ~= "" and not self.following then for _,player in pairs(minetest.get_connected_players()) do local s = self.object:getpos() local p = player:getpos() local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 if self.view_range and dist < self.view_range then self.following = player end end end if self.following and self.following:is_player() then if self.following:get_wielded_item():get_name() ~= self.follow then self.following = nil self.v_start = false else local s = self.object:getpos() local p = self.following:getpos() local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 if dist > self.view_range then self.following = nil self.v_start = false else local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} local yaw = math.atan(vec.z/vec.x)+math.pi/2 if self.drawtype == "side" then yaw = yaw+(math.pi/2) end if p.x > s.x then yaw = yaw+math.pi end self.object:setyaw(yaw) if dist > 2 then if not self.v_start then self.v_start = true self.set_velocity(self, self.walk_velocity) else if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then local v = self.object:getvelocity() v.y = 5 self.object:setvelocity(v) end self.set_velocity(self, self.walk_velocity) end self:set_animation("walk") else self.v_start = false self.set_velocity(self, 0) self:set_animation("stand") end return end end end if self.state == "stand" then if math.random(1, 4) == 1 then self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)) end self.set_velocity(self, 0) self.set_animation(self, "stand") if math.random(1, 100) <= 50 then self.set_velocity(self, self.walk_velocity) self.state = "walk" self.set_animation(self, "walk") end elseif self.state == "walk" then if math.random(1, 100) <= 30 then self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)) end if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then local v = self.object:getvelocity() v.y = 5 self.object:setvelocity(v) end self:set_animation("walk") self.set_velocity(self, self.walk_velocity) if math.random(1, 100) <= 10 then self.set_velocity(self, 0) self.state = "stand" self:set_animation("stand") end elseif self.state == "attack" and self.attack_type == "dogfight" then if not self.attack.player or not self.attack.player:is_player() then self.state = "stand" self:set_animation("stand") return end local s = self.object:getpos() local p = self.attack.player:getpos() local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 if dist > self.view_range or self.attack.player:get_hp() <= 0 then self.state = "stand" self.v_start = false self.set_velocity(self, 0) self.attack = {player=nil, dist=nil} self:set_animation("stand") return else self.attack.dist = dist end local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} local yaw = math.atan(vec.z/vec.x)+math.pi/2 if self.drawtype == "side" then yaw = yaw+(math.pi/2) end if p.x > s.x then yaw = yaw+math.pi end self.object:setyaw(yaw) if self.attack.dist > 2 then if not self.v_start then self.v_start = true self.set_velocity(self, self.run_velocity) else if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then local v = self.object:getvelocity() v.y = 5 self.object:setvelocity(v) end self.set_velocity(self, self.run_velocity) end self:set_animation("run") else self.set_velocity(self, 0) self:set_animation("punch") self.v_start = false if self.timer > 1 then self.timer = 0 if self.sounds and self.sounds.attack then minetest.sound_play(self.sounds.attack, {object = self.object}) end self.attack.player:punch(self.object, 1.0, { full_punch_interval=1.0, damage_groups = {fleshy=self.damage} }, vec) end end elseif self.state == "attack" and self.attack_type == "shoot" then if not self.attack.player or not self.attack.player:is_player() then self.state = "stand" self:set_animation("stand") return end local s = self.object:getpos() local p = self.attack.player:getpos() local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 if dist > self.view_range or self.attack.player:get_hp() <= 0 then self.state = "stand" self.v_start = false self.set_velocity(self, 0) self.attack = {player=nil, dist=nil} self:set_animation("stand") return else self.attack.dist = dist end local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} local yaw = math.atan(vec.z/vec.x)+math.pi/2 if self.drawtype == "side" then yaw = yaw+(math.pi/2) end if p.x > s.x then yaw = yaw+math.pi end self.object:setyaw(yaw) self.set_velocity(self, 0) if self.timer > self.shoot_interval and math.random(1, 100) <= 60 then self.timer = 0 self:set_animation("punch") if self.sounds and self.sounds.attack then minetest.sound_play(self.sounds.attack, {object = self.object}) end local p = self.object:getpos() p.y = p.y + (self.collisionbox[2]+self.collisionbox[5])/2 local obj = minetest.env:add_entity(p, self.arrow) local amount = (vec.x^2+vec.y^2+vec.z^2)^0.5 local v = obj:get_luaentity().velocity vec.y = vec.y+1 vec.x = vec.x*v/amount vec.y = vec.y*v/amount vec.z = vec.z*v/amount obj:setvelocity(vec) end end end, -- =================================================================== on_activate = function(self, staticdata, dtime_s) self.object:set_armor_groups({fleshy=self.armor}) self.object:setacceleration({x=0, y=-10, z=0}) self.state = "stand" self.object:setvelocity({x=0, y=self.object:getvelocity().y, z=0}) self.object:setyaw(math.random(1, 360)/180*math.pi) if self.type == "monster" and codermobs_disable_monsters then self.object:remove() end -- RJK: Future change: -- self.lifetimer = 600 - dtime_s if staticdata then local tmp = minetest.deserialize(staticdata) if tmp and tmp.lifetimer then self.lifetimer = tmp.lifetimer - dtime_s end if tmp and tmp.tamed then self.tamed = tmp.tamed end end if self.lifetimer <= 0 and not self.tamed then self.object:remove() end end , -- =================================================================== get_staticdata = function (self) local tmp = { lifetimer = self.lifetimer, tamed = self.tamed, } return minetest.serialize(tmp) end, -- =================================================================== } param.textures = { image, image } minetest.register_entity (":ufmobs:" .. basename, param) end -- =================================================================== -- End of file.