Table of Contents

Class AICombatPersonality

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Data-driven combat personality asset that makes two NPCs with the same ability set behave differently in combat. Assign to Personality.

The personality provides per-AbilityCategory score multipliers that PickBestAbility(float) applies on top of the default scoring. Two warriors sharing the same ability list but with different personalities will favour different abilities and positioning.

Range thresholds control how abilities are classified. Abilities whose Range falls below MeleeRangeThreshold are considered melee; those above are ranged. Abilities with HitCount greater than 1 or grounded spawn targets are classified as AOE. Self-targeted abilities are classified as Support.

[CreateAssetMenu(fileName = "New Combat Personality", menuName = "FishMMO/Character/NPC/AI/Combat Personality", order = 10)]
public class AICombatPersonality : ScriptableObject
Inheritance
Object
ScriptableObject
AICombatPersonality
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

Fields

AOEHitCountThreshold

[Tooltip("Abilities with HitCount > this value are considered AOE (multi-target).")]
public int AOEHitCountThreshold

Field Value

int

AOEWeight

[Tooltip("Score multiplier for AOE-classified abilities.")]
[Range(0, 5)]
public float AOEWeight

Field Value

float

BuffWeight

[Tooltip("Score multiplier for abilities that strengthen a friend.")]
[Range(0, 5)]
public float BuffWeight

Field Value

float

ControlWeight

[Tooltip("Score multiplier for abilities that stun, root, freeze, interrupt or knock back.")]
[Range(0, 5)]
public float ControlWeight

Field Value

float

DamageWeight

[Header("Ability Intent Weights")]
[Tooltip("Score multiplier for abilities that deal damage.")]
[Range(0, 5)]
public float DamageWeight

Field Value

float

DebuffWeight

[Tooltip("Score multiplier for abilities that weaken a target.")]
[Range(0, 5)]
public float DebuffWeight

Field Value

float

HealWeight

[Tooltip("Score multiplier for abilities that restore health.")]
[Range(0, 5)]
public float HealWeight

Field Value

float

HealthyAggressionBonus

[Tooltip("Bonus score added to abilities when health is above retreat threshold. Encourages aggressive play while healthy.")]
public float HealthyAggressionBonus

Field Value

float

LowHealthSupportBonus

[Tooltip("Bonus score added to support/self-buff abilities when health is below retreat threshold. Encourages defensive play when hurt.")]
public float LowHealthSupportBonus

Field Value

float

MeleeRangeThreshold

[Header("Classification Thresholds")]
[Tooltip("Abilities with range <= this value are considered melee. Above this = ranged.")]
public float MeleeRangeThreshold

Field Value

float

MeleeWeight

[Header("Ability Category Weights")]
[Tooltip("Score multiplier for melee-classified abilities. >1 = prefer, <1 = avoid.")]
[Range(0, 5)]
public float MeleeWeight

Field Value

float

PATHETIC_DEFAULT_RETREAT_THRESHOLD

Fallback retreat threshold applied to a Pathetic personality whose RetreatHealthThreshold was left at zero.

public const float PATHETIC_DEFAULT_RETREAT_THRESHOLD = 0.5

Field Value

float

Remarks

A "pathetic" archetype that silently never flees because a serialized field defaulted to 0 is the exact failure this guards against: the style is the designer's stated intent, so it wins over an unset number rather than being quietly ignored.

RampageRetargetChance

[Tooltip("Chance (0-1) a Rampaging NPC switches to a new random enemy on each re-evaluation.")]
[Range(0, 1)]
public float RampageRetargetChance

Field Value

float

RangedWeight

[Tooltip("Score multiplier for ranged-classified abilities.")]
[Range(0, 5)]
public float RangedWeight

Field Value

float

RetreatHealthThreshold

[Header("Combat Behavior")]
[Tooltip("Health percentage (0-1) at which this NPC considers retreating. Berserker, Determined and Rampaging styles ignore this. 0 = never retreat.")]
[Range(0, 1)]
public float RetreatHealthThreshold

