Skip to content

Supporting ability features

Tirlititi edited this page Nov 26, 2024 · 11 revisions

Table of Contents

Introduction

Memoria allows to have supporting abilities trigger complex effects. The effects of supporting abilities are stored in the file StreamingAssets/Data/Characters/Abilities/AbilityFeatures.txt and can be modified using a simple text editor such as a Notepad. Note that, contrary to the usual behaviour, a custom AbilityFeatures.txt placed in the correct subfolder of a mod folder doesn't completly replace the default file: only supporting abilities re-defined in that custom AbilityFeatures.txt are modified while the supporting abilities missing from it use the effect defined in the default file. In the same file, active ability features can also be defined.

Documentation

The format for coding Supporting Ability features is the following:

>SA {ID} {Comment}
{Feature Type 1} {Feature Arguments 1 (possibly on multiple lines)}
{Feature Type 2} {Feature Arguments 2 (possibly on multiple lines)}
etc...

Generic comments should be placed at the beginning of the file. The 64 supporting abilities must be defined in the main AbilityFeatures.txt. However, only a part of them can be present in AbilityFeatures.txt of mod folders.

A special group of features can be optionally defined using >SA Global+ or >SA GlobalLast+. Features in these global blocks will always apply, even when no Supporting Ability is active, even for enemies. These Global feature blocks can be used to link features with pieces of equipment. The "Global" block applies before other supporting abilities while "GlobalLast" applies after.

It is important for the keyword >SA and for the feature types to be at the start of a new line. The ID must be a number between 0 and 63 corresponding to the supporting ability (0 is the first one, Auto-Reflect by default, and 63 is the last one that is unused by default). Everything on the same line after the ID is ignored.

Feature types

There are 6 different feature types:

Permanent Applies as soon as the ability is enabled (refreshes when equipment changes), typically for stat modifications of a player character.
  Arguments:
    [code=Condition] {Formula} [/code] -> Define a condition for the feature to apply
    [code={Prop.}] {Formula} [/code]   -> Modify the property according to the formula
BattleStart Applies when a battle is triggered, at the moment of picking the start type, typically for changing the chances to have a back attack or preemptive start type.
  Arguments:
    [code=Condition] {Formula} [/code] -> Define a condition for the feature to apply
    [code={Prop.}] {Formula} [/code]   -> Modify the property according to the formula
    PreemptivePriority {DELTA}         -> Use "PreemptivePriority +1" for letting preemptive have priority over back attacks (in case both random checks pass)
StatusInit Applies a status modification at the start of each battle.
  Arguments:
    [code=Condition] {Formula} [/code] -> Define a condition for the feature to apply
    AutoStatus {Status Name}           -> Let the character have a permanent status
    InitialStatus {Status Name}        -> Let the character start the battle with a status
    ResistStatus {Status Name}         -> Let the character be immune to a status
    InitialATB {ATB Pourcent}          -> Fill the character's ATB at start (100 for a full gauge)
Ability Apply an effect at some point during an ability's effect calculation, typically for increasing the power of some attacks or triggering a reaction.
  Arguments:
    EvenImmobilized                    -> (Try to) apply the feature even if the SA user has a status amongst Death, Petrify, Venom, Stop, Freeze, Jump
    AsTarget                           -> Apply the feature if the SA user is one of the target(s) instead of being the caster (default)
    When{Moment}                       -> Pick the moment to apply the feature amongst these:
                                      WhenBattleScriptStart (before the CS script is called)
                                      WhenHitRateSetup (right before hit rate/evasion checks)
                                      WhenCalcDamage (right before calculating HPDamage using Attack, AttackPower and DefensePower)
                                      WhenSteal (when a successful steal occurs)
                                      WhenBattleScriptEnd (right after the CS script is called)
                                      WhenEffectDone (default option - after the damage are dealt)
    [code=Condition] {Formula} [/code] -> Define a condition for the feature to apply
    [code={Prop.}] {Formula} [/code]   -> Modify the property according to the formula
    DisableSA {ID 1} {ID 2}...         -> Disable the "Ability" features of the specified SA for the rest of the ability's effect calculation (even for a different moment but not for a different target)
