battle 2 is done

This commit is contained in:
DizzyEggg 2017-10-06 17:06:45 +02:00
parent 342e616d4b
commit 3cc20c7c3f
15 changed files with 708 additions and 1642 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2570,8 +2570,8 @@ _08033BB6:
.pool .pool
thumb_func_end EmitMoveAnimation thumb_func_end EmitMoveAnimation
thumb_func_start dp01_build_cmdbuf_x10_TODO thumb_func_start EmitPrintString
dp01_build_cmdbuf_x10_TODO: @ 8033BE4 EmitPrintString: @ 8033BE4
push {r4-r7,lr} push {r4-r7,lr}
mov r7, r10 mov r7, r10
mov r6, r9 mov r6, r9
@ -2685,7 +2685,7 @@ _08033C88:
pop {r0} pop {r0}
bx r0 bx r0
.pool .pool
thumb_func_end dp01_build_cmdbuf_x10_TODO thumb_func_end EmitPrintString
thumb_func_start EmitPrintStringPlayerOnly thumb_func_start EmitPrintStringPlayerOnly
EmitPrintStringPlayerOnly: @ 8033CFC EmitPrintStringPlayerOnly: @ 8033CFC

View File

@ -78,7 +78,7 @@ BattleScript_WildMonFled:: @ 82DAAF7
gUnknown_082DAAFE:: @ 82DAAFE gUnknown_082DAAFE:: @ 82DAAFE
.incbin "baserom.gba", 0x2daafe, 0x4 .incbin "baserom.gba", 0x2daafe, 0x4
gUnknown_082DAB02:: @ 82DAB02 BattleScript_PrintFailedToRunString:: @ 82DAB02
.incbin "baserom.gba", 0x2dab02, 0x9 .incbin "baserom.gba", 0x2dab02, 0x9
gUnknown_082DAB0B:: @ 82DAB0B gUnknown_082DAB0B:: @ 82DAB0B

View File

@ -33,7 +33,7 @@ gBattlescriptsForRunningByItem:: @ 82DBD54
.4byte BattleScript_RunByUsingItem .4byte BattleScript_RunByUsingItem
.align 2 .align 2
gUnknown_082DBD58:: @ 82DBD58 gBattlescriptsForSafariActions:: @ 82DBD58
.4byte gUnknown_082DBEBD .4byte gUnknown_082DBEBD
.4byte gUnknown_082DBEC4 .4byte gUnknown_082DBEC4
.4byte gUnknown_082DBECD .4byte gUnknown_082DBECD

View File

