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