Command Apply an effect when a battle command is executed by anyone on anywho, typically for letting a character cover an ally or modifying a flag before visual effect.
  Arguments:
    EvenImmobilized                    -> (Try to) apply the feature even if the SA user has a status amongst Death, Petrify, Venom, Stop, Freeze, Jump
    [code=Condition] {Formula} [/code] -> Define a condition for the feature to apply
    [code={Prop.}] {Formula} [/code]   -> Modify the property according to the formula
BattleResult Apply an effect at the end of a battle, typically for improving the rewards of a battle.
  Arguments:
    When{Moment}                       -> Pick the moment to apply the feature amongst these:
                                      WhenBattleEnd (applies even if there is no reward screen)
                                      WhenRewardAll (modifies rewards of the whole team)
                                      WhenRewardSingle (default - modifies rewards of the SA user) (Note that "WhenRewardAll" only applies once even if there are several users of the same SA in the team)
    [code=Condition] {Formula} [/code] -> Define a condition for the feature to apply
    [code={Prop.}] {Formula} [/code]   -> Modify the property according to the formula

Modifiable properties

The properties that can be modified are the following ones:

Possible codes for Permanent features
  MaxHP, MaxMP, Speed, Strength, Magic, Spirit, Defence, Evade, MagicDefence, MagicEvade,
  PlayerCategory, MPCostFactor, MaxHPLimit, MaxMPLimit, MaxDamageLimit, MaxMPDamageLimit,
  PlayerPermanentStatus

Possible codes for BattleStart features
  BackAttack (chances of having a back attack, with 0 for 0% and 255 for 100%)
  Preemptive (chances of having a back attack, with 0 for 0% and 255 for 100%)

Possible codes for Ability features
  CasterHP, CasterMP, CasterMaxHP, CasterMaxMP, CasterATB, CasterTrance, CasterCurrentStatus,
  CasterPermanentStatus, CasterResistStatus, CasterHalfElement, CasterGuardElement, CasterAbsorbElement,
  CasterWeakElement, CasterBonusElement, CasterSpeed, CasterStrength, CasterMagic, CasterSpirit, CasterDefence,
  CasterEvade, CasterMagicDefence, CasterMagicEvade, CasterRow, CasterSummonCount, CasterCriticalRateBonus,
  CasterCriticalRateResistance, CasterMaxDamageLimit, CasterMaxMPDamageLimit, CasterBonusExp,
  CasterBonusGil, CasterBonusCard,
  (+ same as above for the target, eg. TargetHP),
  EffectCasterFlags, CasterHPDamage, CasterMPDamage, EffectTargetFlags, HPDamage, MPDamage,
  FigureInfo, Power, AbilityStatus, AbilityElement, AbilityElementForBonus, IsShortRanged, IsDrain,
  AbilityCategory, AbilityFlags, Attack, AttackPower, DefencePower, StatusRate, HitRate, Evade,
  EffectFlags, DamageModifierCount, TranceIncrease, ItemSteal, Gil, BattleBonusAP,
  Counter (formula defines the Ability ID of the counter),
  ReturnMagic (formula should return 0),
  AutoItem (formula defines the Item ID of the counter)

Note: Counter can use multiple formulas to specify the ability ID to use, its command ID, the targets of the counter and even the countering unit. Example: the following triggers a counter-Odin by Garnet on all the enemies of the attacked unit, even when Garnet is not the one who is attacked.

[code=Counter] BattleAbilityId_Odin ; BattleCommandId_Counter ; BattleUnitFilter(CandidateIsPlayer != TargetIsPlayer) ; BattleUnitFilter(CandidateIsPlayer == TargetIsPlayer && CandidateCharacterIndex == CharacterId_Garnet) [/code]

Possible codes for Command features
  Power, AbilityStatus, AbilityElement, AbilityElementForBonus, IsShortRanged, AbilityCategory,
  AbilityFlags, IsReflectNull, IsMeteorMiss, IsShortSummon, TryCover, ScriptId, HitRate,
  CommandTargetId, HP, MP, MaxHP, MaxMP, ATB, Trance, CurrentStatus, PermanentStatus, ResistStatus,
  HalfElement, GuardElement, AbsorbElement, WeakElement, BonusElement, Speed, Strength, Magic, Spirit,
  Defence, Evade, MagicDefence, MagicEvade, Row, CriticalRateBonus, CriticalRateResistance,
  MaxDamageLimit, MaxMPDamageLimit, BonusExp, BonusGil, BonusCard, BattleBonusAP,
  Counter (formula defines the Ability ID of the counter)