@ -1,6 +1,11 @@
#ifndef GUARD_BATTLE_H #ifndef GUARD_BATTLE_H
#define GUARD_BATTLE_H #define GUARD_BATTLE_H
// should they be included here or included individually by every file?
#include "battle_util.h"
#include "battle_script_commands.h"
#include "battle_2.h"
/* /*
Banks are a name given to what could be called a 'battlerId' or 'monControllerId'. Banks are a name given to what could be called a 'battlerId' or 'monControllerId'.
Each bank has a value consisting of two bits. Each bank has a value consisting of two bits.
@ -119,8 +124,8 @@
#define STATUS3_MINIMIZED 0x100 #define STATUS3_MINIMIZED 0x100
#define STATUS3_ROOTED 0x400 #define STATUS3_ROOTED 0x400
#define STATUS3_CHARGED_UP 0x200 #define STATUS3_CHARGED_UP 0x200
#define STATUS3_YAWN 0x1800 //two bits #define STATUS3_YAWN 0x1800 // two bits
#define STATUS3_IMPRISONED_OTHERS 0x2000 #define STATUS3_IMPRISONED_OTHERS 0x2000
#define STATUS3_GRUDGE 0x4000 #define STATUS3_GRUDGE 0x4000
#define STATUS3_CANT_SCORE_A_CRIT 0x8000 #define STATUS3_CANT_SCORE_A_CRIT 0x8000
#define STATUS3_MUDSPORT 0x10000 #define STATUS3_MUDSPORT 0x10000
@ -131,6 +136,7 @@
#define STATUS3_SEMI_INVULNERABLE ((STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)) #define STATUS3_SEMI_INVULNERABLE ((STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER))
#define HITMARKER_x10 0x00000010
#define HITMARKER_x20 0x00000020 #define HITMARKER_x20 0x00000020
#define HITMARKER_DESTINYBOND 0x00000040 #define HITMARKER_DESTINYBOND 0x00000040
#define HITMARKER_NO_ANIMATIONS 0x00000080 #define HITMARKER_NO_ANIMATIONS 0x00000080
@ -141,7 +147,7 @@
#define HITMARKER_PURSUIT_TRAP 0x00001000 #define HITMARKER_PURSUIT_TRAP 0x00001000
#define HITMARKER_IGNORE_SAFEGUARD 0x00002000 #define HITMARKER_IGNORE_SAFEGUARD 0x00002000
#define HITMARKER_SYNCHRONISE_EFFECT 0x00004000 #define HITMARKER_SYNCHRONISE_EFFECT 0x00004000
#define HITMARKER_x8000 0x00008000 #define HITMARKER_RUN 0x00008000
#define HITMARKER_IGNORE_ON_AIR 0x00010000 #define HITMARKER_IGNORE_ON_AIR 0x00010000
#define HITMARKER_IGNORE_UNDERGROUND 0x00020000 #define HITMARKER_IGNORE_UNDERGROUND 0x00020000
#define HITMARKER_IGNORE_UNDERWATER 0x00040000 #define HITMARKER_IGNORE_UNDERWATER 0x00040000
@ -152,6 +158,7 @@
#define HITMARKER_x800000 0x00800000 #define HITMARKER_x800000 0x00800000
#define HITMARKER_GRUDGE 0x01000000 #define HITMARKER_GRUDGE 0x01000000
#define HITMARKER_OBEYS 0x02000000 #define HITMARKER_OBEYS 0x02000000
#define HITMARKER_x4000000 0x04000000
#define HITMARKER_x8000000 0x08000000 #define HITMARKER_x8000000 0x08000000
#define HITMARKER_FAINTED(bank) ((gBitTable[bank] << 0x1C)) #define HITMARKER_FAINTED(bank) ((gBitTable[bank] << 0x1C))
#define HITMARKER_UNK(bank) ((0x10000000 << bank)) #define HITMARKER_UNK(bank) ((0x10000000 << bank))
@ -181,32 +188,6 @@
#define ACTION_NOTHING_FAINTED 13 // when choosing an action #define ACTION_NOTHING_FAINTED 13 // when choosing an action
#define ACTION_INIT_VALUE 0xFF #define ACTION_INIT_VALUE 0xFF
#define ABILITYEFFECT_ON_SWITCHIN 0x0
#define ABILITYEFFECT_ENDTURN 0x1
#define ABILITYEFFECT_MOVES_BLOCK 0x2
#define ABILITYEFFECT_ABSORBING 0x3
#define ABILITYEFFECT_CONTACT 0x4
#define ABILITYEFFECT_IMMUNITY 0x5
#define ABILITYEFFECT_FORECAST 0x6
#define ABILITYEFFECT_SYNCHRONIZE 0x7
#define ABILITYEFFECT_ATK_SYNCHRONIZE 0x8
#define ABILITYEFFECT_INTIMIDATE1 0x9
#define ABILITYEFFECT_INTIMIDATE2 0xA
#define ABILITYEFFECT_TRACE 0xB
#define ABILITYEFFECT_CHECK_OTHER_SIDE 0xC
#define ABILITYEFFECT_CHECK_BANK_SIDE 0xD
#define ABILITYEFFECT_FIELD_SPORT 0xE
#define ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK 0xF
#define ABILITYEFFECT_COUNT_OTHER_SIDE 0x10
#define ABILITYEFFECT_COUNT_BANK_SIDE 0x11
#define ABILITYEFFECT_COUNT_ON_FIELD 0x12
#define ABILITYEFFECT_CHECK_ON_FIELD 0x13
#define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF
#define ITEMEFFECT_ON_SWITCH_IN 0x0
#define WEATHER_HAS_EFFECT ((!AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ABILITY_CLOUD_NINE, 0, 0) && !AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ABILITY_AIR_LOCK, 0, 0)))
#define MOVESTATUS_MISSED (1 << 0) #define MOVESTATUS_MISSED (1 << 0)
#define MOVESTATUS_SUPEREFFECTIVE (1 << 1) #define MOVESTATUS_SUPEREFFECTIVE (1 << 1)
#define MOVESTATUS_NOTVERYEFFECTIVE (1 << 2) #define MOVESTATUS_NOTVERYEFFECTIVE (1 << 2)
@ -271,25 +252,6 @@
#define TYPE_MUL_NORMAL 10 #define TYPE_MUL_NORMAL 10
#define TYPE_MUL_SUPER_EFFECTIVE 20 #define TYPE_MUL_SUPER_EFFECTIVE 20
#define BS_GET_TARGET 0
#define BS_GET_ATTACKER 1
#define BS_GET_EFFECT_BANK 2
#define BS_ATTACKER_WITH_PARTNER 4 // for atk98_status_icon_update
#define BS_GET_ATTACKER_SIDE 8 // for atk1E_jumpifability
#define BS_GET_NOT_ATTACKER_SIDE 9 // for atk1E_jumpifability
#define BS_GET_SCRIPTING_BANK 10
#define BS_GET_OPPONENT1 12
#define BS_GET_PLAYER2 13
#define BS_GET_OPPONENT2 14
// for battle script commands
#define CMP_EQUAL 0x0
#define CMP_NOT_EQUAL 0x1
#define CMP_GREATER_THAN 0x2
#define CMP_LESS_THAN 0x3
#define CMP_COMMON_BITS 0x4
#define CMP_NO_COMMON_BITS 0x5
struct TrainerMonNoItemDefaultMoves struct TrainerMonNoItemDefaultMoves
{ {
u16 iv; u16 iv;
@ -375,8 +337,8 @@ struct DisableStruct
/*0x0F*/ u8 perishSong1 : 4; /*0x0F*/ u8 perishSong1 : 4;
/*0x0F*/ u8 perishSong2 : 4; /*0x0F*/ u8 perishSong2 : 4;
/*0x10*/ u8 furyCutterCounter; /*0x10*/ u8 furyCutterCounter;
/*0x11*/ u8 rolloutTimer1 : 4; /*0x11*/ u8 rolloutCounter1 : 4;
/*0x11*/ u8 rolloutTimer2 : 4; /*0x11*/ u8 rolloutCounter2 : 4;
/*0x12*/ u8 chargeTimer1 : 4; /*0x12*/ u8 chargeTimer1 : 4;
/*0x12*/ u8 chargeTimer2 : 4; /*0x12*/ u8 chargeTimer2 : 4;
/*0x13*/ u8 tauntTimer1:4; /*0x13*/ u8 tauntTimer1:4;
@ -408,7 +370,7 @@ struct ProtectStruct
u32 prlzImmobility:1; u32 prlzImmobility:1;
/* field_1 */ /* field_1 */
u32 confusionSelfDmg:1; u32 confusionSelfDmg:1;
u32 notEffective:1; u32 targetNotAffected:1;
u32 chargingTurn:1; u32 chargingTurn:1;
u32 fleeFlag:2; // for RunAway and Smoke Ball u32 fleeFlag:2; // for RunAway and Smoke Ball
u32 usedImprisionedMove:1; u32 usedImprisionedMove:1;
@ -574,6 +536,7 @@ struct BattleResults
u8 playerMon1Name[11]; // 0x8 u8 playerMon1Name[11]; // 0x8
u8 battleTurnCounter; // 0x13 u8 battleTurnCounter; // 0x13
u8 playerMon2Name[11]; // 0x14 u8 playerMon2Name[11]; // 0x14
u8 field_1F; // 0x1F
u16 lastOpponentSpecies; // 0x20 u16 lastOpponentSpecies; // 0x20
u16 lastUsedMovePlayer; // 0x22 u16 lastUsedMovePlayer; // 0x22
u16 lastUsedMoveOpponent; // 0x24 u16 lastUsedMoveOpponent; // 0x24
@ -814,39 +777,10 @@ extern struct BattleStruct* gBattleStruct;
#define B_ANIM_x1C 0x1C #define B_ANIM_x1C 0x1C
#define B_ANIM_x1D 0x1D #define B_ANIM_x1D 0x1D
#define ATK48_STAT_NEGATIVE 0x1
#define ATK48_STAT_BY_TWO 0x2
#define ATK48_BIT_x4 0x4
#define ATK48_LOWER_FAIL_CHECK 0x8
#define ATK4F_DONT_CHECK_STATUSES 0x80
#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0
#define VARIOUS_SET_MAGIC_COAT_TARGET 1
#define VARIOUS_CAN_RUN_FROM_BATTLE 2
#define VARIOUS_GET_MOVE_TARGET 3
#define VARIOUS_RESET_INTIMIDATE_TRACE_BITS 5
#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 6
#define VARIOUS_WAIT_CRY 18
#define VARIOUS_RETURN_OPPONENT_MON1 19
#define VARIOUS_RETURN_OPPONENT_MON2 20
#define VARIOUS_SET_TELEPORT_OUTCOME 25
#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26
#define ATK80_DMG_CHANGE_SIGN 0
#define ATK80_DMG_HALF_BY_TWO_NOT_MORE_THAN_HALF_MAX_HP 1
#define ATK80_DMG_DOUBLED 2
#define GET_STAT_BUFF_ID(n)((n & 0xF)) // first four bits 0x1, 0x2, 0x4, 0x8 #define GET_STAT_BUFF_ID(n)((n & 0xF)) // first four bits 0x1, 0x2, 0x4, 0x8
#define GET_STAT_BUFF_VALUE(n)(((n >> 4) & 7)) // 0x10, 0x20, 0x40 #define GET_STAT_BUFF_VALUE(n)(((n >> 4) & 7)) // 0x10, 0x20, 0x40
#define STAT_BUFF_NEGATIVE 0x80 // 0x80, the sign bit #define STAT_BUFF_NEGATIVE 0x80 // 0x80, the sign bit
#define STAT_CHANGE_BS_PTR 0x1
#define STAT_CHANGE_NOT_PROTECT_AFFECTED 0x20
#define STAT_CHANGE_WORKED 0
#define STAT_CHANGE_DIDNT_WORK 1
#define SET_STAT_BUFF_ID(n)((n & 0xF)) #define SET_STAT_BUFF_ID(n)((n & 0xF))
#define SET_STAT_BUFF_VALUE(n)(((s8)(((s8)(n) << 4)) & 0xF0)) #define SET_STAT_BUFF_VALUE(n)(((s8)(((s8)(n) << 4)) & 0xF0))
@ -892,78 +826,6 @@ void ApplyPlayerChosenFrameToBattleMenu(void);
bool8 LoadChosenBattleElement(u8 caseId); bool8 LoadChosenBattleElement(u8 caseId);
void task00_0800F6FC(u8 taskId); void task00_0800F6FC(u8 taskId);
// battle_2
void CB2_InitBattle(void);
void CB2_QuitRecordedBattle(void);
void CancelMultiTurnMoves(u8 bank);
void PressurePPLose(u8 bankAtk, u8 bankDef, u16 move);
void PrepareStringBattle(u16 stringId, u8 bank);
u8 GetBattleBank(u8 caseId);
void FaintClearSetData(void);
bool8 HasMoveFailed(u8 bank);
void SwitchInClearSetData(void);
void sub_803BDA0(u8 bank);
void sub_803FA70(u8 bank);
void BattleMainCB2(void);
void VBlankCB_Battle(void);
void ResetSentPokesToOpponentValue(void);
bool8 TryRunFromBattle(u8 bank);
bool8 IsRunningFromBattleImpossible(void);
void PressurePPLoseOnUsingPerishSong(u8 bankAtk);
void PressurePPLoseOnUsingImprision(u8 bankAtk);
u8 GetWhoStrikesFirst(u8 bank1, u8 bank2, bool8 ignoreChosenMoves);
void SwapTurnOrder(u8, u8);
void BattleTurnPassed(void);
void RunBattleScriptCommands_PopCallbacksStack(void);
void RunBattleScriptCommands(void);
// battle_3
#define MOVE_LIMITATION_ZEROMOVE (1 << 0)
#define MOVE_LIMITATION_PP (1 << 1)
#define MOVE_LIMITATION_DISABLED (1 << 2)
#define MOVE_LIMITATION_TORMENTED (1 << 3)
#define MOVE_LIMITATION_TAUNT (1 << 4)
#define MOVE_LIMITATION_IMPRISION (1 << 5)
void BattleScriptPush(const u8* bsPtr);
void BattleScriptPushCursor(void);
void BattleScriptPop(void);
u8 TrySetCantSelectMoveBattleScript(void);
u8 CheckMoveLimitations(u8 bank, u8 unusableMoves, u8 check);
bool8 AreAllMovesUnusable(void);
u8 GetImprisonedMovesCount(u8 bank, u16 move);
u8 UpdateTurnCounters(void);
u8 TurnBasedEffects(void);
bool8 sub_8041364(void);
bool8 sub_8041728(void);
void TryClearRageStatuses(void);
u8 AtkCanceller_UnableToUseMove(void);
bool8 sub_80423F4(u8 bank, u8 r1, u8 r2);
u8 CastformDataTypeChange(u8 bank);
u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg);
void BattleScriptExecute(const u8* BS_ptr);
void BattleScriptPushCursorAndCallback(const u8* BS_ptr);
u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn);
void ClearFuryCutterDestinyBondGrudge(u8 bank);
void sub_80458B4(void);
u8 GetMoveTarget(u16 move, u8 useMoveTarget);
u8 IsPokeDisobedient(void);
// battle_script_commands
void AI_CalcDmg(u8 bankAtk, u8 bankDef);
u8 TypeCalc(u16 move, u8 bankAtk, u8 bankDef);
u8 AI_TypeCalc(u16 move, u16 species, u8 ability);
u8 BankGetTurnOrder(u8 bank);
void SetMoveEffect(bool8 primary, u8 certain);
void BattleDestroyCursorAt(u8 cursorPosition);
void BattleCreateCursorAt(u8 cursorPosition);
void BufferMoveToLearnIntoBattleTextBuff2(void);
void sub_8056A3C(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 bank);
extern void (* const gBattleScriptingCommandsTable[])(void);
extern const u8 gUnknown_0831C494[];
// battle_5 // battle_5
void AllocateBattleResrouces(void); void AllocateBattleResrouces(void);
void FreeBattleResources(void); void FreeBattleResources(void);

