summaryrefslogtreecommitdiff
path: root/Better-White-Out-Money-Calculation.md
blob: 623ff8da61f472df8293344be4bbbfac477aca76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
*Credits to **[AsparagusEduardo](https://github.com/AsparagusEduardo)** for creating the implementation of this feature that I will be explaining here, and to **[lightgod87](https://github.com/lightgod87)** for extra polishing it.*

In Pokémon Emerald, whenever you lose a battle you always lose half of your money.

In Pokémon FireRed/LeafGreen, Diamond/Pearl and subsequent games, you lose a more sensible amount influenced by the Pokémon with the highest level of your party and the amount of badges you have.

Today we'll be implementing that in Pokeemerald.

## 1. Adding in some new battle strings

This implementation introduces 2 text strings from FireRed/LeafGreen for extra flavor and faithfulness. This is super easy, so let's get it out of the way.

First we define them by adding a constant in **[include/constants/battle_string_ids.h](https://github.com/pret/pokeemerald/blob/master/include/constants/battle_string_ids.h)**:

```diff
+#define STRINGID_PLAYERLOSTTOENEMYTRAINER   381
+#define STRINGID_PLAYERPAIDPRIZEMONEY       382
```

*Don't forget to add 2 to the current value of your `BATTLESTRINGS_COUNT` in the same file!*

And then we add the actual text strings to **[src/battle_message.c](https://github.com/pret/pokeemerald/blob/master/src/battle_message.c)**.

As to not complicate things, I suggest to put them right below `sText_YouThrowABallNowRight`, but you can add them wherever you want.

```diff
+static const u8 sText_PlayerLostToEnemyTrainer[] = _("{B_PLAYER_NAME} is out of\nusable POKéMON!\pPlayer lost against\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!{PAUSE_UNTIL_PRESS}");
+static const u8 sText_PlayerPaidPrizeMoney[] = _("{B_PLAYER_NAME} paid ¥{B_BUFF1} as the prize\nmoney…\p… … … …\p{B_PLAYER_NAME} whited out!{PAUSE_UNTIL_PRESS}");
```

Now we have to link the constants we added previously to the labels of these new text strings by registering them in the `gBattleStringsTable`.

```diff
+    [STRINGID_PLAYERLOSTTOENEMYTRAINER - 12] = sText_PlayerLostToEnemyTrainer,
+    [STRINGID_PLAYERPAIDPRIZEMONEY - 12] = sText_PlayerPaidPrizeMoney,
```

Again, you can add these wherever you want. If you want to remain consistent, you would want once again add them right under `sText_YouThrowABallNowRight`, but it doesn't matter as long as you add them to the table.

## 2. Modifying the White Out BattleScript

Let's put these new battle strings to use, shall we? To do that, we'll do some quick changes to the BattleScript that triggers when you lose a battle, i.e. `BattleScript_LocalBattleLostPrintWhiteOut` in **[data/battle_scrpts_1.s](https://github.com/pret/pokeemerald/blob/master/data/battle_scripts_1.s)**.

```diff
BattleScript_LocalBattleLostPrintWhiteOut::
+	jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_LocalBattleLostEnd
	printstring STRINGID_PLAYERWHITEOUT
	waitmessage 0x40
+	getmoneyreward
	printstring STRINGID_PLAYERWHITEOUT2
	waitmessage 0x40
+	end2
BattleScript_LocalBattleLostEnd::
+	printstring STRINGID_PLAYERLOSTTOENEMYTRAINER
+	waitmessage 0x40
+	getmoneyreward
+	printstring STRINGID_PLAYERPAIDPRIZEMONEY
+	waitmessage 0x40
	end2
```

Now we'll tweak the text string linked to the constant `STRINGID_PLAYERWHITEOUT2` in order to inform the Player about the amount of money they're losing, which is `sText_PlayerWhiteout2` located in **[src/battle_message.c](https://github.com/pret/pokeemerald/blob/master/src/battle_message.c)**.

```diff
-static const u8 sText_PlayerWhiteout2[] = _("{B_PLAYER_NAME} whited out!{PAUSE_UNTIL_PRESS}");
+static const u8 sText_PlayerWhiteout2[] = _("{B_PLAYER_NAME} panicked and lost ¥{B_BUFF1}…\p… … … …\p{B_PLAYER_NAME} whited out!{PAUSE_UNTIL_PRESS}");
```

So, what are we doing here? Here we're telling the game to run the `BattleScript_LocalBattleLostEnd` if the Player has lost a trainer battle, in order to make use of the new text strings we inserted earlier. If the current battle type is not a trainerbattle though *(which outside of special battle facilities means we're losing a wildbattle)*, then the game will run `BattleScript_LocalBattleLostPrintWhiteOut` normally.

Lastly, we're setting things up so the `Cmd_getmoneyreward` function will be triggered when the Player loses a battle.

Now, you may be wondering; why are we doing that? Normally, `Cmd_getmoneyreward` is in charge of calculating the money you receive as a reward for winning and that alone after all.

You can guess what are we going to change next, can't you?

## 3. Modifying the `Cmd_getmoneyreward` function

Now we want to open **[src/battle_script_commands.c](https://github.com/pret/pokeemerald/blob/master/src/battle_script_commands.c)**.
Before anything, we have to define a new variable and 2 array lists that we're going to use soon enough.

```diff
+extern u8 gMaxPartyLevel;

+static const u16 sBadgeFlags[8] = {
+    FLAG_BADGE01_GET, FLAG_BADGE02_GET, FLAG_BADGE03_GET, FLAG_BADGE04_GET,
+    FLAG_BADGE05_GET, FLAG_BADGE06_GET, FLAG_BADGE07_GET, FLAG_BADGE08_GET,
+};

+static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 60, 80, 100, 120 };
```

***Note**: The base payout while the Player holds 5 badges has been bumped from 60 to 64 starting from Pokémon Black and White, so you may want to do the same here, or not. It's entirely up to you.*

If I were you I'd add them right below `sBattlePalaceNatureToFlavorTextId`, that is right before the first function in the file.

And now we're ready to actually modify `Cmd_getmoneyreward`:

```diff
static void Cmd_getmoneyreward(void)
{
-    u32 moneyReward = GetTrainerMoneyToGive(gTrainerBattleOpponent_A);
-    if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
-        moneyReward += GetTrainerMoneyToGive(gTrainerBattleOpponent_B);
+    u32 money;

-    AddMoney(&gSaveBlock1Ptr->money, moneyReward);
-    PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff1, 5, moneyReward);
+    if (gBattleOutcome == B_OUTCOME_WON)
+    {
+        money = GetTrainerMoneyToGive(gTrainerBattleOpponent_A);
+        if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+            money += GetTrainerMoneyToGive(gTrainerBattleOpponent_B);
+        AddMoney(&gSaveBlock1Ptr->money, money);
+    }
+    else
+    {
+        s32 i, count;
+        for (i = 0; i < PARTY_SIZE; i++)
+        {
+            if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) != SPECIES_NONE
+             && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) != SPECIES_EGG)
+            {
+                if (GetMonData(&gPlayerParty[i], MON_DATA_LEVEL) > gMaxPartyLevel)
+                    gMaxPartyLevel = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+            }
+        }
+        for (count = 0, i = 0; i < ARRAY_COUNT(sBadgeFlags); i++)
+        {
+            if (FlagGet(sBadgeFlags[i]) == TRUE)
+                ++count;
+        }
+        money = sWhiteOutBadgeMoney[count] * gMaxPartyLevel;
+        RemoveMoney(&gSaveBlock1Ptr->money, money);
+    }

+    PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff1, 5, money);
    gBattlescriptCurrInstr++;
}
```

Here, we're making `Cmd_getmoneyreward` handle not only the money calculation for winning a battle, but we're also making it calculate how much money should be removed from the Player when they lose a battle, and then we're storing that amount in a buffer to display it in the `STRINGID_PLAYERPAIDPRIZEMONEY` we added earlier.

As you can see, we're introducing a new extern variable; `gMaxPartyLevel`.

As this variable plays a central role in `Cmd_getmoneyreward` which is a function that can only be triggered In Battle, we have to make the battle system recognize it.

To do that, we'll visit the **[src/battle_main.c](https://github.com/pret/pokeemerald/blob/master/src/battle_main.c)** file and throw it in at the end of the EWRAM vars list like so:

```diff
+EWRAM_DATA u8 gMaxPartyLevel = 1;
```

## 4. Modifying the `DoWhiteOut` function

This function which can be found in the **[src/overworld.c file](https://github.com/pret/pokeemerald/blob/master/src/overworld.c)** is always triggered whenever you lose a battle and it's also in charge of cutting the Player's money by half whenever they lose a battle, as you can easily tell by reading it.

As the last step of this process, we'll remove that bit because we naturally don't want that to happen.

```diff
void DoWhiteOut(void)
{
    ScriptContext2_RunNewScript(EventScript_WhiteOut);
-   SetMoney(&gSaveBlock1Ptr->money, GetMoney(&gSaveBlock1Ptr->money) / 2);
    HealPlayerParty();
    Overworld_ResetStateAfterWhiteOut();
    SetWarpDestinationToLastHealLocation();
    WarpIntoMap();
}
```

And just like that, we're done. Go build a ROM and let a Magikarp faint your party or something.