Implemented affection-now-friendship mechanics

This commit is contained in:
LOuroboros 2022-06-19 16:43:22 -03:00
parent 15fe85902f
commit aa5c6a3f01
12 changed files with 193 additions and 12 deletions

View file

@ -831,6 +831,7 @@ gBattleAnims_General::
.4byte General_AquaRingHeal @ B_ANIM_AQUA_RING_HEAL .4byte General_AquaRingHeal @ B_ANIM_AQUA_RING_HEAL
.4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP
.4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP .4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP
.4byte General_AffectionHangedOn @ B_ANIM_AFFECTION_HANGED_ON
.align 2 .align 2
gBattleAnims_Special:: gBattleAnims_Special::
@ -24774,6 +24775,17 @@ PrimalReversionParticles:
delay 3 delay 3
return 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: SnatchMoveTrySwapFromSubstitute:
createvisualtask AnimTask_IsAttackerBehindSubstitute, 2 createvisualtask AnimTask_IsAttackerBehindSubstitute, 2
jumprettrue SnatchMoveSwapSubstituteForMon jumprettrue SnatchMoveSwapSubstituteForMon

View file

@ -412,6 +412,61 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE .4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE
.4byte BattleScript_EffectSteelBeam @ EFFECT_STEEL_BEAM .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:: BattleScript_EffectSteelBeam::
attackcanceler attackcanceler
attackstring attackstring

View file

@ -184,6 +184,7 @@ struct SpecialStatus
u8 physicalBattlerId; u8 physicalBattlerId;
u8 specialBattlerId; u8 specialBattlerId;
u8 changedStatsBattlerId; // Battler that was responsible for the latest stat change. Can be self. u8 changedStatsBattlerId; // Battler that was responsible for the latest stat change. Can be self.
bool8 affectionEndured:1;
}; };
struct SideTimer struct SideTimer

View file

@ -420,5 +420,7 @@ extern const u8 BattleScript_MagicianActivates[];
extern const u8 BattleScript_BeakBlastSetUp[]; extern const u8 BattleScript_BeakBlastSetUp[];
extern const u8 BattleScript_BeakBlastBurn[]; extern const u8 BattleScript_BeakBlastBurn[];
extern const u8 BattleScript_DefDownSpeedUp[]; extern const u8 BattleScript_DefDownSpeedUp[];
extern const u8 BattleScript_AffectionBasedStatusHeal[];
extern const u8 BattleScript_AffectionBasedEndurance[];
#endif // GUARD_BATTLE_SCRIPTS_H #endif // GUARD_BATTLE_SCRIPTS_H

View file

@ -189,5 +189,6 @@ bool32 CanBeParalyzed(u8 battlerId);
bool32 CanBeFrozen(u8 battlerId); bool32 CanBeFrozen(u8 battlerId);
bool32 CanBeConfused(u8 battlerId); bool32 CanBeConfused(u8 battlerId);
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag);
u32 GetMonFriendshipScore(struct Pokemon *pokemon);
#endif // GUARD_BATTLE_UTIL_H #endif // GUARD_BATTLE_UTIL_H

View file

@ -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) #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 // Flags describing move's result
#define MOVE_RESULT_MISSED (1 << 0) #define MOVE_RESULT_MISSED (1 << 0)
#define MOVE_RESULT_SUPER_EFFECTIVE (1 << 1) #define MOVE_RESULT_SUPER_EFFECTIVE (1 << 1)
#define MOVE_RESULT_NOT_VERY_EFFECTIVE (1 << 2) #define MOVE_RESULT_NOT_VERY_EFFECTIVE (1 << 2)
#define MOVE_RESULT_DOESNT_AFFECT_FOE (1 << 3) #define MOVE_RESULT_DOESNT_AFFECT_FOE (1 << 3)
#define MOVE_RESULT_ONE_HIT_KO (1 << 4) #define MOVE_RESULT_ONE_HIT_KO (1 << 4)
#define MOVE_RESULT_FAILED (1 << 5) #define MOVE_RESULT_FAILED (1 << 5)
#define MOVE_RESULT_FOE_ENDURED (1 << 6) #define MOVE_RESULT_FOE_ENDURED (1 << 6)
#define MOVE_RESULT_FOE_HUNG_ON (1 << 7) #define MOVE_RESULT_FOE_HUNG_ON (1 << 7)
#define MOVE_RESULT_STURDIED (1 << 8) #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_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED)
#define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9)
// Battle Weather flags // Battle Weather flags
#define B_WEATHER_RAIN_TEMPORARY (1 << 0) #define B_WEATHER_RAIN_TEMPORARY (1 << 0)

View file

@ -534,6 +534,7 @@
#define B_ANIM_AQUA_RING_HEAL 32 #define B_ANIM_AQUA_RING_HEAL 32
#define B_ANIM_BEAK_BLAST_SETUP 33 #define B_ANIM_BEAK_BLAST_SETUP 33
#define B_ANIM_SHELL_TRAP_SETUP 34 #define B_ANIM_SHELL_TRAP_SETUP 34
#define B_ANIM_AFFECTION_HANGED_ON 35
// special animations table (gBattleAnims_Special) // special animations table (gBattleAnims_Special)
#define B_ANIM_LVL_UP 0 #define B_ANIM_LVL_UP 0

View file

@ -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_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_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_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 // Animation Settings
#define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. #define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle.

View file

