Table of Contents

Class RogueAttackingState

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Rogue archetype. Melee, but refuses to trade blows face-to-face: it circles into the target's rear arc before opening, and drifts back around whenever the target turns on it.

[CreateAssetMenu(fileName = "New AI Rogue Attacking State", menuName = "FishMMO/Character/NPC/AI/Rogue Attacking State", order = 6)]
public class RogueAttackingState : BaseAttackingState, ICachedObject
Inheritance
Object
ScriptableObject
RogueAttackingState
Implements
Inherited Members
ScriptableObject.SetDirty()
ScriptableObject.CreateInstance<T>()
Object.GetEntityId()
Object.GetInstanceID()
Object.GetHashCode()
Object.InstantiateAsync<T>(T)
Object.InstantiateAsync<T>(T, Transform)
Object.InstantiateAsync<T>(T, Vector3, Quaternion)
Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion, Transform)
Object.Instantiate(Object)
Object.Instantiate(Object, Scene)
Object.Instantiate<T>(T, InstantiateParameters)
Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)
Object.Instantiate(Object, Transform)
Object.Instantiate<T>(T)
Object.Instantiate<T>(T, Vector3, Quaternion)
Object.Instantiate<T>(T, Vector3, Quaternion, Transform)
Object.Instantiate<T>(T, Transform)
Object.Destroy(Object)
Object.DestroyImmediate(Object)
Object.DontDestroyOnLoad(Object)
Object.DestroyObject(Object)
Object.FindObjectsOfType<T>()
Object.FindObjectsByType<T>(FindObjectsSortMode)
Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)
Object.FindObjectOfType<T>()
Object.FindFirstObjectByType<T>()
Object.FindAnyObjectByType<T>()
Object.FindFirstObjectByType<T>(FindObjectsInactive)
Object.FindAnyObjectByType<T>(FindObjectsInactive)
Object.FindObjectsByType<T>()
Object.FindObjectsByType<T>(FindObjectsInactive)
Object.ToString()
Object.name
Object.hideFlags

Remarks

This is the third archetype that needs code: "behind the target" is a function of the target's facing, which no amount of distance tuning can express.

It degrades gracefully — a rogue that cannot reach the rear arc (cornered target, bad navmesh) still attacks from wherever it is rather than standing there circling forever.

Fields

FlankArcDegrees

Half-angle (degrees) of the arc behind the target that counts as "flanked". 90 means the whole rear hemisphere qualifies.

[Header("Rogue Behavior")]
[Range(15, 180)]
[Tooltip("Half-angle of the rear arc that counts as flanked.")]
public float FlankArcDegrees

Field Value

float

FlankStandoffDistance

Distance behind the target the rogue aims for when repositioning.

[Tooltip("Distance behind the target to aim for when repositioning.")]
public float FlankStandoffDistance

Field Value

float

MaxFlankSeconds

How long (seconds) the rogue will keep manoeuvring for a flank before giving up and attacking from wherever it stands. Prevents an infinite circling stalemate.

[Tooltip("Seconds spent trying to flank before attacking from the current position.")]
public float MaxFlankSeconds

Field Value

float

Methods

Enter(AIController)

Called when entering the attacking state. Sets agent speed to run.

public override void Enter(AIController controller)

Parameters

controller AIController

The AI controller.

IsFlanking(AIController)

True when the rogue is currently inside the target's rear arc.

public bool IsFlanking(AIController controller)

Parameters

controller AIController

The AI controller.

Returns

bool

True if flanked.

ReevaluateTarget(AIController, float)

Periodically reconsiders the current target.

protected override void ReevaluateTarget(AIController controller, float deltaTime)

Parameters

controller AIController

The AI controller.

deltaTime float

Seconds elapsed since the previous AI tick.

Remarks

Threat-based NPCs switch when a tracked aggressor exceeds the current target by AggressionSwitchThreshold; a rampaging NPC instead re-rolls onto a random nearby enemy at its personality's retarget chance, which is what makes it impossible to hold with threat.

Candidates come from a fresh detection sweep. The previous implementation scanned controller.SweepHits directly, but that buffer is only filled by AIController's out-of-combat sweep, which is skipped for the whole duration of a fight — so it held stale colliders from before combat started (and entries past the last hit count from sweeps before that), and could retarget onto something no longer present.

TryAttack(AIController, ICharacter)

Spends its flank budget circling into the target's rear arc, then fights normally.

protected override void TryAttack(AIController controller, ICharacter targetCharacter)

Parameters

controller AIController

The AI controller.

targetCharacter ICharacter

The target character being attacked.