dolphins!
parent
0d7375f61d
commit
c3ebb6d19e
596
mobkit/init.lua
596
mobkit/init.lua
|
@ -38,6 +38,7 @@ local neighbors ={
|
|||
{x=1,z=-1}
|
||||
}
|
||||
|
||||
|
||||
-- UTILITY FUNCTIONS
|
||||
|
||||
function mobkit.dir2neighbor(dir)
|
||||
|
@ -149,7 +150,7 @@ function mobkit.get_node_height(pos)
|
|||
if node == nil then return nil end
|
||||
|
||||
if node.walkable then
|
||||
if node.drawtype == 'nodebox' then
|
||||
if node.drawtype == 'nodebox' then
|
||||
if node.node_box == nil then return nil end --added by petz
|
||||
if node.node_box.type == 'fixed' then
|
||||
if type(node.node_box.fixed[1]) == 'number' then
|
||||
|
@ -244,28 +245,23 @@ function mobkit.get_spawn_pos_abr(dtime,intrvl,radius,chance,reduction)
|
|||
end
|
||||
end
|
||||
|
||||
function mobkit.turn2yaw(self,tyaw)
|
||||
function mobkit.turn2yaw(self,tyaw,rate)
|
||||
tyaw = tyaw or 0 --temp
|
||||
rate = rate or 6
|
||||
local yaw = self.object:get_yaw()
|
||||
|
||||
local diff = tyaw-yaw
|
||||
local step = self.dtime*6
|
||||
yaw = yaw+pi
|
||||
tyaw=(tyaw+pi)%(pi*2)
|
||||
|
||||
if abs(diff)<step then
|
||||
self.object:set_yaw(tyaw)
|
||||
return true
|
||||
end
|
||||
|
||||
local dirmod = abs(diff) > pi and -1 or 1
|
||||
|
||||
local nyaw = diff < 0 and yaw+step*-dirmod or yaw+step*dirmod
|
||||
|
||||
if nyaw > pi then
|
||||
nyaw=nyaw-pi*2
|
||||
elseif nyaw < -pi then
|
||||
nyaw=nyaw+pi*2
|
||||
end
|
||||
self.object:set_yaw(nyaw)
|
||||
local step=min(self.dtime*rate,abs(tyaw-yaw)%(pi*2))
|
||||
|
||||
local dir = abs(tyaw-yaw)>pi and -1 or 1
|
||||
dir = tyaw>yaw and dir*1 or dir * -1
|
||||
|
||||
local nyaw = (yaw+step*dir)%(pi*2)
|
||||
self.object:set_yaw(nyaw-pi)
|
||||
|
||||
if nyaw==tyaw then return true
|
||||
else return false end
|
||||
end
|
||||
|
||||
function mobkit.dir_to_rot(v,rot)
|
||||
|
@ -337,7 +333,7 @@ end
|
|||
function mobkit.hurt(luaent,dmg)
|
||||
if not luaent then return false end
|
||||
if type(luaent) == 'table' then
|
||||
luaent.hp = (luaent.hp or 0) - dmg
|
||||
luaent.hp = max((luaent.hp or 0) - dmg,0)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -389,7 +385,7 @@ function mobkit.is_neighbor_node_reachable(self,neighbor) -- todo: take either n
|
|||
local tpos = mobkit.get_node_pos(mobkit.pos_shift(pos,offset))
|
||||
local node_name = minetest.get_node(tpos).name --added by petz
|
||||
if node_name:find("fence") then return --added by petz
|
||||
elseif node_name:find("gate") and node_name:find("closed") then return end --added by petz
|
||||
elseif node_name:find("gate") and node_name:find("closed") then return end --added by petz
|
||||
local height, liquidflag = mobkit.get_terrain_height(tpos)
|
||||
|
||||
if height and abs(height-pos.y) <= self.jump_height then
|
||||
|
@ -450,9 +446,9 @@ function mobkit.get_next_waypoint(self,tpos)
|
|||
if height and not liquidflag
|
||||
and not (nogopos and mobkit.isnear2d(pos2,nogopos,0.1)) then
|
||||
|
||||
heightl = mobkit.is_neighbor_node_reachable(self,mobkit.neighbor_shift(neighbor,-1))
|
||||
local heightl = mobkit.is_neighbor_node_reachable(self,mobkit.neighbor_shift(neighbor,-1))
|
||||
if heightl and abs(heightl-height)<0.001 then
|
||||
heightr = mobkit.is_neighbor_node_reachable(self,mobkit.neighbor_shift(neighbor,1))
|
||||
local heightr = mobkit.is_neighbor_node_reachable(self,mobkit.neighbor_shift(neighbor,1))
|
||||
if heightr and abs(heightr-height)<0.001 then
|
||||
dir.y = 0
|
||||
local dirn = vector.normalize(dir)
|
||||
|
@ -467,7 +463,7 @@ function mobkit.get_next_waypoint(self,tpos)
|
|||
|
||||
for i=1,3 do
|
||||
-- scan left
|
||||
height, pos2, liq = mobkit.is_neighbor_node_reachable(self,mobkit.neighbor_shift(neighbor,-i*self.path_dir))
|
||||
local height, pos2, liq = mobkit.is_neighbor_node_reachable(self,mobkit.neighbor_shift(neighbor,-i*self.path_dir))
|
||||
if height and not liq
|
||||
and not (nogopos and mobkit.isnear2d(pos2,nogopos,0.1)) then
|
||||
update_pos_history(self,pos2)
|
||||
|
@ -547,6 +543,13 @@ function mobkit.goto_next_waypoint(self,tpos)
|
|||
return true
|
||||
end
|
||||
|
||||
function mobkit.go_forward_horizontal(self,yaw,speed) -- sets velocity in yaw direction, y component unaffected
|
||||
local y = self.object:get_velocity().y
|
||||
local vel = vector.multiply(minetest.yaw_to_dir(yaw),speed)
|
||||
vel.y = y
|
||||
self.object:set_velocity(vel)
|
||||
end
|
||||
|
||||
function mobkit.timer(self,s) -- returns true approx every s seconds
|
||||
local t1 = floor(self.time_total)
|
||||
local t2 = floor(self.time_total+self.dtime)
|
||||
|
@ -691,6 +694,205 @@ local function sensors()
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------
|
||||
-- CALLBACKS
|
||||
------------
|
||||
|
||||
function mobkit.default_brain(self)
|
||||
if mobkit.is_queue_empty_high(self) then mobkit.hq_roam(self,0) end
|
||||
end
|
||||
|
||||
function mobkit.statfunc(self)
|
||||
local tmptab={}
|
||||
tmptab.memory = self.memory
|
||||
tmptab.hp = self.hp
|
||||
tmptab.texture_no = self.texture_no
|
||||
return minetest.serialize(tmptab)
|
||||
end
|
||||
|
||||
function mobkit.actfunc(self, staticdata, dtime_s)
|
||||
self.lqueue = {}
|
||||
self.hqueue = {}
|
||||
self.nearby_objects = {}
|
||||
self.nearby_players = {}
|
||||
self.pos_history = {}
|
||||
self.path_dir = 1
|
||||
self.time_total = 0
|
||||
|
||||
local sdata = minetest.deserialize(staticdata)
|
||||
if sdata then
|
||||
for k,v in pairs(sdata) do
|
||||
self[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
if self.timeout and self.timeout>0 and dtime_s > self.timeout and next(self.memory)==nil then
|
||||
self.object:remove()
|
||||
end
|
||||
|
||||
if not self.memory then -- this is the initial activation
|
||||
self.memory = {}
|
||||
|
||||
-- texture variation
|
||||
if #self.textures > 1 then self.texture_no = random(#self.textures) end
|
||||
end
|
||||
|
||||
-- apply texture
|
||||
if self.texture_no then
|
||||
local props = {}
|
||||
props.textures = {self.textures[self.texture_no]}
|
||||
self.object:set_properties(props)
|
||||
end
|
||||
|
||||
--hp
|
||||
self.hp = self.hp or (self.max_hp or 10)
|
||||
--armor
|
||||
if type(self.armor_groups) ~= 'table' then
|
||||
self.armor_groups={}
|
||||
end
|
||||
self.armor_groups.immortal = 1
|
||||
self.object:set_armor_groups(self.armor_groups)
|
||||
|
||||
self.oxygen = self.oxygen or self.lung_capacity
|
||||
self.lastvelocity = {x=0,y=0,z=0}
|
||||
self.height = self.collisionbox[5] - self.collisionbox[2]
|
||||
self.sensefunc=sensors()
|
||||
end
|
||||
|
||||
function mobkit.stepfunc(self,dtime) -- not intended to be modified
|
||||
self.dtime = dtime
|
||||
-- physics comes first
|
||||
-- self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
|
||||
local vel = self.object:get_velocity()
|
||||
|
||||
-- if self.lastvelocity.y == vel.y then
|
||||
if abs(self.lastvelocity.y-vel.y)<0.001 then
|
||||
self.isonground = true
|
||||
else
|
||||
self.isonground = false
|
||||
end
|
||||
|
||||
-- dumb friction
|
||||
if self.isonground and not(self.can_fly) then
|
||||
self.object:set_velocity({x= vel.x> 0.2 and vel.x*mobkit.friction or 0,
|
||||
y=vel.y,
|
||||
z=vel.z > 0.2 and vel.z*mobkit.friction or 0})
|
||||
end
|
||||
|
||||
-- bounciness
|
||||
if self.springiness and self.springiness > 0 then
|
||||
local vnew = vector.new(vel)
|
||||
|
||||
if not self.collided then -- ugly workaround for inconsistent collisions
|
||||
for _,k in ipairs({'y','z','x'}) do
|
||||
if vel[k]==0 and abs(self.lastvelocity[k])> 0.1 then
|
||||
vnew[k]=-self.lastvelocity[k]*self.springiness
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not vector.equals(vel,vnew) then
|
||||
self.collided = true
|
||||
else
|
||||
if self.collided then
|
||||
vnew = vector.new(self.lastvelocity)
|
||||
end
|
||||
self.collided = false
|
||||
end
|
||||
|
||||
self.object:set_velocity(vnew)
|
||||
end
|
||||
|
||||
-- buoyancy
|
||||
local spos = mobkit.get_stand_pos(self)
|
||||
spos.y = spos.y+0.01
|
||||
-- get surface height
|
||||
-- local surface = mobkit.get_node_pos(spos).y+0.5
|
||||
local surface = nil
|
||||
local snodepos = mobkit.get_node_pos(spos)
|
||||
local surfnode = mobkit.nodeatpos(spos)
|
||||
if mobkit.is_alive(self) and not(self.is_baby) then
|
||||
local stand_pos = spos --added by petz
|
||||
stand_pos.y = spos.y + 0.5 --added by petz
|
||||
local stand_node_pos = mobkit.get_node_pos(stand_pos) --added by petz
|
||||
local stand_node = mobkit.nodeatpos(stand_node_pos) --added by petz
|
||||
if stand_node and stand_node.walkable and stand_node.drawtype == "normal" then -- if standing inside solid block then jump to escape --added by petz
|
||||
self.object:set_pos({ --added by petz
|
||||
x = stand_pos.x, --added by petz
|
||||
y = stand_pos.y + self.jump_height, --added by petz
|
||||
z = stand_pos.z --added by petz
|
||||
}) --added by petz
|
||||
end --added by petz
|
||||
end
|
||||
while surfnode and surfnode.drawtype == 'liquid' do
|
||||
surface = snodepos.y+0.5
|
||||
if surface > spos.y+self.height then break end
|
||||
snodepos.y = snodepos.y+1
|
||||
surfnode = mobkit.nodeatpos(snodepos)
|
||||
end
|
||||
if surface then -- standing in liquid
|
||||
self.isinliquid = true
|
||||
local submergence = min(surface-spos.y,self.height)
|
||||
local balance = self.buoyancy*self.height
|
||||
local buoyacc = mobkit.gravity*((balance - submergence)^2/balance^2*sign(balance - submergence))
|
||||
self.object:set_acceleration({x=-vel.x,y=buoyacc-vel.y*abs(vel.y)*0.7,z=-vel.z})
|
||||
else
|
||||
self.isinliquid = false
|
||||
if not(self.can_fly) then --added by petz
|
||||
self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
|
||||
end --added by petz
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- local footnode = mobkit.nodeatpos(spos)
|
||||
-- local headnode
|
||||
-- if footnode and footnode.drawtype == 'liquid' then
|
||||
|
||||
-- vel = self.object:get_velocity()
|
||||
-- headnode = mobkit.nodeatpos(mobkit.pos_shift(spos,{y=self.height or 0})) -- TODO: height may be nil
|
||||
-- local submergence = headnode.drawtype=='liquid'
|
||||
-- and self.buoyancy-1
|
||||
-- or (self.buoyancy*self.height-(1-(spos.y+0.5)%1))^2/(self.buoyancy*self.height)^2*sign(self.buoyancy*self.height-(1-(spos.y+0.5)%1))
|
||||
|
||||
-- local buoyacc = submergence * mobkit.gravity
|
||||
-- self.object:set_acceleration({x=-vel.x,y=buoyacc-vel.y*abs(vel.y)*0.5,z=-vel.z})
|
||||
|
||||
-- end
|
||||
|
||||
if self.brainfunc then
|
||||
-- vitals: fall damage
|
||||
vel = self.object:get_velocity()
|
||||
local velocity_delta = abs(self.lastvelocity.y - vel.y)
|
||||
if velocity_delta > mobkit.safe_velocity then
|
||||
self.hp = self.hp - floor((self.max_hp-100) * min(1, velocity_delta/mobkit.terminal_velocity))
|
||||
end
|
||||
|
||||
-- vitals: oxygen
|
||||
if self.lung_capacity then
|
||||
local headnode = mobkit.nodeatpos(mobkit.pos_shift(self.object:get_pos(),{y=self.collisionbox[5]})) -- node at hitbox top
|
||||
if headnode and headnode.drawtype == 'liquid' then
|
||||
self.oxygen = self.oxygen - self.dtime
|
||||
else
|
||||
self.oxygen = self.lung_capacity
|
||||
end
|
||||
|
||||
if self.oxygen <= 0 then self.hp=0 end -- drown
|
||||
end
|
||||
|
||||
|
||||
self:sensefunc()
|
||||
self:brainfunc()
|
||||
execute_queues(self)
|
||||
end
|
||||
|
||||
self.lastvelocity = self.object:get_velocity()
|
||||
self.time_total=self.time_total+self.dtime
|
||||
end
|
||||
|
||||
----------------------------
|
||||
-- BEHAVIORS
|
||||
----------------------------
|
||||
-- LOW LEVEL QUEUE FUNCTIONS
|
||||
----------------------------
|
||||
|
@ -1148,196 +1350,178 @@ function mobkit.hq_swimto(self,prty,tpos)
|
|||
mobkit.queue_high(self,func,prty)
|
||||
end
|
||||
|
||||
------------
|
||||
-- CALLBACKS
|
||||
------------
|
||||
---------------------
|
||||
-- AQUATIC
|
||||
---------------------
|
||||
|
||||
function mobkit.default_brain(self)
|
||||
if mobkit.is_queue_empty_high(self) then mobkit.hq_roam(self,0) end
|
||||
end
|
||||
|
||||
function mobkit.statfunc(self)
|
||||
local tmptab={}
|
||||
tmptab.memory = self.memory
|
||||
tmptab.hp = self.hp
|
||||
tmptab.texture_no = self.texture_no
|
||||
return minetest.serialize(tmptab)
|
||||
end
|
||||
|
||||
function mobkit.actfunc(self, staticdata, dtime_s)
|
||||
self.lqueue = {}
|
||||
self.hqueue = {}
|
||||
self.nearby_objects = {}
|
||||
self.nearby_players = {}
|
||||
self.pos_history = {}
|
||||
self.path_dir = 1
|
||||
self.time_total = 0
|
||||
|
||||
local sdata = minetest.deserialize(staticdata)
|
||||
if sdata then
|
||||
for k,v in pairs(sdata) do
|
||||
self[k] = v
|
||||
end
|
||||
-- MACROS
|
||||
local function aqua_radar_dumb(pos,yaw,range,reverse)
|
||||
range = range or 4
|
||||
|
||||
local function newpos(p,y,r)
|
||||
return mobkit.pos_shift(p,vector.multiply(minetest.yaw_to_dir(y),r))
|
||||
end
|
||||
|
||||
if self.timeout and self.timeout>0 and dtime_s > self.timeout and next(self.memory)==nil then
|
||||
self.object:remove()
|
||||
end
|
||||
|
||||
if not self.memory then -- this is the initial activation
|
||||
self.memory = {}
|
||||
|
||||
-- texture variation
|
||||
if #self.textures > 1 then self.texture_no = random(#self.textures) end
|
||||
end
|
||||
|
||||
-- apply texture
|
||||
if self.texture_no then
|
||||
local props = {}
|
||||
props.textures = {self.textures[self.texture_no]}
|
||||
self.object:set_properties(props)
|
||||
end
|
||||
|
||||
--hp
|
||||
self.hp = self.hp or (self.max_hp or 10)
|
||||
--armor
|
||||
if type(self.armor_groups) ~= 'table' then
|
||||
self.armor_groups={}
|
||||
end
|
||||
self.armor_groups.immortal = 1
|
||||
self.object:set_armor_groups(self.armor_groups)
|
||||
|
||||
self.oxygen = self.oxygen or self.lung_capacity
|
||||
self.lastvelocity = {x=0,y=0,z=0}
|
||||
self.height = self.collisionbox[5] - self.collisionbox[2]
|
||||
self.sensefunc=sensors()
|
||||
end
|
||||
|
||||
function mobkit.stepfunc(self,dtime) -- not intended to be modified
|
||||
self.dtime = dtime
|
||||
-- physics comes first
|
||||
-- self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
|
||||
local vel = self.object:get_velocity()
|
||||
|
||||
-- if self.lastvelocity.y == vel.y then
|
||||
if abs(self.lastvelocity.y-vel.y)<0.001 then
|
||||
self.isonground = true
|
||||
else
|
||||
self.isonground = false
|
||||
end
|
||||
|
||||
-- dumb friction
|
||||
if self.isonground and not(self.can_fly) then --added by petz
|
||||
self.object:set_velocity({x= vel.x> 0.2 and vel.x*mobkit.friction or 0,
|
||||
y=vel.y,
|
||||
z=vel.z > 0.2 and vel.z*mobkit.friction or 0})
|
||||
end
|
||||
|
||||
-- bounciness
|
||||
if self.springiness and self.springiness > 0 then
|
||||
local vnew = vector.new(vel)
|
||||
|
||||
if not self.collided then -- ugly workaround for inconsistent collisions
|
||||
for _,k in ipairs({'y','z','x'}) do
|
||||
if vel[k]==0 and abs(self.lastvelocity[k])> 0.1 then
|
||||
vnew[k]=-self.lastvelocity[k]*self.springiness
|
||||
local function okpos(p)
|
||||
local node = mobkit.nodeatpos(p)
|
||||
if node then
|
||||
if node.drawtype == 'liquid' then
|
||||
local nodeu = mobkit.nodeatpos(mobkit.pos_shift(p,{y=1}))
|
||||
local noded = mobkit.nodeatpos(mobkit.pos_shift(p,{y=-1}))
|
||||
if (nodeu and nodeu.drawtype == 'liquid') or (noded and noded.drawtype == 'liquid') then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
local h,l = mobkit.get_terrain_height(p)
|
||||
if h then
|
||||
local node2 = mobkit.nodeatpos({x=p.x,y=h+1.99,z=p.z})
|
||||
if node2 and node2.drawtype == 'liquid' then return true, h end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not vector.equals(vel,vnew) then
|
||||
self.collided = true
|
||||
else
|
||||
if self.collided then
|
||||
vnew = vector.new(self.lastvelocity)
|
||||
end
|
||||
self.collided = false
|
||||
return false
|
||||
end
|
||||
|
||||
self.object:set_velocity(vnew)
|
||||
end
|
||||
|
||||
-- buoyancy
|
||||
local spos = mobkit.get_stand_pos(self)
|
||||
spos.y = spos.y+0.01
|
||||
-- get surface height
|
||||
-- local surface = mobkit.get_node_pos(spos).y+0.5
|
||||
local surface = nil
|
||||
local snodepos = mobkit.get_node_pos(spos)
|
||||
local surfnode = mobkit.nodeatpos(spos)
|
||||
if mobkit.is_alive(self) and not(self.is_baby) then
|
||||
local stand_pos = spos --added by petz
|
||||
stand_pos.y = spos.y + 0.5 --added by petz
|
||||
local stand_node_pos = mobkit.get_node_pos(stand_pos) --added by petz
|
||||
local stand_node = mobkit.nodeatpos(stand_node_pos) --added by petz
|
||||
if stand_node and stand_node.walkable and stand_node.drawtype == "normal" then -- if standing inside solid block then jump to escape --added by petz
|
||||
self.object:set_pos({ --added by petz
|
||||
x = stand_pos.x, --added by petz
|
||||
y = stand_pos.y + self.jump_height, --added by petz
|
||||
z = stand_pos.z --added by petz
|
||||
}) --added by petz
|
||||
end --added by petz
|
||||
end
|
||||
while surfnode and surfnode.drawtype == 'liquid' do
|
||||
surface = snodepos.y+0.5
|
||||
if surface > spos.y+self.height then break end
|
||||
snodepos.y = snodepos.y+1
|
||||
surfnode = mobkit.nodeatpos(snodepos)
|
||||
end
|
||||
if surface then -- standing in liquid
|
||||
self.isinliquid = true
|
||||
local submergence = min(surface-spos.y,self.height)
|
||||
local balance = self.buoyancy*self.height
|
||||
local buoyacc = mobkit.gravity*((balance - submergence)^2/balance^2*sign(balance - submergence))
|
||||
self.object:set_acceleration({x=-vel.x,y=buoyacc-vel.y*abs(vel.y)*0.7,z=-vel.z})
|
||||
else
|
||||
self.isinliquid = false
|
||||
if not(self.can_fly) then --added by petz
|
||||
self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
|
||||
end --added by petz
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- local footnode = mobkit.nodeatpos(spos)
|
||||
-- local headnode
|
||||
-- if footnode and footnode.drawtype == 'liquid' then
|
||||
|
||||
-- vel = self.object:get_velocity()
|
||||
-- headnode = mobkit.nodeatpos(mobkit.pos_shift(spos,{y=self.height or 0})) -- TODO: height may be nil
|
||||
-- local submergence = headnode.drawtype=='liquid'
|
||||
-- and self.buoyancy-1
|
||||
-- or (self.buoyancy*self.height-(1-(spos.y+0.5)%1))^2/(self.buoyancy*self.height)^2*sign(self.buoyancy*self.height-(1-(spos.y+0.5)%1))
|
||||
|
||||
-- local buoyacc = submergence * mobkit.gravity
|
||||
-- self.object:set_acceleration({x=-vel.x,y=buoyacc-vel.y*abs(vel.y)*0.5,z=-vel.z})
|
||||
|
||||
-- end
|
||||
|
||||
if self.brainfunc then
|
||||
-- vitals: fall damage
|
||||
vel = self.object:get_velocity()
|
||||
local velocity_delta = abs(self.lastvelocity.y - vel.y)
|
||||
if velocity_delta > mobkit.safe_velocity then
|
||||
self.hp = self.hp - floor((self.max_hp-100) * min(1, velocity_delta/mobkit.terminal_velocity))
|
||||
end
|
||||
|
||||
-- vitals: oxygen
|
||||
local headnode = mobkit.nodeatpos(mobkit.pos_shift(self.object:get_pos(),{y=self.collisionbox[5]})) -- node at hitbox top
|
||||
if headnode and headnode.drawtype == 'liquid' then
|
||||
self.oxygen = self.oxygen - self.dtime
|
||||
local fpos = newpos(pos,yaw,range)
|
||||
local ok,h = okpos(fpos)
|
||||
if not ok then
|
||||
local ffrom, fto, fstep
|
||||
if reverse then
|
||||
ffrom, fto, fstep = 3,1,-1
|
||||
else
|
||||
self.oxygen = self.lung_capacity
|
||||
ffrom, fto, fstep = 1,3,1
|
||||
end
|
||||
|
||||
if self.oxygen <= 0 then self.hp=0 end -- drown
|
||||
|
||||
|
||||
self:sensefunc()
|
||||
self:brainfunc()
|
||||
execute_queues(self)
|
||||
end
|
||||
|
||||
self.lastvelocity = self.object:get_velocity()
|
||||
self.time_total=self.time_total+self.dtime
|
||||
for i=ffrom, fto, fstep do
|
||||
local ok,h = okpos(newpos(pos,yaw+i,range))
|
||||
if ok then return yaw+i,h end
|
||||
ok,h = okpos(newpos(pos,yaw-i,range))
|
||||
if ok then return yaw-i,h end
|
||||
end
|
||||
return yaw+pi,h
|
||||
else
|
||||
return yaw, h
|
||||
end
|
||||
end
|
||||
|
||||
function mobkit.is_in_deep(target)
|
||||
if not target then return false end
|
||||
local nodepos = mobkit.get_stand_pos(target)
|
||||
local node1 = mobkit.nodeatpos(nodepos)
|
||||
nodepos.y=nodepos.y+1
|
||||
local node2 = mobkit.nodeatpos(nodepos)
|
||||
nodepos.y=nodepos.y-2
|
||||
local node3 = mobkit.nodeatpos(nodepos)
|
||||
if node1 and node2 and node1.drawtype=='liquid' and (node2.drawtype=='liquid' or node3.drawtype=='liquid') then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- HQ behaviors
|
||||
|
||||
function mobkit.hq_aqua_roam(self,prty,speed)
|
||||
local tyaw = 0
|
||||
local init = true
|
||||
local prvscanpos = {x=0,y=0,z=0}
|
||||
local center = self.object:get_pos()
|
||||
local func = function(self)
|
||||
if init then
|
||||
mobkit.animate(self, 'swin') --changed by petz
|
||||
init = false
|
||||
end
|
||||
local pos = mobkit.get_stand_pos(self)
|
||||
local yaw = self.object:get_yaw()
|
||||
local pos2d = {x=pos.x,y=0,z=pos.z}
|
||||
local scanpos = mobkit.get_node_pos(vector.add(pos,vector.multiply(minetest.yaw_to_dir(yaw),speed)))
|
||||
if not vector.equals(prvscanpos,scanpos) then
|
||||
prvscanpos=scanpos
|
||||
local nyaw,height = aqua_radar_dumb(pos,yaw,speed,true)
|
||||
if height and height > pos.y+self.collisionbox[2] then
|
||||
local vel = self.object:get_velocity()
|
||||
vel.y = vel.y+1
|
||||
self.object:set_velocity(vel)
|
||||
end
|
||||
if yaw ~= nyaw then
|
||||
tyaw=nyaw
|
||||
mobkit.hq_aqua_turn(self,prty+1,tyaw,speed)
|
||||
return
|
||||
end
|
||||
end
|
||||
if mobkit.timer(self,1) then
|
||||
if vector.distance(pos,center) > abr*16*0.5 then
|
||||
tyaw = minetest.dir_to_yaw(vector.direction(pos,{x=center.x+random()*10-5,y=center.y,z=center.z+random()*10-5}))
|
||||
else
|
||||
if random(10)>=9 then tyaw=tyaw+random()*pi - pi*0.5 end
|
||||
end
|
||||
end
|
||||
|
||||
mobkit.turn2yaw(self,tyaw,3)
|
||||
local yaw = self.object:get_yaw()
|
||||
mobkit.go_forward_horizontal(self,yaw,4)
|
||||
end
|
||||
mobkit.queue_high(self,func,prty)
|
||||
end
|
||||
|
||||
function mobkit.hq_aqua_turn(self,prty,tyaw,speed)
|
||||
local func = function(self)
|
||||
local finished=mobkit.turn2yaw(self,tyaw)
|
||||
local yaw = self.object:get_yaw()
|
||||
mobkit.go_forward_horizontal(self,yaw,speed)
|
||||
if finished then return true end
|
||||
end
|
||||
mobkit.queue_high(self,func,prty)
|
||||
end
|
||||
|
||||
function mobkit.hq_aqua_attack(self,prty,tgtobj,speed)
|
||||
local tyaw = 0
|
||||
local prvscanpos = {x=0,y=0,z=0}
|
||||
local init = true
|
||||
local func = function(self)
|
||||
if not mobkit.is_alive(tgtobj) then return true end
|
||||
if init then
|
||||
mobkit.animate(self,'fast')
|
||||
mobkit.make_sound(self,'attack')
|
||||
init = false
|
||||
end
|
||||
local pos = mobkit.get_stand_pos(self)
|
||||
local yaw = self.object:get_yaw()
|
||||
local pos2d = {x=pos.x,y=0,z=pos.z}
|
||||
local scanpos = mobkit.get_node_pos(vector.add(pos,vector.multiply(minetest.yaw_to_dir(yaw),speed)))
|
||||
if not vector.equals(prvscanpos,scanpos) then
|
||||
prvscanpos=scanpos
|
||||
local nyaw,height = aqua_radar_dumb(pos,yaw,speed)
|
||||
if height and height > pos.y+self.collisionbox[2] then
|
||||
local vel = self.object:get_velocity()
|
||||
vel.y = vel.y+1
|
||||
self.object:set_velocity(vel)
|
||||
end
|
||||
if yaw ~= nyaw then
|
||||
tyaw=nyaw
|
||||
mobkit.hq_aqua_turn(self,prty+1,tyaw,speed)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local tpos = tgtobj:get_pos()
|
||||
local tyaw=minetest.dir_to_yaw(vector.direction(pos,tpos))
|
||||
mobkit.turn2yaw(self,tyaw,3)
|
||||
local yaw = self.object:get_yaw()
|
||||
if mobkit.timer(self,1) then
|
||||
if not mobkit.is_in_deep(tgtobj) then return true end
|
||||
local vel = self.object:get_velocity()
|
||||
if tpos.y>pos.y+0.5 then self.object:set_velocity({x=vel.x,y=vel.y+0.5,z=vel.z})
|
||||
elseif tpos.y<pos.y-0.5 then self.object:set_velocity({x=vel.x,y=vel.y-0.5,z=vel.z}) end
|
||||
end
|
||||
if mobkit.isnear3d(mobkit.pos_shift(pos,vector.multiply(minetest.yaw_to_dir(yaw),0.7)),tpos,0.35) then --bite
|
||||
tgtobj:punch(self.object,1,self.attack)
|
||||
mobkit.hq_aqua_turn(self,prty,yaw-pi,speed)
|
||||
return true
|
||||
end
|
||||
mobkit.go_forward_horizontal(self,yaw,speed)
|
||||
end
|
||||
mobkit.queue_high(self,func,prty)
|
||||
end
|
||||
|
|
|
@ -30,3 +30,4 @@ assert(loadfile(modpath .. "/api/api_silk.lua"))(modpath, S)
|
|||
assert(loadfile(modpath .. "/api/api_sleep.lua"))(modpath, S)
|
||||
assert(loadfile(modpath .. "/api/api_env_damage.lua"))(modpath, S)
|
||||
assert(loadfile(modpath .. "/api/api_on_step.lua"))(modpath, S)
|
||||
assert(loadfile(modpath .. "/api/api_bees.lua"))(modpath, S)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
local modpath, S = ...
|
||||
|
||||
petz.spawn_bee_pos = function(pos) --Check a pos close to a behive to spawn a bee
|
||||
local pos_1 = {
|
||||
x = pos.x - 1,
|
||||
y = pos.y - 1,
|
||||
z = pos.z - 1,
|
||||
}
|
||||
local pos_2 = {
|
||||
x = pos.x + 1,
|
||||
y = pos.y + 1,
|
||||
z = pos.z + 1,
|
||||
}
|
||||
spawn_pos_list = minetest.find_nodes_in_area(pos_1, pos_2, {"air"})
|
||||
if #spawn_pos_list > 0 then
|
||||
return spawn_pos_list[math.random(1, #spawn_pos_list)]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--Beehive
|
||||
minetest.register_node("petz:beehive", {
|
||||
description = S("Beehive"),
|
||||
tiles = {"petz_beehive.png"},
|
||||
is_ground_content = false,
|
||||
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3,
|
||||
flammable = 3, wool = 1},
|
||||
sounds = default.node_sound_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("bee_count", 3)
|
||||
meta:set_int("honey_count", 3)
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(5.0) -- in seconds
|
||||
end,
|
||||
on_timer = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local bee_count = meta:get_int("bee_count") or 0
|
||||
if bee_count > 0 then --if bee inside
|
||||
if math.random(1, 1) == 1 then --opportunitty to go out
|
||||
local spawn_bee_pos = petz.spawn_bee_pos(pos)
|
||||
if spawn_bee_pos then
|
||||
local bee = minetest.add_entity(spawn_bee_pos, "petz:bee")
|
||||
local bee_entity = bee:get_luaentity()
|
||||
bee_entity.behive = pos
|
||||
meta:set_int("bee_count", bee_count - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
})
|
|
@ -188,7 +188,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
pet.object:set_detach()
|
||||
end, pet)
|
||||
elseif fields.btn_show_tag then
|
||||
pet.show_tag = mobkit.remember(pet, "show_tag", petz.to_boolean(fields.btn_show_tag))
|
||||
pet.show_tag = mobkit.remember(pet, "show_tag", minetest.is_yes(fields.btn_show_tag))
|
||||
elseif fields.btn_dreamcatcher then
|
||||
petz.drop_dreamcatcher(pet)
|
||||
elseif fields.btn_saddlebag then
|
||||
|
|
|
@ -3,15 +3,6 @@ local modpath, S = ...
|
|||
--
|
||||
--Helper Functions
|
||||
--
|
||||
|
||||
function petz.to_boolean(val)
|
||||
if val and (val == "true" or val == 1) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function petz.is_night()
|
||||
local timeofday = minetest.get_timeofday() * 24000
|
||||
if (timeofday < 4500) or (timeofday > 19500) then
|
||||
|
|
|
@ -196,17 +196,14 @@ function petz.set_initial_properties(self, staticdata, dtime_s)
|
|||
else
|
||||
self.genes["gen2"] = static_data_table["gen2_mother"]
|
||||
end
|
||||
end
|
||||
|
||||
local textures_count
|
||||
end
|
||||
local textures_count
|
||||
if self.mutation then
|
||||
textures_count = #self.skin_colors - 1
|
||||
else
|
||||
textures_count = #self.skin_colors
|
||||
end
|
||||
self.texture_no = petz.genetics_texture(self, textures_count)
|
||||
|
||||
|
||||
self.texture_no = petz.genetics_texture(self, textures_count)
|
||||
else -- mutation
|
||||
local mutation_gen = #self.skin_colors --the last skin is always the mutation
|
||||
self.genes["gen1"] = mutation_gen
|
||||
|
@ -251,13 +248,13 @@ function petz.set_initial_properties(self, staticdata, dtime_s)
|
|||
--Mob Specific
|
||||
if self.type == "lamb" then --Lamb
|
||||
self.food_count_wool = mobkit.remember(self, "food_count_wool", tonumber(static_data_table["fields"]["food_count_wool"]))
|
||||
self.shaved = mobkit.remember(self, "shaved", petz.to_boolean(static_data_table["fields"]["shaved"]))
|
||||
self.shaved = mobkit.remember(self, "shaved", minetest.is_yes(static_data_table["fields"]["shaved"]))
|
||||
elseif self.type == "wolf" then
|
||||
self.wolf_to_puppy_count = mobkit.remember(self, "wolf_to_puppy_count", tonumber(static_data_table["fields"]["wolf_to_puppy_count"]))
|
||||
end
|
||||
if self.is_mountable == true then
|
||||
self.saddle = petz.to_boolean(static_data_table["fields"]["saddle"])
|
||||
self.saddlebag = petz.to_boolean(static_data_table["fields"]["saddlebag"])
|
||||
self.saddle = minetest.is_yes(static_data_table["fields"]["saddle"])
|
||||
self.saddlebag = minetest.is_yes(static_data_table["fields"]["saddlebag"])
|
||||
self.saddlebag_inventory = minetest.deserialize(static_data_table["fields"]["saddlebag_inventory"])
|
||||
self.max_speed_forward = mobkit.remember(self, "max_speed_forward", tonumber(static_data_table["fields"]["max_speed_forward"] ))
|
||||
self.max_speed_reverse = mobkit.remember(self, "max_speed_reverse", tonumber(static_data_table["fields"]["max_speed_reverse"]))
|
||||
|
@ -270,13 +267,13 @@ function petz.set_initial_properties(self, staticdata, dtime_s)
|
|||
end
|
||||
--Mobs that can have babies
|
||||
if self.breed == true then
|
||||
self.is_male = mobkit.remember(self, "is_male", petz.to_boolean(static_data_table["fields"]["is_male"]) )
|
||||
self.is_rut = mobkit.remember(self, "is_rut", petz.to_boolean(static_data_table["fields"]["is_rut"]))
|
||||
self.is_pregnant = mobkit.remember(self, "is_pregnant", petz.to_boolean(static_data_table["fields"]["is_pregnant"]))
|
||||
self.is_male = mobkit.remember(self, "is_male", minetest.is_yes(static_data_table["fields"]["is_male"]) )
|
||||
self.is_rut = mobkit.remember(self, "is_rut", minetest.is_yes(static_data_table["fields"]["is_rut"]))
|
||||
self.is_pregnant = mobkit.remember(self, "is_pregnant", minetest.is_yes(static_data_table["fields"]["is_pregnant"]))
|
||||
self.pregnant_time = mobkit.remember(self, "pregnant_time", tonumber(static_data_table["fields"]["pregnant_time"]))
|
||||
self.father_genes = mobkit.remember(self, "father_genes", minetest.deserialize(static_data_table["fields"]["father_genes"]))
|
||||
self.father_veloc_stats = mobkit.remember(self, "father_veloc_stats", minetest.deserialize(static_data_table["fields"]["father_veloc_stats"]))
|
||||
self.is_baby = mobkit.remember(self, "is_baby", petz.to_boolean(static_data_table["fields"]["is_baby"]))
|
||||
self.is_baby = mobkit.remember(self, "is_baby", minetest.is_yes(static_data_table["fields"]["is_baby"]))
|
||||
self.pregnant_count = mobkit.remember(self, "pregnant_count", tonumber(static_data_table["fields"]["pregnant_count"]))
|
||||
self.genes = mobkit.remember(self, "genes", minetest.deserialize(static_data_table["fields"]["genes"]))
|
||||
end
|
||||
|
@ -287,10 +284,10 @@ function petz.set_initial_properties(self, staticdata, dtime_s)
|
|||
self.texture_no = tonumber(static_data_table["fields"]["texture_no"])
|
||||
self.set_vars = mobkit.remember(self, "set_vars", true)
|
||||
self.tag = mobkit.remember(self, "tag", static_data_table["fields"]["tag"]) or ""
|
||||
self.show_tag = mobkit.remember(self, "show_tag", petz.to_boolean(static_data_table["fields"]["show_tag"]))
|
||||
self.dreamcatcher = mobkit.remember(self, "dreamcatcher", petz.to_boolean(static_data_table["fields"]["dreamcatcher"]))
|
||||
self.show_tag = mobkit.remember(self, "show_tag", minetest.is_yes(static_data_table["fields"]["show_tag"]))
|
||||
self.dreamcatcher = mobkit.remember(self, "dreamcatcher", minetest.is_yes(static_data_table["fields"]["dreamcatcher"]))
|
||||
self.status = mobkit.remember(self, "status", static_data_table["fields"]["status"]) or ""
|
||||
self.tamed = mobkit.remember(self, "tamed", petz.to_boolean(static_data_table["fields"]["tamed"]))
|
||||
self.tamed = mobkit.remember(self, "tamed", minetest.is_yes(static_data_table["fields"]["tamed"]))
|
||||
self.owner = mobkit.remember(self, "owner", static_data_table["fields"]["owner"])
|
||||
self.food_count = mobkit.remember(self, "food_count", tonumber(static_data_table["fields"]["food_count"]))
|
||||
if self.has_affinity == true then
|
||||
|
|
|
@ -5,6 +5,8 @@ Bat=Murciélago
|
|||
Beaver Fur=Piel de castor
|
||||
Beaver Oil=Aceite de castor
|
||||
Beaver=Castor
|
||||
Bee=Abeja
|
||||
Beehive=Colmena
|
||||
Beef=Carne de ternera
|
||||
Beef Steak=Filete de ternera
|
||||
Bird Stand=Soporte para pájaros
|
||||
|
|
|
@ -1,21 +1,91 @@
|
|||
local modpath, S = ...
|
||||
|
||||
---
|
||||
---COMMON BEHAVIOURS
|
||||
---
|
||||
|
||||
--Runaway from predator
|
||||
function petz.bh_runaway_from_predator(self, pos)
|
||||
local predator_list = petz.settings[self.type.."_predators"]
|
||||
if predator_list then
|
||||
local predators = string.split(predator_list, ',')
|
||||
for i = 1, #predators do --loop thru all preys
|
||||
--minetest.chat_send_player("singleplayer", "spawn node="..spawn_nodes[i])
|
||||
--minetest.chat_send_player("singleplayer", "node name="..node.name)
|
||||
local predator = mobkit.get_closest_entity(self, predators[i]) -- look for predator
|
||||
if predator then
|
||||
if predator and vector.distance(pos, predator:get_pos()) <= self.view_range then
|
||||
mobkit.hq_runfrom(self, 18, predator)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function petz.bh_start_follow(self, pos, player, prty)
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name == self.follow and vector.distance(pos, player:get_pos()) <= self.view_range then
|
||||
self.status = mobkit.remember(self, "status", "follow")
|
||||
mobkit.hq_follow(self, prty, player)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function petz.bh_stop_follow(self, player)
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name ~= self.follow then
|
||||
self.status = mobkit.remember(self, "status", "")
|
||||
mobkit.hq_roam(self, 0)
|
||||
mobkit.clear_queue_high(self)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
petz.ownthing(self)
|
||||
end
|
||||
end
|
||||
|
||||
function petz.bh_replace(self)
|
||||
petz.replace(self)
|
||||
if self.lay_eggs then
|
||||
petz.lay_egg(self)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
--Herbivore Behaviour
|
||||
--
|
||||
|
||||
function petz.herbivore_brain(self)
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
local die = false
|
||||
|
||||
if self.hp <= 0 then
|
||||
petz.on_die(self) -- Die Behaviour
|
||||
return
|
||||
die = true
|
||||
elseif not(petz.is_night()) and self.die_at_daylight == true then --it dies when sun rises up
|
||||
if minetest.get_node_light(self.object:get_pos(), minetest.get_timeofday()) >= self.max_daylight_level then
|
||||
petz.on_die(self)
|
||||
return
|
||||
if pos and self.max_daylight_level then
|
||||
if minetest.get_node_light(pos, minetest.get_timeofday()) >= self.max_daylight_level then
|
||||
die = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if die == true then
|
||||
petz.on_die(self)
|
||||
return
|
||||
end
|
||||
|
||||
if mobkit.timer(self, 1) then
|
||||
|
||||
petz.env_damage(self) --enviromental damage: lava, fire...
|
||||
|
@ -27,52 +97,26 @@ function petz.herbivore_brain(self)
|
|||
return
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local player = mobkit.get_nearby_player(self)
|
||||
|
||||
--Runaway from predator
|
||||
if prty < 18 then
|
||||
local predator_list = petz.settings[self.type.."_predators"]
|
||||
if predator_list then
|
||||
local predators = string.split(predator_list, ',')
|
||||
for i = 1, #predators do --loop thru all preys
|
||||
--minetest.chat_send_player("singleplayer", "spawn node="..spawn_nodes[i])
|
||||
--minetest.chat_send_player("singleplayer", "node name="..node.name)
|
||||
local predator = mobkit.get_closest_entity(self, predators[i]) -- look for predator
|
||||
if predator then
|
||||
if predator and vector.distance(pos, predator:get_pos()) <= self.view_range then
|
||||
mobkit.hq_runfrom(self, 18, predator)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if petz.bh_runaway_from_predator(self, pos) == true then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--Follow Behaviour
|
||||
if prty < 16 then
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name == self.follow and vector.distance(pos, player:get_pos()) <= self.view_range then
|
||||
self.status = mobkit.remember(self, "status", "follow")
|
||||
mobkit.hq_follow(self, 16, player)
|
||||
return
|
||||
end
|
||||
if petz.bh_start_follow(self, pos, player, 16) == true then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if prty == 16 then
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name ~= self.follow then
|
||||
self.status = mobkit.remember(self, "status", "")
|
||||
mobkit.hq_roam(self, 0)
|
||||
mobkit.clear_queue_high(self)
|
||||
return
|
||||
end
|
||||
else
|
||||
petz.ownthing(self)
|
||||
end
|
||||
if petz.bh_stop_follow(self, player) == true then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--Runaway from Player
|
||||
|
@ -87,14 +131,10 @@ function petz.herbivore_brain(self)
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--Replace nodes by others
|
||||
if prty < 6 then
|
||||
petz.replace(self)
|
||||
if self.lay_eggs then
|
||||
petz.lay_egg(self)
|
||||
end
|
||||
petz.bh_replace(self)
|
||||
end
|
||||
|
||||
if prty < 5 then
|
||||
|
@ -267,28 +307,17 @@ function petz.predator_brain(self)
|
|||
local pos = self.object:get_pos() --pos of the petz
|
||||
local player = mobkit.get_nearby_player(self) --get the player close
|
||||
|
||||
--Follow Behaviour
|
||||
--Follow Behaviour
|
||||
if prty < 16 then
|
||||
if player and self.tamed == true then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name == self.follow and vector.distance(pos, player:get_pos()) <= self.view_range then
|
||||
mobkit.hq_follow(self, 16, player)
|
||||
return
|
||||
end
|
||||
if petz.bh_start_follow(self, pos, player, 16) == true then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if prty == 16 then
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name ~= self.follow then
|
||||
mobkit.hq_roam(self, 0)
|
||||
mobkit.clear_queue_high(self)
|
||||
return
|
||||
end
|
||||
else
|
||||
petz.ownthing(self)
|
||||
end
|
||||
if prty == 16 then
|
||||
if petz.bh_stop_follow(self, player) == true then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- hunt a prey
|
||||
|
@ -302,7 +331,7 @@ function petz.predator_brain(self)
|
|||
--minetest.chat_send_player("singleplayer", "node name="..node.name)
|
||||
local prey = mobkit.get_closest_entity(self, preys[i]) -- look for prey
|
||||
if prey then
|
||||
minetest.chat_send_player("singleplayer", "got it")
|
||||
--minetest.chat_send_player("singleplayer", "got it")
|
||||
mobkit.hq_hunt(self, 12, prey) -- and chase it
|
||||
return
|
||||
end
|
||||
|
@ -329,10 +358,7 @@ function petz.predator_brain(self)
|
|||
|
||||
--Replace nodes by others
|
||||
if prty < 6 then
|
||||
petz.replace(self)
|
||||
if self.lay_eggs then
|
||||
petz.lay_egg(self)
|
||||
end
|
||||
petz.bh_replace(self)
|
||||
end
|
||||
|
||||
-- Default Random Sound
|
||||
|
@ -346,6 +372,75 @@ function petz.predator_brain(self)
|
|||
end
|
||||
end
|
||||
|
||||
function petz.bee_brain(self)
|
||||
|
||||
if self.hp <= 0 then
|
||||
petz.on_die(self) -- Die Behaviour
|
||||
return
|
||||
elseif not(petz.is_night()) and self.die_at_daylight == true then --it dies when sun rises up
|
||||
if minetest.get_node_light(self.object:get_pos(), minetest.get_timeofday()) >= self.max_daylight_level then
|
||||
petz.on_die(self)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if mobkit.timer(self, 1) then
|
||||
|
||||
petz.env_damage(self) --enviromental damage: lava, fire...
|
||||
|
||||
local prty = mobkit.get_queue_priority(self)
|
||||
|
||||
if prty < 20 and self.isinliquid then
|
||||
mobkit.hq_liquid_recovery(self, 20)
|
||||
return
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local player = mobkit.get_nearby_player(self)
|
||||
|
||||
--search for flowers
|
||||
if prty < 6 and self.pollen == false then
|
||||
local view_range = self.view_range
|
||||
local nearby_flowers = minetest.find_nodes_in_area(
|
||||
{x = pos.x - view_range, y = pos.y - 1, z = pos.z - view_range},
|
||||
{x = pos.x + view_range, y = pos.y + 1, z = pos.z + view_range},
|
||||
{"group:flower"})
|
||||
if #nearby_flowers >= 1 then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--search for a petz:behive
|
||||
if prty < 4 and self.pollen == true then
|
||||
local view_range = self.view_range
|
||||
local nearby_beehives = minetest.find_nodes_in_area(
|
||||
{x = pos.x - view_range, y = pos.y - 1, z = pos.z - view_range},
|
||||
{x = pos.x + view_range, y = pos.y + 1, z = pos.z + view_range},
|
||||
{"petz:pet_behive"})
|
||||
if #nearby_beehives >= 1 then
|
||||
local tpos = nearby_nodes[1] --the first match
|
||||
local distance = vector.distance(pos, tpos)
|
||||
if distance > 2 then
|
||||
mobkit.hq_goto(self, 4, tpos)
|
||||
elseif distance <=2 then
|
||||
if (petz.settings.tamagochi_mode == true) and (self.fed == false) then
|
||||
petz.do_feed(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Default Random Sound
|
||||
petz.random_mob_sound(self)
|
||||
|
||||
--Roam default
|
||||
if mobkit.is_queue_empty_high(self) and self.status == "" then
|
||||
mobkit.hq_wanderfly(self, 0)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
--Aquatic Behaviour
|
||||
--
|
||||
|
@ -366,76 +461,30 @@ function petz.aquatic_brain(self)
|
|||
|
||||
if mobkit.timer(self, 1) then
|
||||
|
||||
local prty = mobkit.get_queue_priority(self)
|
||||
local pos = self.object:get_pos()
|
||||
local prty = mobkit.get_queue_priority(self)
|
||||
local pos = self.object:get_pos()
|
||||
local player = mobkit.get_nearby_player(self)
|
||||
|
||||
--Runaway from predator
|
||||
if prty < 18 then
|
||||
local predator_list = petz.settings[self.type.."_predators"]
|
||||
if predator_list then
|
||||
local predators = string.split(predator_list, ',')
|
||||
for i = 1, #predators do --loop thru all preys
|
||||
--minetest.chat_send_player("singleplayer", "spawn node="..spawn_nodes[i])
|
||||
--minetest.chat_send_player("singleplayer", "node name="..node.name)
|
||||
local predator = mobkit.get_closest_entity(self, predators[i]) -- look for predator
|
||||
if predator then
|
||||
if predator and vector.distance(pos, predator:get_pos()) < 8 then
|
||||
mobkit.hq_runfrom(self, 18, predator)
|
||||
return
|
||||
if prty < 10 then
|
||||
if player then
|
||||
if (self.tamed == false) or (self.tamed == true and self.status == "guard" and player:get_player_name() ~= self.owner) then
|
||||
if vector.distance(pos, player:get_pos()) <= self.view_range then -- if player close
|
||||
if self.attack_player == true then --attack player
|
||||
mobkit.clear_queue_high(self) -- abandon whatever they've been doing
|
||||
mobkit.hq_aqua_attack(self, 20, puncher, 6) -- get revenge
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Follow Behaviour
|
||||
|
||||
if prty < 16 then
|
||||
local player = mobkit.get_nearby_player(self)
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name == self.follow and vector.distance(pos, player:get_pos()) < 8 then
|
||||
mobkit.hq_follow(self, 16, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if prty == 16 then
|
||||
local player = mobkit.get_nearby_player(self)
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if wielded_item_name ~= self.follow then
|
||||
mobkit.hq_roam(self, 0)
|
||||
mobkit.clear_queue_high(self)
|
||||
return
|
||||
end
|
||||
else
|
||||
petz.ownthing(self)
|
||||
end
|
||||
end
|
||||
|
||||
--Runaway from Player
|
||||
|
||||
if prty < 14 then
|
||||
local player = mobkit.get_nearby_player(self)
|
||||
if player then
|
||||
local wielded_item_name = player:get_wielded_item():get_name()
|
||||
if self.is_pet == false and self.tamed == false and self.follow ~= wielded_item_name and vector.distance(pos, player:get_pos()) < 8 then
|
||||
mobkit.hq_runfrom(self, 14, player)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Default Random Sound
|
||||
petz.random_mob_sound(self)
|
||||
|
||||
--Roam default
|
||||
if mobkit.is_queue_empty_high(self) and not(self.status == "stand") then
|
||||
mobkit.hq_wanderswin(self, 0)
|
||||
end
|
||||
|
||||
if mobkit.is_queue_empty_high(self) then
|
||||
mobkit.hq_aqua_roam(self, 0, 0.5)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -130,8 +130,13 @@ function mobkit.lq_dumbfly(self, speed_factor)
|
|||
local rotation_integer = math.random(0, 5)
|
||||
local rotation_decimals = math.random()
|
||||
local new_yaw = yaw + rotation_integer + rotation_decimals
|
||||
self.object:set_yaw(new_yaw)
|
||||
mobkit.set_velocity(self, self.object:getvelocity())
|
||||
self.object:set_yaw(new_yaw)
|
||||
velocity = {
|
||||
x = self.max_speed* speed_factor,
|
||||
y = self.max_speed* speed_factor,
|
||||
z = self.max_speed* speed_factor,
|
||||
}
|
||||
mobkit.set_velocity(self, velocity)
|
||||
end
|
||||
end
|
||||
if mobkit.check_height(self) == false or mobkit.node_name_in(self, "top") ~= "air" then --check if max height, then stand or descend, or a node above the petz
|
||||
|
|
|
@ -298,3 +298,5 @@ minetest.register_craft({
|
|||
{'', 'default:stick', ''},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@
|
|||
##Important: All the values separated by commas have to be without spaces.
|
||||
##
|
||||
|
||||
petz_list = kitty,puppy,ducky,lamb,lion,calf,panda,grizzly,pony,parrot,chicken,piggy,wolf,elephant,elephant_female,pigeon,moth,camel,clownfish,bat,silkworm,chimp,hamster,dolphin
|
||||
petz_list = kitty,puppy,ducky,lamb,lion,calf,panda,grizzly,pony,parrot,chicken,piggy,wolf,elephant,elephant_female,pigeon,moth,camel,clownfish,bat,silkworm,chimp,hamster,dolphin,bee
|
||||
|
||||
##Type of model [mesh -or- cubic]
|
||||
type_model = mesh
|
||||
|
@ -26,7 +26,7 @@ rob_mobs = false
|
|||
##Spawn Engine
|
||||
## The interval is avg spawn attempt interval for every player
|
||||
spawn_interval = 30
|
||||
## Max number of mobs in abr
|
||||
## Max number of mobs in the active block range
|
||||
max_mobs = 30
|
||||
|
||||
##lashing
|
||||
|
@ -63,7 +63,7 @@ parrot_spawn= true
|
|||
chicken_spawn = true
|
||||
chimp_spawn = true
|
||||
pigeon_spawn = true
|
||||
turtle_spawn = true
|
||||
turtle_spawn = false
|
||||
clownfish_spawn = false
|
||||
tropicalfish_spawn = false
|
||||
wolf_spawn = true
|
||||
|
@ -75,7 +75,8 @@ bat_spawn = true
|
|||
silkworm_spawn = true
|
||||
chimp_spawn = true
|
||||
hamster_spawn = true
|
||||
dolphin_spawn = false
|
||||
dolphin_spawn = true
|
||||
bee_spawn = false
|
||||
|
||||
##Enviromental Damage
|
||||
air_damage = 1
|
||||
|
@ -222,6 +223,12 @@ moth_spawn_chance = 0.8
|
|||
moth_spawn_nodes = default:dirt_with_coniferous_litter
|
||||
moth_spawn_biome = default
|
||||
|
||||
##Bee Specific
|
||||
bee_follow = default:torch
|
||||
bee_spawn_chance = 0.8
|
||||
bee_spawn_nodes = default:dirt_with_grass
|
||||
bee_spawn_biome = default
|
||||
|
||||
##Bat Specific
|
||||
bat_follow = fireflies:firefly
|
||||
bat_spawn_chance = 1.0
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
local S = ...
|
||||
|
||||
local pet_name = "bee"
|
||||
local scale_model = 0.25
|
||||
local mesh = 'petz_bee.b3d'
|
||||
local textures= {"petz_bee.png"}
|
||||
local collisionbox = {-0.35, -0.75*scale_model, -0.28, 0.35, -0.0625, 0.28}
|
||||
|
||||
minetest.register_entity("petz:"..pet_name,{
|
||||
--Petz specifics
|
||||
type = "bee",
|
||||
init_tamagochi_timer = false,
|
||||
is_pet = false,
|
||||
can_fly = true,
|
||||
lay_eggs = true,
|
||||
lay_eggs_in_nest = false,
|
||||
type_of_egg = "node",
|
||||
max_height = 3,
|
||||
has_affinity = false,
|
||||
is_wild = false,
|
||||
give_orders = false,
|
||||
can_be_brushed = false,
|
||||
capture_item = "net",
|
||||
follow = petz.settings.bee_follow,
|
||||
--automatic_face_movement_dir = 0.0,
|
||||
rotate = petz.settings.rotate,
|
||||
physical = true,
|
||||
stepheight = 0.1, --EVIL!
|
||||
collide_with_objects = true,
|
||||
collisionbox = collisionbox,
|
||||
visual = petz.settings.visual,
|
||||
mesh = mesh,
|
||||
textures = textures,
|
||||
visual_size = {x=petz.settings.visual_size.x*scale_model, y=petz.settings.visual_size.y*scale_model},
|
||||
static_save = true,
|
||||
get_staticdata = mobkit.statfunc,
|
||||
-- api props
|
||||
springiness= 0,
|
||||
buoyancy = 0.5, -- portion of hitbox submerged
|
||||
max_speed = 2,
|
||||
jump_height = 2.0,
|
||||
view_range = 10,
|
||||
lung_capacity = 10, -- seconds
|
||||
max_hp = 2,
|
||||
|
||||
attack={range=0.5, damage_groups={fleshy=3}},
|
||||
animation = {
|
||||
walk={range={x=1, y=12}, speed=20, loop=true},
|
||||
run={range={x=13, y=25}, speed=20, loop=true},
|
||||
stand={
|
||||
{range={x=26, y=46}, speed=5, loop=true},
|
||||
{range={x=47, y=59}, speed=5, loop=true},
|
||||
{range={x=60, y=70}, speed=5, loop=true},
|
||||
{range={x=71, y=91}, speed=5, loop=true},
|
||||
},
|
||||
fly={range={x=92, y=98}, speed=30, loop=true},
|
||||
stand_fly={range={x=92, y=98}, speed=30, loop=true},
|
||||
},
|
||||
sounds = {
|
||||
misc = "petz_bee_chirp",
|
||||
moaning = "petz_bee_moaning",
|
||||
},
|
||||
|
||||
brainfunc = petz.bee_brain,
|
||||
|
||||
on_activate = function(self, staticdata, dtime_s) --on_activate, required
|
||||
mobkit.actfunc(self, staticdata, dtime_s)
|
||||
petz.set_initial_properties(self, staticdata, dtime_s)
|
||||
end,
|
||||
|
||||
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||
petz.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
petz.on_rightclick(self, clicker)
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
mobkit.stepfunc(self, dtime) -- required
|
||||
petz.on_step(self, dtime)
|
||||
end,
|
||||
|
||||
})
|
||||
|
||||
petz:register_egg("petz:bee", S("Bee"), "petz_spawnegg_bee.png", false)
|
|
@ -37,7 +37,7 @@ minetest.register_entity("petz:"..pet_name,{
|
|||
-- api props
|
||||
springiness= 0,
|
||||
buoyancy = 0.5, -- portion of hitbox submerged
|
||||
max_speed = 1,
|
||||
max_speed = 0.5,
|
||||
jump_height = 2.0,
|
||||
view_range = 10,
|
||||
lung_capacity = 32767, -- seconds
|
||||
|
|
|
@ -7,7 +7,7 @@ local pet_name = "dolphin"
|
|||
local scale_model = 1.35
|
||||
local mesh = 'petz_dolphin.b3d'
|
||||
local textures= {"petz_dolphin_bottlenose.png"}
|
||||
local collisionbox = {-0.35, -0.75*scale_model, -0.28, 0.35, -0.125, 0.28}
|
||||
local collisionbox = {-0.25, -0.75*scale_model, -0.4375, 0.3125, -0.0625, 0.5}
|
||||
|
||||
minetest.register_entity("petz:"..pet_name,{
|
||||
--Petz specifics
|
||||
|
@ -37,7 +37,7 @@ minetest.register_entity("petz:"..pet_name,{
|
|||
-- api props
|
||||
springiness= 0,
|
||||
buoyancy = 0.5, -- portion of hitbox submerged
|
||||
max_speed = 2.0,
|
||||
max_speed = 1.5,
|
||||
jump_height = 2.0,
|
||||
view_range = 10,
|
||||
lung_capacity = 32767, -- seconds
|
||||
|
|
|
@ -160,6 +160,11 @@ petz.settings.moth_spawn_chance = tonumber(settings:get("moth_spawn_chance"))
|
|||
petz.settings.moth_spawn_nodes = settings:get("moth_spawn_nodes", "")
|
||||
petz.settings.moth_spawn_biome = settings:get("moth_spawn_biome", "default")
|
||||
petz.settings.moth_follow = settings:get("moth_follow", "")
|
||||
petz.settings.bee_spawn = settings:get_bool("bee_spawn", true)
|
||||
petz.settings.bee_spawn_chance = tonumber(settings:get("bee_spawn_chance"))
|
||||
petz.settings.bee_spawn_nodes = settings:get("bee_spawn_nodes", "")
|
||||
petz.settings.bee_spawn_biome = settings:get("bee_spawn_biome", "default")
|
||||
petz.settings.bee_follow = settings:get("bee_follow", "")
|
||||
petz.settings.camel_spawn = settings:get_bool("camel_spawn", true)
|
||||
petz.settings.camel_spawn_chance = tonumber(settings:get("camel_spawn_chance"))
|
||||
petz.settings.camel_spawn_nodes = settings:get("camel_spawn_nodes", "")
|
||||
|
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 462 B |
Loading…
Reference in New Issue