Skip to content

Commit

Permalink
Refactor weather damage script
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexOn1ine committed Jul 12, 2024
1 parent eeb96af commit ecf134d
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 108 deletions.
2 changes: 1 addition & 1 deletion asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@
.byte 0x95
.endm

.macro weatherdamage
.macro unused_96
.byte 0x96
.endm

Expand Down
7 changes: 7 additions & 0 deletions data/battle_anim_scripts.s
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ gBattleAnims_General::
.4byte General_Fog @ B_ANIM_FOG_CONTINUES
.4byte General_TeraCharge @ B_ANIM_TERA_CHARGE
.4byte General_TeraActivate @ B_ANIM_TERA_ACTIVATE
.4byte General_SimpleHeal @ B_ANIM_SIMPLE_HEAL

.align 2
gBattleAnims_Special::
Expand Down Expand Up @@ -27347,6 +27348,12 @@ General_WishHeal:
createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 3, 10, 0, RGB_BLACK
end

General_SimpleHeal:
loadspritegfx ANIM_TAG_BLUE_STAR
call HealingEffect
waitforvisualfinish
end

General_IllusionOff:
monbg ANIM_TARGET
createvisualtask AnimTask_TransformMon, 2, 1, 0
Expand Down
35 changes: 13 additions & 22 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -5921,33 +5921,22 @@ BattleScript_DamagingWeatherContinues::
waitmessage B_WAIT_TIME_LONG
playanimation_var BS_ATTACKER, sB_ANIM_ARG1
setbyte gBattleCommunication, 0
BattleScript_DamagingWeatherLoop::
copyarraywithindex gBattlerAttacker, gBattlerByTurnOrder, gBattleCommunication, 1
weatherdamage
jumpifword CMP_EQUAL, gBattleMoveDamage, 0, BattleScript_DamagingWeatherLoopIncrement
jumpifword CMP_COMMON_BITS gBattleMoveDamage, 1 << 31, BattleScript_DamagingWeatherHeal
end2

BattleScript_DamagingWeather::
printfromtable gSandStormHailDmgStringIds
waitmessage B_WAIT_TIME_LONG
effectivenesssound
hitanimation BS_ATTACKER
goto BattleScript_DamagingWeatherHpChange
BattleScript_DamagingWeatherHeal:
call BattleScript_AbilityPopUp
hitanimation BS_SCRIPTING
goto BattleScript_DoTurnDmg

BattleScript_IceBodyHeal::
call BattleScript_AbilityPopUpScripting
playanimation BS_SCRIPTING, B_ANIM_SIMPLE_HEAL
healthbarupdate BS_SCRIPTING
datahpupdate BS_SCRIPTING
printstring STRINGID_ICEBODYHPGAIN
waitmessage B_WAIT_TIME_LONG
BattleScript_DamagingWeatherHpChange:
orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
tryfaintmon BS_ATTACKER
checkteamslost BattleScript_DamagingWeatherLoopIncrement
BattleScript_DamagingWeatherLoopIncrement::
jumpifbyte CMP_NOT_EQUAL, gBattleOutcome, 0, BattleScript_DamagingWeatherContinuesEnd
addbyte gBattleCommunication, 1
jumpifbytenotequal gBattleCommunication, gBattlersCount, BattleScript_DamagingWeatherLoop
BattleScript_DamagingWeatherContinuesEnd::
bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE
call BattleScript_ActivateWeatherAbilities
end2

BattleScript_SandStormHailSnowEnds::
Expand Down Expand Up @@ -9836,6 +9825,8 @@ BattleScript_DamageNonTypesStarts::
BattleScript_DamageNonTypesContinues::
printfromtable gDamageNonTypesDmgStringIds
waitmessage B_WAIT_TIME_LONG
effectivenesssound
hitanimation BS_SCRIPTING
goto BattleScript_DoTurnDmg

BattleScript_EffectTryReducePP::
Expand Down
2 changes: 2 additions & 0 deletions include/battle_scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ extern const u8 BattleScript_LevelUp[];
extern const u8 BattleScript_RainContinuesOrEnds[];
extern const u8 BattleScript_SnowContinuesOrEnds[];
extern const u8 BattleScript_DamagingWeatherContinues[];
extern const u8 BattleScript_DamagingWeather[];
extern const u8 BattleScript_IceBodyHeal[];
extern const u8 BattleScript_SandStormHailSnowEnds[];
extern const u8 BattleScript_SunlightContinues[];
extern const u8 BattleScript_SunlightFaded[];
Expand Down
2 changes: 1 addition & 1 deletion include/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// still has them in the ROM. This is because the developers forgot
// to define NDEBUG before release, however this has been changed as
// Ruby's actual debug build does not use the AGBPrint features.
#define NDEBUG
// #define NDEBUG

