local M = {}
-- ---------------------------------------------------------
-- NPC行为更新(由Timer驱动,每2秒一次)
-- ---------------------------------------------------------
function M.start()
clicli.timer.loop(2.0, function()
local NpcMgr = require 'core.npc_manager'
local npc_list = NpcMgr.get_npc_list()
for _, npc in ipairs(npc_list) do
if npc:is_alive() then
M.tick(npc)
end
end
end, 'NPC行为更新')
end
function M.tick(npc)
if npc:storage_get('is_panicked') then
return
end
local state = npc:storage_get('ai_state') or 'idle'
if state == 'idle' then
if math.random(100) <= 30 then
M.try_interact(npc)
else
npc:storage_set('ai_state', 'moving')
local road = npc:storage_get('assigned_road')
if road then
npc:move_along_road(road, 1, false, true, true)
end
end
elseif state == 'moving' then
if not npc:is_moving() then
npc:storage_set('ai_state', 'idle')
end
elseif state == 'interacting' then
-- 由互动计时器回调切回idle
end
end
-- ---------------------------------------------------------
-- 互动点检测
-- ---------------------------------------------------------
function M.try_interact(npc)
local interact_configs = {
{ tag = 'interact_bench', anim = 'sit', time_min = 8, time_max = 15 },
{ tag = 'interact_board', anim = 'look', time_min = 5, time_max = 10 },
{ tag = 'interact_well', anim = 'wash', time_min = 5, time_max = 8 },
{ tag = 'interact_vendor', anim = 'trade', time_min = 6, time_max = 12 },
}
local pos = npc:get_point()
for _, cfg in ipairs(interact_configs) do
local areas = clicli.area.get_circle_areas_by_tag(cfg.tag)
for _, area in ipairs(areas) do
if area:is_point_in_area(pos) then
npc:stop()
npc:play_animation(cfg.anim, 1.0, 0, -1, false, true)
npc:storage_set('ai_state', 'interacting')
local wait = math.random(cfg.time_min, cfg.time_max)
clicli.timer.wait(wait, function()
if not npc:is_alive() then return end
npc:stop_cur_animation()
npc:storage_set('ai_state', 'idle')
local road = npc:storage_get('assigned_road')
if road then
npc:move_along_road(road, 1, false, true, true)
npc:storage_set('ai_state', 'moving')
end
end)
return true
end
end
end
return false
end
return M