Possible codes for BattleResult features
  HP, MP, Trance, Status, BonusAP, BonusCard, BonusExp, BonusGil,
  BonusItemAdd, EachBonusItem, EachBonusItemCount,
  BonusItem1, BonusItemCount1, BonusItem2, BonusItemCount2, BonusItem3, BonusItemCount3,
  BonusItem4, BonusItemCount4, BonusItem5, BonusItemCount5, BonusItem6, BonusItemCount6,
  FleeGil (Gil reward of all the enemies, even not killed, divided by 10)

Note: BonusItemAdd can use multiple formulas to give multiple items and specify the amount of each item type. Example: the following adds 3 ores, 2 potions and 1 ether to the item rewards.

[code=BonusItemAdd] RegularItem_Ore ; 3 ; RegularItem_Potion ; 2 ; RegularItem_Ether [/code]

Accessible properties

Check this page for an extensive list of properties and functions that can be used in formulas.

More specifically:

  • Permanent features can use their modifiable properties as part of the formula + a few others.
  • BattleStart features can use only the common informations.
  • StatusInit features can use their modifiable properties as part of the formula + a few others.
  • Ability features can use their modifiable properties as part of the formula + a few others, except ClearStatus, ClearAutoStatus, Counter, ReturnMagic and AutoItem.
  • Command features can use their modifiable properties as part of the formula + a few others, except Counter. Note that:
    • CasterMaxHP and such should only be used in formulas if IsCasterWellDefined is true.
    • TargetMaxHP and such should only be used in formulas if IsSingleTarget is true.
  • BattleResult features can use their modifiable properties as part of the formula + a few others.

Bit flags meanings

Bit flags are numerical identifiers that have a non-numerical meaning in the correct context. Their particularity is that one can add them in order to have a numerical identifier refering to the combination of its summands.

In recent updates, these numerical identifiers tend to be replaced by named identifiers, even though internally they are still numbers.

For example, the elements Thunder and Holy are identified by EffectElement_Thunder and EffectElement_Holy respectively. In order to represent both, the bitwise operation | can be used: EffectElement_Thunder | EffectElement_Holy.

Another important operation is the & operation: that one gives the common elementary pieces of each of its operands. Thus, one can perform checks such as those:

Checks that the target guards against either Holy or Thunder
[code=Condition](TargetGuardElement & (EffectElement_Thunder | EffectElement_Holy)) != 0[/code]
-
Checks that the target guards against both Holy and Thunder
[code=Condition](TargetGuardElement & (EffectElement_Thunder | EffectElement_Holy)) == EffectElement_Thunder | EffectElement_Holy[/code]

Examples

This section shows example of features that can be achieved thanks to this system.

Example of supporting abilities

Auto-Guard: give Auto-Shell or Auto-Protect depending on which one is the most useful and give both if Defence == MagicDefence.

StatusInit [code=Condition] Defence <= MagicDefence [/code] AutoStatus Protect
StatusInit [code=Condition] MagicDefence <= Defence [/code] AutoStatus Shell

Last Resources: save the user from fatal damage at the cost of half of the trance gauge (max is 255), and add Berserk, Vanish and Reflect permanently when doing so. Note how (EffectTargetFlags & CalcFlag_HpDamageOrHeal) == CalcFlag_HpAlteration verifies that the ability deals damage and doesn't heal.

Ability AsTarget WhenBattleScriptEnd
 [code=Condition] HPDamage >= TargetHP && TargetTrance >= 128 && (EffectTargetFlags & CalcFlag_HpDamageOrHeal) == CalcFlag_HpAlteration && CasterIsPlayer != TargetIsPlayer [/code]
 [code=TranceIncrease] -128 [/code]
 [code=TargetPermanentStatus] CombineStatuses(TargetPermanentStatus, BattleStatus_Berserk, BattleStatus_Vanish, BattleStatus_Reflect) [/code]
 [code=HPDamage] 0 [/code]