// To enable printf debugging, comment out "#define NDEBUG". This allows
// the various AGBPrint functions to be used. (See include/gba/isagbprint.h).
Expand Down
1 change: 1 addition & 0 deletions include/constants/battle_anim.h
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@
#define B_ANIM_FOG_CONTINUES 49
#define B_ANIM_TERA_CHARGE 50
#define B_ANIM_TERA_ACTIVATE 51
#define B_ANIM_SIMPLE_HEAL 52

// special animations table (gBattleAnims_Special)
#define B_ANIM_LVL_UP 0
Expand Down
74 changes: 4 additions & 70 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ static void Cmd_setlightscreen(void);
static void Cmd_tryKO(void);
static void Cmd_damagetohalftargethp(void);
static void Cmd_unused_95(void);
static void Cmd_weatherdamage(void);
static void Cmd_unused_96(void);
static void Cmd_tryinfatuating(void);
static void Cmd_updatestatusicon(void);
static void Cmd_setmist(void);
Expand Down Expand Up @@ -749,7 +749,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_tryKO, //0x93
Cmd_damagetohalftargethp, //0x94
Cmd_unused_95, //0x95
Cmd_weatherdamage, //0x96
Cmd_unused_96, //0x96
Cmd_tryinfatuating, //0x97
Cmd_updatestatusicon, //0x98
Cmd_setmist, //0x99
Expand Down Expand Up @@ -12411,74 +12411,8 @@ static void Cmd_unused_95(void)
{
}

static void Cmd_weatherdamage(void)
static void Cmd_unused_96(void)
{
CMD_ARGS();

u32 ability = GetBattlerAbility(gBattlerAttacker);

gBattleMoveDamage = 0;
if (IsBattlerAlive(gBattlerAttacker) && WEATHER_HAS_EFFECT && ability != ABILITY_MAGIC_GUARD)
{
if (gBattleWeather & B_WEATHER_SANDSTORM)
{
if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ROCK)
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GROUND)
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_STEEL)
&& ability != ABILITY_SAND_VEIL
&& ability != ABILITY_SAND_FORCE
&& ability != ABILITY_SAND_RUSH
&& ability != ABILITY_OVERCOAT
&& !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES)
{
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
}
if (gBattleWeather & B_WEATHER_HAIL)
{
if (ability == ABILITY_ICE_BODY
&& !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& !BATTLER_MAX_HP(gBattlerAttacker)
&& !(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK))
{
gBattlerAbility = gBattlerAttacker;
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
}
else if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)
&& ability != ABILITY_SNOW_CLOAK
&& ability != ABILITY_OVERCOAT
&& ability != ABILITY_ICE_BODY
&& !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES)
{
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
}
if (gBattleWeather & B_WEATHER_SNOW)
{
if (ability == ABILITY_ICE_BODY
&& !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& !BATTLER_MAX_HP(gBattlerAttacker)
&& !(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK))
{
gBattlerAbility = gBattlerAttacker;
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
}
}
}

gBattlescriptCurrInstr = cmd->nextInstr;
}

static void Cmd_tryinfatuating(void)
Expand Down Expand Up @@ -14044,7 +13978,7 @@ u32 GetNaturePowerMove(u32 battler)
move = MOVE_PSYCHIC;
else if (sNaturePowerMoves[gBattleTerrain] == MOVE_NONE)
move = MOVE_TRI_ATTACK;

if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE)
{
gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move;
Expand Down
80 changes: 66 additions & 14 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2338,8 +2338,9 @@ enum
ENDTURN_SALT_CURE,
ENDTURN_SYRUP_BOMB,
ENDTURN_DYNAMAX,
ENDTURN_SEA_OF_FIRE_DAMAGE,
ENDTURN_GMAX_MOVE_RESIDUAL_DAMAGE,
ENDTURN_SEA_OF_FIRE_DAMAGE,
ENDTURN_WEATHER_DAMAGE,
ENDTURN_BATTLER_COUNT
};