Field Value

float

Style

[Header("Style")]
[Tooltip("The broad combat archetype. Affects retreat threshold behaviour.")]
public NPCCombatStyle Style

Field Value

NPCCombatStyle

SupportWeight

[Tooltip("Score multiplier for support/self-buff abilities.")]
[Range(0, 5)]
public float SupportWeight

Field Value

float

Targeting

[Header("Targeting")]
[Tooltip("How this NPC chooses between available enemies. Rampaging style forces Random.")]
public AITargetingMode Targeting

Field Value

AITargetingMode

ThreatWeight

[Tooltip("Score multiplier for taunts and other threat manipulation.")]
[Range(0, 5)]
public float ThreatWeight

Field Value

float

Properties

EffectiveRetargetChance

Chance this NPC abandons its current target for a fresh random one on each mid-combat re-evaluation. Non-zero only for Rampaging.

public float EffectiveRetargetChance { get; }

Property Value

float

EffectiveRetreatHealthThreshold

The retreat threshold actually used at runtime, after style overrides. Returns 0 for fearless styles, and the Pathetic fallback for a Pathetic personality left unconfigured.

public float EffectiveRetreatHealthThreshold { get; }

Property Value

float

IsFearless

True when this style is constitutionally incapable of fleeing, whatever RetreatHealthThreshold says.

public bool IsFearless { get; }

Property Value

bool

TargetingMode

The targeting mode actually used at runtime, after style overrides. Rampaging always targets randomly — that unfocused re-targeting is what the style means.

public AITargetingMode TargetingMode { get; }

Property Value

AITargetingMode

Methods

ClassifyAbility(Ability)

Classifies an ability into a AbilityCategory based on its template data. Uses range, spawn target, hit count, and ability type to infer the category.

public AbilityCategory ClassifyAbility(Ability ability)

Parameters

ability Ability

The ability instance to classify.

Returns

AbilityCategory

The inferred category for personality scoring.

GetBonusScore(Ability, float)

Computes a personality-aware bonus score for the given ability, factoring in the NPC's current health and combat style.

public float GetBonusScore(Ability ability, float healthPercent)

Parameters

ability Ability

The ability being scored.

healthPercent float

Current health as a fraction (0-1). Pass 1 if unknown.

Returns

float

An additive bonus to the ability's base score.

GetCategoryWeight(Ability)

Returns the multiplier for how an ability is delivered — melee, ranged, area, or self.

public float GetCategoryWeight(Ability ability)

Parameters

ability Ability

The ability being scored.

Returns

float

The category multiplier.

GetIntentWeight(Ability)

Returns the multiplier for what an ability does, derived from its ECA actions.

public float GetIntentWeight(Ability ability)

Parameters

ability Ability

The ability being scored.

Returns

float

The intent multiplier, or 1 for an ability with no recognised intent.

Remarks

The strongest matching weight, not the product of all of them. Abilities routinely carry several intents — a nuke that also applies a burn is Damage and Debuff — and multiplying would let a merely-compound ability out-score a genuinely specialised one purely for having more flags set.

GetWeight(Ability)

Returns a score multiplier for the given ability, combining how it is delivered with what it does.

public float GetWeight(Ability ability)

Parameters

ability Ability

The ability being scored.

Returns

float

A multiplier (typically 0.1–5.0) to apply to the ability's base score.

Remarks

Called by PickScoredAbility(float, Func<Ability, bool>, float) to bias ability selection. The delivery weight and the intent weight multiply: an archer personality that favours ranged delivery and a caster personality that favours control can share an ability list and still reach for different things in it.

ShouldRetreat(float)

Returns true if this personality's style allows retreating, and the NPC's health has dropped to or below its EffectiveRetreatHealthThreshold.

public bool ShouldRetreat(float healthPercent)

Parameters

healthPercent float

Current health as a fraction (0-1).

Returns

bool

True if the NPC should break off and flee.