@ -613,8 +613,14 @@
#define STRINGID_METEORBEAMCHARGING 611 #define STRINGID_METEORBEAMCHARGING 611
#define STRINGID_HEATUPBEAK 612 #define STRINGID_HEATUPBEAK 612
#define STRINGID_COURTCHANGE 613 #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. // This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table, // String ids before this (e.g. STRINGID_INTROMSG) are not in the table,

View file

@ -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_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_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_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] = 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_COURTCHANGE - BATTLESTRINGS_TABLE_START] = sText_CourtChange,
[STRINGID_HEATUPBEAK - BATTLESTRINGS_TABLE_START] = sText_HeatingUpBeak, [STRINGID_HEATUPBEAK - BATTLESTRINGS_TABLE_START] = sText_HeatingUpBeak,
[STRINGID_METEORBEAMCHARGING - BATTLESTRINGS_TABLE_START] = sText_MeteorBeamCharging, [STRINGID_METEORBEAMCHARGING - BATTLESTRINGS_TABLE_START] = sText_MeteorBeamCharging,

View file

@ -1719,6 +1719,13 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move)
if (gFieldStatuses & STATUS_FIELD_GRAVITY) if (gFieldStatuses & STATUS_FIELD_GRAVITY)
calc = (calc * 5) / 3; // 1.66 Gravity acc boost 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; return calc;
} }
@ -1885,7 +1892,10 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi
+ (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS) + (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS)
+ 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
+ 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) + 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)) if (critChance >= ARRAY_COUNT(sCriticalHitChance))
critChance = ARRAY_COUNT(sCriticalHitChance) - 1; critChance = ARRAY_COUNT(sCriticalHitChance) - 1;
@ -1983,12 +1993,27 @@ static void Cmd_adjustdamage(void)
RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY); RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY);
gSpecialStatuses[gBattlerTarget].sturdied = TRUE; 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 if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE
&& !gProtectStructs[gBattlerTarget].endured && !gProtectStructs[gBattlerTarget].endured
&& !gSpecialStatuses[gBattlerTarget].focusBanded && !gSpecialStatuses[gBattlerTarget].focusBanded
&& !gSpecialStatuses[gBattlerTarget].focusSashed && !gSpecialStatuses[gBattlerTarget].focusSashed
#if B_AFFECTION_MECHANICS == TRUE
&& !gSpecialStatuses[gBattlerTarget].sturdied
&& !gSpecialStatuses[gBattlerTarget].affectionEndured)
#else
&& !gSpecialStatuses[gBattlerTarget].sturdied) && !gSpecialStatuses[gBattlerTarget].sturdied)
#endif
goto END; goto END;
// Handle reducing the dmg to 1 hp. // Handle reducing the dmg to 1 hp.
@ -2008,6 +2033,12 @@ static void Cmd_adjustdamage(void)
gMoveResultFlags |= MOVE_RESULT_STURDIED; gMoveResultFlags |= MOVE_RESULT_STURDIED;
gLastUsedAbility = ABILITY_STURDY; gLastUsedAbility = ABILITY_STURDY;
} }
#if B_AFFECTION_MECHANICS == TRUE
else if (gSpecialStatuses[gBattlerTarget].affectionEndured)
{
gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED_AFFECTION;
}
#endif
END: END:
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
@ -2463,6 +2494,16 @@ static void Cmd_resultmessage(void)
{ {
stringId = STRINGID_BUTITFAILED; 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 else
{ {
gBattleCommunication[MSG_DISPLAY] = 0; gBattleCommunication[MSG_DISPLAY] = 0;
@ -4008,6 +4049,10 @@ static void Cmd_getexp(void)
gBattleMoveDamage = value + 1; gBattleMoveDamage = value + 1;
} }
#endif #endif
#if B_AFFECTION_MECHANICS == TRUE
if (GetMonFriendshipScore(&gPlayerParty[gBattleStruct->expGetterMonId]) >= 2)
gBattleMoveDamage = (gBattleMoveDamage * 120) / 100;
#endif
if (IsTradedMon(&gPlayerParty[gBattleStruct->expGetterMonId])) if (IsTradedMon(&gPlayerParty[gBattleStruct->expGetterMonId]))
{ {
@ -10932,6 +10977,13 @@ static void Cmd_tryKO(void)
gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON; gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON;
gLastUsedItem = gBattleMons[gBattlerTarget].item; 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 else
{ {
gBattleMoveDamage = gBattleMons[gBattlerTarget].hp; gBattleMoveDamage = gBattleMons[gBattlerTarget].hp;

View file

@ -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 enum
{ {
ENDTURN_ORDER, ENDTURN_ORDER,
@ -2105,6 +2123,9 @@ enum
ENDTURN_ION_DELUGE, ENDTURN_ION_DELUGE,
ENDTURN_FAIRY_LOCK, ENDTURN_FAIRY_LOCK,
ENDTURN_RETALIATE, ENDTURN_RETALIATE,
#if B_AFFECTION_MECHANICS == TRUE
ENDTURN_STATUS_HEAL,
#endif
ENDTURN_FIELD_COUNT, ENDTURN_FIELD_COUNT,
}; };
@ -2552,6 +2573,22 @@ u8 DoFieldEndTurnEffects(void)
gSideTimers[B_SIDE_OPPONENT].retaliateTimer--; gSideTimers[B_SIDE_OPPONENT].retaliateTimer--;
gBattleStruct->turnCountersTracker++; gBattleStruct->turnCountersTracker++;
break; 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: case ENDTURN_FIELD_COUNT:
effect++; effect++;
break; break;