Expand Down Expand Up @@ -2926,9 +2927,28 @@ u8 DoBattlerEndTurnEffects(void)
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_GMAX_MOVE_RESIDUAL_DAMAGE:
{
u32 side = GetBattlerSide(gBattlerAttacker);
if (gSideTimers[side].damageNonTypesTimer
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, gSideTimers[side].damageNonTypesType)
&& IsBattlerAlive(gBattlerAttacker)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 6;
BtlController_EmitHitAnimation(battler, BUFFER_A);
MarkBattlerForControllerExec(battler);
ChooseDamageNonTypesString(gSideTimers[side].damageNonTypesType);
BattleScriptExecute(BattleScript_DamageNonTypesContinues);
effect++;
}
gBattleStruct->turnEffectsTracker++;
break;
}
case ENDTURN_SEA_OF_FIRE_DAMAGE:
if (IsBattlerAlive(battler) && gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SEA_OF_FIRE)
{
gBattleScripting.battler = battler;
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8;
BtlController_EmitStatusAnimation(battler, BUFFER_A, FALSE, STATUS1_BURN);
MarkBattlerForControllerExec(battler);
Expand All @@ -2937,23 +2957,55 @@ u8 DoBattlerEndTurnEffects(void)
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_GMAX_MOVE_RESIDUAL_DAMAGE:
case ENDTURN_WEATHER_DAMAGE:
ability = GetBattlerAbility(battler);
if (!IsBattlerAlive(battler) || !WEATHER_HAS_EFFECT || ability == ABILITY_MAGIC_GUARD)
{
u32 side = GetBattlerSide(gBattlerAttacker);
if (gSideTimers[side].damageNonTypesTimer
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, gSideTimers[side].damageNonTypesType)
&& IsBattlerAlive(gBattlerAttacker)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 6;
MarkBattlerForControllerExec(battler);
ChooseDamageNonTypesString(gSideTimers[side].damageNonTypesType);
BattleScriptExecute(BattleScript_DamageNonTypesContinues);
effect++;
}
gBattleStruct->turnEffectsTracker++;
break;
}
else if (gBattleWeather & B_WEATHER_SANDSTORM
&& ability != ABILITY_SAND_VEIL
&& ability != ABILITY_SAND_FORCE
&& ability != ABILITY_SAND_RUSH
&& ability != ABILITY_OVERCOAT
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ROCK)
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GROUND)
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_STEEL)
&& !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES)
{
gBattleScripting.battler = battler;
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16;
BattleScriptExecute(BattleScript_DamagingWeather);
effect++;
}
else if (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)
&& ability == ABILITY_ICE_BODY
&& !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& !BATTLER_MAX_HP(battler)
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
gBattleScripting.battler = battler;
gBattleMoveDamage = -1 * (GetNonDynamaxMaxHP(battler) / 16);
BattleScriptExecute(BattleScript_IceBodyHeal);
effect++;
}
else if (gBattleWeather & B_WEATHER_HAIL
&& !IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
&& ability != ABILITY_SNOW_CLOAK
&& ability != ABILITY_OVERCOAT
&& ability != ABILITY_ICE_BODY
&& !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES)
{
gBattleScripting.battler = battler;
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16;
BattleScriptExecute(BattleScript_DamagingWeather);
effect++;
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_BATTLER_COUNT: // done
gBattleStruct->turnEffectsTracker = 0;
gBattleStruct->turnEffectsBattlerId++;
Expand Down
32 changes: 32 additions & 0 deletions test/battle/weather/hail.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ SINGLE_BATTLE_TEST("Hail deals 1/16 damage per turn")
} THEN { EXPECT_EQ(hailDamage, opponent->maxHP / 16); }
}

SINGLE_BATTLE_TEST("Hail heals 1/16 damage per turn on Icy Body")
{
s16 hailDamage;

GIVEN {
PLAYER(SPECIES_GLALIE);
OPPONENT(SPECIES_SEEL) { HP(1); Ability(ABILITY_ICE_BODY); }
} WHEN {
TURN {MOVE(player, MOVE_HAIL);}
} SCENE {
ABILITY_POPUP(opponent, ABILITY_ICE_BODY);
HP_BAR(opponent, captureDamage: &hailDamage);
} THEN { EXPECT_EQ(hailDamage, -(opponent->maxHP / 16)); }
}

SINGLE_BATTLE_TEST("Hail damage does not affect Ice-type Pokémon")
{
GIVEN {
Expand Down Expand Up @@ -53,3 +68,20 @@ SINGLE_BATTLE_TEST("Hail fails if Desolate Land or Primordial Sea are active")
}
}
}

DOUBLE_BATTLE_TEST("Hail deals based on turn order")
{
GIVEN {
PLAYER(SPECIES_GLALIE);
PLAYER(SPECIES_WYNAUT) { Speed(1); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(2); }
OPPONENT(SPECIES_WYNAUT) { Speed(3); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_HAIL); }
} SCENE {
NOT HP_BAR(playerLeft);
HP_BAR(opponentRight);
HP_BAR(opponentLeft);
HP_BAR(playerRight);
}
}

0 comments on commit ecf134d

Please sign in to comment.