diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 398005f824..becdadac1a 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -1028,6 +1028,10 @@ gBattleAnims_General:: .4byte General_Rainbow @ B_ANIM_RAINBOW .4byte General_SeaOfFire @ B_ANIM_SEA_OF_FIRE .4byte General_Swamp @ B_ANIM_SWAMP + .4byte General_TrickRoom @ B_ANIM_TRICK_ROOM + .4byte General_WonderRoom @ B_ANIM_WONDER_ROOM + .4byte General_MagicRoom @ B_ANIM_MAGIC_ROOM + .4byte General_Tailwind @ B_ANIM_TAILLWIND .align 2 gBattleAnims_Special:: @@ -1316,6 +1320,35 @@ Move_TAILWIND: delay 1 end +General_Tailwind: + loadspritegfx ANIM_TAG_FLYING_DIRT + playsewithpan SE_M_GUST, SOUND_PAN_ATTACKER + call SetHighSpeedBg + setalpha 12, 8 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 10, 2304, 96, 0 + delay 12 + playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 90, 2048, 96, 0 + delay 12 + playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 50, 2560, 96, 0 + delay 12 + playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 20, 2304, 96, 0 + delay 12 + playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 70, 1984, 96, 0 + delay 12 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 0, 2816, 96, 0 + delay 10 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 60, 2560, 96, 0 + waitforvisualfinish + stopsound + call UnsetHighSpeedBg + blendoff + delay 1 + end + Move_ACUPRESSURE: loadspritegfx ANIM_TAG_ACUPRESSURE loadspritegfx ANIM_TAG_SPARK_2 @@ -3303,6 +3336,8 @@ Move_DEFOG: Move_TRICK_ROOM:: call InitRoomAnimation +General_TrickRoom: + playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET fadetobg BG_TRICK_ROOM waitbgfadein delay 0x40 @@ -3312,7 +3347,6 @@ Move_TRICK_ROOM:: end InitRoomAnimation: setalpha 8, 8 - playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET createvisualtask AnimTask_ScaleMonAndRestore, 5, -6, -6, 15, ANIM_TARGET, 1 return @@ -4932,6 +4966,8 @@ PowerSplitLaunch: Move_WONDER_ROOM:: call InitRoomAnimation +General_WonderRoom: + playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET fadetobg BG_WONDER_ROOM waitbgfadein delay 0x40 @@ -5112,6 +5148,8 @@ Move_TELEKINESIS:: Move_MAGIC_ROOM:: call InitRoomAnimation +General_MagicRoom: + playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET fadetobg BG_MAGIC_ROOM waitbgfadein delay 0x40 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d451cf566f..572aedbac7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2534,6 +2534,10 @@ BattleScript_EffectTrickRoom:: waitanimation printfromtable gRoomsStringIds waitmessage B_WAIT_TIME_LONG + call BattleScript_TryRoomServiceLoop + goto BattleScript_MoveEnd + +BattleScript_TryRoomServiceLoop: savetarget setbyte gBattlerTarget, 0 BattleScript_RoomServiceLoop: @@ -2544,7 +2548,7 @@ BattleScript_RoomServiceLoop_NextBattler: addbyte gBattlerTarget, 0x1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_RoomServiceLoop restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectWonderRoom:: BattleScript_EffectMagicRoom:: @@ -5983,6 +5987,19 @@ BattleScript_SunlightFaded:: call BattleScript_ActivateWeatherAbilities end2 +BattleScript_OverworldStatusStarts:: + printfromtable gStartingStatusStringIds + waitmessage B_WAIT_TIME_LONG + playanimation_var BS_ATTACKER, sB_ANIM_ARG1 + call BattleScript_OverworldStatusStarts_TryActivations + end3 + +BattleScript_OverworldStatusStarts_TryActivations: + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SET_TRICK_ROOM, BattleScript_TryRoomServiceLoop + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SET_TAILWIND_PLAYER, BattleScript_TryTailwindAbilitiesLoop + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SET_TAILWIND_OPPONENT, BattleScript_TryTailwindAbilitiesLoop + return + BattleScript_OverworldWeatherStarts:: printfromtable gWeatherStartsStringIds waitmessage B_WAIT_TIME_LONG diff --git a/include/battle.h b/include/battle.h index 5628dd3146..360faace34 100644 --- a/include/battle.h +++ b/include/battle.h @@ -682,9 +682,12 @@ struct BattleStruct } multiBuffer; u8 wishPerishSongState; u8 wishPerishSongBattlerId; - bool8 overworldWeatherDone; - bool8 terrainDone; - u8 isAtkCancelerForCalledMove; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. + u8 overworldWeatherDone:1; + u8 startingStatusDone:1; + u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. + u8 terrainDone:1; + u8 startingStatus; // status to apply at battle start. defined in constants/battle.h + u8 startingStatusTimer; u8 atkCancellerTracker; struct BattleTvMovePoints tvMovePoints; struct BattleTv tv; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 3ff275d3bf..2eeba2cc33 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -54,6 +54,7 @@ extern const u8 BattleScript_DamagingWeatherContinues[]; extern const u8 BattleScript_SandStormHailSnowEnds[]; extern const u8 BattleScript_SunlightContinues[]; extern const u8 BattleScript_SunlightFaded[]; +extern const u8 BattleScript_OverworldStatusStarts[]; extern const u8 BattleScript_OverworldWeatherStarts[]; extern const u8 BattleScript_OverworldTerrain[]; extern const u8 BattleScript_SideStatusWoreOff[]; diff --git a/include/battle_util.h b/include/battle_util.h index 02eec4870f..ad3838b1fc 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -39,6 +39,7 @@ #define ABILITYEFFECT_SWITCH_IN_TERRAIN 16 #define ABILITYEFFECT_SWITCH_IN_WEATHER 17 #define ABILITYEFFECT_OPPORTUNIST 18 +#define ABILITYEFFECT_SWITCH_IN_STATUSES 19 // Special cases #define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6 #define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6 diff --git a/include/config/battle.h b/include/config/battle.h index 163e4c0f08..d67b589a47 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -180,8 +180,8 @@ // Var Settings // To use the following features in scripting, replace the 0s with the var ID you're assigning it to. // Eg: Replace with VAR_UNUSED_0x40F7 so you can use B_VAR_TERRAIN for that feature. -#define B_VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active. -#define B_VAR_TERRAIN_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten. +#define B_VAR_STARTING_STATUS 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active. +#define B_VAR_STARTING_STATUS_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten. #define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15) // Sky Battles diff --git a/include/constants/battle.h b/include/constants/battle.h index a353fbb357..727e746443 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -517,4 +517,17 @@ // Constants for Torment #define PERMANENT_TORMENT 0xF +// Constants for B_VAR_STARTING_STATUS +// Timer value controlled by B_VAR_STARTING_STATUS_TIMER +#define STARTING_STATUS_NONE 0 +#define STARTING_STATUS_ELECTRIC_TERRAIN 1 +#define STARTING_STATUS_MISTY_TERRAIN 2 +#define STARTING_STATUS_GRASSY_TERRAIN 3 +#define STARTING_STATUS_PSYCHIC_TERRAIN 4 +#define STARTING_STATUS_TRICK_ROOM 5 +#define STARTING_STATUS_MAGIC_ROOM 6 +#define STARTING_STATUS_WONDER_ROOM 7 +#define STARTING_STATUS_TAILWIND_PLAYER 8 +#define STARTING_STATUS_TAILWIND_OPPONENT 9 + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index b085d305ab..8bc09ba530 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -563,6 +563,10 @@ #define B_ANIM_RAINBOW 42 #define B_ANIM_SEA_OF_FIRE 43 #define B_ANIM_SWAMP 44 +#define B_ANIM_TRICK_ROOM 45 +#define B_ANIM_WONDER_ROOM 46 +#define B_ANIM_MAGIC_ROOM 47 +#define B_ANIM_TAILWIND 48 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 852e9a26c6..e79e3f55a0 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -703,8 +703,11 @@ #define STRINGID_SHEDITSTAIL 701 #define STRINGID_CLOAKEDINAHARSHLIGHT 702 #define STRINGID_SUPERSWEETAROMAWAFTS 703 +#define STRINGID_DIMENSIONSWERETWISTED 704 +#define STRINGID_BIZARREARENACREATED 705 +#define STRINGID_BIZARREAREACREATED 706 -#define BATTLESTRINGS_COUNT 704 +#define BATTLESTRINGS_COUNT 707 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, @@ -967,6 +970,19 @@ #define B_MSG_TERRAIN_END_GRASSY 7 #define B_MSG_TERRAIN_COUNT 8 +// gStartingStatusStringIds +#define B_MSG_TERRAIN_SET_MISTY 0 +#define B_MSG_TERRAIN_SET_ELECTRIC 1 +#define B_MSG_TERRAIN_SET_PSYCHIC 2 +#define B_MSG_TERRAIN_SET_GRASSY 3 +#define B_MSG_SET_TRICK_ROOM 4 +#define B_MSG_SET_MAGIC_ROOM 5 +#define B_MSG_SET_WONDER_ROOM 6 +#define B_MSG_SET_TAILWIND_PLAYER 7 +#define B_MSG_SET_TAILWIND_OPPONENT 8 +#define B_MSG_STARTING_STATUS_COUNT 9 + + // gWrappedStringIds #define B_MSG_WRAPPED_BIND 0 #define B_MSG_WRAPPED_WRAP 1 diff --git a/include/data.h b/include/data.h index 4727dc605b..4ac1d327fa 100644 --- a/include/data.h +++ b/include/data.h @@ -88,7 +88,7 @@ struct Trainer /*0x13*/ u8 trainerName[TRAINER_NAME_LENGTH + 1]; /*0x1E*/ bool8 doubleBattle:1; bool8 mugshotEnabled:1; - u8 padding:6; + u8 startingStatus:6; // this trainer starts a battle with a given status. see include/constants/battle.h for values /*0x1F*/ u8 mugshotColor; /*0x20*/ u8 partySize; }; diff --git a/src/battle_main.c b/src/battle_main.c index 4aa7e43a91..7ed28ea63c 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3701,6 +3701,24 @@ static void DoBattleIntro(void) gBattleStruct->overworldWeatherDone = FALSE; SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers Ai_InitPartyStruct(); // Save mons party counts, and first 2/4 mons on the battlefield. + + // Try to set a status to start the battle with + gBattleStruct->startingStatus = 0; + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && gTrainers[gTrainerBattleOpponent_B].startingStatus) + { + gBattleStruct->startingStatus = gTrainers[gTrainerBattleOpponent_B].startingStatus; + gBattleStruct->startingStatusTimer = 0; // infinite + } + else if (gTrainers[gTrainerBattleOpponent_A].startingStatus) + { + gBattleStruct->startingStatus = gTrainers[gTrainerBattleOpponent_A].startingStatus; + gBattleStruct->startingStatusTimer = 0; // infinite + } + else if (B_VAR_STARTING_STATUS != 0) + { + gBattleStruct->startingStatus = VarGet(B_VAR_STARTING_STATUS); + gBattleStruct->startingStatusTimer = VarGet(B_VAR_STARTING_STATUS_TIMER); + } gBattleMainFunc = TryDoEventsBeforeFirstTurn; } break; @@ -3766,6 +3784,14 @@ static void TryDoEventsBeforeFirstTurn(void) return; } + if (!gBattleStruct->startingStatusDone + && gBattleStruct->startingStatus + && AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_STATUSES, 0, 0, ABILITYEFFECT_SWITCH_IN_STATUSES, 0) != 0) + { + gBattleStruct->startingStatusDone = TRUE; + return; + } + // Totem boosts for (i = 0; i < gBattlersCount; i++) { diff --git a/src/battle_message.c b/src/battle_message.c index a99f3cde9d..cad7916b94 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -559,6 +559,7 @@ static const u8 sText_PkmnSwitchedStatChanges[] = _("{B_ATK_NAME_WITH_PREFIX} sw static const u8 sText_PkmnSurroundedWithVeilOfWater[] = _("{B_ATK_NAME_WITH_PREFIX} surrounded itself\nwith a veil of water!"); static const u8 sText_PkmnLevitatedOnElectromagnetism[] = _("{B_ATK_NAME_WITH_PREFIX} levitated on\nelectromagnetism!"); static const u8 sText_PkmnTwistedDimensions[] = _("{B_ATK_NAME_WITH_PREFIX} twisted\nthe dimensions!"); +static const u8 sText_DimensionsWereTwisted[] = _("The dimensions were\ntwisted!"); static const u8 sText_PointedStonesFloat[] =_("Pointed stones float in the air\naround {B_DEF_TEAM2} team!"); static const u8 sText_CloakedInMysticalMoonlight[] =_("It became cloaked in mystical\nmoonlight!"); static const u8 sText_TrappedBySwirlingMagma[] =_("{B_DEF_NAME_WITH_PREFIX} became\ntrapped by swirling magma!"); @@ -567,9 +568,11 @@ static const u8 sText_ProtectedTeam[] =_("{B_CURRENT_MOVE} protected\n{B_ATK_TEA static const u8 sText_SharedItsGuard[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\nguard with the target!"); static const u8 sText_SharedItsPower[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\npower with the target!"); static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp. Def stats are swapped!"); +static const u8 sText_BizzareAreaCreated[] =_("A bizarre area was created in which the\nDefense and Sp. Def stats are swapped!"); static const u8 sText_BecameNimble[] =_("{B_ATK_NAME_WITH_PREFIX} became nimble!"); static const u8 sText_HurledIntoTheAir[] =_("{B_DEF_NAME_WITH_PREFIX} was hurled\ninto the air!"); static const u8 sText_HeldItemsLoseEffects[] =_("It created a bizarre area in which\nPokémon's held items lose their effects!"); +static const u8 sText_BizarreArenaCreated[] =_("A bizarre area was created!\nHold items lost their effects!"); static const u8 sText_FellStraightDown[] =_("{B_DEF_NAME_WITH_PREFIX} fell\nstraight down!"); static const u8 sText_TargetChangedType[] =_("{B_DEF_NAME_WITH_PREFIX} transformed\ninto the {B_BUFF1} type!"); static const u8 sText_PkmnAcquiredSimple[] =_("{B_DEF_NAME_WITH_PREFIX} acquired\nSimple!"); @@ -1384,6 +1387,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_PKMNSURROUNDEDWITHVEILOFWATER - BATTLESTRINGS_TABLE_START] = sText_PkmnSurroundedWithVeilOfWater, [STRINGID_PKMNLEVITATEDONELECTROMAGNETISM - BATTLESTRINGS_TABLE_START] = sText_PkmnLevitatedOnElectromagnetism, [STRINGID_PKMNTWISTEDDIMENSIONS - BATTLESTRINGS_TABLE_START] = sText_PkmnTwistedDimensions, + [STRINGID_DIMENSIONSWERETWISTED - BATTLESTRINGS_TABLE_START] = sText_DimensionsWereTwisted, [STRINGID_POINTEDSTONESFLOAT - BATTLESTRINGS_TABLE_START] = sText_PointedStonesFloat, [STRINGID_CLOAKEDINMYSTICALMOONLIGHT - BATTLESTRINGS_TABLE_START] = sText_CloakedInMysticalMoonlight, [STRINGID_TRAPPEDBYSWIRLINGMAGMA - BATTLESTRINGS_TABLE_START] = sText_TrappedBySwirlingMagma, @@ -1392,9 +1396,11 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_SHAREDITSGUARD - BATTLESTRINGS_TABLE_START] = sText_SharedItsGuard, [STRINGID_SHAREDITSPOWER - BATTLESTRINGS_TABLE_START] = sText_SharedItsPower, [STRINGID_SWAPSDEFANDSPDEFOFALLPOKEMON - BATTLESTRINGS_TABLE_START] = sText_SwapsDefAndSpDefOfAllPkmn, + [STRINGID_BIZARREAREACREATED - BATTLESTRINGS_TABLE_START] = sText_BizzareAreaCreated, [STRINGID_BECAMENIMBLE - BATTLESTRINGS_TABLE_START] = sText_BecameNimble, [STRINGID_HURLEDINTOTHEAIR - BATTLESTRINGS_TABLE_START] = sText_HurledIntoTheAir, [STRINGID_HELDITEMSLOSEEFFECTS - BATTLESTRINGS_TABLE_START] = sText_HeldItemsLoseEffects, + [STRINGID_BIZARREARENACREATED - BATTLESTRINGS_TABLE_START] = sText_BizarreArenaCreated, [STRINGID_FELLSTRAIGHTDOWN - BATTLESTRINGS_TABLE_START] = sText_FellStraightDown, [STRINGID_TARGETCHANGEDTYPE - BATTLESTRINGS_TABLE_START] = sText_TargetChangedType, [STRINGID_PKMNACQUIREDSIMPLE - BATTLESTRINGS_TABLE_START] = sText_PkmnAcquiredSimple, @@ -1563,6 +1569,19 @@ const u16 gMentalHerbCureStringIds[] = [B_MSG_MENTALHERBCURE_DISABLE] = STRINGID_PKMNMOVEDISABLEDNOMORE, }; +const u16 gStartingStatusStringIds[B_MSG_STARTING_STATUS_COUNT] = +{ + [B_MSG_TERRAIN_SET_MISTY] = STRINGID_TERRAINBECOMESMISTY, + [B_MSG_TERRAIN_SET_ELECTRIC] = STRINGID_TERRAINBECOMESELECTRIC, + [B_MSG_TERRAIN_SET_PSYCHIC] = STRINGID_TERRAINBECOMESPSYCHIC, + [B_MSG_TERRAIN_SET_GRASSY] = STRINGID_TERRAINBECOMESGRASSY, + [B_MSG_SET_TRICK_ROOM] = STRINGID_DIMENSIONSWERETWISTED, + [B_MSG_SET_MAGIC_ROOM] = STRINGID_BIZARREARENACREATED, + [B_MSG_SET_WONDER_ROOM] = STRINGID_BIZARREAREACREATED, + [B_MSG_SET_TAILWIND_PLAYER] = STRINGID_TAILWINDBLEW, + [B_MSG_SET_TAILWIND_OPPONENT] = STRINGID_TAILWINDBLEW, +}; + const u16 gTerrainStringIds[B_MSG_TERRAIN_COUNT] = { [B_MSG_TERRAIN_SET_MISTY] = STRINGID_TERRAINBECOMESMISTY, diff --git a/src/battle_util.c b/src/battle_util.c index b6f959ac67..43d8d675b6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1907,7 +1907,7 @@ u8 DoFieldEndTurnEffects(void) gBattlerAttacker = gSideTimers[side].tailwindBattlerId; if (gSideStatuses[side] & SIDE_STATUS_TAILWIND) { - if (--gSideTimers[side].tailwindTimer == 0) + if (gSideTimers[side].tailwindTimer > 0 && --gSideTimers[side].tailwindTimer == 0) { gSideStatuses[side] &= ~SIDE_STATUS_TAILWIND; BattleScriptExecute(BattleScript_TailwindEnds); @@ -2088,7 +2088,7 @@ u8 DoFieldEndTurnEffects(void) } break; case ENDTURN_TRICK_ROOM: - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && --gFieldTimers.trickRoomTimer == 0) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer > 0 && --gFieldTimers.trickRoomTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_TRICK_ROOM; BattleScriptExecute(BattleScript_TrickRoomEnds); @@ -2097,7 +2097,7 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_WONDER_ROOM: - if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM && --gFieldTimers.wonderRoomTimer == 0) + if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM && gFieldTimers.wonderRoomTimer > 0 && --gFieldTimers.wonderRoomTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_WONDER_ROOM; BattleScriptExecute(BattleScript_WonderRoomEnds); @@ -2106,7 +2106,7 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_MAGIC_ROOM: - if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM && --gFieldTimers.magicRoomTimer == 0) + if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM && gFieldTimers.magicRoomTimer > 0 && --gFieldTimers.magicRoomTimer == 0) { gFieldStatuses &= ~STATUS_FIELD_MAGIC_ROOM; BattleScriptExecute(BattleScript_MagicRoomEnds); @@ -4000,78 +4000,155 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 switch (caseID) { - case ABILITYEFFECT_SWITCH_IN_TERRAIN: + case ABILITYEFFECT_SWITCH_IN_STATUSES: // starting field/side/etc statuses with a variable { - u8 varTerrainTimer = VarGet(B_VAR_TERRAIN_TIMER); + u8 timerVal = gBattleStruct->startingStatusTimer; gBattleScripting.battler = battler; - if (VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY) + switch (gBattleStruct->startingStatus) { - u16 terrainFlags = VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY; // only works for status flag (1 << 15) - - if (varTerrainTimer == 0) + case STARTING_STATUS_ELECTRIC_TERRAIN: + if (!(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)) { - gFieldStatuses = terrainFlags | STATUS_FIELD_TERRAIN_PERMANENT; // terrain is permanent - } - else - { - gFieldStatuses |= terrainFlags; - gFieldTimers.terrainTimer = varTerrainTimer; - } - - switch (VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY) - { - case STATUS_FIELD_ELECTRIC_TERRAIN: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; - break; - case STATUS_FIELD_MISTY_TERRAIN: + gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN; + if (timerVal == 0) + gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT; + else + gFieldTimers.terrainTimer = timerVal; + effect = 2; + } + break; + case STARTING_STATUS_MISTY_TERRAIN: + if (!(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) + { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; - break; - case STATUS_FIELD_GRASSY_TERRAIN: + gFieldStatuses |= STATUS_FIELD_MISTY_TERRAIN; + if (timerVal == 0) + gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT; + else + gFieldTimers.terrainTimer = timerVal; + effect = 2; + } + break; + case STARTING_STATUS_GRASSY_TERRAIN: + if (!(gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN)) + { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY; - break; - case STATUS_FIELD_PSYCHIC_TERRAIN: + gFieldStatuses |= STATUS_FIELD_GRASSY_TERRAIN; + if (timerVal == 0) + gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT; + else + gFieldTimers.terrainTimer = timerVal; + effect = 2; + } + break; + case STARTING_STATUS_PSYCHIC_TERRAIN: + if (!(gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN)) + { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; - break; + gFieldStatuses |= STATUS_FIELD_PSYCHIC_TERRAIN; + if (timerVal == 0) + gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT; + else + gFieldTimers.terrainTimer = timerVal; + effect = 2; } - BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); - effect++; + break; + case STARTING_STATUS_TRICK_ROOM: + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_TRICK_ROOM; + gFieldStatuses |= STATUS_FIELD_TRICK_ROOM; + gBattleScripting.animArg1 = B_ANIM_TRICK_ROOM; + if (timerVal == 0) + gFieldTimers.trickRoomTimer = 0; // infinite + else + gFieldTimers.trickRoomTimer = 5; + effect = 1; + } + break; + case STARTING_STATUS_MAGIC_ROOM: + if (!(gFieldStatuses & STATUS_FIELD_MAGIC_ROOM)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MAGIC_ROOM; + gFieldStatuses |= STATUS_FIELD_MAGIC_ROOM; + gBattleScripting.animArg1 = B_ANIM_MAGIC_ROOM; + if (timerVal == 0) + gFieldTimers.magicRoomTimer = 0; // infinite + else + gFieldTimers.magicRoomTimer = 5; + effect = 1; + } + break; + case STARTING_STATUS_WONDER_ROOM: + if (!(gFieldStatuses & STATUS_FIELD_WONDER_ROOM)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_WONDER_ROOM; + gFieldStatuses |= STATUS_FIELD_WONDER_ROOM; + gBattleScripting.animArg1 = B_ANIM_WONDER_ROOM; + if (timerVal == 0) + gFieldTimers.wonderRoomTimer = 0; // infinite + else + gFieldTimers.wonderRoomTimer = 5; + effect = 1; + } + break; + case STARTING_STATUS_TAILWIND_PLAYER: + if (!(gSideStatuses[B_SIDE_PLAYER] & SIDE_STATUS_TAILWIND)) + { + gBattlerAttacker = B_POSITION_PLAYER_LEFT; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_TAILWIND_PLAYER; + gSideStatuses[B_SIDE_PLAYER] |= SIDE_STATUS_TAILWIND; + gBattleScripting.animArg1 = B_ANIM_TAILWIND; + if (timerVal == 0) + gSideTimers[B_SIDE_PLAYER].tailwindTimer = 0; // infinite + else + gSideTimers[B_SIDE_PLAYER].tailwindTimer = 5; + effect = 1; + } + break; + case STARTING_STATUS_TAILWIND_OPPONENT: + if (!(gSideStatuses[B_SIDE_OPPONENT] & SIDE_STATUS_TAILWIND)) + { + gBattlerAttacker = B_POSITION_OPPONENT_LEFT; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_TAILWIND_OPPONENT; + gSideStatuses[B_SIDE_OPPONENT] |= SIDE_STATUS_TAILWIND; + gBattleScripting.animArg1 = B_ANIM_TAILWIND; + if (timerVal == 0) + gSideTimers[B_SIDE_OPPONENT].tailwindTimer = 0; // infinite + else + gSideTimers[B_SIDE_OPPONENT].tailwindTimer = 5; + effect = 1; + } + break; } - else if (B_THUNDERSTORM_TERRAIN == TRUE - && GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM - && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)) - { - // overworld weather started rain, so just do electric terrain anim - if (varTerrainTimer == 0) - { - gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); - } - else - { - gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN; - gFieldTimers.terrainTimer = varTerrainTimer; - } - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; + + if (effect == 1) + BattleScriptPushCursorAndCallback(BattleScript_OverworldStatusStarts); + else if (effect == 2) BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); - effect++; - } - else if (B_FOG_TERRAIN == TRUE - && (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL) - && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) - { - if (varTerrainTimer == 0) - { - gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); - } - else - { - gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN; - gFieldTimers.terrainTimer = varTerrainTimer; - } - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; - BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); - effect++; - } + } + break; + case ABILITYEFFECT_SWITCH_IN_TERRAIN: // terrain starting from overworld weather + if (B_THUNDERSTORM_TERRAIN == TRUE + && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + && GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM) + { + // overworld weather started rain, so just do electric terrain anim + gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; + BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); + effect++; + } + else if (B_FOG_TERRAIN == TRUE + && (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL) + && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) + { + gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; + BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); + effect++; } break; case ABILITYEFFECT_SWITCH_IN_WEATHER: diff --git a/src/overworld.c b/src/overworld.c index 8bad752cc0..e53e556302 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -401,12 +401,12 @@ void Overworld_ResetStateAfterDigEscRope(void) #if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE void Overworld_ResetBattleFlagsAndVars(void) { - #if B_VAR_TERRAIN != 0 - VarSet(B_VAR_TERRAIN, 0); + #if B_VAR_STARTING_STATUS != 0 + VarSet(B_VAR_STARTING_STATUS, 0); #endif - #if B_VAR_TERRAIN_TIMER != 0 - VarSet(B_VAR_TERRAIN_TIMER, 0); + #if B_VAR_STARTING_STATUS_TIMER != 0 + VarSet(B_VAR_STARTING_STATUS_TIMER, 0); #endif #if B_VAR_WILD_AI_FLAGS != 0