dolphins!

master
runs 2019-09-22 16:43:43 +02:00
parent 0d7375f61d
commit c3ebb6d19e
20 changed files with 751 additions and 369 deletions

View File

@ -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

View File

@ -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)

53
petz/api/api_bees.lua Normal file
View File

@ -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
})

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -298,3 +298,5 @@ minetest.register_craft({
{'', 'default:stick', ''},
}
})

BIN
petz/models/petz_bee.b3d Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

86
petz/petz/bee_mobkit.lua Normal file
View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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", "")

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B