Fix randomization of new state not working as intended
This commit is contained in:
parent
f96188e06a
commit
529fea79b3
@ -1,8 +1,8 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Mob Framework Mod by Sapier
|
||||
--
|
||||
--
|
||||
-- You may copy, use, modify or do nearly anything except removing this
|
||||
-- copyright notice.
|
||||
-- copyright notice.
|
||||
-- And of course you are NOT allow to pretend you have written it.
|
||||
--
|
||||
--! @file mob_state.lua
|
||||
@ -14,7 +14,7 @@
|
||||
--! @defgroup mob_state State handling functions
|
||||
--! @brief a component to do basic changes to mob on state change
|
||||
--! @ingroup framework_int
|
||||
--! @{
|
||||
--! @{
|
||||
--
|
||||
-- Contact sapier a t gmx net
|
||||
-------------------------------------------------------------------------------
|
||||
@ -37,36 +37,36 @@ mob_state.default_state_time = 30
|
||||
-------------------------------------------------------------------------------
|
||||
function mob_state.initialize(entity,now)
|
||||
|
||||
dbg_mobf.mob_state_lvl3("MOBF: " .. entity.data.name
|
||||
dbg_mobf.mob_state_lvl3("MOBF: " .. entity.data.name
|
||||
.. " initializing state dynamic data")
|
||||
|
||||
|
||||
local state = {
|
||||
current = "default",
|
||||
time_to_next_change = 30,
|
||||
locked = false,
|
||||
enabled = false,
|
||||
}
|
||||
|
||||
|
||||
local sum_chances = 0
|
||||
local state_count = 0
|
||||
|
||||
|
||||
if entity.data.states ~= nil then
|
||||
for s = 1, #entity.data.states , 1 do
|
||||
sum_chances = sum_chances + entity.data.states[s].chance
|
||||
|
||||
|
||||
if entity.data.states[s].name ~= "combat" and
|
||||
entity.data.states[s].name ~= "default" then
|
||||
state_count = state_count +1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--sanity check for state chances
|
||||
if sum_chances > 1 then
|
||||
minetest.log(LOGLEVEL_WARNING,"MOBF: Warning sum of state chances for mob "
|
||||
minetest.log(LOGLEVEL_WARNING,"MOBF: Warning sum of state chances for mob "
|
||||
.. entity.data.name .. " > 1")
|
||||
end
|
||||
|
||||
|
||||
--only enable state changeing if there is at least one state
|
||||
if state_count > 0 then
|
||||
state.enabled = true
|
||||
@ -95,7 +95,7 @@ function mob_state.get_state_by_name(entity,name)
|
||||
return entity.data.states[i]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -114,11 +114,11 @@ function mob_state.lock(entity,value)
|
||||
return
|
||||
end
|
||||
if entity.dynamic_data.state == nil then
|
||||
dbg_mobf.mob_state_lvl1("MOBF: unable to lock state for: "
|
||||
dbg_mobf.mob_state_lvl1("MOBF: unable to lock state for: "
|
||||
.. entity.data.name .. " no state dynamic data present")
|
||||
return
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
entity.dynamic_data.state.locked = value
|
||||
end
|
||||
|
||||
@ -140,7 +140,7 @@ function mob_state.callback(entity,now,dstep)
|
||||
|
||||
--TODO find out if this needs to be replaced
|
||||
-- if entity.dynamic_data.state == nil then
|
||||
-- minetest.log(LOGLEVEL_ERRROR,"MOBF BUG: " .. entity.data.name
|
||||
-- minetest.log(LOGLEVEL_ERRROR,"MOBF BUG: " .. entity.data.name
|
||||
-- .. " mob state callback without mob dynamic data!")
|
||||
-- mob_state.initialize(entity,now)
|
||||
-- local default_state = mob_state.get_state_by_name(self,"default")
|
||||
@ -149,35 +149,35 @@ function mob_state.callback(entity,now,dstep)
|
||||
-- entity = spawning.replace_entity(entity,entity.data.modname .. ":"..entity.data.name,true)
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
|
||||
--abort state change if current state is locked
|
||||
if entity.dynamic_data.state.locked or
|
||||
if entity.dynamic_data.state.locked or
|
||||
entity.dynamic_data.state.enabled == false then
|
||||
dbg_mobf.mob_state_lvl3("MOBF: " .. entity.data.name
|
||||
dbg_mobf.mob_state_lvl3("MOBF: " .. entity.data.name
|
||||
.. " state locked or no custom states definded ")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
entity.dynamic_data.state.time_to_next_change = entity.dynamic_data.state.time_to_next_change -dstep
|
||||
|
||||
|
||||
--do only change if last state timed out
|
||||
if entity.dynamic_data.state.time_to_next_change < 0 then
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " time to change state: " .. entity.dynamic_data.state.time_to_next_change
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " time to change state: " .. entity.dynamic_data.state.time_to_next_change
|
||||
.. " , " .. dstep .. " entity=" .. tostring(entity))
|
||||
|
||||
|
||||
local rand = math.random()
|
||||
|
||||
|
||||
local maxvalue = 0
|
||||
|
||||
|
||||
local state_table = {}
|
||||
|
||||
|
||||
--fill table with available states
|
||||
for i=1, #entity.data.states, 1 do
|
||||
if (entity.data.states[i].HANDLER_precondition == nil or
|
||||
entity.data.states[i].HANDLER_precondition(entity,entity.data.states[i])) and
|
||||
--ignore states that are not supposed to be switched to
|
||||
--ignore states that are not supposed to be switched to
|
||||
--by automatic state change handling e.g. fighting states or
|
||||
--manual set states
|
||||
( entity.data.states[i].state_mode == nil or
|
||||
@ -185,13 +185,16 @@ function mob_state.callback(entity,now,dstep)
|
||||
table.insert(state_table,entity.data.states[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name .. " "
|
||||
.. dump(#state_table) .. " states do pass pecondition check ")
|
||||
|
||||
--try to get a random state to change to
|
||||
for i=1, #state_table, 1 do
|
||||
|
||||
|
||||
local rand_state = math.random(#state_table)
|
||||
local current_chance = 0
|
||||
|
||||
|
||||
if type (state_table[rand_state].chance) == "function" then
|
||||
current_chance = state_table[rand_state].chance(entity,now,dstep)
|
||||
else
|
||||
@ -199,21 +202,31 @@ function mob_state.callback(entity,now,dstep)
|
||||
current_chance = state_table[rand_state].chance
|
||||
end
|
||||
end
|
||||
|
||||
if math.random() < current_chance then
|
||||
|
||||
local random_value = math.random()
|
||||
|
||||
if random_value < current_chance then
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " switching to state " .. state_table[rand_state].name)
|
||||
mob_state.change_state(entity,state_table[rand_state])
|
||||
return true
|
||||
else
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " not switching to state " .. state_table[rand_state].name
|
||||
.. " rand was: " .. random_value)
|
||||
table.remove(state_table,rand_state)
|
||||
end
|
||||
end
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " no specific state selected switching to default state ")
|
||||
--switch to default state (only reached if no change has been done
|
||||
mob_state.change_state(entity,mob_state.get_state_by_name(entity,"default"))
|
||||
else
|
||||
dbg_mobf.mob_state_lvl3("MOBF: " .. entity.data.name
|
||||
dbg_mobf.mob_state_lvl3("MOBF: " .. entity.data.name
|
||||
.. " is not ready for state change ")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
@ -231,7 +244,7 @@ function mob_state.switch_movgen(entity,state)
|
||||
mobf_assert_backtrace(entity ~= nil)
|
||||
mobf_assert_backtrace(state ~= nil)
|
||||
local mov_to_set = nil
|
||||
|
||||
|
||||
--determine new movement gen
|
||||
if state.movgen ~= nil then
|
||||
mov_to_set = getMovementGen(state.movgen)
|
||||
@ -239,12 +252,12 @@ function mob_state.switch_movgen(entity,state)
|
||||
local default_state = mob_state.get_state_by_name(entity,"default")
|
||||
mov_to_set = getMovementGen(default_state.movgen)
|
||||
end
|
||||
|
||||
|
||||
--check if new mov gen differs from old one
|
||||
if mov_to_set ~= nil and
|
||||
mov_to_set ~= entity.dynamic_data.current_movement_gen then
|
||||
entity.dynamic_data.current_movement_gen = mov_to_set
|
||||
|
||||
|
||||
--TODO initialize new movement gen
|
||||
entity.dynamic_data.current_movement_gen.init_dynamic_data(entity,mobf_get_current_time())
|
||||
end
|
||||
@ -263,34 +276,34 @@ end
|
||||
-------------------------------------------------------------------------------
|
||||
function mob_state.change_state(entity,state)
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " state change called entity=" .. tostring(entity) .. " state:"
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " state change called entity=" .. tostring(entity) .. " state:"
|
||||
.. dump(state))
|
||||
|
||||
|
||||
--check if custom precondition handler tells us to stop state change
|
||||
if state ~= nil and
|
||||
type(state.HANDLER_precondition) == "function" then
|
||||
if not state.HANDLER_precondition(entity,state) then
|
||||
dbg_mobf.mob_state_lvl1("MOBF: " .. entity.data.name
|
||||
dbg_mobf.mob_state_lvl1("MOBF: " .. entity.data.name
|
||||
.. " custom precondition handler didn't meet ")
|
||||
mobf_assert_backtrace("trying to enter state but invalid precondition" == nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--switch to default state if no state given
|
||||
if state == nil then
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " invalid state switch, switching to default instead of: "
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " invalid state switch, switching to default instead of: "
|
||||
.. dump(state))
|
||||
state = mob_state.get_state_by_name(entity,"default")
|
||||
end
|
||||
|
||||
|
||||
local entityname = entity.data.name
|
||||
local statename = state.name
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entityname .. " switching state to "
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entityname .. " switching state to "
|
||||
.. statename)
|
||||
|
||||
|
||||
if entity.dynamic_data.state == nil then
|
||||
mobf_bug_warning(LOGLEVEL_WARNING,"MOBF BUG!!! mob_state no state dynamic data")
|
||||
end
|
||||
@ -301,36 +314,36 @@ function mob_state.change_state(entity,state)
|
||||
type(entity.dynamic_data.state.current.HANDLER_leave_state) == "function" then
|
||||
entity.dynamic_data.state.current.HANDLER_leave_state(entity,state)
|
||||
end
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " different states now really changeing to " .. state.name)
|
||||
|
||||
mob_state.switch_model(entity,state)
|
||||
mob_state.switch_movgen(entity,state)
|
||||
|
||||
|
||||
entity.dynamic_data.state.time_to_next_change =
|
||||
mob_state.getTimeToNextState(state.typical_state_time)
|
||||
entity.dynamic_data.state.current = state
|
||||
|
||||
|
||||
graphics.set_animation(entity,state.animation)
|
||||
|
||||
|
||||
if state.HANDLER_enter_state ~= nil and
|
||||
type(state.HANDLER_enter_state) == "function" then
|
||||
state.HANDLER_enter_state(entity)
|
||||
end
|
||||
else
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
dbg_mobf.mob_state_lvl2("MOBF: " .. entity.data.name
|
||||
.. " switching to same state as before")
|
||||
entity.dynamic_data.state.time_to_next_change = mob_state.getTimeToNextState(state.typical_state_time)
|
||||
|
||||
|
||||
if state.HANDLER_enter_state ~= nil and
|
||||
type(state.HANDLER_enter_state) == "function" then
|
||||
state.HANDLER_enter_state(entity)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: time to next change = "
|
||||
|
||||
dbg_mobf.mob_state_lvl2("MOBF: time to next change = "
|
||||
.. entity.dynamic_data.state.time_to_next_change)
|
||||
end
|
||||
|
||||
@ -355,26 +368,26 @@ function mob_state.getTimeToNextState(typical_state_time)
|
||||
|
||||
local u1 = 2 * math.random() -1
|
||||
local u2 = 2 * math.random() -1
|
||||
|
||||
|
||||
local q = u1*u1 + u2*u2
|
||||
|
||||
|
||||
local maxtries = 0
|
||||
|
||||
|
||||
while (q == 0 or q >= 1) and maxtries < 10 do
|
||||
u1 = math.random()
|
||||
u2 = math.random() * -1
|
||||
q = u1*u1 + u2*u2
|
||||
|
||||
|
||||
maxtries = maxtries +1
|
||||
end
|
||||
|
||||
|
||||
--abort random generation
|
||||
if maxtries >= 10 then
|
||||
return typical_state_time
|
||||
end
|
||||
|
||||
local p = math.sqrt( (-2*math.log(q))/q )
|
||||
|
||||
|
||||
local retval = 2
|
||||
--calculate normalized state time with maximum error or half typical time up and down
|
||||
if math.random() < 0.5 then
|
||||
@ -382,7 +395,7 @@ function mob_state.getTimeToNextState(typical_state_time)
|
||||
else
|
||||
retval = typical_state_time + ( u2*p * (typical_state_time/2))
|
||||
end
|
||||
|
||||
|
||||
-- ensure minimum state time of 2 seconds
|
||||
if retval > 2 then
|
||||
return retval
|
||||
@ -408,20 +421,20 @@ function mob_state.prepare_states(mob)
|
||||
for s = 1, #mob.states , 1 do
|
||||
if mob.states[s].name == "combat" then
|
||||
builtin_state_overrides["combat"] = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--TODO patrol state
|
||||
|
||||
|
||||
--hunger state
|
||||
if mob.states[s].name == "RSVD_hunger" then
|
||||
builtin_state_overrides["RSVD_hunger"] = true
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
else
|
||||
mob.states = {}
|
||||
end
|
||||
|
||||
|
||||
--add a default combat state if no custom state is defined
|
||||
if mob.combat ~= nil and builtin_state_overrides["combat"] ~= true then
|
||||
table.insert(mob.states,
|
||||
@ -433,10 +446,10 @@ function mob_state.prepare_states(mob)
|
||||
chance = 0,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
if mob.hunger ~= nil and builtin_state_overrides["RSVD_hunger"] ~= true then
|
||||
table.insert(mob.states,
|
||||
{
|
||||
{
|
||||
name = "RSVD_hunger",
|
||||
HANDLER_precondition = mob_state.BuiltinHungerPrecondition(mob),
|
||||
HANDLER_leave_state = mob_state.BuiltinHungerLeave(mob),
|
||||
@ -447,7 +460,7 @@ function mob_state.prepare_states(mob)
|
||||
animation = mob.hunger.animation or "walk"
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@ -484,29 +497,29 @@ function mob_state.BuiltinHungerPrecondition(mob)
|
||||
return function(entity,state)
|
||||
mobf_assert_backtrace(state ~= nil)
|
||||
mobf_assert_backtrace(state.name == "RSVD_hunger")
|
||||
|
||||
|
||||
local pos = entity.object:getpos()
|
||||
--mobf_print("MOBF: trying to find " ..
|
||||
--mobf_print("MOBF: trying to find " ..
|
||||
-- dump(mob.hunger.target_nodes) .. " or " ..
|
||||
-- dump(mob.hunger.target_entities) ..
|
||||
-- " around: " .. printpos(pos))
|
||||
|
||||
|
||||
local lower_pos = {x=pos.x-mob.hunger.range,
|
||||
y=pos.y-mob.hunger.range,
|
||||
z=pos.z-mob.hunger.range}
|
||||
local upper_pos = {x=pos.x+mob.hunger.range,
|
||||
y=pos.y+mob.hunger.range,
|
||||
z=pos.z+mob.hunger.range}
|
||||
|
||||
|
||||
local target_nodes = nil
|
||||
local target_entities = nil
|
||||
|
||||
|
||||
if mob.hunger.target_nodes ~= nil then
|
||||
target_nodes = minetest.find_nodes_in_area(lower_pos,
|
||||
upper_pos,
|
||||
mob.hunger.target_nodes)
|
||||
end
|
||||
|
||||
|
||||
if mob.hunger.target_entities ~= nil then
|
||||
local objectlist = minetest.get_objects_inside_radius(pos,mob.hunger.range)
|
||||
--mobf_print("MOBF: found: " .. #objectlist .. " objects around")
|
||||
@ -514,40 +527,40 @@ function mob_state.BuiltinHungerPrecondition(mob)
|
||||
target_entities = {}
|
||||
for i=1,#objectlist,1 do
|
||||
local luaentity = objectlist[i]:get_luaentity()
|
||||
if luaentity ~= nil and
|
||||
if luaentity ~= nil and
|
||||
mobf_contains(mob.hunger.target_entities,luaentity.name) then
|
||||
table.insert(target_entities,objectlist[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local targets = {}
|
||||
|
||||
|
||||
if target_nodes ~= nil then
|
||||
for i=1,#target_nodes,1 do
|
||||
table.insert(targets,target_nodes[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if target_entities ~= nil then
|
||||
for i=1,#target_entities,1 do
|
||||
table.insert(targets,target_entities[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if targets ~= nil then
|
||||
dbg_mobf.mob_state_lvl3("MOBF: Hunger found " .. #targets .. " targets")
|
||||
for i=1,5,1 do
|
||||
if #targets == 0 then
|
||||
break
|
||||
end
|
||||
|
||||
|
||||
local index = math.floor(math.random(1,#targets) + 0.5)
|
||||
|
||||
|
||||
local target = targets[index]
|
||||
table.remove(targets,index)
|
||||
|
||||
|
||||
--target is a entity
|
||||
if type(target) == "userdata" then
|
||||
entity.dynamic_data.hunger = {}
|
||||
@ -557,16 +570,16 @@ function mob_state.BuiltinHungerPrecondition(mob)
|
||||
else
|
||||
local targetpos = target
|
||||
targetpos.y = targetpos.y +1
|
||||
|
||||
|
||||
--if mob is not in air try 1 above for pathfinding
|
||||
local current_node = minetest.get_node(pos)
|
||||
if current_node ~= nil and
|
||||
current_node.name ~= "air" then
|
||||
pos.y = pos.y+1
|
||||
end
|
||||
|
||||
|
||||
local path = minetest.find_path(pos,targetpos,5,1,1,"A*_noprefetch")
|
||||
|
||||
|
||||
if path ~= nil then
|
||||
entity.dynamic_data.hunger = {}
|
||||
entity.dynamic_data.hunger.target = { x=targetpos.x,y=targetpos.y-1,z=targetpos.z}
|
||||
@ -595,7 +608,7 @@ end
|
||||
--! @return function to be called as leave handler
|
||||
-------------------------------------------------------------------------------
|
||||
function mob_state.BuiltinHungerLeave(mob)
|
||||
|
||||
|
||||
return function(entity,state)
|
||||
--restore old stepheight
|
||||
entity.object:set_properties({stepheight=entity.dynamic_data.hunger.old_stepheight})
|
||||
@ -603,7 +616,7 @@ function mob_state.BuiltinHungerLeave(mob)
|
||||
p_mov_gen.set_cycle_path(entity,nil)
|
||||
p_mov_gen.set_path(entity,nil)
|
||||
p_mov_gen.set_end_of_path_handler(entity,nil)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -622,22 +635,22 @@ function mob_state.BuiltinHungerEnter(mob)
|
||||
return function(entity)
|
||||
mobf_assert_backtrace(entity.dynamic_data.state.current.name == "RSVD_hunger")
|
||||
mobf_assert_backtrace(entity.dynamic_data.hunger ~= nil)
|
||||
|
||||
|
||||
--use stepheight 1 as we did look for a path by using this
|
||||
entity.dynamic_data.hunger.old_stepheight = entity.stepheight
|
||||
|
||||
|
||||
if (type(entity.dynamic_data.hunger.target) == "userdata") then
|
||||
if not p_mov_gen.set_target(entity,entity.dynamic_data.hunger.target) then
|
||||
dbg_mobf.mob_state_lvl1("MOBF: EnterHungerState, failed to set target")
|
||||
end
|
||||
else
|
||||
entity.object:set_properties({stepheight=1})
|
||||
entity.object:set_properties({stepheight=1})
|
||||
p_mov_gen.set_path(entity,entity.dynamic_data.hunger.path)
|
||||
end
|
||||
--p_mov_gen.set_cycle_path(entity,handler)
|
||||
p_mov_gen.set_cycle_path(entity,false)
|
||||
p_mov_gen.set_end_of_path_handler(entity,mob_state.BuiltinHungerTargetReached)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -653,25 +666,25 @@ end
|
||||
function mob_state.BuiltinHungerTargetReached(entity)
|
||||
--consume original target
|
||||
if (entity.dynamic_data.hunger.target ~= nil) and
|
||||
(entity.data.hunger.keep_food == nil or
|
||||
(entity.data.hunger.keep_food == nil or
|
||||
entity.data.hunger.keep_food == false) then
|
||||
if type(entity.dynamic_data.hunger.target) ~= "userdata" then
|
||||
dbg_mobf.mob_state_lvl2("MOBF: consuming targetnode: " ..
|
||||
dbg_mobf.mob_state_lvl2("MOBF: consuming targetnode: " ..
|
||||
printpos(entity.dynamic_data.hunger.target))
|
||||
minetest.remove_node(entity.dynamic_data.hunger.target)
|
||||
else
|
||||
local targetentity = entity.dynamic_data.hunger.target:get_luaentity()
|
||||
|
||||
if targetentity ~= nil and
|
||||
|
||||
if targetentity ~= nil and
|
||||
type(targetentity.mobf_hunger_interface) == "function" then
|
||||
targetentity.mobf_hunger_interface(entity,"HUNGER_CONSUME")
|
||||
dbg_mobf.mob_state_lvl2("MOBF: consuming targetentity")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local eating_state = mob_state.get_state_by_name(entity,"eating")
|
||||
|
||||
|
||||
if eating_state ~= nil then
|
||||
mob_state.change_state(entity,eating_state)
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user