Battlefield Control: Make battles 1/2 preemptives, 1/4 back attacks (the preemptive check has to fail) and also give Long Reach to all the player's characters.

BattleStart PreemptivePriority +1
 [code=Preemptive] 128 [/code]
 [code=BackAttack] 128 [/code]
Command EvenImmobilized
 [code=Condition] IsAllyOfCaster [/code]
 [code=IsShortRanged] false [/code]

Friendly Aid: cast Cura as a counter on an ally that uses an ability on the SA user. The user doesn't need to know the spell to use it as a counter but it costs MP. Note that it will trigger on any command, including counters, thus potentially looping.

Ability AsTarget
 [code=Condition] CasterIsPlayer == TargetIsPlayer && CasterHP < CasterMaxHP && CasterCharacterIndex != TargetCharacterIndex [/code]
 [code=Counter] BattleAbilityId_Cura [/code]

Wisdom to the Wise: Give a 1.5x, 2.5x or 5x bonus experience depending on the user's level. The format {condition} ? {formula 1} : {formula 2} uses the 1st formula if the condition is satisfied and uses the 2nd formula if not.

BattleResult [code=BonusExp] Level < 40 ? 1.5 * BonusExp : (Level < 80 ? 2.5 * BonusExp : 5 * BonusExp) [/code]

Examples of equipment passive effects

Those must be included in the >SA Global+ or >SA GlobalLast+ section in order not to be bound to any supporting ability.

➤ Have the claws Avenger make its wearer start the battle with Doom.

StatusInit [code=Condition] WeaponId == RegularItem_Avenger [/code] InitialStatus Doom

➤ Have the sword Defender triggers a counter-attack when its wearer is defending.

Ability AsTarget
 [code=Condition] TargetWeaponId == RegularItem_Defender && CheckAnyStatus(TargetCurrentStatus, BattleStatus_Defend) && IsCounterableCommand && CasterIsPlayer != TargetIsPlayer && (AbilityCategory & 8) != 0 [/code]
 [code=Counter] BattleAbilityId_Attack [/code]
 DisableSA 36 54 56

➤ Have the staff Mace of Zeus reduce MP cost of all spells to 0.

Permanent [code=Condition] WeaponId == RegularItem_MaceOfZeus [/code] [code=MPCostFactor] 0 [/code]

➤ Have the dagger Orichalcon make its wearer start the battle with its ATB filled.

StatusInit [code=Condition] WeaponId == RegularItem_Orichalcon && !CheckAnyStatus(CurrentStatus, BattleStatus_Immobilized) [/code] InitialATB 100

➤ Have the spear Kain's Lance trigger a Lancer counter-attack based on its wearer's spirit.

Ability AsTarget
 [code=Condition] TargetWeaponId == RegularItem_KainLance && TargetMP >= 18 && IsCounterableCommand && CasterIsPlayer != TargetIsPlayer && (AbilityCategory & 8) != 0 && (TargetHasSA(39) ? 2 * TargetSpirit : TargetSpirit) > GetRandom(0, 100) [/code]
 [code=Counter] BattleAbilityId_Lancer [/code]
 DisableSA 36 54 56

➤ Have the claws Duel Claws sometimes make its wearer attack twice in a row.

Ability
 [code=Condition] CasterWeaponId == RegularItem_DuelClaws && AbilityId == BattleAbilityId_Attack && IsCounterableCommand && CasterSpirit > GetRandom(0, 100) [/code]
 [code=Counter] BattleAbilityId_Attack [/code]

➤ Have the flute Fairy Flute make any buff casted by its wearer on an ally also apply on the wearer.

Ability EvenImmobilized
 [code=Condition] CasterWeaponId == RegularItem_FairyFlute && CasterIsPlayer == TargetIsPlayer [/code]
 [code=CasterCurrentStatus] CombineStatuses(CasterCurrentStatus, StatusesInflicted) [/code]

➤ Have the staff High Mage Staff increase the spell MP cost by 50%, apply a damage boost (+50% if there is not other boost of the same kind) and make single-targeted damaging spells absorb HP.

Permanent
 [code=Condition] WeaponId == RegularItem_HighMageStaff [/code]
 [code=MPCostFactor] MPCostFactor + MPCostFactor / 2 [/code]
