landsandboat/scripts/mixins/helper_npc.lua

135 lines
4.2 KiB
Lua

-----------------------------------
-- Helper NPCs that assist players in battlefields.
--
-- Waits for a timer or until target mobs are engaged, then attacks the first available target.
-- Defaults to no roaming unless allowRoaming = true.
--
-- Usage:
-- mixins = { require('scripts/mixins/helper_npc') }
--
-- local helperConfig = {
-- engageWaitTime = 90, -- seconds to wait (optional, default 0 = target engagement only)
-- allowRoaming = false, -- allow roaming (optional, default false)
-- isAggroable = true, -- can be targeted by enemies (optional, default true)
-- targetMobs = function(mob) return {...} end -- function returning target mob IDs (required)
-- }
--
-- xi.mix.helperNpc.config(mob, helperConfig)
-----------------------------------
require('scripts/globals/mixins')
-----------------------------------
xi = xi or {}
xi.mix = xi.mix or {}
xi.mix.helperNpc = xi.mix.helperNpc or {}
g_mixins = g_mixins or {}
-- Configuration function
xi.mix.helperNpc.config = function(mob, params)
if not params then
return
end
local engageWaitTime = 0
if
params.engageWaitTime and
params.engageWaitTime > 0
then
engageWaitTime = params.engageWaitTime
end
mob:setLocalVar('[helperNpc]engageWaitTime', engageWaitTime)
if params.allowRoaming then
mob:setLocalVar('[helperNpc]allowRoaming', 1)
end
local isAggroable = 1
if params.isAggroable ~= nil and not params.isAggroable then
isAggroable = 0
end
mob:setLocalVar('[helperNpc]isAggroable', isAggroable)
if params.targetMobs and type(params.targetMobs) == 'function' then
xi.mix.helperNpc.targetMobFunctions = xi.mix.helperNpc.targetMobFunctions or {}
xi.mix.helperNpc.targetMobFunctions[mob:getID()] = params.targetMobs
end
end
local function getMobList(mob)
if
xi.mix.helperNpc.targetMobFunctions and
xi.mix.helperNpc.targetMobFunctions[mob:getID()]
then
return xi.mix.helperNpc.targetMobFunctions[mob:getID()](mob)
end
return {}
end
-- Helper function to find available target
local function findAvailableTarget(mob)
local targetMobs = getMobList(mob)
if not targetMobs or #targetMobs == 0 then
return nil
end
for i = 1, #targetMobs do
local targetMob = GetMobByID(targetMobs[i], mob:getInstance())
if targetMob and targetMob:isSpawned() and not targetMob:isDead() then
return targetMob
end
end
return nil
end
g_mixins.helper_npc = function(helperMob)
helperMob:addListener('SPAWN', 'HELPER_NPC_SPAWN', function(mob)
local isAggroableVar = mob:getLocalVar('[helperNpc]isAggroable')
local isAggroable = isAggroableVar ~= 0
mob:setIsAggroable(isAggroable)
-- Default to no roaming unless specified
if mob:getLocalVar('[helperNpc]allowRoaming') ~= 1 then
mob:setMobMod(xi.mobMod.ROAM_DISTANCE, 0)
end
local engageWaitTime = mob:getLocalVar('[helperNpc]engageWaitTime')
if engageWaitTime > 0 then
mob:setLocalVar('engageWait', GetSystemTime() + engageWaitTime)
end
end)
helperMob:addListener('ROAM_TICK', 'HELPER_NPC_ROAM', function(mob)
local engageWaitTime = mob:getLocalVar('[helperNpc]engageWaitTime')
local engageWait = mob:getLocalVar('engageWait')
local targetMobs = getMobList(mob)
local shouldEngage = false
if engageWaitTime > 0 and GetSystemTime() > engageWait then
shouldEngage = true
end
if not shouldEngage then
for _, targetMobId in ipairs(targetMobs) do
local targetMob = GetMobByID(targetMobId, mob:getInstance())
if targetMob and targetMob:isSpawned() and targetMob:isEngaged() then
shouldEngage = true
break
end
end
end
if shouldEngage and not mob:getTarget() then
local targetMob = findAvailableTarget(mob)
if targetMob then
mob:addEnmity(targetMob, 0, 1)
mob:updateEnmity(targetMob)
end
end
end)
end
return g_mixins.helper_npc