19
include/battle_2.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef GUARD_BATTLE_2_H
#define GUARD_BATTLE_2_H
void CB2_InitBattle(void);
void CB2_QuitRecordedBattle(void);
void FaintClearSetData(void);
void SwitchInClearSetData(void);
void sub_803BDA0(u8 bank);
void BattleMainCB2(void);
void VBlankCB_Battle(void);
bool8 TryRunFromBattle(u8 bank);
u8 IsRunningFromBattleImpossible(void);
u8 GetWhoStrikesFirst(u8 bank1, u8 bank2, bool8 ignoreChosenMoves);
void SwapTurnOrder(u8 id1, u8 id2);
void BattleTurnPassed(void);
void RunBattleScriptCommands_PopCallbacksStack(void);
void RunBattleScriptCommands(void);
#endif // GUARD_BATTLE_2_H

View File

@ -1,6 +1,28 @@
#ifndef GUARD_BATTLE_CONTROLLERS_H #ifndef GUARD_BATTLE_CONTROLLERS_H
#define GUARD_BATTLE_CONTROLLERS_H #define GUARD_BATTLE_CONTROLLERS_H
#define REQUEST_ALL_BATTLE 0x0
#define REQUEST_SPECIES_BATTLE 0x1
#define REQUEST_HELDITEM_BATTLE 0x2
#define REQUEST_MOVES_PP_BATTLE 0x3
#define REQUEST_PPMOVE1_BATTLE 0x9
#define REQUEST_PPMOVE2_BATTLE 0xA
#define REQUEST_PPMOVE3_BATTLE 0xB
#define REQUEST_PPMOVE4_BATTLE 0xC
#define REQUEST_STATUS_BATTLE 0x28
#define REQUEST_HP_BATTLE 0x2A
#define RESET_ACTION_MOVE_SELECTION 0
#define RESET_ACTION_SELECTION 1
#define RESET_MOVE_SELECTION 2
#define BALL_NO_SHAKES 0
#define BALL_1_SHAKE 1
#define BALL_2_SHAKES 2
#define BALL_3_SHAKES_FAIL 3
#define BALL_3_SHAKES_SUCCESS 4
#define BALL_TRAINER_BLOCK 5
struct HpAndStatus struct HpAndStatus
{ {
u16 hp; u16 hp;
@ -24,17 +46,6 @@ struct ChooseMoveStruct
u8 monType2; u8 monType2;
}; };
#define REQUEST_ALL_BATTLE 0x0
#define REQUEST_SPECIES_BATTLE 0x1
#define REQUEST_HELDITEM_BATTLE 0x2
#define REQUEST_MOVES_PP_BATTLE 0x3
#define REQUEST_PPMOVE1_BATTLE 0x9
#define REQUEST_PPMOVE2_BATTLE 0xA
#define REQUEST_PPMOVE3_BATTLE 0xB
#define REQUEST_PPMOVE4_BATTLE 0xC
#define REQUEST_STATUS_BATTLE 0x28
#define REQUEST_HP_BATTLE 0x2A
// rom3.s, emitters // rom3.s, emitters
void EmitSetMonData(u8 bufferId, u8 request, u8 c, u8 bytes, void *data); void EmitSetMonData(u8 bufferId, u8 request, u8 c, u8 bytes, void *data);
void EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct* disableStructPtr, u8 multihit); void EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct* disableStructPtr, u8 multihit);
@ -70,22 +81,8 @@ void EmitChooseAction(u8 bufferId, u8 arg1, u16 arg2);
void EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct* movePpData); void EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct* movePpData);
void EmitOpenBag(u8 bufferId, u8* arg1); void EmitOpenBag(u8 bufferId, u8* arg1);
void Emit_x32(u8 bufferId); void Emit_x32(u8 bufferId);
void EmitPrintString(u8 bufferId, u16 stringId);
#define RESET_ACTION_MOVE_SELECTION 0
#define RESET_ACTION_SELECTION 1
#define RESET_MOVE_SELECTION 2
void EmitResetActionMoveSelection(u8 bufferId, u8 caseId); void EmitResetActionMoveSelection(u8 bufferId, u8 caseId);
#define BALL_NO_SHAKES 0
#define BALL_1_SHAKE 1
#define BALL_2_SHAKES 2
#define BALL_3_SHAKES_FAIL 3
#define BALL_3_SHAKES_SUCCESS 4
#define BALL_TRAINER_BLOCK 5
void EmitBallThrow(u8 bufferId, u8 caseId); void EmitBallThrow(u8 bufferId, u8 caseId);
void MarkBufferBankForExecution(u8 bank);
#endif // GUARD_BATTLE_CONTROLLERS_H #endif // GUARD_BATTLE_CONTROLLERS_H

