Skip to content

Commit

Permalink
Merge pull request #1936 from GriffinRichards/doc-datahpupdate
Browse files Browse the repository at this point in the history
Document datahpupdate
  • Loading branch information
GriffinRichards committed Nov 7, 2023
2 parents 2e1fe4c + 5712777 commit 12a64fe
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 50 deletions.
4 changes: 2 additions & 2 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -3208,7 +3208,7 @@ BattleScript_DamagingWeatherLoop::
jumpifword CMP_EQUAL, gBattleMoveDamage, 0, BattleScript_DamagingWeatherLoopIncrement
printfromtable gSandStormHailDmgStringIds
waitmessage B_WAIT_TIME_LONG
orword gHitMarker, HITMARKER_SKIP_DMG_TRACK | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
effectivenesssound
hitanimation BS_ATTACKER
healthbarupdate BS_ATTACKER
Expand All @@ -3220,7 +3220,7 @@ BattleScript_DamagingWeatherLoopIncrement::
addbyte gBattleCommunication, 1
jumpifbytenotequal gBattleCommunication, gBattlersCount, BattleScript_DamagingWeatherLoop
BattleScript_DamagingWeatherContinuesEnd::
bicword gHitMarker, HITMARKER_SKIP_DMG_TRACK | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
end2

BattleScript_SandStormHailEnds::
Expand Down
15 changes: 9 additions & 6 deletions include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@

#define BATTLE_BUFFER_LINK_SIZE 0x1000

// Special indicator value for shellBellDmg in SpecialStatus
#define IGNORE_SHELL_BELL 0xFFFF

struct ResourceFlags
{
u32 flags[MAX_BATTLERS_COUNT];
Expand Down Expand Up @@ -133,7 +136,7 @@ struct SpecialStatus
u32 ppNotAffectedByPressure:1;
u32 faintedHasReplacement:1;
u32 focusBanded:1;
s32 dmg;
s32 shellBellDmg;
s32 physicalDmg;
s32 specialDmg;
u8 physicalBattlerId;
Expand Down Expand Up @@ -445,9 +448,9 @@ struct BattleStruct
// The assert below is to ensure palaceFlags is large enough to store these flags without overlap.
STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLERS_COUNT + MAX_MON_MOVES, PalaceFlagsTooSmall)

#define F_DYNAMIC_TYPE_1 (1 << 6)
#define F_DYNAMIC_TYPE_2 (1 << 7)
#define DYNAMIC_TYPE_MASK (F_DYNAMIC_TYPE_1 - 1)
#define DYNAMIC_TYPE_MASK ((1 << 6) - 1)
#define F_DYNAMIC_TYPE_IGNORE_PHYSICALITY (1 << 6) // If set, the dynamic type's physicality won't be used for certain move effects.
#define F_DYNAMIC_TYPE_SET (1 << 7) // Set for all dynamic types to distinguish a dynamic type of Normal (0) from no dynamic type.

