Skip to content

Modding status effects

Tirlititi edited this page Aug 11, 2024 · 6 revisions

Table of contents

  1. Status CSV files
  2. Status attributes
  3. C# scripts
    1. Status own scripts
    2. Overloaded C# methods

In the base game, there are 32 different statuses, including special ones like Jump, Low HP...

Using Memoria, it is possible to have up to 64 different statuses. A new status has been added to handle many positive/negative stat changes (like Power Break, Focus or Lv3 Defless), making it easier to create a dispel effect that reverts these stat changes (or only the positive parts of them, or only the negative parts of them). There are thus 31 slots of statuses that are free to use for whole new statuses.

Status effects are intertwined within the battle's overall system. Many aspects of them can be modified in various places:

  • CSV databases (that can currently only be edited manually, most likely with a text editor), that handle the duration, frequency and classical visual effects of the statuses,
  • Dictionary Patch entries that handle status attributes (positive, negative, those that immobilise their target, those that persist out of battles) and status icons,
  • C# scripts that handle the advanced effects of statuses, such as Doom's countdown and final effect, or the attack/target automatised by Berserk and Confuse; on top of each status's own C# scripts, their effect are spread in many other scripts that can be modded within the DLL Memoria.Scripts (eg. physical ability scripts include the defence provided by Protect in their own script).

Status CSV files

The main basic database for statuses is the CSV file StreamingAssets/Data/Battle/StatusData.csv. It contains the standard base duration of temporary statuses, the tick base frequency of statuses that act regularly (eg. Poison), the status incompatibility scheme, etc... Now it also setups the standard visual effects of statuses: whether they use a SPS or SHP and whether they change the color of the unit affected by the status (eg. Zombie or Protect).

As that's not a CSV that Hades Workshop can use or generate, it's most likely a file that needs to be modified / created manually with a text editor. Here's an example of a StatusData.csv that defines the default parameters of Venom:

#! UnshiftStatuses
#! IncludeVisuals

# Comment	; Id ; Priority(unused) ; OprCount(tick) ; ContiCount(duration) ; ClearOnApply		 ; ImmunityProvided	; SPSEffect ; SPSAttach ; SPSExtraPos	; SHPEffect ; SHPAttach ; SHPExtraPos	; ColorKind ; ColorPriority ; ColorBase
Venom		; 1  ; 7		; 20		 ; 0			; Defend(15), Poison(16) ; Poison(16)		; 1	    ; 0		; 0, 0, 0	; -1	    ; 0		; 0, 0, 0	; -1	    ; 0		    ; 0, 0, 0

