Skip to content

Commit

Permalink
Merge pull request #2117 from AgustinGDLV/symbiosis
Browse files Browse the repository at this point in the history
ABILITY_SYMBIOSIS
  • Loading branch information
AsparagusEduardo authored Sep 24, 2022
2 parents ba9f085 + 0fa8e20 commit 0f743c4
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 21 deletions.
5 changes: 5 additions & 0 deletions asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2132,3 +2132,8 @@
.macro skydropyawn
various 0, VARIOUS_SKY_DROP_YAWN
.endm

@ Used by effects that may proc Symbiosis but do not call removeitem.
.macro trysymbiosis
various BS_ATTACKER, VARIOUS_TRY_SYMBIOSIS
.endm
9 changes: 9 additions & 0 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ BattleScript_EffectFlingConsumeBerry:
restorebattleritem BS_TARGET
BattleScript_FlingEnd:
tryfaintmon BS_TARGET
trysymbiosis
goto BattleScript_MoveEnd

BattleScript_FlingFlameOrb:
Expand Down Expand Up @@ -1392,6 +1393,7 @@ BattleScript_MoveEffectBugBite::
consumeberry BS_ATTACKER, TRUE @ consume the berry, then restore the item from changedItems
bicword gHitMarker, HITMARKER_NO_ANIMATIONS
setbyte sBERRY_OVERRIDE, FALSE
trysymbiosis
return

BattleScript_EffectCoreEnforcer:
Expand Down Expand Up @@ -1763,6 +1765,7 @@ BattleScript_EffectBestow:
waitanimation
printstring STRINGID_BESTOWITEMGIVING
waitmessage B_WAIT_TIME_LONG
trysymbiosis
goto BattleScript_MoveEnd

BattleScript_EffectAfterYou:
Expand Down Expand Up @@ -9841,3 +9844,9 @@ BattleScript_MagicianActivates::
call BattleScript_AbilityPopUp
call BattleScript_ItemSteal
return

BattleScript_SymbiosisActivates::
call BattleScript_AbilityPopUp
printstring STRINGID_SYMBIOSISITEMPASS
waitmessage B_WAIT_TIME_LONG
return
1 change: 1 addition & 0 deletions include/battle_scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ extern const u8 BattleScript_BeakBlastBurn[];
extern const u8 BattleScript_DefDownSpeedUp[];
extern const u8 BattleScript_AffectionBasedStatusHeal[];
extern const u8 BattleScript_AffectionBasedEndurance[];
extern const u8 BattleScript_SymbiosisActivates[];

// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];
Expand Down
1 change: 1 addition & 0 deletions include/constants/battle_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
#define B_STURDY GEN_LATEST // In Gen5+, Sturdy causes the Pokémon to have 1 HP remaining if another Pokémon's attack or confusion damage would have brought it from full health to 0 HP.
#define B_PLUS_MINUS_INTERACTION GEN_LATEST // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it.
#define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms.
#define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply.

// Item settings
#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.
Expand Down
6 changes: 4 additions & 2 deletions include/constants/battle_script_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
#define VARIOUS_SET_BEAK_BLAST 151
#define VARIOUS_SWAP_SIDE_STATUSES 152
#define VARIOUS_SET_Z_EFFECT 153
#define VARIOUS_TRY_SYMBIOSIS 154

// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0
Expand Down Expand Up @@ -312,8 +313,9 @@
#define MOVEEND_DANCER 28
#define MOVEEND_EMERGENCY_EXIT 29
#define MOVEEND_WEATHER_FORM 30
#define MOVEEND_CLEAR_BITS 31
#define MOVEEND_COUNT 32
#define MOVEEND_SYMBIOSIS 31
#define MOVEEND_CLEAR_BITS 32
#define MOVEEND_COUNT 33

// switch cases
#define B_SWITCH_NORMAL 0
Expand Down
2 changes: 1 addition & 1 deletion src/battle_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ static const u8 sText_HarvestBerry[] = _("{B_ATK_NAME_WITH_PREFIX} harvested\nit
static const u8 sText_LastAbilityRaisedBuff1[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}\nraised its {B_BUFF1}!");
static const u8 sText_MagicBounceActivates[] = _("The {B_DEF_NAME_WITH_PREFIX} bounced the\n{B_ATK_NAME_WITH_PREFIX} back!");
static const u8 sText_ProteanTypeChange[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} transformed\nit into the {B_BUFF1} type!");
static const u8 sText_SymbiosisItemPass[] = _("{B_ATK_NAME_WITH_PREFIX} passed its {B_LAST_ITEM}\nto {B_SCR_ACTIVE_NAME_WITH_PREFIX} through {B_ATK_ABILITY}!");
static const u8 sText_SymbiosisItemPass[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} passed its {B_LAST_ITEM}\nto {B_ATK_NAME_WITH_PREFIX} through {B_LAST_ABILITY}!");
static const u8 sText_StealthRockDmg[] = _("Pointed stones dug into\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}!");
static const u8 sText_ToxicSpikesAbsorbed[] = _("The poison spikes disappeared\nfrom around the opposing team's feet!");
static const u8 sText_ToxicSpikesPoisoned[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} was poisoned!");
Expand Down
106 changes: 88 additions & 18 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ static void PutMonIconOnLvlUpBanner(void);
static void DrawLevelUpBannerText(void);
static void SpriteCB_MonIconOnLvlUpBanner(struct Sprite *sprite);
static bool32 CriticalCapture(u32 odds);
static void BestowItem(u32 battlerAtk, u32 battlerDef);

static void Cmd_attackcanceler(void);
static void Cmd_accuracycheck(void);
Expand Down Expand Up @@ -5084,6 +5085,15 @@ static bool32 TryKnockOffBattleScript(u32 battlerDef)
return FALSE;
}

#define SYMBIOSIS_CHECK(battler, ally) \
GetBattlerAbility(ally) == ABILITY_SYMBIOSIS \
&& gBattleMons[battler].item == ITEM_NONE \
&& gBattleMons[ally].item != ITEM_NONE \
&& CanBattlerGetOrLoseItem(battler, gBattleMons[ally].item) \
&& CanBattlerGetOrLoseItem(ally, gBattleMons[ally].item) \
&& gBattleMons[battler].hp != 0 \
&& gBattleMons[ally].hp != 0

static u32 GetNextTarget(u32 moveTarget)
{
u32 i;
Expand Down Expand Up @@ -5748,13 +5758,11 @@ static void Cmd_moveend(void)
switch (gBattleMons[i].species)
{
case SPECIES_CASTFORM:
case SPECIES_CHERRIM:
#ifdef POKEMON_EXPANSION
case SPECIES_CASTFORM_RAINY:
case SPECIES_CASTFORM_SNOWY:
case SPECIES_CASTFORM_SUNNY:
case SPECIES_CHERRIM:
case SPECIES_CHERRIM_SUNSHINE:
#endif
effect = TryWeatherFormChange(i);
if (effect)
{
Expand All @@ -5766,6 +5774,26 @@ static void Cmd_moveend(void)
}
gBattleScripting.moveendState++;
break;
case MOVEEND_SYMBIOSIS:
for (i = 0; i < gBattlersCount; i++)
{
if ((gSpecialStatuses[i].berryReduced
#if B_SYMBIOSIS_GEMS >= GEN_7
|| gSpecialStatuses[i].gemBoost
#endif
) && SYMBIOSIS_CHECK(i, BATTLE_PARTNER(i)))
{
BestowItem(BATTLE_PARTNER(i), i);
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability;
gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i);
gBattlerAttacker = i;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SymbiosisActivates;
effect = TRUE;
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits.
if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3;
Expand Down Expand Up @@ -7244,6 +7272,49 @@ static bool32 TryCheekPouch(u32 battlerId, u32 itemId)
return FALSE;
}

// Used by Bestow and Symbiosis to take an item from one battler and give to another.
static void BestowItem(u32 battlerAtk, u32 battlerDef)
{
gLastUsedItem = gBattleMons[battlerAtk].item;

gActiveBattler = battlerAtk;
gBattleMons[battlerAtk].item = ITEM_NONE;
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerAtk].item), &gBattleMons[battlerAtk].item);
MarkBattlerForControllerExec(battlerAtk);
CheckSetUnburden(battlerAtk);