#define GET_MOVE_TYPE(move, typeArg) \
{ \
Expand Down Expand Up @@ -647,7 +650,7 @@ extern u16 gChosenMove;
extern u16 gCalledMove;
extern s32 gBattleMoveDamage;
extern s32 gHpDealt;
extern s32 gTakenDmg[MAX_BATTLERS_COUNT];
extern s32 gBideDmg[MAX_BATTLERS_COUNT];
extern u16 gLastUsedItem;
extern u8 gLastUsedAbility;
extern u8 gBattlerAttacker;
Expand All @@ -673,7 +676,7 @@ extern u8 gLastHitBy[MAX_BATTLERS_COUNT];
extern u16 gChosenMoveByBattler[MAX_BATTLERS_COUNT];
extern u8 gMoveResultFlags;
extern u32 gHitMarker;
extern u8 gTakenDmgByBattler[MAX_BATTLERS_COUNT];
extern u8 gBideTarget[MAX_BATTLERS_COUNT];
extern u8 gUnusedFirstBattleVar2;
extern u16 gSideStatuses[NUM_BATTLE_SIDES];
extern struct SideTimer gSideTimers[NUM_BATTLE_SIDES];
Expand Down
2 changes: 1 addition & 1 deletion include/constants/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@

// Not really sure what a "hitmarker" is.
#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked.
#define HITMARKER_SKIP_DMG_TRACK (1 << 5)
#define HITMARKER_IGNORE_BIDE (1 << 5)
#define HITMARKER_DESTINYBOND (1 << 6)
#define HITMARKER_NO_ANIMATIONS (1 << 7)
#define HITMARKER_IGNORE_SUBSTITUTE (1 << 8)
Expand Down
4 changes: 2 additions & 2 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ EWRAM_DATA u16 gChosenMove = 0;
EWRAM_DATA u16 gCalledMove = 0;
EWRAM_DATA s32 gBattleMoveDamage = 0;
EWRAM_DATA s32 gHpDealt = 0;
EWRAM_DATA s32 gTakenDmg[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA s32 gBideDmg[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u16 gLastUsedItem = 0;
EWRAM_DATA u8 gLastUsedAbility = 0;
EWRAM_DATA u8 gBattlerAttacker = 0;
Expand All @@ -197,7 +197,7 @@ EWRAM_DATA u16 gChosenMoveByBattler[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gMoveResultFlags = 0;
EWRAM_DATA u32 gHitMarker = 0;
EWRAM_DATA static u8 sUnusedBattlersArray[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gTakenDmgByBattler[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gBideTarget[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gUnusedFirstBattleVar2 = 0; // Never read
EWRAM_DATA u16 gSideStatuses[NUM_BATTLE_SIDES] = {0};
EWRAM_DATA struct SideTimer gSideTimers[NUM_BATTLE_SIDES] = {0};
Expand Down
73 changes: 46 additions & 27 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1836,16 +1836,21 @@ static void Cmd_healthbarupdate(void)
gBattlescriptCurrInstr += 2;
}

// Update the active battler's HP and various HP trackers (Substitute, Bide, etc.)
static void Cmd_datahpupdate(void)
{
u32 moveType;

if (gBattleControllerExecFlags)
return;

// moveType will be used later to record for Counter/Mirror Coat whether this was physical or special damage.
// For moves with a dynamic type that have F_DYNAMIC_TYPE_IGNORE_PHYSICALITY set (in vanilla, just Hidden Power) this will ignore
// the dynamic type and use the move's base type instead, meaning (as a Normal type) Hidden Power will only ever trigger Counter.
// It also means that Hidden Power Fire is unable to defrost targets.
if (gBattleStruct->dynamicMoveType == 0)
moveType = gBattleMoves[gCurrentMove].type;
else if (!(gBattleStruct->dynamicMoveType & F_DYNAMIC_TYPE_1))
else if (!(gBattleStruct->dynamicMoveType & F_DYNAMIC_TYPE_IGNORE_PHYSICALITY))
moveType = gBattleStruct->dynamicMoveType & DYNAMIC_TYPE_MASK;
else
moveType = gBattleMoves[gCurrentMove].type;
Expand All @@ -1855,23 +1860,26 @@ static void Cmd_datahpupdate(void)
gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
if (gBattleMons[gActiveBattler].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBattler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
{
// Target has an active Substitute, deal damage to that instead.
if (gDisableStructs[gActiveBattler].substituteHP >= gBattleMoveDamage)
{
if (gSpecialStatuses[gActiveBattler].dmg == 0)
gSpecialStatuses[gActiveBattler].dmg = gBattleMoveDamage;
if (gSpecialStatuses[gActiveBattler].shellBellDmg == 0)
gSpecialStatuses[gActiveBattler].shellBellDmg = gBattleMoveDamage;
gDisableStructs[gActiveBattler].substituteHP -= gBattleMoveDamage;
gHpDealt = gBattleMoveDamage;
}
else
{
if (gSpecialStatuses[gActiveBattler].dmg == 0)
gSpecialStatuses[gActiveBattler].dmg = gDisableStructs[gActiveBattler].substituteHP;
// Substitute has less HP than the damage dealt, set its HP to 0.
if (gSpecialStatuses[gActiveBattler].shellBellDmg == 0)
gSpecialStatuses[gActiveBattler].shellBellDmg = gDisableStructs[gActiveBattler].substituteHP;
gHpDealt = gDisableStructs[gActiveBattler].substituteHP;
gDisableStructs[gActiveBattler].substituteHP = 0;
}
// check substitute fading

if (gDisableStructs[gActiveBattler].substituteHP == 0)
{
// Substitute fades
gBattlescriptCurrInstr += 2;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SubstituteFade;
Expand All @@ -1881,28 +1889,30 @@ static void Cmd_datahpupdate(void)
else
{
gHitMarker &= ~HITMARKER_IGNORE_SUBSTITUTE;
if (gBattleMoveDamage < 0) // hp goes up
if (gBattleMoveDamage < 0)
{
gBattleMons[gActiveBattler].hp -= gBattleMoveDamage;
// Negative damage is HP gain
gBattleMons[gActiveBattler].hp += -gBattleMoveDamage;
if (gBattleMons[gActiveBattler].hp > gBattleMons[gActiveBattler].maxHP)
gBattleMons[gActiveBattler].hp = gBattleMons[gActiveBattler].maxHP;

}
else // hp goes down
else
{
if (gHitMarker & HITMARKER_SKIP_DMG_TRACK)
if (gHitMarker & HITMARKER_IGNORE_BIDE)
{
gHitMarker &= ~HITMARKER_SKIP_DMG_TRACK;
gHitMarker &= ~HITMARKER_IGNORE_BIDE;
}
else
{
gTakenDmg[gActiveBattler] += gBattleMoveDamage;
// Record damage/attacker for Bide
gBideDmg[gActiveBattler] += gBattleMoveDamage;
if (gBattlescriptCurrInstr[1] == BS_TARGET)
gTakenDmgByBattler[gActiveBattler] = gBattlerAttacker;
gBideTarget[gActiveBattler] = gBattlerAttacker;
else
gTakenDmgByBattler[gActiveBattler] = gBattlerTarget;
gBideTarget[gActiveBattler] = gBattlerTarget;
}

// Deal damage to the battler
if (gBattleMons[gActiveBattler].hp > gBattleMoveDamage)
{
gBattleMons[gActiveBattler].hp -= gBattleMoveDamage;
Expand All @@ -1914,11 +1924,16 @@ static void Cmd_datahpupdate(void)
gBattleMons[gActiveBattler].hp = 0;
}

if (!gSpecialStatuses[gActiveBattler].dmg && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE))
gSpecialStatuses[gActiveBattler].dmg = gHpDealt;
// Record damage for Shell Bell
if (gSpecialStatuses[gActiveBattler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE))
gSpecialStatuses[gActiveBattler].shellBellDmg = gHpDealt;

// Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are
// used in combination as general damage trackers for other purposes. specialDmg is additionally used
// to help determine if a fire move should defrost the target.
if (IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE) && gCurrentMove != MOVE_PAIN_SPLIT)
{
// Record physical damage/attacker for Counter
gProtectStructs[gActiveBattler].physicalDmg = gHpDealt;
gSpecialStatuses[gActiveBattler].physicalDmg = gHpDealt;
if (gBattlescriptCurrInstr[1] == BS_TARGET)
Expand All @@ -1934,6 +1949,7 @@ static void Cmd_datahpupdate(void)
}
else if (!IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE))
{
// Record special damage/attacker for Mirror Coat
gProtectStructs[gActiveBattler].specialDmg = gHpDealt;
gSpecialStatuses[gActiveBattler].specialDmg = gHpDealt;
if (gBattlescriptCurrInstr[1] == BS_TARGET)
Expand All @@ -1949,15 +1965,18 @@ static void Cmd_datahpupdate(void)
}
}
gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE;

// Send updated HP
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[gActiveBattler].hp), &gBattleMons[gActiveBattler].hp);
MarkBattlerForControllerExec(gActiveBattler);
}
}
else
{
// MOVE_RESULT_NO_EFFECT was set
gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
if (gSpecialStatuses[gActiveBattler].dmg == 0)
gSpecialStatuses[gActiveBattler].dmg = 0xFFFF;
if (gSpecialStatuses[gActiveBattler].shellBellDmg == 0)
gSpecialStatuses[gActiveBattler].shellBellDmg = IGNORE_SHELL_BELL;
}
gBattlescriptCurrInstr += 2;
}
Expand Down Expand Up @@ -7092,7 +7111,7 @@ static void Cmd_setbide(void)
{
gBattleMons[gBattlerAttacker].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gBattlerAttacker] = gCurrentMove;
gTakenDmg[gBattlerAttacker] = 0;
gBideDmg[gBattlerAttacker] = 0;
gBattleMons[gBattlerAttacker].status2 |= STATUS2_BIDE_TURN(2);

gBattlescriptCurrInstr++;
Expand Down Expand Up @@ -7984,7 +8003,7 @@ static void Cmd_painsplitdmgcalc(void)
storeLoc[3] = (painSplitHp & 0xFF000000) >> 24;

gBattleMoveDamage = gBattleMons[gBattlerAttacker].hp - hpDiff;
gSpecialStatuses[gBattlerTarget].dmg = 0xFFFF;
gSpecialStatuses[gBattlerTarget].shellBellDmg = IGNORE_SHELL_BELL;

gBattlescriptCurrInstr += 5;
}
Expand Down Expand Up @@ -8822,7 +8841,7 @@ static void Cmd_hiddenpowercalc(void)
gBattleStruct->dynamicMoveType = ((NUMBER_OF_MON_TYPES - 3) * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
gBattleStruct->dynamicMoveType++;
gBattleStruct->dynamicMoveType |= F_DYNAMIC_TYPE_1 | F_DYNAMIC_TYPE_2;
gBattleStruct->dynamicMoveType |= F_DYNAMIC_TYPE_IGNORE_PHYSICALITY | F_DYNAMIC_TYPE_SET;

gBattlescriptCurrInstr++;
}
Expand Down Expand Up @@ -9699,15 +9718,15 @@ static void Cmd_setweatherballtype(void)
if (gBattleWeather & B_WEATHER_ANY)
gBattleScripting.dmgMultiplier = 2;
if (gBattleWeather & B_WEATHER_RAIN)
*(&gBattleStruct->dynamicMoveType) = TYPE_WATER | F_DYNAMIC_TYPE_2;
*(&gBattleStruct->dynamicMoveType) = TYPE_WATER | F_DYNAMIC_TYPE_SET;
else if (gBattleWeather & B_WEATHER_SANDSTORM)
*(&gBattleStruct->dynamicMoveType) = TYPE_ROCK | F_DYNAMIC_TYPE_2;
*(&gBattleStruct->dynamicMoveType) = TYPE_ROCK | F_DYNAMIC_TYPE_SET;
else if (gBattleWeather & B_WEATHER_SUN)
*(&gBattleStruct->dynamicMoveType) = TYPE_FIRE | F_DYNAMIC_TYPE_2;
*(&gBattleStruct->dynamicMoveType) = TYPE_FIRE | F_DYNAMIC_TYPE_SET;
else if (gBattleWeather & B_WEATHER_HAIL)
*(&gBattleStruct->dynamicMoveType) = TYPE_ICE | F_DYNAMIC_TYPE_2;
*(&gBattleStruct->dynamicMoveType) = TYPE_ICE | F_DYNAMIC_TYPE_SET;
else
*(&gBattleStruct->dynamicMoveType) = TYPE_NORMAL | F_DYNAMIC_TYPE_2;
*(&gBattleStruct->dynamicMoveType) = TYPE_NORMAL | F_DYNAMIC_TYPE_SET;
}

gBattlescriptCurrInstr++;
Expand Down
24 changes: 12 additions & 12 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,7 @@ u8 DoBattlerEndTurnEffects(void)
{
u8 effect = 0;

gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK);
gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE);
while (gBattleStruct->turnEffectsBattlerId < gBattlersCount && gBattleStruct->turnEffectsTracker <= ENDTURN_BATTLER_COUNT)
{
gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->turnEffectsBattlerId];
Expand Down Expand Up @@ -1761,13 +1761,13 @@ u8 DoBattlerEndTurnEffects(void)
return effect;
}
}
gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK);
gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE);
return 0;
}