Here, the fields are shifted with spaces to keep an alignment for easy reading, but in general the file is presented without this vertical alignment. The two first lines #! UnshiftStatuses and #! IncludeVisuals should be included at the start of the file, so all the fields are used.

  • OprCount is the base tick frequency: the higher it is, the longer it takes between ticks. The exact period duration is computed with the Memoria.ini option [Battle] StatusTickFormula, which normally uses OprCnt as a factor.
  • ContiCount is similar but for the whole duration of the status. Here it is 0 because Venom is a permanent status. The formula is specified by the Memoria.ini option [Battle] StatusDurationFormula, which normally uses ContiCnt as a factor
  • ClearOnApply are the statuses that are removed when Venom is inflicted: here Defend and Poison are removed when anyone gets inflicted.
  • ImmunityProvided are the statuses that are incompatible with Venom: once it is applied, the character is immune to Poison as long as Venom is there. This immunity displays a message Miss for status-inflicting spells, not Guard.
  • SPSEffect, SPSAttach and SPSExtraPos are the settings for a visual SPS effect. SPS are small visual effects that are defined in StreamingAssets/Data/SpecialEffects/Common/SPS.csv (see #461 for detailed infos). Using a SPSEffect of -1 means that no SPS is tied to that status. Here, the SPS used are the little colored "bubbles" above the character's head.
  • The same goes for a SHP effect (same documentation as for SPS). Only Haste, Slow, Trouble and Silence use a SHP by default.
  • ColorKind determines the type of color change of the character inflicted by the status. It can be either:
    • -1: no color effect,
    • 0: a constant color is applied, like with Zombie (brown) or Berserk (red).
    • 1: a glowing color is applied, like Shell and Protect.
    • 2: the trance glowing color is applied; since trance color is different for each character (or enemy), the ColorBase is ignored when using that color kind.
  • ColorPriority determines the color of which status is used when multiple statuses have a character color attribute. For example, that priority is 100 for Zombie and only 50 for Shell, so the color of Zombie is used when both statuses are applied. For glowing colors, you can have the same priority, in which case the glowing alternates between the colors of the different statuses.
  • ColorBase is a RGB color with channels that can range from -255 (lower the intensity of the color channel) to 255 (increase the intensity). For example, Berserk as a base color of 16, -40, -40, which means it increases the red color while lowering the green and blue colors.

Status attributes

An important aspect of statuses is whether they belong to the different logical status groups. For example, statuses that completly freeze their target form the group Immobilized (that group contains Petrify, Venom, Stop and Freeze by default) or the statuses that triggers a Game Over when the whole party has them form the group BattleEnd.

You can change important aspects of the statuses by modifying these groups, adding or removing statuses from them. This is done with a file DictionaryPatch.txt in a mod folder and using BattleStatus lines.

Here are the different logical groups that can be modified:

OutOfBattle
AnyPositive
AnyNegative
Achievement
ContiCount
OprCount
CmdCancel
NoInput
Immobilized
FrozenAnimation
NoReaction
NoDamageMotion
CannotAct
PreventEnemyCmd
PreventCounter
StopAtb
IdleDying
IdleDefend
ChgPolyClut
CannotEscape
CannotTrance
NoRebirthFlame
NoReset
BattleEnd
BattleEndFull
BattleEndInMenu
RemoveOnMainCommand
RemoveOnMagicallyAttacked
RemoveOnPhysicallyAttacked
RemoveOnEvent
RemoveOnMonsterTransform
PenaltyEvade
PreventAlternateCamera
PreventATBConfirm
PreventReflect
VictoryClear
CannotHealInMenu
CannotUseAbilityInMenu
CannotUseMagic
ApplyReflect
ApplyTrouble
ZombieEffect
DisableRewards
CannotSpeak

Another thing that can be modified / completed in the DictionaryPatch.txt is the icon sprites of the statuses. That is done with the instructions BuffIcon and DebuffIcon. Whether you use Buff / Debuff here impacts whether they are displayed in battles when targeting an ally for providing good statuses or for curing bad statuses. It is not exactly the same as being marked as AnyPositive or AnyNegative: for example, Berserk is consider neither a positive or a negative status in multiple aspects, but its icon appears as a debuff when curing bad statuses.

Also, only debuff icons appear in the menu out of battles.

C# scripts

Status own scripts

Each status has a code that runs when it applies to and when it is removed from a target. That code can be externalised. It works similarly to external battle scripts: you need to create C# files in the sub-path StreamingAssets/Scripts/Sources/ of your mod folder and define classes corresponding to the effect of the status. Default C# codes and examples for new statuses can be found there. For example, the default script of Auto-Life is this one:

using System;
using Memoria.Data;
using Object = System.Object;

namespace Memoria.DefaultScripts
{
    [StatusScript(BattleStatusId.AutoLife)]
    public class AutoLifeStatusScript : StatusScriptBase, IDeathChangerStatusScript
    {
        public UInt32 HPRestore = 1;

        public override UInt32 Apply(BattleUnit target, BattleUnit inflicter, params Object[] parameters)
        {
            base.Apply(target, inflicter, parameters);
            HPRestore = Math.Max(HPRestore, parameters.Length > 0 ? (UInt32)parameters[0] : 1);
            return btl_stat.ALTER_SUCCESS;
        }

        public override Boolean Remove()
        {
            return true;
        }

        public Boolean OnDeath()
        {
            btl_stat.RemoveStatus(Target, BattleStatusId.AutoLife);
            if (HPRestore > 0)
            {
                Target.CurrentHp = Math.Min(HPRestore, Target.MaximumHp);
                btl_stat.RemoveStatus(Target, BattleStatusId.Death);
            }
            BattleVoice.TriggerOnStatusChange(Target, "Used", BattleStatusId.AutoLife);
            return true;
        }
    }
}

Each class coding status effect must have the attribute [StatusScript(STATUS_ID)] and be a sub-class of StatusScriptBase. It can also have interfaces like IDeathChangerStatusScript if it triggers something at specific key moments.

There, the status AutoLife can make use of a special parameter (parameters[0]) that, if provided, determines the HP value with which the beneficiary will be revived. When it's not provided, the character is revived with 1 HP on their death.

The different interfaces can be found here:

  • StatusScriptBase, that every status script must have, which codes what happens when trying to apply / remove the status.
  • IOprStatusScript for statuses with a regular update (eg. Poison or Doom).
  • IDeathChangerStatusScript for statuses triggering on death and possibly preventing it (only AutoLife by default).
  • IAutoAttackStatusScript for statuses triggering when the ATB is filled and possibly send an automatic command in place of the player (Confuse and Berserk by default).
  • IFinishCommandScript for statuses that watches the commands performed by the character affected by it. By default, it is used by Trance to monitor Garnet's Eidolon command and activate periodic replicates, and by Jump to handle what happens at the end of the jumping and spearing commands.
  • IFigurePointStatusScript for statuses that triggers an effect at the "figure point" of attacks, ie. not when the damage is actually done but when it is displayed as a figure (or a message like Miss, Death...). By default, only Trouble uses it to spread damage to the allies of the affected character. Note that the figures displayed can be modified there (for statuses that hides to the player the damage taken or dealt) but not the actual damage.

Overloaded C# methods

A couple of overloadable methods are heavily tied to specific status effects:

  • IOverloadUnitCheckPointScript determines by default whether the status LowHP is applied to a character, as well as their UI color in battles.
  • IOverloadOnBattleScriptStartScript handles the instant killing of targets under Freeze when attacked physically.
  • IOverloadOnCommandRunScript handles the instant killing of acting characters under Heat.