View File

@ -0,0 +1,58 @@
#ifndef GUARD_BATTLE_SCRIPT_COMMANDS_H
#define GUARD_BATTLE_SCRIPT_COMMANDS_H
#define CMP_EQUAL 0x0
#define CMP_NOT_EQUAL 0x1
#define CMP_GREATER_THAN 0x2
#define CMP_LESS_THAN 0x3
#define CMP_COMMON_BITS 0x4
#define CMP_NO_COMMON_BITS 0x5
#define BS_ATTACKER_WITH_PARTNER 4 // for atk98_status_icon_update
#define BS_GET_ATTACKER_SIDE 8 // for atk1E_jumpifability
#define BS_GET_NOT_ATTACKER_SIDE 9 // for atk1E_jumpifability
#define ATK48_STAT_NEGATIVE 0x1
#define ATK48_STAT_BY_TWO 0x2
#define ATK48_BIT_x4 0x4
#define ATK48_LOWER_FAIL_CHECK 0x8
#define ATK4F_DONT_CHECK_STATUSES 0x80
#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0
#define VARIOUS_SET_MAGIC_COAT_TARGET 1
#define VARIOUS_CAN_RUN_FROM_BATTLE 2
#define VARIOUS_GET_MOVE_TARGET 3
#define VARIOUS_RESET_INTIMIDATE_TRACE_BITS 5
#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 6
#define VARIOUS_WAIT_CRY 18
#define VARIOUS_RETURN_OPPONENT_MON1 19
#define VARIOUS_RETURN_OPPONENT_MON2 20
#define VARIOUS_SET_TELEPORT_OUTCOME 25
#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26
#define ATK80_DMG_CHANGE_SIGN 0
#define ATK80_DMG_HALF_BY_TWO_NOT_MORE_THAN_HALF_MAX_HP 1
#define ATK80_DMG_DOUBLED 2
#define STAT_CHANGE_BS_PTR 0x1
#define STAT_CHANGE_NOT_PROTECT_AFFECTED 0x20
#define STAT_CHANGE_WORKED 0
#define STAT_CHANGE_DIDNT_WORK 1
void AI_CalcDmg(u8 bankAtk, u8 bankDef);
u8 TypeCalc(u16 move, u8 bankAtk, u8 bankDef);
u8 AI_TypeCalc(u16 move, u16 species, u8 ability);
u8 BankGetTurnOrder(u8 bank);
void SetMoveEffect(bool8 primary, u8 certain);
void BattleDestroyCursorAt(u8 cursorPosition);
void BattleCreateCursorAt(u8 cursorPosition);
void BufferMoveToLearnIntoBattleTextBuff2(void);
void sub_8056A3C(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 bank);
extern void (* const gBattleScriptingCommandsTable[])(void);
extern const u8 gUnknown_0831C494[];
#endif // GUARD_BATTLE_SCRIPT_COMMANDS_H

83
include/battle_util.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef GUARD_BATTLE_UTIL_H
#define GUARD_BATTLE_UTIL_H
#define MOVE_LIMITATION_ZEROMOVE (1 << 0)
#define MOVE_LIMITATION_PP (1 << 1)
#define MOVE_LIMITATION_DISABLED (1 << 2)
#define MOVE_LIMITATION_TORMENTED (1 << 3)
#define MOVE_LIMITATION_TAUNT (1 << 4)
#define MOVE_LIMITATION_IMPRISION (1 << 5)
#define ABILITYEFFECT_ON_SWITCHIN 0x0
#define ABILITYEFFECT_ENDTURN 0x1
#define ABILITYEFFECT_MOVES_BLOCK 0x2
#define ABILITYEFFECT_ABSORBING 0x3
#define ABILITYEFFECT_CONTACT 0x4
#define ABILITYEFFECT_IMMUNITY 0x5
#define ABILITYEFFECT_FORECAST 0x6
#define ABILITYEFFECT_SYNCHRONIZE 0x7
#define ABILITYEFFECT_ATK_SYNCHRONIZE 0x8
#define ABILITYEFFECT_INTIMIDATE1 0x9
#define ABILITYEFFECT_INTIMIDATE2 0xA
#define ABILITYEFFECT_TRACE 0xB
#define ABILITYEFFECT_CHECK_OTHER_SIDE 0xC
#define ABILITYEFFECT_CHECK_BANK_SIDE 0xD
#define ABILITYEFFECT_FIELD_SPORT 0xE
#define ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK 0xF
#define ABILITYEFFECT_COUNT_OTHER_SIDE 0x10
#define ABILITYEFFECT_COUNT_BANK_SIDE 0x11
#define ABILITYEFFECT_COUNT_ON_FIELD 0x12
#define ABILITYEFFECT_CHECK_ON_FIELD 0x13
#define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF
#define ITEMEFFECT_ON_SWITCH_IN 0x0
#define WEATHER_HAS_EFFECT ((!AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ABILITY_CLOUD_NINE, 0, 0) && !AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ABILITY_AIR_LOCK, 0, 0)))
#define BS_GET_TARGET 0
#define BS_GET_ATTACKER 1
#define BS_GET_EFFECT_BANK 2
#define BS_GET_SCRIPTING_BANK 10
#define BS_GET_PLAYER1 11
#define BS_GET_OPPONENT1 12
#define BS_GET_PLAYER2 13
#define BS_GET_OPPONENT2 14
u8 GetBattleBank(u8 caseId);
void PressurePPLose(u8 bankDef, u8 bankAtk, u16 move);
void PressurePPLoseOnUsingPerishSong(u8 bankAtk);
void PressurePPLoseOnUsingImprision(u8 bankAtk);
void MarkAllBufferBanksForExecution(void); // unused
void MarkBufferBankForExecution(u8 bank);
void sub_803F850(u8 arg0);
void CancelMultiTurnMoves(u8 bank);
bool8 WasUnableToUseMove(u8 bank);
void PrepareStringBattle(u16 stringId, u8 bank);
void ResetSentPokesToOpponentValue(void);
void sub_803F9EC(u8 bank);
void sub_803FA70(u8 bank);
void BattleScriptPush(const u8* bsPtr);
void BattleScriptPushCursor(void);
void BattleScriptPop(void);
u8 TrySetCantSelectMoveBattleScript(void);
u8 CheckMoveLimitations(u8 bank, u8 unusableMoves, u8 check);
bool8 AreAllMovesUnusable(void);
u8 GetImprisonedMovesCount(u8 bank, u16 move);
u8 UpdateTurnCounters(void);
u8 TurnBasedEffects(void);
bool8 sub_8041364(void);
bool8 sub_8041728(void);
void TryClearRageStatuses(void);
u8 AtkCanceller_UnableToUseMove(void);
bool8 sub_80423F4(u8 bank, u8 r1, u8 r2);
u8 CastformDataTypeChange(u8 bank);
u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg);
void BattleScriptExecute(const u8* BS_ptr);
void BattleScriptPushCursorAndCallback(const u8* BS_ptr);
u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn);
void ClearFuryCutterDestinyBondGrudge(u8 bank);
void HandleAction_RunBattleScript(void);
u8 GetMoveTarget(u16 move, u8 useMoveTarget);
u8 IsPokeDisobedient(void);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -183,5 +183,6 @@ bool8 sub_800A520(void);
bool8 sub_8010500(void); bool8 sub_8010500(void);
void sub_800DFB4(u8, u8); void sub_800DFB4(u8, u8);
void sub_800ADF8(void); void sub_800ADF8(void);
u8 sub_8009FCC(void);
#endif // GUARD_LINK_H #endif // GUARD_LINK_H

