Skip to content

Partners

Each partner has a world file in world/partner/, such as world/partner/kooper.c, and a battle file in battle/partner/, such as battle/partner/kooper.c.

How a partner's field ability works

A world file ends with OVL_DEF_PARTNER(), which lists what the partner does in the world:

FieldWhat it is
initA C function that runs when the partner appears, and sets it up, such as its collision size.
takeOutThe EVT script that runs while the partner comes out.
updateThe EVT script that runs while the partner follows the player.
useAbilityThe EVT script that runs when the player presses C-Down. When it ends, update starts again.
putAwayThe EVT script that runs while the partner goes away, such as when the player switches partners.
canUseAbilityA C function that returns whether the player can use the ability. Without one, the player always can.
canPlayerOpenMenusA C function that returns whether the player can open menus, such as while the ability is in use.
isFlyingWhether the partner flies.
idleThe partner's idle animation.

Some partners also set testFirstStrike, preBattle, postBattle, onEnterMap, or syncPlayerPosition for what they do around battles and map changes.

Each of these EVT scripts calls API functions that do the work in C over several frames. For most partners, the field ability is in an API function called UseAbility, such as in world/partner/kooper.c.

How a partner's battle moves work

A battle file defines the partner like an actor, with a blueprint, parts, and tables. On the partner's turn, its EVS_ExecuteAction gets the move the player chose with GetMenuSelection, and runs that move's EVT script:

Switch(LVar2)
    CaseEq(MOVE_HEADBONK1)
        ExecWait(EVS_Attack_Headbonk1)
    CaseEq(MOVE_TATTLE)
        ExecWait(EVS_Move_Tattle)
    // ...
EndSwitch

Each partner has six moves in registry/moves.yaml, in this order:

PositionOfferedGoombario's
1At normal rankHeadbonk (Headbonk1)
2At Super rankHeadbonk (Headbonk2)
3At Ultra rankHeadbonk (Headbonk3)
4AlwaysTattle
5From Super rankCharge
6From Ultra rankMultibonk

The battle menu finds a partner's moves by their position, so you can change a partner's moves but not add more. A move's entry sets its name, FP cost, and targets, and its EVT script deals damage with PartnerDamageEnemy. See Moves for what the fields and arguments mean.

Changing a partner's move

This example makes Goombario's normal-rank Headbonk deal 2 damage per hit instead of 1.

  1. Open battle/partner/goombario.c, and find EVS_Attack_Headbonk1.

  2. Before each PartnerDamageEnemy in it, change Add(LVar0, 1) to Add(LVar0, 2). There are three: two for the first hit, and one for the second.

    Call(GetChargeAmount)
    Add(LVar0, 2)
    Call(PartnerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, LVar0, BS_FLAGS1_NICE_HIT | BS_FLAGS1_INCLUDE_POWER_UPS)

    LVar0 starts as the damage that Charge added, and Add puts the base damage on top.

To change a move's FP cost, change its costFP in registry/moves.yaml. For example, to make Power Shell cost 2 FP, set costFP: 2 in the PowerShell entry.

To test a change, open the debug menu, use Edit Partners to add the partner at the rank you changed, then start a battle with Battle Select.

Giving the player a partner

In a map, ChangeNpcToPartner turns one of the map's NPCs into a partner, adds the partner to the party, and makes it the active partner. Include it in the map's file, then call it with the NPC and the partner:

#include "world/common/util/ChangeNpcToPartner.inc.c"

EvtScript EVS_KooperJoins = {
    // ...
    Call(ChangeNpcToPartner, NPC_Kooper, PARTNER_KOOPER)
    Return
    End
};