From aa5c6a3f0126bf693b84cb2ce6ae4a271dd45148 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Sun, 19 Jun 2022 16:43:22 -0300 Subject: [PATCH 01/10] Implemented affection-now-friendship mechanics --- data/battle_anim_scripts.s | 12 ++++++ data/battle_scripts_1.s | 55 +++++++++++++++++++++++++++ include/battle.h | 1 + include/battle_scripts.h | 2 + include/battle_util.h | 1 + include/constants/battle.h | 21 +++++----- include/constants/battle_anim.h | 1 + include/constants/battle_config.h | 1 + include/constants/battle_string_ids.h | 8 +++- src/battle_message.c | 12 ++++++ src/battle_script_commands.c | 54 +++++++++++++++++++++++++- src/battle_util.c | 37 ++++++++++++++++++ 12 files changed, 193 insertions(+), 12 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index d76aff05a6..1ea6fc2b4d 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -831,6 +831,7 @@ gBattleAnims_General:: .4byte General_AquaRingHeal @ B_ANIM_AQUA_RING_HEAL .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP .4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP + .4byte General_AffectionHangedOn @ B_ANIM_AFFECTION_HANGED_ON .align 2 gBattleAnims_Special:: @@ -24774,6 +24775,17 @@ PrimalReversionParticles: delay 3 return +General_AffectionHangedOn:: @ Shameless copy of General_HangedOn + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, 2, 7, 0, 9, RGB_RED + playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER + createvisualtask AnimTask_SlideMonForFocusBand, 5, 30, 128, 0, 1, 2, 0, 1 + waitforvisualfinish + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, 2, 4, 9, 0, RGB_RED + waitforvisualfinish + delay 6 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 0, 0, 0, 15 + end + SnatchMoveTrySwapFromSubstitute: createvisualtask AnimTask_IsAttackerBehindSubstitute, 2 jumprettrue SnatchMoveSwapSubstituteForMon diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a9c15040d3..80df7a9943 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -412,6 +412,61 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE .4byte BattleScript_EffectSteelBeam @ EFFECT_STEEL_BEAM +BattleScript_AffectionBasedEndurance:: + playanimation BS_TARGET, B_ANIM_AFFECTION_HANGED_ON + printstring STRINGID_TARGETTOUGHEDITOUT + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_AffectionBasedStatusHeal:: + jumpifstatus BS_ATTACKER, STATUS1_POISON, BattleScript_AffectionBasedStatusHeal_Poison + jumpifstatus BS_ATTACKER, STATUS1_TOXIC_POISON, BattleScript_AffectionBasedStatusHeal_Poison + jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_AffectionBasedStatusHeal_Sleep + jumpifstatus BS_ATTACKER, STATUS1_PARALYSIS, BattleScript_AffectionBasedStatusHeal_Paralysis + jumpifstatus BS_ATTACKER, STATUS1_BURN, BattleScript_AffectionBasedStatusHeal_Burn + jumpifstatus BS_ATTACKER, STATUS1_FREEZE, BattleScript_AffectionBasedStatusHeal_Freeze + end2 +BattleScript_AffectionBasedStatusHeal_Poison: + printstring STRINGID_ATTACKEREXPELLEDTHEPOISON + waitmessage B_WAIT_TIME_LONG + clearstatus BS_ATTACKER + waitstate + updatestatusicon BS_ATTACKER + waitstate + end2 +BattleScript_AffectionBasedStatusHeal_Sleep: + printstring STRINGID_ATTACKERSHOOKITSELFAWAKE + waitmessage B_WAIT_TIME_LONG + clearstatus BS_ATTACKER + waitstate + updatestatusicon BS_ATTACKER + waitstate + end2 +BattleScript_AffectionBasedStatusHeal_Paralysis: + printstring STRINGID_ATTACKERBROKETHROUGHPARALYSIS + waitmessage B_WAIT_TIME_LONG + clearstatus BS_ATTACKER + waitstate + updatestatusicon BS_ATTACKER + waitstate + end2 +BattleScript_AffectionBasedStatusHeal_Burn: + printstring STRINGID_ATTACKERHEALEDITSBURN + waitmessage B_WAIT_TIME_LONG + clearstatus BS_ATTACKER + waitstate + updatestatusicon BS_ATTACKER + waitstate + end2 +BattleScript_AffectionBasedStatusHeal_Freeze: + printstring STRINGID_ATTACKERMELTEDTHEICE + waitmessage B_WAIT_TIME_LONG + clearstatus BS_ATTACKER + waitstate + updatestatusicon BS_ATTACKER + waitstate + end2 + BattleScript_EffectSteelBeam:: attackcanceler attackstring diff --git a/include/battle.h b/include/battle.h index ea556c012a..6d6dc46959 100644 --- a/include/battle.h +++ b/include/battle.h @@ -184,6 +184,7 @@ struct SpecialStatus u8 physicalBattlerId; u8 specialBattlerId; u8 changedStatsBattlerId; // Battler that was responsible for the latest stat change. Can be self. + bool8 affectionEndured:1; }; struct SideTimer diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 4134a87dcf..071a0846af 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -420,5 +420,7 @@ extern const u8 BattleScript_MagicianActivates[]; extern const u8 BattleScript_BeakBlastSetUp[]; extern const u8 BattleScript_BeakBlastBurn[]; extern const u8 BattleScript_DefDownSpeedUp[]; +extern const u8 BattleScript_AffectionBasedStatusHeal[]; +extern const u8 BattleScript_AffectionBasedEndurance[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_util.h b/include/battle_util.h index f1864f0967..0f982423ee 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -189,5 +189,6 @@ bool32 CanBeParalyzed(u8 battlerId); bool32 CanBeFrozen(u8 battlerId); bool32 CanBeConfused(u8 battlerId); bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); +u32 GetMonFriendshipScore(struct Pokemon *pokemon); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle.h b/include/constants/battle.h index d651dab189..6a078f7a18 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -248,16 +248,17 @@ #define STATUS_FIELD_TERRAIN_ANY (STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN) // Flags describing move's result -#define MOVE_RESULT_MISSED (1 << 0) -#define MOVE_RESULT_SUPER_EFFECTIVE (1 << 1) -#define MOVE_RESULT_NOT_VERY_EFFECTIVE (1 << 2) -#define MOVE_RESULT_DOESNT_AFFECT_FOE (1 << 3) -#define MOVE_RESULT_ONE_HIT_KO (1 << 4) -#define MOVE_RESULT_FAILED (1 << 5) -#define MOVE_RESULT_FOE_ENDURED (1 << 6) -#define MOVE_RESULT_FOE_HUNG_ON (1 << 7) -#define MOVE_RESULT_STURDIED (1 << 8) -#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) +#define MOVE_RESULT_MISSED (1 << 0) +#define MOVE_RESULT_SUPER_EFFECTIVE (1 << 1) +#define MOVE_RESULT_NOT_VERY_EFFECTIVE (1 << 2) +#define MOVE_RESULT_DOESNT_AFFECT_FOE (1 << 3) +#define MOVE_RESULT_ONE_HIT_KO (1 << 4) +#define MOVE_RESULT_FAILED (1 << 5) +#define MOVE_RESULT_FOE_ENDURED (1 << 6) +#define MOVE_RESULT_FOE_HUNG_ON (1 << 7) +#define MOVE_RESULT_STURDIED (1 << 8) +#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) +#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9) // Battle Weather flags #define B_WEATHER_RAIN_TEMPORARY (1 << 0) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index bddb727fd7..8e34fbcc09 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -534,6 +534,7 @@ #define B_ANIM_AQUA_RING_HEAL 32 #define B_ANIM_BEAK_BLAST_SETUP 33 #define B_ANIM_SHELL_TRAP_SETUP 34 +#define B_ANIM_AFFECTION_HANGED_ON 35 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 74ac9e1299..0a58ba94d8 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -254,6 +254,7 @@ #define B_MULTI_BATTLE_WHITEOUT GEN_8 // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. #define B_EVOLUTION_AFTER_WHITEOUT GEN_6 // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. #define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) +#define B_AFFECTION_MECHANICS FALSE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead. // Animation Settings #define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 4eff91c857..bfc0472994 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -613,8 +613,14 @@ #define STRINGID_METEORBEAMCHARGING 611 #define STRINGID_HEATUPBEAK 612 #define STRINGID_COURTCHANGE 613 +#define STRINGID_ATTACKEREXPELLEDTHEPOISON 614 +#define STRINGID_ATTACKERSHOOKITSELFAWAKE 615 +#define STRINGID_ATTACKERBROKETHROUGHPARALYSIS 616 +#define STRINGID_ATTACKERHEALEDITSBURN 617 +#define STRINGID_ATTACKERMELTEDTHEICE 618 +#define STRINGID_TARGETTOUGHEDITOUT 619 -#define BATTLESTRINGS_COUNT 614 +#define BATTLESTRINGS_COUNT 620 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/src/battle_message.c b/src/battle_message.c index 8cf9a508b2..dae30f176c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -738,9 +738,21 @@ static const u8 sText_TargetTooHeavy[] = _("But the target\nwas too heavy!"); static const u8 sText_MeteorBeamCharging[] = _("{B_ATK_NAME_WITH_PREFIX} is overflowing\nwith space energy!"); static const u8 sText_HeatingUpBeak[] = _("{B_ATK_NAME_WITH_PREFIX} started\nheating up its beak!"); static const u8 sText_CourtChange[] = _("{B_ATK_NAME_WITH_PREFIX} swapped the battle\neffects affecting each side!"); +static const u8 sText_AttackerExpelledThePoison[] = _("{B_ATK_NAME_WITH_PREFIX} managed to\nexpel the poison!"); +static const u8 sText_AttackerShookItselfAwake[] = _("{B_ATK_NAME_WITH_PREFIX} shook itself awake!"); +static const u8 sText_AttackerBrokeThroughParalysis[] = _("{B_ATK_NAME_WITH_PREFIX} gathered all its energy\nto overcome its paralysis!"); +static const u8 sText_AttackerHealedItsBurn[] = _("{B_ATK_NAME_WITH_PREFIX} healed its burn with\nits sheer determination!"); +static const u8 sText_AttackerMeltedTheIce[] = _("{B_ATK_NAME_WITH_PREFIX} melted the ice with\nits fiery determination!"); +static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_TARGETTOUGHEDITOUT - BATTLESTRINGS_TABLE_START] = sText_TargetToughedItOut, + [STRINGID_ATTACKERMELTEDTHEICE - BATTLESTRINGS_TABLE_START] = sText_AttackerMeltedTheIce, + [STRINGID_ATTACKERHEALEDITSBURN - BATTLESTRINGS_TABLE_START] = sText_AttackerHealedItsBurn, + [STRINGID_ATTACKERBROKETHROUGHPARALYSIS - BATTLESTRINGS_TABLE_START] = sText_AttackerBrokeThroughParalysis, + [STRINGID_ATTACKERSHOOKITSELFAWAKE - BATTLESTRINGS_TABLE_START] = sText_AttackerShookItselfAwake, + [STRINGID_ATTACKEREXPELLEDTHEPOISON - BATTLESTRINGS_TABLE_START] = sText_AttackerExpelledThePoison, [STRINGID_COURTCHANGE - BATTLESTRINGS_TABLE_START] = sText_CourtChange, [STRINGID_HEATUPBEAK - BATTLESTRINGS_TABLE_START] = sText_HeatingUpBeak, [STRINGID_METEORBEAMCHARGING - BATTLESTRINGS_TABLE_START] = sText_MeteorBeamCharging, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 15915c71a6..1d42e55116 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1719,6 +1719,13 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move) if (gFieldStatuses & STATUS_FIELD_GRAVITY) calc = (calc * 5) / 3; // 1.66 Gravity acc boost +#if B_AFFECTION_MECHANICS == TRUE + // With high affection/friendship there's a chance to evade a move by substracting 10% of its accuracy. + // I can't find exact information about that chance, so I'm just gonna write it as a 20% chance for now. + if (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[battlerDef]]) >= 4 && (Random() % 100) <= 20) + calc = (calc * 90) / 100; +#endif + return calc; } @@ -1885,7 +1892,10 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi + (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS) + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) + 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) - + (abilityAtk == ABILITY_SUPER_LUCK); + + (abilityAtk == ABILITY_SUPER_LUCK) + #if B_AFFECTION_MECHANICS == TRUE + *= 2 (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= 5); + #endif if (critChance >= ARRAY_COUNT(sCriticalHitChance)) critChance = ARRAY_COUNT(sCriticalHitChance) - 1; @@ -1983,12 +1993,27 @@ static void Cmd_adjustdamage(void) RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY); gSpecialStatuses[gBattlerTarget].sturdied = TRUE; } +#if B_AFFECTION_MECHANICS == TRUE + else if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) >= 3) + { + if ((GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 6 && (Random() % 100) < 25) + || (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 5 && (Random() % 100) < 20) + || (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 4 && (Random() % 100) < 15) + || (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 3 && (Random() % 100) < 10)) + gSpecialStatuses[gBattlerTarget].affectionEndured = TRUE; + } +#endif if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBattlerTarget].endured && !gSpecialStatuses[gBattlerTarget].focusBanded && !gSpecialStatuses[gBattlerTarget].focusSashed +#if B_AFFECTION_MECHANICS == TRUE + && !gSpecialStatuses[gBattlerTarget].sturdied + && !gSpecialStatuses[gBattlerTarget].affectionEndured) +#else && !gSpecialStatuses[gBattlerTarget].sturdied) +#endif goto END; // Handle reducing the dmg to 1 hp. @@ -2008,6 +2033,12 @@ static void Cmd_adjustdamage(void) gMoveResultFlags |= MOVE_RESULT_STURDIED; gLastUsedAbility = ABILITY_STURDY; } +#if B_AFFECTION_MECHANICS == TRUE + else if (gSpecialStatuses[gBattlerTarget].affectionEndured) + { + gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED_AFFECTION; + } +#endif END: gBattlescriptCurrInstr++; @@ -2463,6 +2494,16 @@ static void Cmd_resultmessage(void) { stringId = STRINGID_BUTITFAILED; } + #if B_AFFECTION_MECHANICS == TRUE + else if (gMoveResultFlags & MOVE_RESULT_FOE_ENDURED_AFFECTION) + { + gSpecialStatuses[gBattlerTarget].affectionEndured = FALSE; + gMoveResultFlags &= ~MOVE_RESULT_FOE_ENDURED_AFFECTION; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AffectionBasedEndurance; + return; + } + #endif else { gBattleCommunication[MSG_DISPLAY] = 0; @@ -4008,6 +4049,10 @@ static void Cmd_getexp(void) gBattleMoveDamage = value + 1; } #endif + #if B_AFFECTION_MECHANICS == TRUE + if (GetMonFriendshipScore(&gPlayerParty[gBattleStruct->expGetterMonId]) >= 2) + gBattleMoveDamage = (gBattleMoveDamage * 120) / 100; + #endif if (IsTradedMon(&gPlayerParty[gBattleStruct->expGetterMonId])) { @@ -10932,6 +10977,13 @@ static void Cmd_tryKO(void) gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON; gLastUsedItem = gBattleMons[gBattlerTarget].item; } + #if B_AFFECTION_MECHANICS == TRUE + else if (gSpecialStatuses[gBattlerTarget].affectionEndured) + { + gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1; + gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED_AFFECTION; + } + #endif else { gBattleMoveDamage = gBattleMons[gBattlerTarget].hp; diff --git a/src/battle_util.c b/src/battle_util.c index ebd7917d47..89f2b86fab 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2077,6 +2077,24 @@ void TryToRevertMimicry(void) } } +u32 GetMonFriendshipScore(struct Pokemon *pokemon) // Based on GetLeadMonFriendshipScore +{ + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == 255) + return 6; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 200) + return 5; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 150) + return 4; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 100) + return 3; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 50) + return 2; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 1) + return 1; + + return 0; +} + enum { ENDTURN_ORDER, @@ -2105,6 +2123,9 @@ enum ENDTURN_ION_DELUGE, ENDTURN_FAIRY_LOCK, ENDTURN_RETALIATE, +#if B_AFFECTION_MECHANICS == TRUE + ENDTURN_STATUS_HEAL, +#endif ENDTURN_FIELD_COUNT, }; @@ -2552,6 +2573,22 @@ u8 DoFieldEndTurnEffects(void) gSideTimers[B_SIDE_OPPONENT].retaliateTimer--; gBattleStruct->turnCountersTracker++; break; + #if B_AFFECTION_MECHANICS == TRUE + case ENDTURN_STATUS_HEAL: + for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) + { + if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER + && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= 4 + && (Random() % 100 < 20)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + BattleScriptExecute(BattleScript_AffectionBasedStatusHeal); + break; + } + } + gBattleStruct->turnCountersTracker++; + break; + #endif case ENDTURN_FIELD_COUNT: effect++; break; From deef09112f75f0d6de4bc32e9bb35776d42a7edc Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 22 Jun 2022 08:42:31 -0300 Subject: [PATCH 02/10] Corrected usage of B_AFFECTION_MECHANICS in CalcCritChanceStage --- src/battle_script_commands.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1d42e55116..4e238c54d2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1892,9 +1892,11 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi + (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS) + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) + 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) - + (abilityAtk == ABILITY_SUPER_LUCK) #if B_AFFECTION_MECHANICS == TRUE + + (abilityAtk == ABILITY_SUPER_LUCK) *= 2 (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= 5); + #else + + (abilityAtk == ABILITY_SUPER_LUCK); #endif if (critChance >= ARRAY_COUNT(sCriticalHitChance)) From e792fae415303310a27f06797a5273463dc2589f Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 09:37:42 -0300 Subject: [PATCH 03/10] Review corrections -Simplified the affection mechanics' battle scripts. -Corrected the value seting inside CalcCritChanceStage. -Simplified the checks inside Cmd_adjustdamage -Simplified the contents of GetLeadMonFriendshipScore now that a more general function to do the same thing was added. -Added constants for the values returned by GetMonFriendshipScore. --- data/battle_scripts_1.s | 52 ++++++++++++------------------------ include/constants/pokemon.h | 9 +++++++ src/battle_script_commands.c | 31 +++++++++++---------- src/battle_util.c | 21 ++++++++------- src/field_specials.c | 17 ++---------- 5 files changed, 54 insertions(+), 76 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 236e5d41dd..5cdb44597e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -421,47 +421,29 @@ BattleScript_AffectionBasedEndurance:: return BattleScript_AffectionBasedStatusHeal:: - jumpifstatus BS_ATTACKER, STATUS1_POISON, BattleScript_AffectionBasedStatusHeal_Poison - jumpifstatus BS_ATTACKER, STATUS1_TOXIC_POISON, BattleScript_AffectionBasedStatusHeal_Poison - jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_AffectionBasedStatusHeal_Sleep - jumpifstatus BS_ATTACKER, STATUS1_PARALYSIS, BattleScript_AffectionBasedStatusHeal_Paralysis - jumpifstatus BS_ATTACKER, STATUS1_BURN, BattleScript_AffectionBasedStatusHeal_Burn - jumpifstatus BS_ATTACKER, STATUS1_FREEZE, BattleScript_AffectionBasedStatusHeal_Freeze + jumpifstatus BS_ATTACKER, STATUS1_POISON, BattleScript_AffectionBasedStatus_HealPoisonString + jumpifstatus BS_ATTACKER, STATUS1_TOXIC_POISON, BattleScript_AffectionBasedStatus_HealPoisonString + jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_AffectionBasedStatus_HealSleepString + jumpifstatus BS_ATTACKER, STATUS1_PARALYSIS, BattleScript_AffectionBasedStatus_HealParalysisString + jumpifstatus BS_ATTACKER, STATUS1_BURN, BattleScript_AffectionBasedStatus_HealBurnString + jumpifstatus BS_ATTACKER, STATUS1_FREEZE, BattleScript_AffectionBasedStatus_HealFreezeString end2 -BattleScript_AffectionBasedStatusHeal_Poison: +BattleScript_AffectionBasedStatus_HealPoisonString: printstring STRINGID_ATTACKEREXPELLEDTHEPOISON - waitmessage B_WAIT_TIME_LONG - clearstatus BS_ATTACKER - waitstate - updatestatusicon BS_ATTACKER - waitstate - end2 -BattleScript_AffectionBasedStatusHeal_Sleep: + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatus_HealSleepString: printstring STRINGID_ATTACKERSHOOKITSELFAWAKE - waitmessage B_WAIT_TIME_LONG - clearstatus BS_ATTACKER - waitstate - updatestatusicon BS_ATTACKER - waitstate - end2 -BattleScript_AffectionBasedStatusHeal_Paralysis: + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatus_HealParalysisString: printstring STRINGID_ATTACKERBROKETHROUGHPARALYSIS - waitmessage B_WAIT_TIME_LONG - clearstatus BS_ATTACKER - waitstate - updatestatusicon BS_ATTACKER - waitstate - end2 -BattleScript_AffectionBasedStatusHeal_Burn: + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatus_HealBurnString: printstring STRINGID_ATTACKERHEALEDITSBURN - waitmessage B_WAIT_TIME_LONG - clearstatus BS_ATTACKER - waitstate - updatestatusicon BS_ATTACKER - waitstate - end2 -BattleScript_AffectionBasedStatusHeal_Freeze: + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatus_HealFreezeString: printstring STRINGID_ATTACKERMELTEDTHEICE + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatusHeal_Continue: waitmessage B_WAIT_TIME_LONG clearstatus BS_ATTACKER waitstate diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 13db5644ef..dc8955656c 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -273,6 +273,15 @@ #define FRIENDSHIP_EVENT_FAINT_FIELD_PSN 7 #define FRIENDSHIP_EVENT_FAINT_LARGE 8 // If opponent was >= 30 levels higher. See AdjustFriendshipOnBattleFaint +// Constants for GetLeadMonFriendshipScore +#define FRIENDSHIP_NONE 0 +#define FRIENDSHIP_GE_1 1 +#define FRIENDSHIP_GE_50 2 +#define FRIENDSHIP_GE_100 3 +#define FRIENDSHIP_GE_150 4 +#define FRIENDSHIP_GE_200 5 +#define FRIENDSHIP_MAX 6 + #define MAX_FRIENDSHIP 255 #define MAX_SHEEN 255 #define MAX_CONDITION 255 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5d3f8772ec..6182e09bab 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -59,6 +59,7 @@ #include "constants/songs.h" #include "constants/trainers.h" #include "battle_util.h" +#include "constants/pokemon.h" extern struct Evolution gEvolutionTable[][EVOS_PER_MON]; @@ -1732,7 +1733,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u #if B_AFFECTION_MECHANICS == TRUE // With high affection/friendship there's a chance to evade a move by substracting 10% of its accuracy. // I can't find exact information about that chance, so I'm just gonna write it as a 20% chance for now. - if (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[battlerDef]]) >= 4 && (Random() % 100) <= 20) + if (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[battlerDef]]) >= FRIENDSHIP_GE_150 && (Random() % 100) <= 20) calc = (calc * 90) / 100; #endif @@ -1904,11 +1905,9 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) + 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) #if B_AFFECTION_MECHANICS == TRUE - + (abilityAtk == ABILITY_SUPER_LUCK) - + 2 * (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= 5); - #else - + (abilityAtk == ABILITY_SUPER_LUCK); + + 2 * (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_GE_200) #endif + + (abilityAtk == ABILITY_SUPER_LUCK); if (critChance >= ARRAY_COUNT(sCriticalHitChance)) critChance = ARRAY_COUNT(sCriticalHitChance) - 1; @@ -1976,6 +1975,8 @@ static void Cmd_adjustdamage(void) { u8 holdEffect, param; u32 moveType; + u32 friendshipScore = GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]); + u32 rand = Random() % 100; GET_MOVE_TYPE(gCurrentMove, moveType); @@ -1991,7 +1992,7 @@ static void Cmd_adjustdamage(void) gPotentialItemEffectBattler = gBattlerTarget; - if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < param) + if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param) { RecordItemEffectBattle(gBattlerTarget, holdEffect); gSpecialStatuses[gBattlerTarget].focusBanded = TRUE; @@ -2009,12 +2010,12 @@ static void Cmd_adjustdamage(void) gSpecialStatuses[gBattlerTarget].focusSashed = TRUE; } #if B_AFFECTION_MECHANICS == TRUE - else if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) >= 3) + else if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && friendshipScore >= FRIENDSHIP_GE_100) { - if ((GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 6 && (Random() % 100) < 25) - || (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 5 && (Random() % 100) < 20) - || (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 4 && (Random() % 100) < 15) - || (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]) == 3 && (Random() % 100) < 10)) + if ((friendshipScore == FRIENDSHIP_MAX && rand < 25) + || (friendshipScore == FRIENDSHIP_GE_200 && rand < 20) + || (friendshipScore == FRIENDSHIP_GE_150 && rand < 15) + || (friendshipScore == FRIENDSHIP_GE_100 && rand < 10)) gSpecialStatuses[gBattlerTarget].affectionEndured = TRUE; } #endif @@ -2024,11 +2025,9 @@ static void Cmd_adjustdamage(void) && !gSpecialStatuses[gBattlerTarget].focusBanded && !gSpecialStatuses[gBattlerTarget].focusSashed #if B_AFFECTION_MECHANICS == TRUE - && !gSpecialStatuses[gBattlerTarget].sturdied - && !gSpecialStatuses[gBattlerTarget].affectionEndured) -#else - && !gSpecialStatuses[gBattlerTarget].sturdied) + && !gSpecialStatuses[gBattlerTarget].affectionEndured #endif + && !gSpecialStatuses[gBattlerTarget].sturdied) goto END; // Handle reducing the dmg to 1 hp. @@ -4063,7 +4062,7 @@ static void Cmd_getexp(void) } #endif #if B_AFFECTION_MECHANICS == TRUE - if (GetMonFriendshipScore(&gPlayerParty[gBattleStruct->expGetterMonId]) >= 2) + if (GetMonFriendshipScore(&gPlayerParty[gBattleStruct->expGetterMonId]) >= FRIENDSHIP_GE_50) gBattleMoveDamage = (gBattleMoveDamage * 120) / 100; #endif diff --git a/src/battle_util.c b/src/battle_util.c index 5a7f445ac2..b5d55df055 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -45,6 +45,7 @@ #include "constants/species.h" #include "constants/trainers.h" #include "constants/weather.h" +#include "constants/pokemon.h" extern struct Evolution gEvolutionTable[][EVOS_PER_MON]; @@ -2084,22 +2085,22 @@ void TryToRevertMimicry(void) } } -u32 GetMonFriendshipScore(struct Pokemon *pokemon) // Based on GetLeadMonFriendshipScore +u32 GetMonFriendshipScore(struct Pokemon *pokemon) { - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == 255) - return 6; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == MAX_FRIENDSHIP) + return FRIENDSHIP_MAX; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 200) - return 5; + return FRIENDSHIP_GE_200; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 150) - return 4; + return FRIENDSHIP_GE_150; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 100) - return 3; + return FRIENDSHIP_GE_100; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 50) - return 2; + return FRIENDSHIP_GE_50; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 1) - return 1; + return FRIENDSHIP_GE_1; - return 0; + return FRIENDSHIP_NONE; } enum @@ -2585,7 +2586,7 @@ u8 DoFieldEndTurnEffects(void) for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER - && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= 4 + && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_GE_150 && (Random() % 100 < 20)) { gBattleCommunication[MULTISTRING_CHOOSER] = 1; diff --git a/src/field_specials.c b/src/field_specials.c index 4ed2a2e03d..9305083726 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -65,6 +65,7 @@ #include "constants/weather.h" #include "constants/metatile_labels.h" #include "palette.h" +#include "battle_util.h" EWRAM_DATA bool8 gBikeCyclingChallenge = FALSE; EWRAM_DATA u8 gBikeCollisions = 0; @@ -939,21 +940,7 @@ u16 GetWeekCount(void) u8 GetLeadMonFriendshipScore(void) { - struct Pokemon *pokemon = &gPlayerParty[GetLeadMonIndex()]; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == MAX_FRIENDSHIP) - return 6; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 200) - return 5; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 150) - return 4; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 100) - return 3; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 50) - return 2; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 1) - return 1; - - return 0; + return GetMonFriendshipScore(&gPlayerParty[GetLeadMonIndex()]); } static void CB2_FieldShowRegionMap(void) From 1fc63c34313a4d7ec4f44b57d928ffa95c5c10d6 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 11:52:21 -0300 Subject: [PATCH 04/10] More review corrections --- data/battle_anim_scripts.s | 8 ++++---- include/constants/battle.h | 2 +- include/constants/battle_anim.h | 2 +- src/battle_util.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 572052f5d2..da1e45b232 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -868,7 +868,7 @@ gBattleAnims_General:: .4byte General_AquaRingHeal @ B_ANIM_AQUA_RING_HEAL .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP .4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP - .4byte General_ZMoveActivate @ B_ANIM_ZMOVE_ACTIVATE + .4byte General_ZMoveActivate @ B_ANIM_ZMOVE_ACTIVATE .4byte General_AffectionHangedOn @ B_ANIM_AFFECTION_HANGED_ON .align 2 @@ -24885,12 +24885,12 @@ PrimalReversionParticles: delay 3 return -General_AffectionHangedOn:: @ Shameless copy of General_HangedOn - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, 2, 7, 0, 9, RGB_RED +General_AffectionHangedOn:: @ TODO: Make new animation, currenty a copy of General_HangedOn. + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, F_PAL_ATTACKER, 7, 0, 9, RGB_RED playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER createvisualtask AnimTask_SlideMonForFocusBand, 5, 30, 128, 0, 1, 2, 0, 1 waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, 2, 4, 9, 0, RGB_RED + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, F_PAL_ATTACKER, 4, 9, 0, RGB_RED waitforvisualfinish delay 6 createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 0, 0, 0, 15 diff --git a/include/constants/battle.h b/include/constants/battle.h index 7019befc32..048c98dfcb 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -259,8 +259,8 @@ #define MOVE_RESULT_FOE_ENDURED (1 << 6) #define MOVE_RESULT_FOE_HUNG_ON (1 << 7) #define MOVE_RESULT_STURDIED (1 << 8) -#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) #define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9) +#define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) // Battle Weather flags #define B_WEATHER_RAIN_TEMPORARY (1 << 0) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 28bcb283d4..f6e1bed716 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -536,7 +536,7 @@ #define B_ANIM_BEAK_BLAST_SETUP 33 #define B_ANIM_SHELL_TRAP_SETUP 34 #define B_ANIM_ZMOVE_ACTIVATE 35 // Using Z Moves -#define B_ANIM_AFFECTION_HANGED_ON 36 +#define B_ANIM_AFFECTION_HANGED_ON 36 // TODO: Make new animation, currently a copy of B_ANIM_HANGED_ON. // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/src/battle_util.c b/src/battle_util.c index b5d55df055..e473b02f69 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2581,10 +2581,10 @@ u8 DoFieldEndTurnEffects(void) gSideTimers[B_SIDE_OPPONENT].retaliateTimer--; gBattleStruct->turnCountersTracker++; break; - #if B_AFFECTION_MECHANICS == TRUE case ENDTURN_STATUS_HEAL: for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) { + #if B_AFFECTION_MECHANICS == TRUE if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_GE_150 && (Random() % 100 < 20)) @@ -2593,10 +2593,10 @@ u8 DoFieldEndTurnEffects(void) BattleScriptExecute(BattleScript_AffectionBasedStatusHeal); break; } + #endif } gBattleStruct->turnCountersTracker++; break; - #endif case ENDTURN_FIELD_COUNT: effect++; break; From 1bfff42ad2c0afa88f13694812747b92d156acfc Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 12:38:47 -0300 Subject: [PATCH 05/10] Fixed ENDTURN_STATUS_HEAL --- src/battle_util.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index e473b02f69..eb93f45eec 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2131,9 +2131,7 @@ enum ENDTURN_ION_DELUGE, ENDTURN_FAIRY_LOCK, ENDTURN_RETALIATE, -#if B_AFFECTION_MECHANICS == TRUE ENDTURN_STATUS_HEAL, -#endif ENDTURN_FIELD_COUNT, }; From 5dd143f19d4da6d7de2f88bbdea2281e3b9d7f8a Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 13:07:52 -0300 Subject: [PATCH 06/10] Applied Blackforest's changes to General_AffectionHangedOn --- data/battle_anim_scripts.s | 19 +++++++++++-------- include/constants/battle_anim.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index da1e45b232..a84796cc55 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24885,15 +24885,18 @@ PrimalReversionParticles: delay 3 return -General_AffectionHangedOn:: @ TODO: Make new animation, currenty a copy of General_HangedOn. - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, F_PAL_ATTACKER, 7, 0, 9, RGB_RED - playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER - createvisualtask AnimTask_SlideMonForFocusBand, 5, 30, 128, 0, 1, 2, 0, 1 +General_AffectionHangedOn:: + loadspritegfx ANIM_TAG_RED_HEART + loopsewithpan SE_M_CHARM, SOUND_PAN_ATTACKER, 12, 3 + createvisualtask AnimTask_SwayMon, 5, 0, 12, 4096, 4, ANIM_ATTACKER + delay 15 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 416, -38 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -128, -22 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -384, -31 waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, F_PAL_ATTACKER, 4, 9, 0, RGB_RED - waitforvisualfinish - delay 6 - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 0, 0, 0, 15 end SnatchMoveTrySwapFromSubstitute: diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index f6e1bed716..28bcb283d4 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -536,7 +536,7 @@ #define B_ANIM_BEAK_BLAST_SETUP 33 #define B_ANIM_SHELL_TRAP_SETUP 34 #define B_ANIM_ZMOVE_ACTIVATE 35 // Using Z Moves -#define B_ANIM_AFFECTION_HANGED_ON 36 // TODO: Make new animation, currently a copy of B_ANIM_HANGED_ON. +#define B_ANIM_AFFECTION_HANGED_ON 36 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 From 75390519425008f54d48e1a7ab8ba948e42a3f46 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 13:28:13 -0300 Subject: [PATCH 07/10] Further tweaked the affection animation --- data/battle_anim_scripts.s | 28 ++++++++++++++++++++++++++++ src/battle_anim_new.c | 26 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index a84796cc55..b00cd0aaf3 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24890,6 +24890,13 @@ General_AffectionHangedOn:: loopsewithpan SE_M_CHARM, SOUND_PAN_ATTACKER, 12, 3 createvisualtask AnimTask_SwayMon, 5, 0, 12, 4096, 4, ANIM_ATTACKER delay 15 + launchtask AnimTask_AffectionHangedOn 0x5 0x0 + jumpargeq 0x0, FRIENDSHIP_MAX, General_AffectionHangedOn_6Hearts + jumpargeq 0x0, FRIENDSHIP_GE_200, General_AffectionHangedOn_5Hearts + jumpargeq 0x0, FRIENDSHIP_GE_150, General_AffectionHangedOn_4Hearts + jumpargeq 0x0, FRIENDSHIP_GE_100, General_AffectionHangedOn_3Hearts + end +General_AffectionHangedOn_6Hearts: createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 @@ -24898,6 +24905,27 @@ General_AffectionHangedOn:: createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -384, -31 waitforvisualfinish end +General_AffectionHangedOn_5Hearts: + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 416, -38 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -128, -22 + waitforvisualfinish + end +General_AffectionHangedOn_4Hearts: + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 416, -38 + waitforvisualfinish + end +General_AffectionHangedOn_3Hearts: + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 + createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 + waitforvisualfinish + end SnatchMoveTrySwapFromSubstitute: createvisualtask AnimTask_IsAttackerBehindSubstitute, 2 diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 96faf23dd7..6079889d1b 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -18,6 +18,7 @@ #include "constants/moves.h" #include "constants/hold_effects.h" #include "constants/items.h" +#include "constants/pokemon.h" // function declarations static void SpriteCB_SpriteToCentreOfSide(struct Sprite* sprite); @@ -7895,3 +7896,28 @@ void AnimTask_TerrainPulse(u8 taskId) } DestroyAnimVisualTask(taskId); } + +void AnimTask_AffectionHangedOn(u8 taskId) +{ + int side = GetBattlerSide(gBattleAnimTarget); + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + + switch (GetMonFriendshipScore(&party[gBattlerPartyIndexes[gBattleAnimTarget]])) + { + case FRIENDSHIP_MAX: + gBattleAnimArgs[0] = FRIENDSHIP_MAX; + break; + case FRIENDSHIP_GE_200: + gBattleAnimArgs[0] = FRIENDSHIP_GE_200; + break; + case FRIENDSHIP_GE_150: + gBattleAnimArgs[0] = FRIENDSHIP_GE_150; + break; + case FRIENDSHIP_GE_100: + gBattleAnimArgs[0] = FRIENDSHIP_GE_100; + break; + default: + break; + } + DestroyAnimVisualTask(taskId); +} From 2cf2c00b29dfe058a6c81eadab71d1788aa1c5a9 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 17:10:11 -0300 Subject: [PATCH 08/10] Updated friendship labels --- data/battle_anim_scripts.s | 6 +++--- include/constants/pokemon.h | 14 +++++++------- src/battle_anim_new.c | 12 ++++++------ src/battle_script_commands.c | 14 +++++++------- src/battle_util.c | 12 ++++++------ 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index b00cd0aaf3..0649fe50b1 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24892,9 +24892,9 @@ General_AffectionHangedOn:: delay 15 launchtask AnimTask_AffectionHangedOn 0x5 0x0 jumpargeq 0x0, FRIENDSHIP_MAX, General_AffectionHangedOn_6Hearts - jumpargeq 0x0, FRIENDSHIP_GE_200, General_AffectionHangedOn_5Hearts - jumpargeq 0x0, FRIENDSHIP_GE_150, General_AffectionHangedOn_4Hearts - jumpargeq 0x0, FRIENDSHIP_GE_100, General_AffectionHangedOn_3Hearts + jumpargeq 0x0, FRIENDSHIP_200_TO_254, General_AffectionHangedOn_5Hearts + jumpargeq 0x0, FRIENDSHIP_150_TO_199, General_AffectionHangedOn_4Hearts + jumpargeq 0x0, FRIENDSHIP_100_TO_149, General_AffectionHangedOn_3Hearts end General_AffectionHangedOn_6Hearts: createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index dc8955656c..355b43b1a3 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -274,13 +274,13 @@ #define FRIENDSHIP_EVENT_FAINT_LARGE 8 // If opponent was >= 30 levels higher. See AdjustFriendshipOnBattleFaint // Constants for GetLeadMonFriendshipScore -#define FRIENDSHIP_NONE 0 -#define FRIENDSHIP_GE_1 1 -#define FRIENDSHIP_GE_50 2 -#define FRIENDSHIP_GE_100 3 -#define FRIENDSHIP_GE_150 4 -#define FRIENDSHIP_GE_200 5 -#define FRIENDSHIP_MAX 6 +#define FRIENDSHIP_NONE 0 +#define FRIENDSHIP_1_TO_49 1 +#define FRIENDSHIP_50_TO_99 2 +#define FRIENDSHIP_100_TO_149 3 +#define FRIENDSHIP_150_TO_199 4 +#define FRIENDSHIP_200_TO_254 5 +#define FRIENDSHIP_MAX 6 #define MAX_FRIENDSHIP 255 #define MAX_SHEEN 255 diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 6079889d1b..4e47def939 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -7907,14 +7907,14 @@ void AnimTask_AffectionHangedOn(u8 taskId) case FRIENDSHIP_MAX: gBattleAnimArgs[0] = FRIENDSHIP_MAX; break; - case FRIENDSHIP_GE_200: - gBattleAnimArgs[0] = FRIENDSHIP_GE_200; + case FRIENDSHIP_200_TO_254: + gBattleAnimArgs[0] = FRIENDSHIP_200_TO_254; break; - case FRIENDSHIP_GE_150: - gBattleAnimArgs[0] = FRIENDSHIP_GE_150; + case FRIENDSHIP_150_TO_199: + gBattleAnimArgs[0] = FRIENDSHIP_150_TO_199; break; - case FRIENDSHIP_GE_100: - gBattleAnimArgs[0] = FRIENDSHIP_GE_100; + case FRIENDSHIP_100_TO_149: + gBattleAnimArgs[0] = FRIENDSHIP_100_TO_149; break; default: break; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6182e09bab..47b0b2cab7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1733,7 +1733,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u #if B_AFFECTION_MECHANICS == TRUE // With high affection/friendship there's a chance to evade a move by substracting 10% of its accuracy. // I can't find exact information about that chance, so I'm just gonna write it as a 20% chance for now. - if (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[battlerDef]]) >= FRIENDSHIP_GE_150 && (Random() % 100) <= 20) + if (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[battlerDef]]) >= FRIENDSHIP_150_TO_199 && (Random() % 100) <= 20) calc = (calc * 90) / 100; #endif @@ -1905,7 +1905,7 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) + 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) #if B_AFFECTION_MECHANICS == TRUE - + 2 * (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_GE_200) + + 2 * (GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_200_TO_254) #endif + (abilityAtk == ABILITY_SUPER_LUCK); @@ -2010,12 +2010,12 @@ static void Cmd_adjustdamage(void) gSpecialStatuses[gBattlerTarget].focusSashed = TRUE; } #if B_AFFECTION_MECHANICS == TRUE - else if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && friendshipScore >= FRIENDSHIP_GE_100) + else if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && friendshipScore >= FRIENDSHIP_100_TO_149) { if ((friendshipScore == FRIENDSHIP_MAX && rand < 25) - || (friendshipScore == FRIENDSHIP_GE_200 && rand < 20) - || (friendshipScore == FRIENDSHIP_GE_150 && rand < 15) - || (friendshipScore == FRIENDSHIP_GE_100 && rand < 10)) + || (friendshipScore == FRIENDSHIP_200_TO_254 && rand < 20) + || (friendshipScore == FRIENDSHIP_150_TO_199 && rand < 15) + || (friendshipScore == FRIENDSHIP_100_TO_149 && rand < 10)) gSpecialStatuses[gBattlerTarget].affectionEndured = TRUE; } #endif @@ -4062,7 +4062,7 @@ static void Cmd_getexp(void) } #endif #if B_AFFECTION_MECHANICS == TRUE - if (GetMonFriendshipScore(&gPlayerParty[gBattleStruct->expGetterMonId]) >= FRIENDSHIP_GE_50) + if (GetMonFriendshipScore(&gPlayerParty[gBattleStruct->expGetterMonId]) >= FRIENDSHIP_50_TO_99) gBattleMoveDamage = (gBattleMoveDamage * 120) / 100; #endif diff --git a/src/battle_util.c b/src/battle_util.c index eb93f45eec..74893a7099 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2090,15 +2090,15 @@ u32 GetMonFriendshipScore(struct Pokemon *pokemon) if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == MAX_FRIENDSHIP) return FRIENDSHIP_MAX; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 200) - return FRIENDSHIP_GE_200; + return FRIENDSHIP_200_TO_254; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 150) - return FRIENDSHIP_GE_150; + return FRIENDSHIP_150_TO_199; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 100) - return FRIENDSHIP_GE_100; + return FRIENDSHIP_100_TO_149; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 50) - return FRIENDSHIP_GE_50; + return FRIENDSHIP_50_TO_99; if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 1) - return FRIENDSHIP_GE_1; + return FRIENDSHIP_1_TO_49; return FRIENDSHIP_NONE; } @@ -2584,7 +2584,7 @@ u8 DoFieldEndTurnEffects(void) { #if B_AFFECTION_MECHANICS == TRUE if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER - && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_GE_150 + && GetMonFriendshipScore(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]) >= FRIENDSHIP_150_TO_199 && (Random() % 100 < 20)) { gBattleCommunication[MULTISTRING_CHOOSER] = 1; From 8bd7103b9d7a39c04775d63c3cc1307ab4b2252f Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 17:29:02 -0300 Subject: [PATCH 09/10] Even more review corrections --- data/battle_scripts_1.s | 4 +--- include/battle.h | 2 +- src/battle_anim_new.c | 18 +----------------- src/battle_util.c | 14 ++++++++------ 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5cdb44597e..4ba190c5c4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -421,8 +421,7 @@ BattleScript_AffectionBasedEndurance:: return BattleScript_AffectionBasedStatusHeal:: - jumpifstatus BS_ATTACKER, STATUS1_POISON, BattleScript_AffectionBasedStatus_HealPoisonString - jumpifstatus BS_ATTACKER, STATUS1_TOXIC_POISON, BattleScript_AffectionBasedStatus_HealPoisonString + jumpifstatus BS_ATTACKER, STATUS1_POISON | STATUS1_TOXIC_POISON, BattleScript_AffectionBasedStatus_HealPoisonString jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_AffectionBasedStatus_HealSleepString jumpifstatus BS_ATTACKER, STATUS1_PARALYSIS, BattleScript_AffectionBasedStatus_HealParalysisString jumpifstatus BS_ATTACKER, STATUS1_BURN, BattleScript_AffectionBasedStatus_HealBurnString @@ -442,7 +441,6 @@ BattleScript_AffectionBasedStatus_HealBurnString: goto BattleScript_AffectionBasedStatusHeal_Continue BattleScript_AffectionBasedStatus_HealFreezeString: printstring STRINGID_ATTACKERMELTEDTHEICE - goto BattleScript_AffectionBasedStatusHeal_Continue BattleScript_AffectionBasedStatusHeal_Continue: waitmessage B_WAIT_TIME_LONG clearstatus BS_ATTACKER diff --git a/include/battle.h b/include/battle.h index 7176b73780..ed77992ab5 100644 --- a/include/battle.h +++ b/include/battle.h @@ -178,13 +178,13 @@ struct SpecialStatus u8 dancerOriginalTarget:3; u8 announceNeutralizingGas:1; // See Cmd_switchineffects u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS + u8 affectionEndured:1; s32 dmg; s32 physicalDmg; s32 specialDmg; u8 physicalBattlerId; u8 specialBattlerId; u8 changedStatsBattlerId; // Battler that was responsible for the latest stat change. Can be self. - bool8 affectionEndured:1; }; struct SideTimer diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 4e47def939..b6cc48b918 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -7902,22 +7902,6 @@ void AnimTask_AffectionHangedOn(u8 taskId) int side = GetBattlerSide(gBattleAnimTarget); struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - switch (GetMonFriendshipScore(&party[gBattlerPartyIndexes[gBattleAnimTarget]])) - { - case FRIENDSHIP_MAX: - gBattleAnimArgs[0] = FRIENDSHIP_MAX; - break; - case FRIENDSHIP_200_TO_254: - gBattleAnimArgs[0] = FRIENDSHIP_200_TO_254; - break; - case FRIENDSHIP_150_TO_199: - gBattleAnimArgs[0] = FRIENDSHIP_150_TO_199; - break; - case FRIENDSHIP_100_TO_149: - gBattleAnimArgs[0] = FRIENDSHIP_100_TO_149; - break; - default: - break; - } + gBattleAnimArgs[0] = GetMonFriendshipScore(&party[gBattlerPartyIndexes[gBattleAnimTarget]]); DestroyAnimVisualTask(taskId); } diff --git a/src/battle_util.c b/src/battle_util.c index 74893a7099..dbdecfb178 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2087,17 +2087,19 @@ void TryToRevertMimicry(void) u32 GetMonFriendshipScore(struct Pokemon *pokemon) { - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == MAX_FRIENDSHIP) + u32 friendshipScore = GetMonData(pokemon, MON_DATA_FRIENDSHIP); + + if (friendshipScore == MAX_FRIENDSHIP) return FRIENDSHIP_MAX; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 200) + if (friendshipScore >= 200) return FRIENDSHIP_200_TO_254; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 150) + if (friendshipScore >= 150) return FRIENDSHIP_150_TO_199; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 100) + if (friendshipScore >= 100) return FRIENDSHIP_100_TO_149; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 50) + if (friendshipScore >= 50) return FRIENDSHIP_50_TO_99; - if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 1) + if (friendshipScore >= 1) return FRIENDSHIP_1_TO_49; return FRIENDSHIP_NONE; From 410045028ab765cf9006e3f3c75b2d5b15440f48 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 25 Aug 2022 20:01:14 -0300 Subject: [PATCH 10/10] Optimized General_AffectionHangedOn --- data/battle_anim_scripts.s | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 0649fe50b1..a7e3f34612 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24891,35 +24891,14 @@ General_AffectionHangedOn:: createvisualtask AnimTask_SwayMon, 5, 0, 12, 4096, 4, ANIM_ATTACKER delay 15 launchtask AnimTask_AffectionHangedOn 0x5 0x0 - jumpargeq 0x0, FRIENDSHIP_MAX, General_AffectionHangedOn_6Hearts - jumpargeq 0x0, FRIENDSHIP_200_TO_254, General_AffectionHangedOn_5Hearts - jumpargeq 0x0, FRIENDSHIP_150_TO_199, General_AffectionHangedOn_4Hearts jumpargeq 0x0, FRIENDSHIP_100_TO_149, General_AffectionHangedOn_3Hearts - end -General_AffectionHangedOn_6Hearts: - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 416, -38 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -128, -22 + jumpargeq 0x0, FRIENDSHIP_150_TO_199, General_AffectionHangedOn_4Hearts + jumpargeq 0x0, FRIENDSHIP_200_TO_254, General_AffectionHangedOn_5Hearts createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -384, -31 - waitforvisualfinish - end General_AffectionHangedOn_5Hearts: - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 416, -38 createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -128, -22 - waitforvisualfinish - end General_AffectionHangedOn_4Hearts: - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40 - createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 128, -16 createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 416, -38 - waitforvisualfinish - end General_AffectionHangedOn_3Hearts: createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, 160, -32 createsprite gRedHeartBurstSpriteTemplate, ANIM_ATTACKER, 3, -256, -40