View File

@ -640,6 +640,8 @@ u8 CheckPartyPokerus(struct Pokemon *party, u8 selection);
u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection); u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection);
void UpdatePartyPokerusTime(u16 days); void UpdatePartyPokerusTime(u16 days);
void PartySpreadPokerus(struct Pokemon *party); void PartySpreadPokerus(struct Pokemon *party);
s8 GetMonFlavourRelation(struct Pokemon *mon, u8 a2);
s8 GetFlavourRelationByPersonality(u32 personality, u8 a2);
#include "sprite.h" #include "sprite.h"

View File

@ -58,8 +58,7 @@ SECTIONS {
src/decompress.o(.text); src/decompress.o(.text);
asm/battle_1.o(.text); asm/battle_1.o(.text);
src/battle_2.o(.text); src/battle_2.o(.text);
asm/battle_2.o(.text); src/battle_util.o(.text);
src/battle_3.o(.text);
src/battle_script_commands.o(.text); src/battle_script_commands.o(.text);
asm/battle_5.o(.text); asm/battle_5.o(.text);
asm/battle_controller_player.o(.text); asm/battle_controller_player.o(.text);

View File

@ -40,6 +40,7 @@
#include "trainer_classes.h" #include "trainer_classes.h"
#include "evolution_scene.h" #include "evolution_scene.h"
#include "roamer.h" #include "roamer.h"
#include "safari_zone.h"
struct UnknownStruct6 struct UnknownStruct6
{ {
@ -157,6 +158,10 @@ extern const struct BgTemplate gUnknown_0831AA08[];
extern const struct WindowTemplate * const gUnknown_0831ABA0[]; extern const struct WindowTemplate * const gUnknown_0831ABA0[];
extern const u8 gUnknown_0831ACE0[]; extern const u8 gUnknown_0831ACE0[];
extern const u8 gStatStageRatios[][2]; extern const u8 gStatStageRatios[][2];
extern const u8 gUnknown_0831BCE0[];
extern const u8 gUnknown_0831BCEF[];
extern const u8 gUnknown_0831BCF3[];
extern const u8 * const gBattleScriptsForMoveEffects[];
// strings // strings
extern const u8 gText_LinkStandby3[]; extern const u8 gText_LinkStandby3[];
@ -190,6 +195,7 @@ extern const u8 BattleScript_GotAwaySafely[];
extern const u8 BattleScript_WildMonFled[]; extern const u8 BattleScript_WildMonFled[];
extern const u8 BattleScript_MoveUsedLoafingAround[]; extern const u8 BattleScript_MoveUsedLoafingAround[];
extern const u8 BattleScript_ActionSwitch[]; extern const u8 BattleScript_ActionSwitch[];
extern const u8 BattleScript_PrintFailedToRunString[];
// functions // functions
extern void HandleLinkBattleSetup(void); // rom_3 extern void HandleLinkBattleSetup(void); // rom_3
@ -2942,7 +2948,7 @@ void FaintClearSetData(void)
gProtectStructs[gActiveBank].flag0Unknown = 0; gProtectStructs[gActiveBank].flag0Unknown = 0;
gProtectStructs[gActiveBank].prlzImmobility = 0; gProtectStructs[gActiveBank].prlzImmobility = 0;
gProtectStructs[gActiveBank].confusionSelfDmg = 0; gProtectStructs[gActiveBank].confusionSelfDmg = 0;
gProtectStructs[gActiveBank].notEffective = 0; gProtectStructs[gActiveBank].targetNotAffected = 0;
gProtectStructs[gActiveBank].chargingTurn = 0; gProtectStructs[gActiveBank].chargingTurn = 0;
gProtectStructs[gActiveBank].fleeFlag = 0; gProtectStructs[gActiveBank].fleeFlag = 0;
gProtectStructs[gActiveBank].usedImprisionedMove = 0; gProtectStructs[gActiveBank].usedImprisionedMove = 0;
@ -3824,15 +3830,18 @@ void sub_803BDA0(u8 bank)
} }
} }
#define STATE_TURN_START_RECORD 0 enum
#define STATE_BEFORE_ACTION_CHOSEN 1 {
#define STATE_WAIT_ACTION_CHOSEN 2 STATE_TURN_START_RECORD,
#define STATE_WAIT_ACTION_CASE_CHOSEN 3 STATE_BEFORE_ACTION_CHOSEN,
#define STATE_WAIT_ACTION_CONFIRMED_STANDBY 4 STATE_WAIT_ACTION_CHOSEN,
#define STATE_WAIT_ACTION_CONFIRMED 5 STATE_WAIT_ACTION_CASE_CHOSEN,
#define STATE_SELECTION_SCRIPT 6 STATE_WAIT_ACTION_CONFIRMED_STANDBY,
#define STATE_WAIT_SET_BEFORE_ACTION 7 STATE_WAIT_ACTION_CONFIRMED,
#define STATE_SELECTION_SCRIPT_MAY_RUN 8 STATE_SELECTION_SCRIPT,
STATE_WAIT_SET_BEFORE_ACTION,
STATE_SELECTION_SCRIPT_MAY_RUN
};
void HandleTurnActionSelectionState(void) void HandleTurnActionSelectionState(void)
{ {
@ -4137,7 +4146,7 @@ void HandleTurnActionSelectionState(void)
} }
break; break;
case ACTION_RUN: case ACTION_RUN:
gHitMarker |= HITMARKER_x8000; gHitMarker |= HITMARKER_RUN;
gBattleCommunication[gActiveBank]++; gBattleCommunication[gActiveBank]++;
break; break;
case ACTION_WATCHES_CAREFULLY: case ACTION_WATCHES_CAREFULLY:
@ -4160,7 +4169,7 @@ void HandleTurnActionSelectionState(void)
gBattleCommunication[gActiveBank]++; gBattleCommunication[gActiveBank]++;
break; break;
case ACTION_SAFARI_ZONE_RUN: case ACTION_SAFARI_ZONE_RUN:
gHitMarker |= HITMARKER_x8000; gHitMarker |= HITMARKER_RUN;
gBattleCommunication[gActiveBank]++; gBattleCommunication[gActiveBank]++;
break; break;
case ACTION_9: case ACTION_9:
@ -4221,7 +4230,7 @@ void HandleTurnActionSelectionState(void)
{ {
if (gBattleBufferB[gActiveBank][1] == 13) if (gBattleBufferB[gActiveBank][1] == 13)
{ {
gHitMarker |= HITMARKER_x8000; gHitMarker |= HITMARKER_RUN;
gActionForBanks[gActiveBank] = ACTION_RUN; gActionForBanks[gActiveBank] = ACTION_RUN;
gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED_STANDBY; gBattleCommunication[gActiveBank] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
} }
@ -4613,7 +4622,7 @@ void SpecialStatusesClear(void)
static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void)
{ {
if (!(gHitMarker & HITMARKER_x8000)) if (!(gHitMarker & HITMARKER_RUN))
{ {
while (gBattleStruct->focusPunchBank < gNoOfAllBanks) while (gBattleStruct->focusPunchBank < gNoOfAllBanks)
{ {
@ -4976,8 +4985,6 @@ void RunBattleScriptCommands(void)
gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
} }
extern const u8 * const gBattleScriptsForMoveEffects[];
void HandleAction_UseMove(void) void HandleAction_UseMove(void)
{ {
u8 side; u8 side;
@ -5216,6 +5223,7 @@ void HandleAction_Switch(void)
extern const u8 * const gBattlescriptsForBallThrow[]; extern const u8 * const gBattlescriptsForBallThrow[];
extern const u8 * const gBattlescriptsForRunningByItem[]; extern const u8 * const gBattlescriptsForRunningByItem[];
extern const u8 * const gUnknown_082DBD3C[]; extern const u8 * const gUnknown_082DBD3C[];
extern const u8 * const gBattlescriptsForSafariActions[];
void HandleAction_UseItem(void) void HandleAction_UseItem(void)
{ {
@ -5375,3 +5383,198 @@ bool8 TryRunFromBattle(u8 bank)
return effect; return effect;
} }
void HandleAction_Run(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
{
gCurrentTurnActionNumber = gNoOfAllBanks;
for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
{
if (GetBankSide(gActiveBank) == SIDE_PLAYER)
{
if (gActionForBanks[gActiveBank] == ACTION_RUN)
gBattleOutcome |= BATTLE_LOST;
}
else
{
if (gActionForBanks[gActiveBank] == ACTION_RUN)
gBattleOutcome |= BATTLE_WON;
}
}
gBattleOutcome |= BATTLE_OUTCOME_BIT_x80;
gSaveBlock2Ptr->field_CA9_b = 1;
}
else
{
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
{
if (!TryRunFromBattle(gBankAttacker)) // failed to run away
{
ClearFuryCutterDestinyBondGrudge(gBankAttacker);
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
}
}
else
{
if (gBattleMons[gBankAttacker].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
{
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
}
else
{
gCurrentTurnActionNumber = gNoOfAllBanks;
gBattleOutcome = BATTLE_POKE_FLED;
}
}
}
}
void HandleAction_WatchesCarefully(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
gBattlescriptCurrInstr = gBattlescriptsForSafariActions[0];
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
}
void HandleAction_SafariZoneBallThrow(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
gNumSafariBalls--;
gLastUsedItem = ITEM_SAFARI_BALL;
gBattlescriptCurrInstr = gBattlescriptsForBallThrow[ITEM_SAFARI_BALL];
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
}
void HandleAction_ThrowPokeblock(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
gBattleCommunication[MULTISTRING_CHOOSER] = gBattleBufferB[gBankAttacker][1] - 1;
gLastUsedItem = gBattleBufferB[gBankAttacker][2];
if (gBattleResults.field_1F < 0xFF)
gBattleResults.field_1F++;
if (gBattleStruct->field_7A < 3)
gBattleStruct->field_7A++;
if (gBattleStruct->field_7B > 1)
{
if (gBattleStruct->field_7B < gUnknown_0831BCE0[3 * gBattleStruct->field_7A + gBattleCommunication[MULTISTRING_CHOOSER]])
gBattleStruct->field_7B = 1;
else
gBattleStruct->field_7B -= gUnknown_0831BCE0[3 * gBattleStruct->field_7A + gBattleCommunication[MULTISTRING_CHOOSER]];
}
gBattlescriptCurrInstr = gBattlescriptsForSafariActions[2];
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
}
void HandleAction_GoNear(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
gBattleStruct->field_7C += gUnknown_0831BCEF[gBattleStruct->field_79];
if (gBattleStruct->field_7C > 20)
gBattleStruct->field_7C = 20;
gBattleStruct->field_7B +=gUnknown_0831BCF3[gBattleStruct->field_79];
if (gBattleStruct->field_7B > 20)
gBattleStruct->field_7B = 20;
if (gBattleStruct->field_79 < 3)
{
gBattleStruct->field_79++;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
gBattlescriptCurrInstr = gBattlescriptsForSafariActions[1];
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
}
void HandleAction_SafriZoneRun(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
PlaySE(SE_NIGERU);
gCurrentTurnActionNumber = gNoOfAllBanks;
gBattleOutcome = BATTLE_RAN;
}
void HandleAction_Action9(void)
{
gBankAttacker = gBanksByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBankAttacker, gBattlePartyID[gBankAttacker])
gBattlescriptCurrInstr = gBattlescriptsForSafariActions[3];
gCurrentActionFuncId = ACTION_RUN_BATTLESCRIPT;
gActionsByTurnOrder[1] = ACTION_FINISHED;
}
void HandleAction_Action11(void)
{
if (!sub_8041728())
{
gBattleStruct->field_4D = 0;
gCurrentActionFuncId = ACTION_FINISHED;
}
}
void HandleAction_NothingIsFainted(void)
{
gCurrentTurnActionNumber++;
gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
| HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_IGNORE_ON_AIR
| HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_x100000
| HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
| HITMARKER_x8000000 | HITMARKER_x4000000);
}
void HandleAction_ActionFinished(void)
{
*(gBattleStruct->field_5C + gBanksByTurnOrder[gCurrentTurnActionNumber]) = 6;
gCurrentTurnActionNumber++;
gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
SpecialStatusesClear();
gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
| HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_IGNORE_ON_AIR
| HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_x100000
| HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
| HITMARKER_x8000000 | HITMARKER_x4000000);
gCurrentMove = 0;
gBattleMoveDamage = 0;
gBattleMoveFlags = 0;
gBattleScripting.animTurn = 0;
gBattleScripting.animTargetsHit = 0;
gUnknown_02024250[gBankAttacker] = 0;
gUnknown_02024258[gBankAttacker] = 0;
gBattleStruct->dynamicMoveType = 0;
gDynamicBasePower = 0;
gBattleScripting.atk49_state = 0;
gBattleCommunication[3] = 0;
gBattleCommunication[4] = 0;
gBattleScripting.field_16 = 0;
gBattleResources->battleScriptsStack->size = 0;
}

View File

@ -1600,7 +1600,7 @@ static void atk06_typecalc(void)
RecordAbilityBattle(gBankTarget, gLastUsedAbility); RecordAbilityBattle(gBankTarget, gLastUsedAbility);
} }
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
gProtectStructs[gBankAttacker].notEffective = 1; gProtectStructs[gBankAttacker].targetNotAffected = 1;
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
} }
@ -1639,14 +1639,14 @@ static void CheckWonderGuardAndLevitate(void)
if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 0) if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 0)
{ {
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
gProtectStructs[gBankAttacker].notEffective = 1; gProtectStructs[gBankAttacker].targetNotAffected = 1;
} }
if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 && if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 &&
gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 &&
gTypeEffectiveness[i + 2] == TYPE_MUL_NO_EFFECT) gTypeEffectiveness[i + 2] == TYPE_MUL_NO_EFFECT)
{ {
gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
gProtectStructs[gBankAttacker].notEffective = 1; gProtectStructs[gBankAttacker].targetNotAffected = 1;
} }
// check super effective // check super effective
@ -5066,7 +5066,7 @@ static void atk49_moveend(void)
case 9: // make attacker sprite visible case 9: // make attacker sprite visible
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT if (gBattleMoveFlags & MOVESTATUS_NOEFFECT
|| !(gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE)) || !(gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE))
|| HasMoveFailed(gBankAttacker)) || WasUnableToUseMove(gBankAttacker))
{ {
gActiveBank = gBankAttacker; gActiveBank = gBankAttacker;
EmitSpriteInvisibility(0, FALSE); EmitSpriteInvisibility(0, FALSE);
@ -5297,7 +5297,7 @@ static void atk4A_typecalc2(void)
RecordAbilityBattle(gBankTarget, gLastUsedAbility); RecordAbilityBattle(gBankTarget, gLastUsedAbility);
} }
if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
gProtectStructs[gBankAttacker].notEffective = 1; gProtectStructs[gBankAttacker].targetNotAffected = 1;
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
} }
@ -9518,19 +9518,19 @@ static void atkB3_rolloutdamagecalculation(void)
if (!(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) // first hit if (!(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) // first hit
{ {
gDisableStructs[gBankAttacker].rolloutTimer1 = 5; gDisableStructs[gBankAttacker].rolloutCounter1 = 5;
gDisableStructs[gBankAttacker].rolloutTimer2 = 5; gDisableStructs[gBankAttacker].rolloutCounter2 = 5;
gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS; gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gBankAttacker] = gCurrentMove; gLockedMoves[gBankAttacker] = gCurrentMove;
} }
if (--gDisableStructs[gBankAttacker].rolloutTimer1 == 0) // last hit if (--gDisableStructs[gBankAttacker].rolloutCounter1 == 0) // last hit
{ {
gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS); gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
} }
gDynamicBasePower = gBattleMoves[gCurrentMove].power; gDynamicBasePower = gBattleMoves[gCurrentMove].power;
for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutTimer1); i++) for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutCounter1); i++)
gDynamicBasePower *= 2; gDynamicBasePower *= 2;
if (gBattleMons[gBankAttacker].status2 & STATUS2_DEFENSE_CURL) if (gBattleMons[gBankAttacker].status2 & STATUS2_DEFENSE_CURL)