bool8 HandleWishPerishSongOnTurnEnd(void)
{
gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK);
gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE);

switch (gBattleStruct->wishPerishSongState)
{
Expand Down Expand Up @@ -1796,7 +1796,7 @@ bool8 HandleWishPerishSongOnTurnEnd(void)
gBattlerTarget = gActiveBattler;
gBattlerAttacker = gWishFutureKnock.futureSightAttacker[gActiveBattler];
gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gActiveBattler];
gSpecialStatuses[gBattlerTarget].dmg = 0xFFFF;
gSpecialStatuses[gBattlerTarget].shellBellDmg = IGNORE_SHELL_BELL;
BattleScriptExecute(BattleScript_MonTookFutureAttack);

if (gWishFutureKnock.futureSightCounter[gActiveBattler] == 0
Expand Down Expand Up @@ -1867,7 +1867,7 @@ bool8 HandleWishPerishSongOnTurnEnd(void)
break;
}

gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK);
gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_IGNORE_BIDE);

return FALSE;
}
Expand Down Expand Up @@ -2212,11 +2212,11 @@ u8 AtkCanceller_UnableToUseMove(void)
{
// This is removed in FRLG and Emerald for some reason
//gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS;
if (gTakenDmg[gBattlerAttacker])
if (gBideDmg[gBattlerAttacker])
{
gCurrentMove = MOVE_BIDE;
*bideDmg = gTakenDmg[gBattlerAttacker] * 2;
gBattlerTarget = gTakenDmgByBattler[gBattlerAttacker];
*bideDmg = gBideDmg[gBattlerAttacker] * 2;
gBattlerTarget = gBideTarget[gBattlerAttacker];
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1);
gBattlescriptCurrInstr = BattleScript_BideAttack;
Expand Down Expand Up @@ -3769,19 +3769,19 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
break;
case HOLD_EFFECT_SHELL_BELL:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gSpecialStatuses[gBattlerTarget].dmg != 0
&& gSpecialStatuses[gBattlerTarget].dmg != 0xFFFF
&& gSpecialStatuses[gBattlerTarget].shellBellDmg != 0
&& gSpecialStatuses[gBattlerTarget].shellBellDmg != IGNORE_SHELL_BELL
&& gBattlerAttacker != gBattlerTarget
&& gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP
&& gBattleMons[gBattlerAttacker].hp != 0)
{
gLastUsedItem = atkItem;
gPotentialItemEffectBattler = gBattlerAttacker;
gBattleScripting.battler = gBattlerAttacker;
gBattleMoveDamage = (gSpecialStatuses[gBattlerTarget].dmg / atkHoldEffectParam) * -1;
gBattleMoveDamage = (gSpecialStatuses[gBattlerTarget].shellBellDmg / atkHoldEffectParam) * -1;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = -1;
gSpecialStatuses[gBattlerTarget].dmg = 0;
gSpecialStatuses[gBattlerTarget].shellBellDmg = 0;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret;
effect++;
Expand Down

0 comments on commit 12a64fe

Please sign in to comment.