Lua AI Common Function Repository
-- AI function repository by king bore haha / george
-- Made for DS1, but knowledge is very compatible with other games.
-- OnIf. Allows mid-action logic
-- Example: "combo 1, OnIf" allows you to recheck the target's distance and angle and decide the combo followup attack afterwards.
function OnIf_######(ai, goal, codeNo) -- Change ###### to the number ID defined in goal_list.lua (example: for Gwyn, it would be 537000)
-- GOAL_COMMON_If codeNo can be checked here for different behavior.
if codeNo == 10 then --
-- Action go here
elseif codeNo == 20 then
-- Action go here
end
return
end
goal:AddSubGoal(GOAL_COMMON_If, 10, codeNo) -- codeNo checked in onIf function to allow different behavior
-- OnIf v2.0, devised by Meowmaritus
ENABLE_COMBO_ATK_CANCEL(GOAL_COMMON_If) -- Allows GOAL_COMMON_If to utilize Combo recovery events. (Personally, I put this in "if.lua".)
function OnIf_######(ai, goal, codeNo) -- Change ###### to the number ID defined in goal_list.lua (example: for Gwyn, it would be 537000)
-- GOAL_COMMON_If codeNo can be checked here for different behavior.
if codeNo == 3000 then --
-- Action go here
elseif codeNo == 3010 then
-- Action go here
end
-- goal:AddSubGoal(GOAL_COMMON_ComboFinal, 0, 0, TARGET_ENE_0, 0, 0) -- forcibly end combo (no matter what)
return
end
goal:AddSubGoal(GOAL_COMMON_If, 10, codeNo) -- codeNo checked in onIf function to allow different behavior
--
goal:AddSubGoal -- Add an AI goal. first in, first out
goal:AddtopGoal -- Add an AI goal. PROBABLY added to the top of priority list
goal:ClearSubGoal() -- Clear all queued goals
ai:GetRandam_Int(ValueMin, ValueMax) -- generate integer between values
ai:GetRandam_Float(ValueMin, ValueMax) -- generate float between values
-- Event request. Gets value from EMEVD command RequestCharacterAICommand(EntityID, SendValue, SlotNumber)
-- Extremely useful reviving information from EMEVD
-- Also works with EMEVD command RequestCharacterAICommandAndEventValue, but don't use that because it sucks and is broken (it requires reset AI for it to work)
local EventSlot = 0
ai:GetEventRequest(EventSlot) -- return value of event slot (0 by default)
-- Timers. Used to keep track of time
local TimerSlot = 0 -- which timer to use. Values start at 0, end at 3 (4 total)
local TimerAmount = 60 -- time in seconds to set timer
ai:IsFinishTimer(TimerSlot) -- returns true/false
ai:GetTimer(TimerSlot) -- returns number of seconds left on timer
ai:SetTimer(TimerSlot, TimerAmount) -- sets timer
-- Store a value that can be checked later
local NumberSlot = 0 -- Which slot to store value in. Values start at 0, end AT LEAST at 6
local Value = 420 -- Value to use
ai:SetNumber(NumberSlot, Value) -- set value
ai:GetNumber(NumberSlot) -- check value
-- HasSpecialEffectId
-- Check if target has a special effect
local SpecialEffectID = 5470 -- ID of special effect to check
ai:HasSpecialEffectId(TargetType, SpecialEffectID) -- true if target/self has special effect
ai:HasSpecialEffectId(TARGET_SELF, 5470) -- true if target/self has special effect
-- GetNpcThinkParamID
-- Returns NpcThinkParam ID being used. Extremely useful for variant behavior.
local myThinkID = ai:GetNpcThinkParamID()
-- Target Types (TargetType)
-- Any instance of a targetType in list list can be replaced with any other type. (Example: replacing an attack's TARGET_ENE_0 with TARGET_FRI_0 will make them aim at an ally)
-- (In example commands, I used in default target types that are USUALLY what you want)
TARGET_NONE
TARGET_SELF -- self
TARGET_ENE_0 -- enemy
TARGET_FRI_0 -- ally
TARGET_EVENT -- unused
TARGET_LOCALPLAYER -- the player (host)
TARGET_LowHp_Friend -- unused
POINT_EVENT -- location of a specific map region. Set with SetEventMoveTarget
--
ai:SetEventMoveTarget(RegionEntityID) -- set POINT_EVENT (targetType) location to a map region
-- Example: move to map region
ai:SetEventMoveTarget(RegionEntityID)
goal:AddSubGoal(GOAL_COMMON_ApproachTarget, 20, POINT_EVENT, 1, TARGET_SELF, false, -1)
--
-- GetHpRate
-- Check HP ratio of a target. Values are 0 to 1 (1 = 100% HP, 0 = 0% HP)
ai:GetHpRate(TargetType)
local HpRate = ai:GetHpRate(TARGET_SELF)
-- GetDist
-- Check target's distance in comparison to self's origin position (in meters)
-- Distance is offset by self's npcParam hitRadius
-- If target is within hitRadius, distance will be negative. Distance will continue to decrease as target approaches origin
-- -- Lowest possible value is when target is at self origin, which would have a distance of negative hitRadius
-- If target is outside of hitRadius, distance will be positive. Distance will continue to increase as target leaves origin
-- -- If target is exactly hitRadius's distance away, distance will be exactly 0
ai:GetDist(TargetType);
local targetDist = ai:GetDist(TARGET_ENE_0);
-- GetDistY / GetDistYSigned
-- Check target's elevation in comparison to self (in meters)
ai:GetDistY(TARGET_ENE_0) -- Returns absolute elevation difference (positive value only).
ai:GetDistYSigned(TARGET_ENE_0) -- Returns elevation difference (+ or -). negative values = target is lower, positive values = target is higher
-- IsInsideTargetRegion
-- Check if target is inside of a map region
ai:IsInsideTargetRegion(TargetType, MapRegionEntityID) -- Check if target is inside of a map region
-- Direction Types (DirectionType)
AI_DIR_TYPE_F -- Front
AI_DIR_TYPE_B -- Back
AI_DIR_TYPE_L -- Left
AI_DIR_TYPE_R -- Right
AI_DIR_TYPE_CENTER -- Center (? Used with certain commands.)
AI_DIR_TYPE_Top -- Above
AI_DIR_TYPE_ToF -- Above Front?
AI_DIR_TYPE_ToB -- Above Back?
AI_DIR_TYPE_ToL -- Above Left?
AI_DIR_TYPE_ToR -- Above right?
-- Distance Types (DistType)
-- Values refer to npcthinkParam fields. Can be substituted with variable values (in "meters")
DIST_Near
DIST_Middle
DIST_Far
DIST_Out
DIST_None
-- IsInsideTarget
-- Check if a target is within an direction and angle
local DirectionType = AI_DIR_TYPE_F -- direction to check for target
local Angle = 50 -- Angle to check that target is within
ai:IsInsideTarget(TARGET_ENE_0, DirectionType, Angle)
ai:IsInsideTarget(TARGET_ENE_0, AI_DIR_TYPE_F, 50)
-- GOAL_COMMON_ApproachTarget
-- Approach a target until within a certain distance
local CancelTime = 4 -- time in seconds before goal is canceled
local Dist = 3 -- Minimum distance to target for goal completion
local GuardID = -1 -- Determines guarding (NOT AN ANIMATION ID) -1 = do not guard. -- non-c0000: 9910 = guard,, 9920 = special guarding (uses different IDs). -- c0000: 4 = guard
local WalkBool = false -- Which movement animations to use. false = dash, true = walk
goal:AddSubGoal(GOAL_COMMON_ApproachTarget, CancelTime, TARGET_ENE_0, Dist, TARGET_SELF, WalkBool, GuardID)
goal:AddSubGoal(GOAL_COMMON_ApproachTarget, 4, TARGET_ENE_0, 3, TARGET_SELF, false, -1) -- Approach enemy
goal:AddSubGoal(GOAL_COMMON_ApproachTarget, 10, POINT_INITIAL, 2, TARGET_SELF, false, -1) -- Return to home. Usually followed by Wait
-- Note: Attack goals have additional parameters for up angle/down angle anim offsets, which is used for a small amount of enemies.
-- GOAL_COMMON_ComboAttackTunableSpin / GOAL_COMMON_ComboRepeat / GOAL_COMMON_ComboFinal
-- Combo attacks while turning. Works by using TAE combo recovery events during animations, making them end earlier
local CancelTime = 5 -- Time in seconds before goal is canceled
local AnimationID = 700 -- Animation ID to use
local SpinTime = 1 -- Time in seconds to turn and face target before making action. See SpinAngle
local SpinAngle = 90 -- Angle to face target before making action. see SpinTime
local Dist = DIST_Middle -- Maximum distance before ending combo early. Can use DistType or an actual value.
goal:AddSubGoal(GOAL_COMMON_ComboAttackTunableSpin, CancelTime, AnimationID, TARGET_ENE_0, Dist, SpinTime, SpinAngle) -- always add first
goal:AddSubGoal(GOAL_COMMON_ComboRepeat, CancelTime, AnimationID, TARGET_ENE_0, Dist, 0, -1) -- add between GOAL_COMMON_ComboAttackTunableSpin and GOAL_COMMON_ComboFinal as many times as needed
goal:AddSubGoal(GOAL_COMMON_ComboFinal, CancelTime, AnimationID, TARGET_ENE_0, Dist, 0, -1) -- always add last
--
goal:AddSubGoal(GOAL_COMMON_ComboAttackTunableSpin, 5, 3000, TARGET_ENE_0, DIST_Middle, 1, 90) -- always add first
goal:AddSubGoal(GOAL_COMMON_ComboRepeat, 5, 3001, TARGET_ENE_0, DIST_Middle, 0, -1) -- add between GOAL_COMMON_ComboAttackTunableSpin and GOAL_COMMON_ComboFinal as many times as needed
goal:AddSubGoal(GOAL_COMMON_ComboFinal, 5, 3002, TARGET_ENE_0, DIST_Middle, 0, -1) -- always add
--
goal:AddSubGoal(GOAL_COMMON_ComboAttackTunableSpin, 5, 3000, TARGET_ENE_0, DIST_Middle, 1, 90) -- always add first
goal:AddSubGoal(GOAL_COMMON_ComboFinal, 5, 3002, TARGET_ENE_0, DIST_Middle, 0, -1) -- always add last
--
goal:AddSubGoal(GOAL_COMMON_ComboAttackTunableSpin, 5, 3000, TARGET_ENE_0, DIST_Middle, 1, 90) -- always add first
goal:AddSubGoal(GOAL_COMMON_ComboRepeat, 5, 3001, TARGET_ENE_0, DIST_Middle, 0, -1) -- add between GOAL_COMMON_ComboAttackTunableSpin and GOAL_COMMON_ComboFinal as many times as needed
goal:AddSubGoal(GOAL_COMMON_ComboRepeat, 5, 3002, TARGET_ENE_0, DIST_Middle, 0, -1) -- add between GOAL_COMMON_ComboAttackTunableSpin and GOAL_COMMON_ComboFinal as many times as needed
goal:AddSubGoal(GOAL_COMMON_ComboFinal, 5, 3001, TARGET_ENE_0, DIST_Middle, 0, -1) -- always add last
--
-- GOAL_COMMON_AttackTunableSpin
-- Attack while turning. Uses (slower) TAE attack recovery, rather than combo attack recovery.
local CancelTime = 5 -- Time in seconds before goal is canceled
local AnimationID = 700 -- Animation ID to use
local SpinTime = 1 -- Time in seconds to turn and face target before making action. See SpinAngle
local SpinAngle = 90 -- Angle to face target before making action. see SpinTime
local Dist = DIST_Middle -- Maximum distance before ending combo early. Can use DistType or an actual value.
goal:AddSubGoal(GOAL_COMMON_AttackTunableSpin, CancelTime, AnimationID, TARGET_ENE_0, Dist, SpinTime, SpinAngle)
-- GOAL_COMMON_NonspinningAttack
-- Attack, but don't require/allow turning
goal:AddSubGoal(GOAL_COMMON_NonspinningAttack, CancelTime, AnimationID, TARGET_ENE_0, DIST_None)
goal:AddSubGoal(GOAL_COMMON_NonspinningAttack, 5, 3000, TARGET_ENE_0, DIST_None)
-- GOAL_COMMON_SpinStep
-- Used for dodging. Useful for preventing jumping off of cliffs
local CancelTime = 5 -- Time in seconds before goal is canceled
local AnimationID = 700 -- Animation ID to use
local SpinTime = 0 -- time in seconds to turn and face target before making action (Untested, may not actually work)
local DirectionType = AI_DIR_TYPE_B -- direction to check if map collision exists
local SafeDist = 3 -- distance to check if map collision exists. Cancels if it does not.
goal:AddSubGoal(GOAL_COMMON_SpinStep, CancelTime, AnimationID, TARGET_ENE_0, SpinTime, DirectionType, SafeDist)
goal:AddSubGoal(GOAL_COMMON_SpinStep, 4, 700, TARGET_ENE_0, 0, AI_DIR_TYPE_B, 3)
-- GOAL_COMMON_MoveToSomewhere
-- Move to a position. Can offset move target coordinates by angle + distance
-- Offset coordinates example these would make the move target 10 units above the target
-- OffsetDirectionType = AI_DIR_TYPE_TOP
-- OffsetDistance = 10
local CancelTime = 20 -- time in seconds before goal is canceled
local Dist = 1.5 -- Minimum distance to target for goal completion
local WalkBool = false -- Which movement animations to use. false = dash, true = walk
local OffsetDirectionType = AI_DIR_TYPE_CENTER -- direction to use for target offset. Use AI_DIR_TYPE_CENTER for no offset.
local OffsetDistance = 0 -- distance to use for target offset
goal:AddSubGoal(GOAL_COMMON_MoveToSomewhere, CancelTime, TARGET_ENE_0, OffsetDirectionType, Dist, TARGET_SELF, WalkBool, OffsetDistance)
goal:AddSubGoal(GOAL_COMMON_MoveToSomewhere, 20, TARGET_ENE_0, AI_DIR_TYPE_CENTER, 1.5, TARGET_SELF, false, 0)
-- AddObserveArea
-- Constantly check if a target is within defined angle & distance
-- To be used with INTERUPT_Inside_ObserveArea
local ObserveNo = 0 -- index. Vanilla uses 0-7
local DirectionType = AI_DIR_TYPE_B -- direction to check if map collision exists
local Angle = 60 -- angle to check if target is within
local Dist = 2 -- distance to check if target is within
ai:AddObserveArea(ObserveNo, TARGET_ENE_0, TARGET_SELF, DirectionType, Angle, Dist)
ai:AddObserveArea(0, TARGET_ENE_0, TARGET_SELF, AI_DIR_TYPE_B, 60, 2) -- check if target is behind and close
ai:IsInterupt(INTERUPT_Inside_ObserveArea) -- Triggers upon ANY AddObserveArea passing
-- IsOnNearMeshByPos
-- Check if map collision exists in target's direction + distance
-- Useful for not jumping off the map during some actions.
local Dist = 2 -- distance to check
ai:IsOnNearMeshByPos(TargetType, DirectionType, Dist)
ai:IsOnNearMeshByPos(TARGET_SELF, AI_DIR_TYPE_B, 2)
-- GOAL_COMMON_LeaveTarget
-- Move away from target
local CancelTime = 5 -- Time in seconds before goal is canceled
local Dist = ai:GetRandam_Float(1.5, 2) -- Minimum distance to target for goal completion
local GuardID = -1 -- Determines guarding (NOT AN ANIMATION ID) -1 = do not guard. -- non-c0000: 9910 = guard,, 9920 = special guarding (uses different IDs). -- c0000: 4 = guard
local WalkBool = true -- Which movement animations to use. false = dash, true = walk
goal:AddSubGoal(GOAL_COMMON_LeaveTarget, CancelTime, TARGET_ENE_0, Dist, TARGET_ENE_0, WalkBool, GuardID)
goal:AddSubGoal(GOAL_COMMON_LeaveTarget, 5, TARGET_ENE_0, ai:GetRandam_Float(1.5, 2), TARGET_ENE_0, true, -1)
local Duration -- how long to leave target for OR cancel time? probably latter
local LeaveDist -- minimum Distance to reach before goal completion?
local WalkBool = false
local GuardID = -1 -- Determines guarding (NOT AN ANIMATION ID) -1 = do not guard. -- non-c0000: 9910 = guard,, 9920 = special guarding (uses different IDs). -- c0000: 4 = guard
local LeftOrRight -- right = 1, left = 0
local UnkTrue = true -- unknown. always true
goal:AddSubGoal(GOAL_COMMON_SidewayMove, Duration, TARGET_ENE_0, LeftOrRight, Angle, WalkBool, UnkTrue, GuardID)
goal:AddSubGoal(GOAL_COMMON_SidewayMove, ai:GetRandam_Float(1.5, 3), TARGET_ENE_0, ai:GetRandam_Int(0, 1), ai:GetRandam_Int(30, 45), true, true, -1)
goal:AddSubGoal(GOAL_COMMON_Wait, ai:GetRandam_Float(1.5, 2.5), TARGET_NONE, 0, 0, 0)
goal:AddSubGoal(GOAL_COMMON_Turn, 3.0, TARGET_ENE_0, TurnAngle)
-- Approach_and_Attack_Act
-- Simplified function. uses GOAL_COMMON_ApproachTarget and GOAL_COMMON_AttackTunableSpin
-- Checks distance to decide dash vs walk
-- Adds random chance of guarding.
local AppDist = 4 -- Minimum distance to target for goal completion
local DashDist = 10 -- Minimum distance to target to start dashing instead of walking
local Odds_Guard = 0 -- % chance (0 - 100) to guard while approaching. Uses GuardID 9910
local AnimationID = 3000 -- Animation ID to use
local AttDist
local TurnTime
local TurnFaceAngle
Approach_and_Attack_Act(ai, goal, AppDist, DashDist, Odds_Guard, AttID, AttDist, TurnTime, TurnFaceAngle)
Approach_Act(ai, goal, AppDist, DashDist, Odds_Guard, life)
Approach_or_Leave_Act(ai, goal, LeaveDist, AppDist, DashDist, Odds_Guard)
Backstab_Act(ai, goal, ObserveNo, ApproachDist, TimerIndex, Time)
-- NPC_Approach_Act
-- Simplified function for c0000 approaches
local AppDist = 4 -- Minimum distance to target for goal completion
local DashDist = 10 -- Minimum distance to target to start dashing instead of walking
local Odds_Guard = 0 -- % chance (0 - 100) to guard while approaching. Uses GuardID 9910
NPC_Approach_Act(ai, goal, AppDist, DashDist, Odds_Guard)
NPC_Approach_Act(ai, goal, 4, 10, 0)
ai:StartDash() -- for c0000 NPCs. Use before an approach act to make them dash (used in NPC_Approach_Act)
ai:EndDash()
-- ChkNearLowHpFriend
-- Check HP of all allies within defined distance
local HpRatio = .8
local Dist = 20
ai:ChkNearLowHpFriend(HpRatio, Dist)
-- Get and check current role in AI queue, determined by number of allies and team attack effective counter (npcThinkParam)
local role = ai:GetTeamOrder(ORDER_TYPE_Role) -- Get TeamAttackEffectivity role
if role == ROLE_TYPE_Attack then -- true if self in AI queue <= 100
elseif role == ROLE_TYPE_Torimaki then -- true if self in AI queue > 100 and <= 200
elseif role == ROLE_TYPE_Kankyaku then -- true if self in AI queue > 200
end
goal:AddSubGoal(GOAL_COMMON_AttackTunableSpin, CancelTime, AnimationID, TARGET_ENE_0, Dist, SpinTime, SpinAngle)
-- GOAL_COMMON_NonspinningAttack
-- Attack, but don't require/allow turning
goal:AddSubGoal(GOAL_COMMON_NonspinningAttack, CancelTime, AnimationID, TARGET_ENE_0, DIST_None)
goal:AddSubGoal(GOAL_COMMON_NonspinningAttack, 5, 3000, TARGET_ENE_0, DIST_None)
-- GOAL_COMMON_SpinStep
-- Used for dodging. Useful for preventing jumping off of cliffs
local CancelTime = 5 -- Time in seconds before goal is canceled
local AnimationID = 700 -- Animation ID to use
local SpinTime = 0 -- time in seconds to turn and face target before making action (Untested, may not actually work)
local DirectionType = AI_DIR_TYPE_B -- direction to check if map collision exists
local SafeDist = 3 -- distance to check if map collision exists. Cancels if it does not.
goal:AddSubGoal(GOAL_COMMON_SpinStep, CancelTime, AnimationID, TARGET_ENE_0, SpinTime, DirectionType, SafeDist)
goal:AddSubGoal(GOAL_COMMON_SpinStep, 4, 700, TARGET_ENE_0, 0, AI_DIR_TYPE_B, 3)
-- GOAL_COMMON_MoveToSomewhere
-- Move to a position. Can offset move target coordinates by angle + distance
-- Offset coordinates example these would make the move target 10 units above the target
-- OffsetDirectionType = AI_DIR_TYPE_TOP
-- OffsetDistance = 10
local CancelTime = 20 -- time in seconds before goal is canceled
local Dist = 1.5 -- Minimum distance to target for goal completion
local WalkBool = false -- Which movement animations to use. false = dash, true = walk
local OffsetDirectionType = AI_DIR_TYPE_CENTER -- direction to use for target offset. Use AI_DIR_TYPE_CENTER for no offset.
local OffsetDistance = 0 -- distance to use for target offset
goal:AddSubGoal(GOAL_COMMON_MoveToSomewhere, CancelTime, TARGET_ENE_0, OffsetDirectionType, Dist, TARGET_SELF, WalkBool, OffsetDistance)
goal:AddSubGoal(GOAL_COMMON_MoveToSomewhere, 20, TARGET_ENE_0, AI_DIR_TYPE_CENTER, 1.5, TARGET_SELF, false, 0)
-- AddObserveArea
-- Constantly check if a target is within defined angle & distance
-- To be used with INTERUPT_Inside_ObserveArea
local ObserveNo = 0 -- index. Vanilla uses 0-7
local DirectionType = AI_DIR_TYPE_B -- direction to check if map collision exists
local Angle = 60 -- angle to check if target is within
local Dist = 2 -- distance to check if target is within
ai:AddObserveArea(ObserveNo, TARGET_ENE_0, TARGET_SELF, DirectionType, Angle, Dist)
ai:AddObserveArea(0, TARGET_ENE_0, TARGET_SELF, AI_DIR_TYPE_B, 60, 2) -- check if target is behind and close
ai:IsInterupt(INTERUPT_Inside_ObserveArea) -- Triggers upon ANY AddObserveArea passing
-- IsOnNearMeshByPos
-- Check if map collision exists in target's direction + distance
-- Useful for not jumping off the map during some actions.
local Dist = 2 -- distance to check
ai:IsOnNearMeshByPos(TargetType, DirectionType, Dist)
ai:IsOnNearMeshByPos(TARGET_SELF, AI_DIR_TYPE_B, 2)
-- GOAL_COMMON_LeaveTarget
-- Move away from target
local CancelTime = 5 -- Time in seconds before goal is canceled
local Dist = ai:GetRandam_Float(1.5, 2) -- Minimum distance to target for goal completion
local GuardID = -1 -- Determines guarding (NOT AN ANIMATION ID) -1 = do not guard. -- non-c0000: 9910 = guard,, 9920 = special guarding (uses different IDs). -- c0000: 4 = guard
local WalkBool = true -- Which movement animations to use. false = dash, true = walk
goal:AddSubGoal(GOAL_COMMON_LeaveTarget, CancelTime, TARGET_ENE_0, Dist, TARGET_ENE_0, WalkBool, GuardID)
goal:AddSubGoal(GOAL_COMMON_LeaveTarget, 5, TARGET_ENE_0, ai:GetRandam_Float(1.5, 2), TARGET_ENE_0, true, -1)
local Duration -- how long to leave target for OR cancel time? probably latter
local LeaveDist -- minimum Distance to reach before goal completion?
local WalkBool = false
local GuardID = -1 -- Determines guarding (NOT AN ANIMATION ID) -1 = do not guard. -- non-c0000: 9910 = guard,, 9920 = special guarding (uses different IDs). -- c0000: 4 = guard
local LeftOrRight -- right = 1, left = 0
local UnkTrue = true -- unknown. always true
goal:AddSubGoal(GOAL_COMMON_SidewayMove, Duration, TARGET_ENE_0, LeftOrRight, Angle, WalkBool, UnkTrue, GuardID)
goal:AddSubGoal(GOAL_COMMON_Wait, ai:GetRandam_Float(1.5, 2.5), TARGET_NONE, 0, 0, 0)
goal:AddSubGoal(GOAL_COMMON_Turn, 3.0, TARGET_ENE_0, TurnAngle)
-- Approach_and_Attack_Act
-- Simplified function. uses GOAL_COMMON_ApproachTarget and GOAL_COMMON_AttackTunableSpin
-- Checks distance to decide dash vs walk
-- Adds random chance of guarding.
local AppDist = 4 -- Minimum distance to target for goal completion
local DashDist = 10 -- Minimum distance to target to start dashing instead of walking
local Odds_Guard = 0 -- % chance (0 - 100) to guard while approaching. Uses GuardID 9910
local AnimationID = 3000 -- Animation ID to use
local AttDist
local TurnTime
local TurnFaceAngle
Approach_and_Attack_Act(ai, goal, AppDist, DashDist, Odds_Guard, AttID, AttDist, TurnTime, TurnFaceAngle)
Approach_Act(ai, goal, AppDist, DashDist, Odds_Guard, life)
Approach_or_Leave_Act(ai, goal, LeaveDist, AppDist, DashDist, Odds_Guard)
Backstab_Act(ai, goal, ObserveNo, ApproachDist, TimerIndex, Time)
-- NPC_Approach_Act
-- Simplified function for c0000 approaches
local AppDist = 4 -- Minimum distance to target for goal completion
local DashDist = 10 -- Minimum distance to target to start dashing instead of walking
local Odds_Guard = 0 -- % chance (0 - 100) to guard while approaching. Uses GuardID 9910
NPC_Approach_Act(ai, goal, AppDist, DashDist, Odds_Guard)
NPC_Approach_Act(ai, goal, 4, 10, 0)
ai:StartDash() -- for c0000 NPCs. Use before an approach act to make them dash (used in NPC_Approach_Act)
ai:EndDash()
-- ChkNearLowHpFriend
-- Check HP of all allies within defined distance
local HpRatio = .8
local Dist = 20
ai:ChkNearLowHpFriend(HpRatio, Dist)
-- Get and check current role in AI queue, determined by number of allies and team attack effective counter (npcThinkParam)
local role = ai:GetTeamOrder(ORDER_TYPE_Role) -- Get TeamAttackEffectivity role
if role == ROLE_TYPE_Attack then -- true if self in AI queue <= 100
elseif role == ROLE_TYPE_Torimaki then -- true if self in AI queue > 100 and <= 200
elseif role == ROLE_TYPE_Kankyaku then -- true if self in AI queue > 200
end