View File

@ -17,6 +17,7 @@
#include "battle_controllers.h" #include "battle_controllers.h"
#include "event_data.h" #include "event_data.h"
#include "calculate_base_damage.h" #include "calculate_base_damage.h"
#include "link.h"
extern const u8* gBattlescriptCurrInstr; extern const u8* gBattlescriptCurrInstr;
extern const u8* gBattlescriptPtrsForSelection[BATTLE_BANKS_COUNT]; extern const u8* gBattlescriptPtrsForSelection[BATTLE_BANKS_COUNT];
@ -33,7 +34,7 @@ extern u8 gBankTarget;
extern u8 gAbsentBankFlags; extern u8 gAbsentBankFlags;
extern u16 gBattleWeather; extern u16 gBattleWeather;
extern u8 gBanksByTurnOrder[BATTLE_BANKS_COUNT]; extern u8 gBanksByTurnOrder[BATTLE_BANKS_COUNT];
extern u16 gSideAffecting[]; extern u16 gSideAffecting[2];
extern u8 gBattleCommunication[]; extern u8 gBattleCommunication[];
extern void (*gBattleMainFunc)(void); extern void (*gBattleMainFunc)(void);
extern s32 gBattleMoveDamage; extern s32 gBattleMoveDamage;
@ -45,7 +46,7 @@ extern u32 gHitMarker;
extern u8 gEffectBank; extern u8 gEffectBank;
extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
extern u8 gBank1; extern u8 gBank1;
extern u16 gChosenMovesByBanks[]; extern u16 gChosenMovesByBanks[BATTLE_BANKS_COUNT];
extern u8 gBattleMoveFlags; extern u8 gBattleMoveFlags;
extern s32 gTakenDmg[BATTLE_BANKS_COUNT]; extern s32 gTakenDmg[BATTLE_BANKS_COUNT];
extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT]; extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT];
@ -55,8 +56,10 @@ extern u32 gBattleExecBuffer;
extern u16 gRandomMove; extern u16 gRandomMove;
extern u8 gCurrMovePos; extern u8 gCurrMovePos;
extern u8 gUnknown_020241E9; extern u8 gUnknown_020241E9;
extern u8 gSentPokesToOpponent[2];
extern const struct BattleMove gBattleMoves[]; extern const struct BattleMove gBattleMoves[];
extern const u16 gSoundMovesTable[];
// scripts // scripts
extern const u8 gUnknown_082DAE2A[]; extern const u8 gUnknown_082DAE2A[];
@ -169,6 +172,7 @@ extern const u8 gUnknown_082DB6A5[]; //disobedient, uses a random move
extern const u8 gUnknown_082DB6D9[]; //disobedient, went to sleep extern const u8 gUnknown_082DB6D9[]; //disobedient, went to sleep
extern const u8 gUnknown_082DB6F0[]; //disobedient, hits itself extern const u8 gUnknown_082DB6F0[]; //disobedient, hits itself
// strings
extern const u8 gStatusConditionString_PoisonJpn[]; extern const u8 gStatusConditionString_PoisonJpn[];
extern const u8 gStatusConditionString_SleepJpn[]; extern const u8 gStatusConditionString_SleepJpn[];
extern const u8 gStatusConditionString_ParalysisJpn[]; extern const u8 gStatusConditionString_ParalysisJpn[];
@ -176,12 +180,272 @@ extern const u8 gStatusConditionString_BurnJpn[];
extern const u8 gStatusConditionString_IceJpn[]; extern const u8 gStatusConditionString_IceJpn[];
extern const u8 gStatusConditionString_ConfusionJpn[]; extern const u8 gStatusConditionString_ConfusionJpn[];
extern const u8 gStatusConditionString_LoveJpn[]; extern const u8 gStatusConditionString_LoveJpn[];
extern const u16 gSoundMovesTable[];
extern void sub_803F9EC();
extern bool8 sub_80423F4(u8 bank, u8, u8);
extern u8 weather_get_current(void); extern u8 weather_get_current(void);
extern s8 GetFlavourRelationByPersonality(u32 personality, u8 flavor);
u8 GetBattleBank(u8 caseId)
{
u8 ret = 0;
switch (caseId)
{
case BS_GET_TARGET:
ret = gBankTarget;
break;
case BS_GET_ATTACKER:
ret = gBankAttacker;
break;
case BS_GET_EFFECT_BANK:
ret = gEffectBank;
break;
case 7:
ret = 0;
break;
case BS_GET_SCRIPTING_BANK:
ret = gBattleScripting.bank;
break;
case 3:
ret = gBank1;
break;
case 5:
ret = gBank1;
break;
case 4:
case 6:
case 8:
case 9:
case BS_GET_PLAYER1:
ret = GetBankByIdentity(IDENTITY_PLAYER_MON1);
break;
case BS_GET_OPPONENT1:
ret = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
break;
case BS_GET_PLAYER2:
ret = GetBankByIdentity(IDENTITY_PLAYER_MON2);
break;
case BS_GET_OPPONENT2:
ret = GetBankByIdentity(IDENTITY_OPPONENT_MON2);
break;
}
return ret;
}
void PressurePPLose(u8 bankDef, u8 bankAtk, u16 move)
{
s32 i;
if (gBattleMons[bankDef].ability != ABILITY_PRESSURE)
return;
for (i = 0; i < 4; i++)
{
if (gBattleMons[bankAtk].moves[i] == move)
break;
}
if (i == 4) // mons don't share any moves
return;
if (gBattleMons[bankAtk].pp[i] != 0)
gBattleMons[bankAtk].pp[i]--;
if (!(gBattleMons[bankAtk].status2 & STATUS2_TRANSFORMED)
&& !(gDisableStructs[bankAtk].unk18_b & gBitTable[i]))
{
gActiveBank = bankAtk;
EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBank].pp[i]);
MarkBufferBankForExecution(gActiveBank);
}
}
void PressurePPLoseOnUsingImprision(u8 bankAtk)
{
s32 i, j;
s32 imprisionPos = 4;
u8 atkSide = GetBankSide(bankAtk);
for (i = 0; i < gNoOfAllBanks; i++)
{
if (atkSide != GetBankSide(i) && gBattleMons[i].ability == ABILITY_PRESSURE)
{
for (j = 0; j < 4; j++)
{
if (gBattleMons[bankAtk].moves[j] == MOVE_IMPRISON)
break;
}
if (j != 4)
{
imprisionPos = j;
if (gBattleMons[bankAtk].pp[j] != 0)
gBattleMons[bankAtk].pp[j]--;
}
}
}
if (imprisionPos != 4
&& !(gBattleMons[bankAtk].status2 & STATUS2_TRANSFORMED)
&& !(gDisableStructs[bankAtk].unk18_b & gBitTable[imprisionPos]))
{
gActiveBank = bankAtk;
EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + imprisionPos, 0, 1, &gBattleMons[gActiveBank].pp[imprisionPos]);
MarkBufferBankForExecution(gActiveBank);
}
}
void PressurePPLoseOnUsingPerishSong(u8 bankAtk)
{
s32 i, j;
s32 perishSongPos = 4;
for (i = 0; i < gNoOfAllBanks; i++)
{
if (gBattleMons[i].ability == ABILITY_PRESSURE && i != bankAtk)
{
for (j = 0; j < 4; j++)
{
if (gBattleMons[bankAtk].moves[j] == MOVE_PERISH_SONG)
break;
}
if (j != 4)
{
perishSongPos = j;
if (gBattleMons[bankAtk].pp[j] != 0)
gBattleMons[bankAtk].pp[j]--;
}
}
}
if (perishSongPos != 4
&& !(gBattleMons[bankAtk].status2 & STATUS2_TRANSFORMED)
&& !(gDisableStructs[bankAtk].unk18_b & gBitTable[perishSongPos]))
{
gActiveBank = bankAtk;
EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + perishSongPos, 0, 1, &gBattleMons[gActiveBank].pp[perishSongPos]);
MarkBufferBankForExecution(gActiveBank);
}
}
void MarkAllBufferBanksForExecution(void) // unused
{
s32 i;
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
for (i = 0; i < gNoOfAllBanks; i++)
gBattleExecBuffer |= gBitTable[i] << 0x1C;
}
else
{
for (i = 0; i < gNoOfAllBanks; i++)
gBattleExecBuffer |= gBitTable[i];
}
}
void MarkBufferBankForExecution(u8 bank)
{
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
gBattleExecBuffer |= gBitTable[bank] << 0x1C;
}
else
{
gBattleExecBuffer |= gBitTable[bank];
}
}
void sub_803F850(u8 arg0)
{
s32 i;
for (i = 0; i < sub_8009FCC(); i++)
gBattleExecBuffer |= gBitTable[arg0] << (i << 2);
gBattleExecBuffer &= ~(0x10000000 << arg0);
}
void CancelMultiTurnMoves(u8 bank)
{
gBattleMons[bank].status2 &= ~(STATUS2_MULTIPLETURNS);
gBattleMons[bank].status2 &= ~(STATUS2_LOCK_CONFUSE);
gBattleMons[bank].status2 &= ~(STATUS2_UPROAR);
gBattleMons[bank].status2 &= ~(STATUS2_BIDE);
gStatuses3[bank] &= ~(STATUS3_SEMI_INVULNERABLE);
gDisableStructs[bank].rolloutCounter1 = 0;
gDisableStructs[bank].furyCutterCounter = 0;
}
bool8 WasUnableToUseMove(u8 bank)
{
if (gProtectStructs[bank].prlzImmobility
|| gProtectStructs[bank].targetNotAffected
|| gProtectStructs[bank].usedImprisionedMove
|| gProtectStructs[bank].loveImmobility
|| gProtectStructs[bank].usedDisabledMove
|| gProtectStructs[bank].usedTauntedMove
|| gProtectStructs[bank].flag2Unknown
|| gProtectStructs[bank].flinchImmobility
|| gProtectStructs[bank].confusionSelfDmg)
return TRUE;
else
return FALSE;
}
void PrepareStringBattle(u16 stringId, u8 bank)
{
gActiveBank = bank;
EmitPrintString(0, stringId);
MarkBufferBankForExecution(gActiveBank);
}
void ResetSentPokesToOpponentValue(void)
{
s32 i;
u32 bits = 0;
gSentPokesToOpponent[0] = 0;
gSentPokesToOpponent[1] = 0;
for (i = 0; i < gNoOfAllBanks; i += 2)
bits |= gBitTable[gBattlePartyID[i]];
for (i = 1; i < gNoOfAllBanks; i += 2)
gSentPokesToOpponent[(i & BIT_MON) >> 1] = bits;
}
void sub_803F9EC(u8 bank)
{
s32 i = 0;
u32 bits = 0;
if (GetBankSide(bank) == SIDE_OPPONENT)
{
u8 id = ((bank & BIT_MON) >> 1);
gSentPokesToOpponent[id] = 0;
for (i = 0; i < gNoOfAllBanks; i += 2)
{
if (!(gAbsentBankFlags & gBitTable[i]))
bits |= gBitTable[gBattlePartyID[i]];
}
gSentPokesToOpponent[id] = bits;
}
}
void sub_803FA70(u8 bank)
{
if (GetBankSide(bank) == SIDE_OPPONENT)
{
sub_803F9EC(bank);
}
else
{
s32 i;
for (i = 1; i < gNoOfAllBanks; i++)
gSentPokesToOpponent[(i & BIT_MON) >> 1] |= gBitTable[gBattlePartyID[bank]];
}
}
void BattleScriptPush(const u8* bsPtr) void BattleScriptPush(const u8* bsPtr)
{ {
@ -828,7 +1092,7 @@ u8 TurnBasedEffects(void)
{ {
gBankAttacker = gActiveBank; gBankAttacker = gActiveBank;
gBattleMons[gActiveBank].status2 -= 0x10; // uproar timer goes down gBattleMons[gActiveBank].status2 -= 0x10; // uproar timer goes down
if (HasMoveFailed(gActiveBank)) if (WasUnableToUseMove(gActiveBank))
{ {
CancelMultiTurnMoves(gActiveBank); CancelMultiTurnMoves(gActiveBank);
gBattleCommunication[MULTISTRING_CHOOSER] = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 1;
@ -854,7 +1118,7 @@ u8 TurnBasedEffects(void)
if (gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE) if (gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE)
{ {
gBattleMons[gActiveBank].status2 -= 0x400; gBattleMons[gActiveBank].status2 -= 0x400;
if (HasMoveFailed(gActiveBank)) if (WasUnableToUseMove(gActiveBank))
CancelMultiTurnMoves(gActiveBank); CancelMultiTurnMoves(gActiveBank);
else if (!(gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE) else if (!(gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE)
&& (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS)) && (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS))
@ -1125,7 +1389,7 @@ bool8 sub_8041728(void)
case 4: case 4:
do do
{ {
gBank1 = gBankTarget = gBattleStruct->field_4E; //or should banks be switched? gBank1 = gBankTarget = gBattleStruct->field_4E;
if (gBattleMons[gBattleStruct->field_4E].hp == 0 if (gBattleMons[gBattleStruct->field_4E].hp == 0
&& !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E])) && !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E]))
{ {
@ -6190,7 +6454,7 @@ void ClearFuryCutterDestinyBondGrudge(u8 bank)
gStatuses3[bank] &= ~(STATUS3_GRUDGE); gStatuses3[bank] &= ~(STATUS3_GRUDGE);
} }
void sub_80458B4(void) void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands
{ {
if (gBattleExecBuffer == 0) if (gBattleExecBuffer == 0)
gBattleScriptingCommandsTable[*gBattlescriptCurrInstr](); gBattleScriptingCommandsTable[*gBattlescriptCurrInstr]();