pokeemmo/src/battle_util2.c
psf d1183f4b8a
Add B_SHOW_TYPES and cleaned up IsDoubleBattle (#5131)
* First attempt at a port

* Slightly broken but working

* Got images working and opponent palettes

* half finished compressed spritesheet approach instead

* fix the palettes (smh)

* fix hflip, and a lot of clean-up

* Add B_SHOW_TYPES

* Got Illusion working

* Add num type enum

* Updated function to get type

* Fixed type icon position and cleaned up functions

* Updated illusions and Tera handling

* Added BATTLE_TYPE_IS_SINGLE and DOUBLE

* Removed IS_BATTLE_TYPE_SINGLE

* Implemented BATTLE_TYPE_IS_DOUBLE across repo

* Removed SIDE macro

* Updated config

* Deprecated battler alive macro

* Reindented file

* Added exceptions for 2v1

* Replaced Fainted check with Null check

* Added functionality for only types of caught mons

* UseDoubleBattleCoords updated

* Added ShouldFlipTypeIcon

* Renamed TryLoadTypeIcon

* Refactored functions

* Refactored functions

* Refactored functions

* Refactored functions

* Renamed SEEN to CAUGHT

* Reset config

* Added useSecondPalette and isOrdinary to gTypesInfo

* Further simplified secondPalette and isOrdinary

* Changed isordinary to isSpecialCase

* Renamed to useSecondTypeIconPalette

* Fixed Stellar type interactions

* fixed spacing

* fixed include/config/battle.h

* fixed

* fixed include/config/general.h

* changed type1 and type2

* Moved IsDoubleBattle to include.battle.h
Removed BATTLE_TYPE_IS_DOUBLE
Removed IS_DOUBLE_BATTLE

* Changed IsBattlerFainted to IsBattlerAlive

* Removed IsBattlerNull

* Moved GetBattlerData to be inline

* Renamed GetMonDefensiveTeraType

* Removed IsIllusionActive

* Fixed identation

* found one last isDoubleBattle hold out

* fixed redundant brackets

* Fixed spacing for B_SHOW_TYPES

* Update src/battle_script_commands.c

Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>

* Fixed padding

* Reindent file and refactored GetTypeIconHideMovement

* Update include/data.h

---------

Co-authored-by: RavePossum <ravepossum@proton.me>
Co-authored-by: Frank <fdeblasio1004@gmail.com>
Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
2024-08-11 17:55:51 +02:00

217 lines
7.8 KiB
C

#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_controllers.h"
#include "malloc.h"
#include "pokemon.h"
#include "trainer_hill.h"
#include "party_menu.h"
#include "event_data.h"
#include "constants/abilities.h"
#include "random.h"
#include "battle_scripts.h"
#include "constants/battle_string_ids.h"
void AllocateBattleResources(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
InitTrainerHillBattleStruct();
gBattleStruct = AllocZeroed(sizeof(*gBattleStruct));
#if B_FLAG_SKY_BATTLE
gBattleStruct->isSkyBattle = FlagGet(B_FLAG_SKY_BATTLE);
#endif
gBattleResources = AllocZeroed(sizeof(*gBattleResources));
gBattleResources->secretBase = AllocZeroed(sizeof(*gBattleResources->secretBase));
gBattleResources->flags = AllocZeroed(sizeof(*gBattleResources->flags));
gBattleResources->battleScriptsStack = AllocZeroed(sizeof(*gBattleResources->battleScriptsStack));
gBattleResources->battleCallbackStack = AllocZeroed(sizeof(*gBattleResources->battleCallbackStack));
gBattleResources->beforeLvlUp = AllocZeroed(sizeof(*gBattleResources->beforeLvlUp));
gBattleResources->ai = AllocZeroed(sizeof(*gBattleResources->ai));
gBattleResources->aiData = AllocZeroed(sizeof(*gBattleResources->aiData));
gBattleResources->aiParty = AllocZeroed(sizeof(*gBattleResources->aiParty));
gBattleResources->battleHistory = AllocZeroed(sizeof(*gBattleResources->battleHistory));
gLinkBattleSendBuffer = AllocZeroed(BATTLE_BUFFER_LINK_SIZE);
gLinkBattleRecvBuffer = AllocZeroed(BATTLE_BUFFER_LINK_SIZE);
gBattleAnimBgTileBuffer = AllocZeroed(0x2000);
gBattleAnimBgTilemapBuffer = AllocZeroed(0x1000);
if (gBattleTypeFlags & BATTLE_TYPE_SECRET_BASE)
{
u16 currSecretBaseId = VarGet(VAR_CURRENT_SECRET_BASE);
CreateSecretBaseEnemyParty(&gSaveBlock1Ptr->secretBases[currSecretBaseId]);
}
}
void FreeBattleResources(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL)
FreeTrainerHillBattleStruct();
gFieldStatuses = 0;
if (gBattleResources != NULL)
{
FREE_AND_SET_NULL(gBattleStruct);
FREE_AND_SET_NULL(gBattleResources->secretBase);
FREE_AND_SET_NULL(gBattleResources->flags);
FREE_AND_SET_NULL(gBattleResources->battleScriptsStack);
FREE_AND_SET_NULL(gBattleResources->battleCallbackStack);
FREE_AND_SET_NULL(gBattleResources->beforeLvlUp);
FREE_AND_SET_NULL(gBattleResources->ai);
FREE_AND_SET_NULL(gBattleResources->aiData);
FREE_AND_SET_NULL(gBattleResources->aiParty);
FREE_AND_SET_NULL(gBattleResources->battleHistory);
FREE_AND_SET_NULL(gBattleResources);
FREE_AND_SET_NULL(gLinkBattleSendBuffer);
FREE_AND_SET_NULL(gLinkBattleRecvBuffer);
FREE_AND_SET_NULL(gBattleAnimBgTileBuffer);
FREE_AND_SET_NULL(gBattleAnimBgTilemapBuffer);
}
}
void AdjustFriendshipOnBattleFaint(u8 battler)
{
u8 opposingBattlerId;
if (IsDoubleBattle())
{
u8 opposingBattlerId2;
opposingBattlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
opposingBattlerId2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
if (gBattleMons[opposingBattlerId2].level > gBattleMons[opposingBattlerId].level)
opposingBattlerId = opposingBattlerId2;
}
else
{
opposingBattlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
}
if (gBattleMons[opposingBattlerId].level > gBattleMons[battler].level)
{
if (gBattleMons[opposingBattlerId].level - gBattleMons[battler].level > 29)
AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battler]], FRIENDSHIP_EVENT_FAINT_LARGE);
else
AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battler]], FRIENDSHIP_EVENT_FAINT_SMALL);
}
else
{
AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battler]], FRIENDSHIP_EVENT_FAINT_SMALL);
}
}
void SwitchPartyOrderInGameMulti(u8 battler, u8 arg1)
{
if (GetBattlerSide(battler) != B_SIDE_OPPONENT)
{
s32 i;
for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++)
gBattlePartyCurrentOrder[i] = *(0 * 3 + i + (u8 *)(gBattleStruct->battlerPartyOrders));
SwitchPartyMonSlots(GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[battler]), GetPartyIdFromBattlePartyId(arg1));
for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++)
*(0 * 3 + i + (u8 *)(gBattleStruct->battlerPartyOrders)) = gBattlePartyCurrentOrder[i];
}
}
// Called when a Pokémon is unable to attack during a Battle Palace battle.
// Check if it was because they are frozen/asleep, and if so try to cure the status.
u32 BattlePalace_TryEscapeStatus(u8 battler)
{
u32 effect = 0;
do
{
switch (gBattleCommunication[MULTIUSE_STATE])
{
case 0:
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
{
if (UproarWakeUpCheck(battler))
{
// Wake up from Uproar
gBattleMons[battler].status1 &= ~(STATUS1_SLEEP);
gBattleMons[battler].status2 &= ~(STATUS2_NIGHTMARE);
BattleScriptPushCursor();
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR;
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp;
effect = 2;
}
else
{
u32 toSub;
if (GetBattlerAbility(battler) == ABILITY_EARLY_BIRD)
toSub = 2;
else
toSub = 1;
// Reduce number of sleep turns
if ((gBattleMons[battler].status1 & STATUS1_SLEEP) < toSub)
gBattleMons[battler].status1 &= ~(STATUS1_SLEEP);
else
gBattleMons[battler].status1 -= toSub;
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
{
// Still asleep
gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep;
effect = 2;
}
else
{
// Wake up
gBattleMons[battler].status2 &= ~(STATUS2_NIGHTMARE);
BattleScriptPushCursor();
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP;
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp;
effect = 2;
}
}
}
gBattleCommunication[MULTIUSE_STATE]++;
break;
case 1:
if (gBattleMons[battler].status1 & STATUS1_FREEZE)
{
if (Random() % 5 != 0)
{
// Still frozen
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen;
}
else
{
// Unfreeze
gBattleMons[battler].status1 &= ~(STATUS1_FREEZE);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
}
effect = 2;
}
gBattleCommunication[MULTIUSE_STATE]++;
break;
case 2:
break;
}
// Loop until reaching the final state, or stop early if Pokémon was Asleep/Frozen
} while (gBattleCommunication[MULTIUSE_STATE] != 2 && effect == 0);
if (effect == 2)
{
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
}
return effect;
}