gActiveBattler = battlerDef;
gBattleMons[battlerDef].item = gLastUsedItem;
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerDef].item), &gBattleMons[battlerDef].item);
MarkBattlerForControllerExec(battlerDef);
gBattleResources->flags->flags[battlerDef] &= ~RESOURCE_FLAG_UNBURDEN;
}

// Called by Cmd_removeitem. itemId represents the item that was removed, not being given.
static bool32 TrySymbiosis(u32 battler, u32 itemId)
{
if (!gBattleStruct->itemStolen[gBattlerPartyIndexes[battler]].stolen
&& gBattleStruct->changedItems[battler] == ITEM_NONE
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_BUTTON
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_PACK
#if B_SYMBIOSIS_GEMS >= GEN_7
&& !(gSpecialStatuses[battler].gemBoost)
#endif
&& gCurrentMove != MOVE_FLING //Fling and damage-reducing berries are handled separately.
&& !gSpecialStatuses[battler].berryReduced
&& SYMBIOSIS_CHECK(battler, BATTLE_PARTNER(battler)))
{
BestowItem(BATTLE_PARTNER(battler), battler);
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability;
gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler);
gBattlerAttacker = battler;
BattleScriptPush(gBattlescriptCurrInstr + 2);
gBattlescriptCurrInstr = BattleScript_SymbiosisActivates;
return TRUE;
}
return FALSE;
}

static void Cmd_removeitem(void)
{
u16 itemId = 0;
Expand All @@ -7262,7 +7333,7 @@ static void Cmd_removeitem(void)
MarkBattlerForControllerExec(gActiveBattler);

ClearBattlerItemEffectHistory(gActiveBattler);
if (!TryCheekPouch(gActiveBattler, itemId))
if (!TryCheekPouch(gActiveBattler, itemId) && !TrySymbiosis(gActiveBattler, itemId))
gBattlescriptCurrInstr += 2;
}

Expand Down Expand Up @@ -9045,20 +9116,7 @@ static void Cmd_various(void)
}
else
{
gLastUsedItem = gBattleMons[gBattlerAttacker].item;

gActiveBattler = gBattlerAttacker;
gBattleMons[gActiveBattler].item = ITEM_NONE;
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gActiveBattler].item), &gBattleMons[gActiveBattler].item);
MarkBattlerForControllerExec(gActiveBattler);
CheckSetUnburden(gBattlerAttacker);

gActiveBattler = gBattlerTarget;
gBattleMons[gActiveBattler].item = gLastUsedItem;
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gActiveBattler].item), &gBattleMons[gActiveBattler].item);
MarkBattlerForControllerExec(gActiveBattler);
gBattleResources->flags->flags[gBattlerTarget] &= ~RESOURCE_FLAG_UNBURDEN;

BestowItem(gBattlerAttacker, gBattlerTarget);
gBattlescriptCurrInstr += 7;
}
return;
Expand Down Expand Up @@ -9788,6 +9846,18 @@ static void Cmd_various(void)
case VARIOUS_SWAP_SIDE_STATUSES:
CourtChangeSwapSideStatuses();
break;
case VARIOUS_TRY_SYMBIOSIS: //called by Bestow, Fling, and Bug Bite, which don't work with Cmd_removeitem.
if (SYMBIOSIS_CHECK(gActiveBattler, BATTLE_PARTNER(gActiveBattler)))
{
BestowItem(BATTLE_PARTNER(gActiveBattler), gActiveBattler);
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(gActiveBattler)].ability;
gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(gActiveBattler);
gBattlerAttacker = gActiveBattler;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SymbiosisActivates;
return;
}
break;
} // End of switch (gBattlescriptCurrInstr[2])

gBattlescriptCurrInstr += 3;
Expand Down

0 comments on commit 0f743c4

Please sign in to comment.