2024-10-26 11:37:28 +00:00
--[[
Script Name : SpawnScripts / Generic / NPCModule.lua
Script Author : LordPazuzu
Script Date : 2023.11 .20 08 : 11 : 41
2025-08-01 00:00:15 +00:00
Script Purpose : NPC Statistics Control Script
2024-10-26 11:37:28 +00:00
: Consult LordPazuzu before modifying
2025-08-01 00:00:15 +00:00
: Updated 7 / 31 / 2025
2024-10-26 11:37:28 +00:00
--]]
2025-06-27 00:00:08 +00:00
--Add plugin modules as a require below.
require " SpawnScripts/Generic/EquipmentModule " -- NPC equipment appearance presets.
2025-08-01 00:00:15 +00:00
require " SpawnScripts/Generic/NPCRaces " --NPC racial appearance functions.
require " SpawnScripts/Generic/IdleAnimations " -- Idle animation packages for compatible NPC model types.
2024-10-26 11:37:28 +00:00
GlobalDmgMod = 1.0 -- Global Damage Multiplier- make global adjustments to all NPC autoattack damage.
GlobalStatMod = 1.0 -- Global Attribute Multiplier- make global adjustments to NPC attribute scores.
GlobalHPMod = 1.0 -- Global Hit Point Multiplier
GlobalPowerMod = 1.0 -- Global Power Pool Multiplier
function NPCModule ( NPC , Spawn )
level = GetLevel ( NPC ) -- NPC Level
difficulty = GetDifficulty ( NPC ) -- NPC Difficulty
--Included functions. Comment out a function to disable.
2025-05-24 00:00:11 +00:00
SpawnAnimations ( NPC , Spawn ) -- Special spawn animations by model type.
2024-10-26 11:37:28 +00:00
Attributes ( NPC , Spawn ) -- Determines basic stats of the NPC(str, agi, sta, int, wis)
2025-06-27 00:00:08 +00:00
NewAutoAttack ( NPC , Spawn ) -- Determines the NPC's tier for the purposes of autoattack damage.
2024-10-26 11:37:28 +00:00
Regen ( NPC , Spawn ) -- Sets NPC's health and/or power regeneration rates or disables regeneration entirely.
HealthPower ( NPC , Spawn ) -- Calculates NPC's based on level and difficulty.
2025-06-27 00:00:08 +00:00
AddTimer ( NPC , 25 , " Heroic " ) -- Applies heroic flag immediately after spawn in accordance with the way the server loads spawns. Spawnscript functions that check heroic status should be run on a delay longer than 1000. 6000 is the standard delay to run a function after spawn.
2024-10-26 11:37:28 +00:00
AddTimer ( NPC , 1000 , " Heroic " ) -- Redundant heroic check to compensate for server lag when using developer commands to reload spawns.
end
2025-07-26 00:00:06 +00:00
2024-10-26 11:37:28 +00:00
-- Set attributes based on NPC level and difficulty
function Attributes ( NPC , Spawn )
-- Calculate attributes
2025-02-05 20:59:38 +00:00
if level <= 5 then
baseStat = 22
else
baseStat = level + 22
2024-10-26 11:37:28 +00:00
end
2025-02-05 20:59:38 +00:00
if level < 10 then
low = baseStat -- Difficulty 1-3 vvv
four = baseStat -- Difficulty 4 vv
five = baseStat -- Difficulty 5 v
six = baseStat -- Difficulty 6 -
seven = baseStat * 1.25 -- Difficulty 7 ^
eight = baseStat * 1.5 -- Difficulty 8 ^^
nine = baseStat * 2.0 -- Difficulty 9 ^^^
else
low = baseStat -- Difficulty 1-3 vvv
four = baseStat * 1.5 -- Difficulty 4 vv
five = baseStat * 2.0 -- Difficulty 5 v
six = baseStat * 2.5 -- Difficulty 6 -
seven = baseStat * 3.0 -- Difficulty 7 ^
eight = baseStat * 3.5 -- Difficulty 8 ^^
nine = baseStat * 4.0 -- Difficulty 9 ^^^
end
2024-10-26 11:37:28 +00:00
lowStat = math.floor ( low * GlobalStatMod )
fourStat = math.floor ( four * GlobalStatMod )
fiveStat = math.floor ( five * GlobalStatMod )
2025-02-05 20:59:38 +00:00
sixStat = math.floor ( six * GlobalStatMod )
2024-10-26 11:37:28 +00:00
sevenStat = math.floor ( seven * GlobalStatMod )
eightStat = math.floor ( eight * GlobalStatMod )
nineStat = math.floor ( nine * GlobalStatMod )
-- Determine attribute by difficulty
if difficulty <= 3 then
finalStat = lowStat
elseif difficulty == 4 then
finalStat = fourStat
elseif difficulty == 5 then
finalStat = fiveStat
elseif difficulty == 6 then
finalStat = sixStat
elseif difficulty == 7 then
finalStat = sevenStat
elseif difficulty == 8 then
finalStat = eightStat
elseif difficulty == 9 then
finalStat = nineStat
end
SetInfoStructFloat ( NPC , " str " , finalStat )
SetStrBase ( NPC , finalStat )
SetInfoStructFloat ( NPC , " agi " , finalStat )
SetAgiBase ( NPC , finalStat )
SetInfoStructFloat ( NPC , " sta " , finalStat )
SetStaBase ( NPC , finalStat )
SetInfoStructFloat ( NPC , " intel " , finalStat )
SetIntBase ( NPC , finalStat )
SetInfoStructFloat ( NPC , " wis " , finalStat )
SetWisBase ( NPC , finalStat )
AttributeModifiers ( NPC ) -- Determine modifiers based on primary attributes.
end
function AttributeModifiers ( NPC , Spawn )
2025-07-26 00:00:06 +00:00
MeleeDmgMod = math.ceil ( GetStr ( NPC ) / 10 ) -- Determines strength bonus to auttoattack damage.
StaminaHPMod = math.ceil ( GetSta ( NPC ) / 10 ) -- Determins stamina bonus to hitpoints. Not implemented.
2024-10-26 11:37:28 +00:00
end
--Health and power regeneration rates
function Regen ( NPC , Spawn )
--if IsInCombat(NPC) == true then
-- In-combat health regeneration
SetInfoStructUInt ( NPC , " hp_regen_override " , 1 ) -- Set to 0 to disable and allow the server to set the regen rate.
SetInfoStructSInt ( NPC , " hp_regen " , 0 ) -- Set Regen Amount. Default 0
-- In-combat power regeneration
SetInfoStructUInt ( NPC , " pw_regen_override " , 1 ) -- Set to 0 to disable and allow the server to set the regen rate.
SetInfoStructSInt ( NPC , " pw_regen " , 0 ) -- Set Regen Amount. Default 0
end
2025-07-26 00:00:06 +00:00
--Autoattack damage calculation.
function NewAutoAttack ( NPC , Spawn )
if difficulty <= 4 then
difMod = 0.3
elseif difficulty == 5 then
difMod = 0.7
elseif difficulty == 6 then
difMod = 1.0
2024-10-26 11:37:28 +00:00
elseif difficulty == 7 then
2025-07-26 00:00:06 +00:00
difMod = 1.5
elseif difficulty == 8 then
difMod = 2.25
elseif difficulty == 9 then
difMod = 3.5
2024-10-26 11:37:28 +00:00
end
2025-07-26 00:00:06 +00:00
2025-08-01 00:00:15 +00:00
if level <= 34 then
MaxDmgMod = 0.01
elseif level >= 35 then
MaxDmgMod = 0.015
end
2025-07-26 00:00:06 +00:00
minDmg = ( level * 0.6 ) * difMod
2025-08-01 00:00:15 +00:00
maxDmg = ( ( level * 1.6 * MaxDmgMod ) * difMod )
2025-07-26 00:00:06 +00:00
lowDmg = math.floor ( ( minDmg + MeleeDmgMod ) * GlobalDmgMod )
highDmg = math.ceil ( ( maxDmg + MeleeDmgMod ) * GlobalDmgMod )
2024-10-26 11:37:28 +00:00
damage ( NPC )
end
--Autoattack damage override function.
function damage ( NPC , Spawn )
SetInfoStructUInt ( NPC , " override_primary_weapon " , 1 ) --Set to 1 enables override for autoattack damage. Set to 0 to allow server to set damage.
SetInfoStructUInt ( NPC , " primary_weapon_damage_low " , lowDmg )
SetInfoStructUInt ( NPC , " primary_weapon_damage_high " , highDmg )
2025-02-17 20:23:31 +00:00
SetInfoStructUInt ( NPC , " primary_weapon_delay " , 3000 )
2024-10-26 11:37:28 +00:00
end
--Calculate Hitpoints and Power
function HealthPower ( NPC , Spawn )
-- Calculate multipliers based on difficulty tier
if difficulty == 1 then
HPMod = 0.20
PWMod = 0.20
elseif difficulty == 2 then
HPMod = 0.25
PWMod = 0.25
elseif difficulty == 3 then
HPMod = 0.35
PWMod = 0.35
elseif difficulty == 4 then
HPMod = 0.45
PWMod = 0.45
elseif difficulty == 5 then
HPMod = 0.66
PWMod = 0.66
elseif difficulty == 6 then
HPMod = 1.0
PWMod = 1.0
elseif difficulty == 7 then
HPMod = 1.45
PWMod = 1.45
elseif difficulty == 8 then
HPMod = 2.2
PWMod = 2.2
elseif difficulty == 9 then
HPMod = 3.25
PWMod = 3.25
end
--Calculate hitpoints and power based on level and difficuty
if level == 1 then
hp = 30 * HPMod * GlobalHPMod
pw = 25 * PWMod * GlobalPowerMod
elseif level == 2 then
hp = 45 * HPMod * GlobalHPMod
pw = 35 * PWMod * GlobalPowerMod
elseif level == 3 then
hp = 75 * HPMod * GlobalHPMod
pw = 45 * PWMod * GlobalPowerMod
elseif level == 4 then
hp = 110 * HPMod * GlobalHPMod
pw = 55 * PWMod * GlobalPowerMod
elseif level == 5 then
hp = 130 * HPMod * GlobalHPMod
pw = 65 * PWMod * GlobalPowerMod
elseif level == 6 then
hp = 150 * HPMod * GlobalHPMod
pw = 80 * PWMod * GlobalPowerMod
elseif level == 7 then
hp = 200 * HPMod * GlobalHPMod
pw = 90 * PWMod * GlobalPowerMod
elseif level == 8 then
hp = 240 * HPMod * GlobalHPMod
pw = 100 * PWMod * GlobalPowerMod
elseif level == 9 then
hp = 275 * HPMod * GlobalHPMod
pw = 110 * PWMod * GlobalPowerMod
elseif level == 10 then
hp = 370 * HPMod * GlobalHPMod
pw = 130 * PWMod * GlobalPowerMod
elseif level == 11 then
hp = 430 * HPMod * GlobalHPMod
pw = 160 * PWMod * GlobalPowerMod
elseif level == 12 then
hp = 550 * HPMod * GlobalHPMod
pw = 185 * PWMod * GlobalPowerMod
elseif level == 13 then
hp = 680 * HPMod * GlobalHPMod
pw = 205 * PWMod * GlobalPowerMod
elseif level == 14 then
hp = 795 * HPMod * GlobalHPMod
pw = 240 * PWMod * GlobalPowerMod
elseif level == 15 then
hp = 920 * HPMod * GlobalHPMod
pw = 270 * PWMod * GlobalPowerMod
elseif level == 16 then
hp = 1045 * HPMod * GlobalHPMod
pw = 310 * PWMod * GlobalPowerMod
elseif level == 17 then
hp = 1180 * HPMod * GlobalHPMod
pw = 360 * PWMod * GlobalPowerMod
elseif level == 18 then
hp = 1290 * HPMod * GlobalHPMod
pw = 410 * PWMod * GlobalPowerMod
elseif level == 19 then
hp = 1440 * HPMod * GlobalHPMod
pw = 425 * PWMod * GlobalPowerMod
elseif level == 20 then
hp = 1930 * HPMod * GlobalHPMod
pw = 475 * PWMod * GlobalPowerMod
elseif level == 21 then
hp = 2120 * HPMod * GlobalHPMod
pw = 500 * PWMod * GlobalPowerMod
elseif level == 22 then
hp = 2355 * HPMod * GlobalHPMod
pw = 545 * PWMod * GlobalPowerMod
elseif level == 23 then
hp = 2595 * HPMod * GlobalHPMod
pw = 575 * PWMod * GlobalPowerMod
elseif level == 24 then
hp = 2840 * HPMod * GlobalHPMod
pw = 620 * PWMod * GlobalPowerMod
elseif level == 25 then
hp = 3080 * HPMod * GlobalHPMod
pw = 670 * PWMod * GlobalPowerMod
elseif level == 26 then
hp = 3340 * HPMod * GlobalHPMod
pw = 700 * PWMod * GlobalPowerMod
elseif level == 27 then
hp = 3600 * HPMod * GlobalHPMod
pw = 755 * PWMod * GlobalPowerMod
elseif level == 28 then
hp = 3820 * HPMod * GlobalHPMod
pw = 795 * PWMod * GlobalPowerMod
elseif level == 29 then
hp = 4240 * HPMod * GlobalHPMod
pw = 835 * PWMod * GlobalPowerMod
elseif level == 30 then
hp = 4380 * HPMod * GlobalHPMod
pw = 895 * PWMod * GlobalPowerMod
elseif level == 31 then
hp = 4570 * HPMod * GlobalHPMod
pw = 935 * PWMod * GlobalPowerMod
elseif level == 32 then
hp = 4825 * HPMod * GlobalHPMod
pw = 985 * PWMod * GlobalPowerMod
elseif level == 33 then
hp = 5030 * HPMod * GlobalHPMod
pw = 1040 * PWMod * GlobalPowerMod
elseif level == 34 then
hp = 5240 * HPMod * GlobalHPMod
pw = 1070 * PWMod * GlobalPowerMod
elseif level == 35 then
hp = 5455 * HPMod * GlobalHPMod
pw = 1165 * PWMod * GlobalPowerMod
elseif level == 36 then
hp = 5735 * HPMod * GlobalHPMod
pw = 1290 * PWMod * GlobalPowerMod
elseif level == 37 then
hp = 5875 * HPMod * GlobalHPMod
pw = 1255 * PWMod * GlobalPowerMod
elseif level == 38 then
hp = 6095 * HPMod * GlobalHPMod
pw = 1335 * PWMod * GlobalPowerMod
elseif level == 39 then
hp = 6320 * HPMod * GlobalHPMod
pw = 1375 * PWMod * GlobalPowerMod
elseif level == 40 then
hp = 6550 * HPMod * GlobalHPMod
pw = 1475 * PWMod * GlobalPowerMod
elseif level == 41 then
hp = 6805 * HPMod * GlobalHPMod
pw = 1595 * PWMod * GlobalPowerMod
elseif level == 42 then
hp = 7260 * HPMod * GlobalHPMod
pw = 1640 * PWMod * GlobalPowerMod
elseif level == 43 then
hp = 7295 * HPMod * GlobalHPMod
pw = 1675 * PWMod * GlobalPowerMod
elseif level == 44 then
hp = 7835 * HPMod * GlobalHPMod
pw = 1750 * PWMod * GlobalPowerMod
elseif level == 45 then
hp = 7920 * HPMod * GlobalHPMod
pw = 1810 * PWMod * GlobalPowerMod
elseif level == 46 then
hp = 8125 * HPMod * GlobalHPMod
pw = 1875 * PWMod * GlobalPowerMod
elseif level == 47 then
hp = 8490 * HPMod * GlobalHPMod
pw = 2040 * PWMod * GlobalPowerMod
elseif level == 48 then
hp = 8785 * HPMod * GlobalHPMod
pw = 2110 * PWMod * GlobalPowerMod
elseif level == 49 then
hp = 9020 * HPMod * GlobalHPMod
pw = 2195 * PWMod * GlobalPowerMod
elseif level == 50 then
hp = 9325 * HPMod * GlobalHPMod
pw = 2675 * PWMod * GlobalPowerMod
elseif level > 50 then
hp = 9625 * HPMod * GlobalHPMod
pw = 2840 * PWMod * GlobalPowerMod
end
ModifyMaxHP ( NPC , math.floor ( hp ) )
ModifyHP ( NPC , math.floor ( hp ) )
ModifyMaxPower ( NPC , math.floor ( pw ) )
ModifyPower ( NPC , math.floor ( hp ) )
end
--Automatically set heroic flags based on specified criteria
function Heroic ( NPC , Spawn )
local group = GetGroup ( NPC )
if group ~= nil then
local groupsize = # group
if groupsize > 1 then
SpawnSet ( NPC , " heroic " , 1 )
end
end
if difficulty == 8 or difficulty == 9 then
SpawnSet ( NPC , " heroic " , 1 )
end
end
-- PATHING SCRIPTS --
--[[ Randomized Movement Loops
Call the RandomMovement ( ) function in the NPC ' s spawn function.
Example format : RandomMovement ( NPC , Spawn , - 5 , 5 , 2 , 8 , 15 )
This exampled sets the NPC to randomly move anywhere in a 5 meter radius
from it ' s spawn point at a speed of 2, moving every 8-15 seconds.
--]]
function RandomMovement ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
local X = GetX ( NPC )
local Y = GetY ( NPC )
local Z = GetZ ( NPC )
MovementLoopAddLocation ( NPC , X , Y , Z , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementMod ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
MovementLoopAddLocation ( NPC , X + LocModX , Y , Z + LocModZ , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementMod ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
MovementLoopAddLocation ( NPC , X + LocModX , Y , Z + LocModZ , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementMod ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
MovementLoopAddLocation ( NPC , X + LocModX , Y , Z + LocModZ , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementMod ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
MovementLoopAddLocation ( NPC , X + LocModX , Y , Z + LocModZ , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementMod ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
MovementLoopAddLocation ( NPC , X + LocModX , Y , Z + LocModZ , Speed , MakeRandomInt ( MinDly , MaxDly ) )
end
function RandomMovementFlight ( NPC , Spawn , NegDist , PosDist , NegHeight , PosHeight , Speed , MinDly , MaxDly )
local X = GetX ( NPC )
local Y = GetY ( NPC )
local Z = GetZ ( NPC )
MovementLoopAddLocation ( NPC , X , Y , Z , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementLoopAddLocation ( NPC , X + MakeRandomInt ( NegDist , PosDist ) , Y + MakeRandomInt ( NegHeight , PosHeight ) , Z + MakeRandomInt ( NegDist , PosDist ) , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementLoopAddLocation ( NPC , X + MakeRandomInt ( NegDist , PosDist ) , Y + MakeRandomInt ( NegHeight , PosHeight ) , Z + MakeRandomInt ( NegDist , PosDist ) , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementLoopAddLocation ( NPC , X + MakeRandomInt ( NegDist , PosDist ) , Y + MakeRandomInt ( NegHeight , PosHeight ) , Z + MakeRandomInt ( NegDist , PosDist ) , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementLoopAddLocation ( NPC , X + MakeRandomInt ( NegDist , PosDist ) , Y + MakeRandomInt ( NegHeight , PosHeight ) , Z + MakeRandomInt ( NegDist , PosDist ) , Speed , MakeRandomInt ( MinDly , MaxDly ) )
MovementLoopAddLocation ( NPC , X + MakeRandomInt ( NegDist , PosDist ) , Y + MakeRandomInt ( NegHeight , PosHeight ) , Z + MakeRandomInt ( NegDist , PosDist ) , Speed , MakeRandomInt ( MinDly , MaxDly ) )
end
function MovementMod ( NPC , Spawn , NegDist , PosDist , Speed , MinDly , MaxDly )
MinNegDist = math.ceil ( NegDist / 2 )
MinPosDist = math.ceil ( PosDist / 2 )
MinX = MakeRandomInt ( 1 , 2 )
MinZ = MakeRandomInt ( 1 , 2 )
if MinX == 1 then
LocModX = MakeRandomInt ( MinNegDist , NegDist )
elseif MinX == 2 then
LocModX = MakeRandomInt ( MinPostDist , PosDist )
end
if MinZ == 1 then
LocModZ = MakeRandomInt ( MinNegDist , NegDist )
elseif MinZ == 2 then
LocModZ = MakeRandomInt ( MinPostDist , PosDist )
end
end
-- Automatically calculate hit points, power, and regeneration for named NPCs
function Named ( NPC , Spawn )
level = GetLevel ( NPC )
difficulty = GetDifficulty ( NPC )
NamedMod = 1.5
AttributeMod = NamedMod * 2
2025-09-01 19:53:26 +00:00
SpawnAnimations ( NPC , Spawn )
2024-10-26 11:37:28 +00:00
HealthPower ( NPC )
Attributes ( NPC , Spawn )
ModifyMaxHP ( NPC , math.floor ( hp * NamedMod ) )
ModifyHP ( NPC , math.floor ( hp * NamedMod ) )
ModifyMaxPower ( NPC , math.floor ( pw * NamedMod ) )
ModifyPower ( NPC , math.floor ( hp * NamedMod ) )
SetInfoStructUInt ( NPC , " hp_regen_override " , 1 )
SetInfoStructSInt ( NPC , " hp_regen " , ( level * 2 ) + ( difficulty * 2 ) )
SetInfoStructUInt ( NPC , " pw_regen_override " , 1 )
2024-10-27 17:31:14 +00:00
SetInfoStructSInt ( NPC , " pw_regen " , ( level * 2 ) + ( difficulty * 2 ) )
2024-10-26 11:37:28 +00:00
2024-10-27 17:31:14 +00:00
--Disabled until named autoattack damage can be integrated into the Named() function.
--[[SetInfoStructFloat(NPC, "str", finalStat * AttributeMod)
2024-10-26 11:37:28 +00:00
SetStrBase ( NPC , finalStat * AttributeMod )
SetInfoStructFloat ( NPC , " agi " , finalStat * AttributeMod )
SetAgiBase ( NPC , finalStat * AttributeMod )
SetInfoStructFloat ( NPC , " sta " , finalStat * AttributeMod )
SetStaBase ( NPC , finalStat * AttributeMod )
SetInfoStructFloat ( NPC , " intel " , finalStat * AttributeMod )
SetIntBase ( NPC , finalStat * AttributeMod )
SetInfoStructFloat ( NPC , " wis " , finalStat * AttributeMod )
2024-10-27 17:31:14 +00:00
SetWisBase ( NPC , finalStat * AttributeMod ) --]]
2024-10-26 11:37:28 +00:00
end
2024-10-27 17:31:14 +00:00
2025-08-01 00:00:15 +00:00
--Spawn Animations for specific NPC model types.
2025-05-24 00:00:11 +00:00
function SpawnAnimations ( NPC , Spawn )
if GetModelType ( NPC ) == 138 then
SetSpawnAnimation ( NPC , 13016 )
end
if GetModelType ( NPC ) == 1521 then
SetSpawnAnimation ( NPC , 13016 )
end
if GetModelType ( NPC ) == 140 then
SetSpawnAnimation ( NPC , 13016 )
end
if GetModelType ( NPC ) == 1584 then
SetSpawnAnimation ( NPC , 13016 )
end
if GetModelType ( NPC ) == 2411 then
SetSpawnAnimation ( NPC , 13016 )
end
if GetModelType ( NPC ) == 2412 then
SetSpawnAnimation ( NPC , 13016 )
end
if GetModelType ( NPC ) == 2413 then
SetSpawnAnimation ( NPC , 13016 )
end
2025-07-26 00:00:06 +00:00
end