Ability WhenCalcDamage EvenImmobilized
 [code=Condition] CasterWeaponId == RegularItem_HighMageStaff && CasterIsPlayer != TargetIsPlayer && (ScriptId == 9 || (ScriptId >= 15 && ScriptId <= 18)) [/code]
 [code=DamageModifierCount] DamageModifierCount + 1 [/code]
 [code=IsDrain] !IsAbilityMultiTarget ? true : IsDrain [/code]

➤ Increase the HP threshold of Eat and Cook when wearing the Bistro Fork.

Ability WhenBattleScriptStart EvenImmobilized
 [code=Condition] CasterWeaponId == RegularItem_BistroFork && (AbilityId == BattleAbilityId_Eat || AbilityId == BattleAbilityId_Cook) [/code]
 [code=Power] AbilityId == BattleAbilityId_Eat ? 3 : 1 [/code]

➤ Give MP+20% to a Magus Hat wearer (cumulative with supporting abilities).

Permanent [code=Condition] HeadId == RegularItem_MagusHat [/code] [code=MaxMP] MaxMP + MaxMP / 5 [/code]

➤ Make a wearer of Ninja Gear starts battles under the status Vanish.

StatusInit [code=Condition] ArmorId == RegularItem_NinjaGear && !CheckAnyStatus(CurrentStatus, BattleStatus_Immobilized) [/code] InitialStatus Vanish

➤ Give a bonus in HP and MP to a wearer of a Glutton's Robe depending on the number of frogs catched (x10 and x1 respectively).

Permanent [code=Condition] ArmorId == RegularItem_GluttonRobe [/code] [code=MaxHP] MaxHP + 10 * FrogCount [/code] [code=MaxMP] MaxMP + FrogCount [/code]

➤ Prevent trance to activate when wearing a Gold Choker (as High Tide changes the trance increase after the battle script starts, High Tide removes that limitation).

Ability AsTarget WhenBattleScriptStart EvenImmobilized
 [code=Condition] TargetAccessoryId == RegularItem_GoldChoker [/code]
 [code=TranceIncrease] Min(TranceIncrease, 254 - TargetTrance) [/code]

➤ Break the 9999 damage limit for trance abilities, for summons, or when fighting one of the superbosses (Quale, Hades and Ozma).

Ability WhenBattleScriptStart EvenImmobilized
 [code=Condition] CheckAnyStatus(CasterCurrentStatus, BattleStatus_Trance) || CommandId == BattleCommandId_SummonGarnet || CommandId == BattleCommandId_SummonEiko || BattleId == 191 || BattleId == 211 || BattleId == 57 || BattleId == 330 [/code]
 [code=CasterMaxDamageLimit] 99999 [/code]
Ability WhenEffectDone EvenImmobilized
 [code=Condition] CasterMaxDamageLimit > 9999 [/code]
 [code=CasterMaxDamageLimit] 9999 [/code]

Examples of global balance changes

On top of all that, these features can also be used to adjust many aspects of the game regarding the battle rewards, difficulty of the enemies, etc. Multiple examples in this section can be used by non-modders to eg. use a Exp / AP / Gil multiplier.

The base file StreamingAssets/Data/Characters/Abilities/AbilityFeatures.txt can be modified for that purpose in order to add these tweaks without the need to create a whole mod folder for them. The following lines are meant to be added at the end of that file for that purpose.

Battle reward multipliers

➤ Double the Experience, AP and Gil obtained after each battle. You can use any other number to adjust the multipliers. You can also use 0 to completly disable these rewards (or some of them).

>SA GlobalLast+
BattleResult WhenRewardAll
 [code=BonusExp] 2 * BonusExp [/code]
 [code=BonusAP] 2 * BonusAP [/code]
 [code=BonusGil] 2 * BonusGil [/code]

➤ Give 99 of each item dropped by the regular enemies: every item that you successfully obtain from a random encounter is directly maxed to its maximal amount. You can also remove the condition line to extend the effect to the items dropped by bosses and other special battles (eg. the friendly monsters).

>SA GlobalLast+
BattleResult WhenRewardAll
 [code=Condition] IsRandomBattle [/code]
 [code=EachBonusItemCount] 99 [/code]
Clone this wiki locally