mirror of https://github.com/pret/pokeemerald.git
Created Allow Running From Trainer Battles (markdown)
parent
41604ef983
commit
1236a7c38c
|
@ -0,0 +1,227 @@
|
|||
By devolov
|
||||
**Goal:** Allow running from a battle with an NPC trainer. When you run from them, you can still talk to them to battle, they just won't `see` you until you either change maps or walk in front of someone else who can battle you.
|
||||
|
||||
![bar1](https://user-images.githubusercontent.com/36523934/230449381-addb805f-2a54-43c4-b96e-c97f13a3c463.gif)
|
||||
|
||||
|
||||
```diff
|
||||
------------------------------ src/battle_setup.c ------------------------------
|
||||
index 03bc0a08e7..e17db26d14 100644
|
||||
@@ -113,8 +113,9 @@ EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL;
|
||||
EWRAM_DATA static u8 *sTrainerABattleScriptRetAddr = NULL;
|
||||
EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL;
|
||||
EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE;
|
||||
EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0;
|
||||
+EWRAM_DATA static u32 sPrevTrainerSeeing = 0;
|
||||
|
||||
// The first transition is used if the enemy pokemon are lower level than our pokemon.
|
||||
// Otherwise, the second transition is used.
|
||||
static const u8 sBattleTransitionTable_Wild[][2] =
|
||||
@@ -1271,9 +1272,13 @@ void SetUpTwoTrainersBattle(void)
|
||||
|
||||
bool32 GetTrainerFlagFromScriptPointer(const u8 *data)
|
||||
{
|
||||
u32 flag = TrainerBattleLoadArg16(data + 2);
|
||||
- return FlagGet(TRAINER_FLAGS_START + flag);
|
||||
+ if (flag != sPrevTrainerSeeing){
|
||||
+ sPrevTrainerSeeing = flag;
|
||||
+ FlagClear(FLAG_RAN_FROM_TRAINER);
|
||||
+ }
|
||||
+ return (FlagGet(TRAINER_FLAGS_START + flag) || FlagGet(FLAG_RAN_FROM_TRAINER));
|
||||
}
|
||||
|
||||
// Set trainer's movement type so they stop and remain facing that direction
|
||||
// Note: Only for trainers who are spoken to directly
|
||||
@@ -1298,8 +1303,13 @@ bool8 GetTrainerFlag(void)
|
||||
else
|
||||
return FlagGet(GetTrainerAFlag());
|
||||
}
|
||||
|
||||
+static void SetBattledTrainersSeeFlag(void)
|
||||
+{
|
||||
+ FlagSet(FLAG_RAN_FROM_TRAINER);
|
||||
+}
|
||||
+
|
||||
static void SetBattledTrainersFlags(void)
|
||||
{
|
||||
if (gTrainerBattleOpponent_B != 0)
|
||||
FlagSet(GetTrainerBFlag());
|
||||
@@ -1412,10 +1422,16 @@ static void CB2_EndTrainerBattle(void)
|
||||
{
|
||||
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
|
||||
if (!InBattlePyramid() && !InTrainerHillChallenge())
|
||||
{
|
||||
- RegisterTrainerInMatchCall();
|
||||
- SetBattledTrainersFlags();
|
||||
+ if (gBattleOutcome == B_OUTCOME_RAN){
|
||||
+ SetBattledTrainersSeeFlag();
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ RegisterTrainerInMatchCall();
|
||||
+ SetBattledTrainersFlags();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
------------------------------ src/trainer_see.c ------------------------------
|
||||
index 7b7533a337..642b6bd0f1 100644
|
||||
@@ -421,16 +421,14 @@ static u8 CheckTrainer(u8 objectEventId)
|
||||
{
|
||||
if (GetHillTrainerFlag(objectEventId))
|
||||
return 0;
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- if (GetTrainerFlagFromScriptPointer(scriptPtr))
|
||||
- return 0;
|
||||
- }
|
||||
|
||||
approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]);
|
||||
|
||||
if (approachDistance != 0)
|
||||
{
|
||||
+ if (GetTrainerFlagFromScriptPointer(scriptPtr))
|
||||
+ return 0;
|
||||
if (scriptPtr[1] == TRAINER_BATTLE_DOUBLE
|
||||
|| scriptPtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE
|
||||
```
|
||||
|
||||
```diff
|
||||
------------------------------- src/event_data.c -------------------------------
|
||||
index 50f6f68da4..4a00bcac40 100644
|
||||
@@ -44,8 +44,9 @@ void InitEventData(void)
|
||||
void ClearTempFieldEventData(void)
|
||||
{
|
||||
memset(gSaveBlock1Ptr->flags + (TEMP_FLAGS_START / 8), 0, TEMP_FLAGS_SIZE);
|
||||
memset(gSaveBlock1Ptr->vars + ((TEMP_VARS_START - VARS_START) * 2), 0, TEMP_VARS_SIZE);
|
||||
+ FlagClear(FLAG_RAN_FROM_TRAINER);
|
||||
FlagClear(FLAG_SYS_ENC_UP_ITEM);
|
||||
FlagClear(FLAG_SYS_ENC_DOWN_ITEM);
|
||||
FlagClear(FLAG_SYS_USE_STRENGTH);
|
||||
FlagClear(FLAG_SYS_CTRL_OBJ_DELETE);
|
||||
```
|
||||
|
||||
```diff
|
||||
-------------------------- include/constants/flags.h --------------------------
|
||||
index 7f36cacc8f..2a25e074f6 100644
|
||||
@@ -1241,9 +1241,9 @@
|
||||
-#define FLAG_UNUSED_0x4AC 0x4AC // Unused Flag
|
||||
+#define FLAG_RAN_FROM_TRAINER 0x4AC
|
||||
#define FLAG_UNUSED_0x4AD 0x4AD // Unused Flag
|
||||
#define FLAG_UNUSED_0x4AE 0x4AE // Unused Flag
|
||||
#define FLAG_UNUSED_0x4AF 0x4AF // Unused Flag
|
||||
#define FLAG_UNUSED_0x4B0 0x4B0 // Unused Flag
|
||||
```
|
||||
|
||||
```diff
|
||||
------------------------------ src/battle_main.c ------------------------------
|
||||
@@ -4552,14 +4577,26 @@ static void HandleTurnActionSelectionState(void)
|
||||
*(gBattleStruct->selectionScriptFinished + gActiveBattler) = FALSE;
|
||||
*(gBattleStruct->stateIdAfterSelScript + gActiveBattler) = STATE_BEFORE_ACTION_CHOSEN;
|
||||
return;
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK))
|
||||
&& gBattleBufferB[gActiveBattler][1] == B_ACTION_RUN)
|
||||
{
|
||||
- BattleScriptExecute(BattleScript_PrintCantRunFromTrainer);
|
||||
- gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
+ gBattleCommunication[gActiveBattler]++;
|
||||
}
|
||||
else if (IsRunningFromBattleImpossible() != BATTLE_RUN_SUCCESS
|
||||
&& gBattleBufferB[gActiveBattler][1] == B_ACTION_RUN)
|
||||
{
|
||||
```
|
||||
|
||||
## Make Important Trainer Battles Ones That You Still Can't Run From
|
||||
Some battles (Battle Frontier, Rival, Elite Four), may be ones that you don't want to run from. The following tweak can be added in `battle_main.c`:
|
||||
|
||||
```diff
|
||||
static void HandleEndTurn_BattleLost(void);
|
||||
static void HandleEndTurn_RanFromBattle(void);
|
||||
static void HandleEndTurn_MonFled(void);
|
||||
static void HandleEndTurn_FinishBattle(void);
|
||||
static void SpriteCB_UnusedBattleInit(struct Sprite *sprite);
|
||||
static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite);
|
||||
+static bool8 IsTrainerCantRunFrom(void);
|
||||
|
||||
EWRAM_DATA u16 gBattle_BG0_X = 0;
|
||||
```
|
||||
|
||||
```diff
|
||||
return BATTLE_RUN_FORBIDDEN;
|
||||
}
|
||||
return BATTLE_RUN_SUCCESS;
|
||||
}
|
||||
|
||||
+static u8 IsTrainerCantRunFrom(void){
|
||||
+ u8 trainerClass;
|
||||
+ if (FlagGet(FLAG_NUZLOCKE))
|
||||
+ return BATTLE_RUN_FORBIDDEN;
|
||||
+ if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_TRAINER_HILL))
|
||||
+ return BATTLE_RUN_FORBIDDEN;
|
||||
+ trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
|
||||
+ switch (trainerClass)
|
||||
+ {
|
||||
+ case TRAINER_CLASS_AQUA_LEADER:
|
||||
+ case TRAINER_CLASS_MAGMA_LEADER:
|
||||
+ case TRAINER_CLASS_TEAM_AQUA:
|
||||
+ case TRAINER_CLASS_TEAM_MAGMA:
|
||||
+ case TRAINER_CLASS_AQUA_ADMIN:
|
||||
+ case TRAINER_CLASS_MAGMA_ADMIN:
|
||||
+ case TRAINER_CLASS_LEADER:
|
||||
+ case TRAINER_CLASS_CHAMPION:
|
||||
+ case TRAINER_CLASS_RIVAL:
|
||||
+ case TRAINER_CLASS_ELITE_FOUR:
|
||||
+ return BATTLE_RUN_FORBIDDEN;
|
||||
+ default:
|
||||
+ return BATTLE_RUN_SUCCESS;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void SwitchPartyOrder(u8 battler)
|
||||
{
|
||||
s32 i;
|
||||
```
|
||||
```diff
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK))
|
||||
&& gBattleBufferB[gActiveBattler][1] == B_ACTION_RUN)
|
||||
{
|
||||
- gBattleCommunication[gActiveBattler]++;
|
||||
+ if (IsTrainerCantRunFrom())
|
||||
+ {
|
||||
+ BattleScriptExecute(BattleScript_PrintCantRunFromTrainer);
|
||||
+ gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ gBattleCommunication[gActiveBattler]++;
|
||||
+ }
|
||||
+ }
|
||||
```
|
||||
|
||||
For proper wording, in `battle_messages.c`:
|
||||
```diff
|
||||
----------------------------- src/battle_message.c -----------------------------
|
||||
index 11f7f8d5f3..8cc21e0fc5 100644
|
||||
@@ -332,9 +332,10 @@ static const u8 sText_PlayerLostToTwo[] = _("Player lost to {B_LINK_OPPONENT1_NA
|
||||
static const u8 sText_PlayerBattledToDrawLinkTrainer[] = _("Player battled to a draw against\n{B_LINK_OPPONENT1_NAME}!");
|
||||
static const u8 sText_PlayerBattledToDrawVsTwo[] = _("Player battled to a draw against\n{B_LINK_OPPONENT1_NAME} and {B_LINK_OPPONENT2_NAME}!");
|
||||
static const u8 sText_WildFled[] = _("{PLAY_SE SE_FLEE}{B_LINK_OPPONENT1_NAME} fled!");
|
||||
static const u8 sText_TwoWildFled[] = _("{PLAY_SE SE_FLEE}{B_LINK_OPPONENT1_NAME} and\n{B_LINK_OPPONENT2_NAME} fled!");
|
||||
-static const u8 sText_NoRunningFromTrainers[] = _("No! There's no running\nfrom a TRAINER battle!\p");
|
||||
+static const u8 sText_NoRunningFromTrainers[] = _("No! There's no running\nfrom this TRAINER battle!\p");
|
||||
static const u8 sText_CantEscape[] = _("Can't escape!\p");
|
||||
static const u8 sText_DontLeaveBirch[] = _("PROF. BIRCH: Don't leave me like this!\p");
|
||||
static const u8 sText_ButNothingHappened[] = _("But nothing happened!");
|
||||
static const u8 sText_ButItFailed[] = _("But it failed!");
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue