summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorExpoSeed <43502820+ExpoSeed@users.noreply.github.com>2020-07-09 16:06:09 -0500
committerExpoSeed <43502820+ExpoSeed@users.noreply.github.com>2020-07-09 16:06:09 -0500
commitab5eced4c236988a4e5e2646276e0ccca4bd0a5b (patch)
tree92eeea0198fa7fda6a9fec3778f2725b6eb0200f
parent2f54cd2480b684b0f3b4c0b7a6a1bcfa83944ae8 (diff)
i'm not done yet
-rw-r--r--Gen-6-Exp-Share.md226
1 files changed, 214 insertions, 12 deletions
diff --git a/Gen-6-Exp-Share.md b/Gen-6-Exp-Share.md
index 95b6845..7dccf41 100644
--- a/Gen-6-Exp-Share.md
+++ b/Gen-6-Exp-Share.md
@@ -35,16 +35,218 @@ We also need to change the Exp Share's item description. Edit [src/data/text/ite
Now that out of battle strings are taken care of, let's work on the item properties. Edit [src/data/items.h](../blob/master/src/data/items.h):
```diff
- [ITEM_EXP_SHARE] =
- {
- .name = _("EXP. SHARE"),
- .itemId = ITEM_EXP_SHARE,
- .price = 3000,
- .holdEffect = HOLD_EFFECT_EXP_SHARE,
- .description = sExpShareDesc,
- .pocket = POCKET_ITEMS,
- .type = 4,
- .fieldUseFunc = ItemUseOutOfBattle_CannotUse,
- .secondaryId = 0,
- },
+ [ITEM_EXP_SHARE] =
+ {
+ .name = _("EXP. SHARE"),
+ .itemId = ITEM_EXP_SHARE,
+ .price = 3000,
+ .holdEffect = HOLD_EFFECT_EXP_SHARE,
+ .description = sExpShareDesc,
+- .pocket = POCKET_ITEMS,
+- .type = 4,
+- .fieldUseFunc = ItemUseOutOfBattle_CannotUse,
++ .importance = 1,
++ .pocket = POCKET_KEY_ITEMS,
++ .type = 2,
++ .fieldUseFunc = ItemUseOutOfBattle_ExpShare,
+ .secondaryId = 0,
+ },
+```
+We've changed the pocket, set the type to be the same type as other key items (this value only gets read by specific field callbacks like medicines, stones, and the bike anyways, so it's irrelevant), given the item an importance of 1 (so it cannot be tossed or deposited in the PC), and also gave it a function for field use. We will define the field use function next.
+
+Edit [include/global.h](../blob/master/include/global.h):
+```diff
+ struct SaveBlock2
+ {
+ /*0x00*/ u8 playerName[PLAYER_NAME_LENGTH + 1];
+ /*0x08*/ u8 playerGender; // MALE, FEMALE
+ /*0x09*/ u8 specialSaveWarpFlags;
+ /*0x0A*/ u8 playerTrainerId[TRAINER_ID_LENGTH];
+ /*0x0E*/ u16 playTimeHours;
+ /*0x10*/ u8 playTimeMinutes;
+ /*0x11*/ u8 playTimeSeconds;
+ /*0x12*/ u8 playTimeVBlanks;
+ /*0x13*/ u8 optionsButtonMode; // OPTIONS_BUTTON_MODE_[NORMAL/LR/L_EQUALS_A]
+ /*0x14*/ u16 optionsTextSpeed:3; // OPTIONS_TEXT_SPEED_[SLOW/MID/FAST]
+ u16 optionsWindowFrameType:5; // Specifies one of the 20 decorative borders for text boxes
+ u16 optionsSound:1; // OPTIONS_SOUND_[MONO/STEREO]
+ u16 optionsBattleStyle:1; // OPTIONS_BATTLE_STYLE_[SHIFT/SET]
+ u16 optionsBattleSceneOff:1; // whether battle animations are disabled
+ u16 regionMapZoom:1; // whether the map is zoomed in
++ u16 expShare:1;
+ /*0x18*/ struct Pokedex pokedex;
+ /*0x90*/ u8 filler_90[0x8];
+ /*0x98*/ struct Time localTimeOffset;
+ /*0xA0*/ struct Time lastBerryTreeUpdate;
+ /*0xA8*/ u32 gcnLinkFlags; // Read by Pokemon Colosseum/XD
+ /*0xAC*/ u32 encryptionKey;
+ /*0xB0*/ struct PlayersApprentice playerApprentice;
+ /*0xDC*/ struct Apprentice apprentices[APPRENTICE_COUNT];
+ /*0x1EC*/ struct BerryCrush berryCrush;
+ /*0x1FC*/ struct PokemonJumpResults pokeJump;
+ /*0x20C*/ struct BerryPickingResults berryPick;
+ /*0x21C*/ struct RankingHall1P hallRecords1P[HALL_FACILITIES_COUNT][2][3]; // From record mixing.
+ /*0x57C*/ struct RankingHall2P hallRecords2P[2][3]; // From record mixing.
+ /*0x624*/ u16 contestLinkResults[5][4]; // 4 positions for 5 categories.
+ /*0x64C*/ struct BattleFrontier frontier;
+ }; // sizeof=0xF2C
+```
+Declare a new function in [include/item_use.h](../blob/master/include/item_use.h):
+```c
+void ItemUseOutOfBattle_ExpShare(u8);
+```
+Insert this function into [src/item_use.c](../blob/master/src/item_use.c):
+```c
+void ItemUseOutOfBattle_ExpShare(u8 taskId)
+{
+ if (!gSaveBlock2Ptr->expShare)
+ {
+ PlaySE(SE_EXPMAX);
+ if (!gTasks[taskId].data[2]) // to account for pressing select in the overworld
+ {
+ DisplayItemMessageOnField(taskId, gText_ExpShareOn, Task_CloseCantUseKeyItemMessage);
+ }
+ else
+ {
+ DisplayItemMessage(taskId, 1, gText_ExpShareOn, BagMenu_InitListsMenu);
+ }
+ }
+ else
+ {
+ PlaySE(SE_PC_OFF);
+ if (!gTasks[taskId].data[2]) // to account for pressing select in the overworld
+ {
+ DisplayItemMessageOnField(taskId, gText_ExpShareOff, Task_CloseCantUseKeyItemMessage);
+ }
+ else
+ {
+ DisplayItemMessage(taskId, 1, gText_ExpShareOff, BagMenu_InitListsMenu);
+ }
+ }
+ gSaveBlock2Ptr->expShare = !gSaveBlock2Ptr->expShare;
+}
+```
+This function will toggle `expShare` on or off and display the appropriate message. It is also possible to register the item, so we need to account for that as well.
+
+Now, all our changes out of battle are complete. In the next step, we will focus on having the new sharing functionality work properly.
+
+## 2. Edit behavior in battle
+
+First, we will need some new text for the new Exp. Share. We need to define a new id. Edit [include/constants/battle_string_ids.h](../blob/master/include/constants/battle_string_ids.h):
+```diff
+-#define BATTLESTRINGS_COUNT 369
++#define BATTLESTRINGS_COUNT 370
+```
+```diff
++#define STRINGID_TEAMGAINEDEXP 381
+```
+
+Add this to [src/battle_message.c](../blob/master/src/battle_message.c). This can be done anywhere as long as it is before `gBattleStringsTable`:
+```c
+static const u8 sText_TeamGainedEXP[] = _("The rest of the team gained EXP. Points\nthanks to the EXP. SHARE!\p");
+```
+Then add this to `gBattleStringsTable`:
+```diff
+ [STRINGID_PKMNBOXLANETTESPCFULL - 12] = gText_PkmnTransferredLanettesPCBoxFull,
+ [STRINGID_TRAINER1WINTEXT - 12] = sText_Trainer1WinText,
+ [STRINGID_TRAINER2WINTEXT - 12] = sText_Trainer2WinText,
++ [STRINGID_TEAMGAINEDEXP - 12] = sText_TeamGainedEXP,
+ };
+```
+
+Now, the rest of our changes will be in `Cmd_getexp` of [src/battle_script_commands.c](../blob/master/src/battle_script_commands.c):
+```diff
+ case 1: // calculate experience points to redistribute
+ {
+ u16 calculatedExp;
+ s32 viaSentIn;
+
+ for (viaSentIn = 0, i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) == SPECIES_NONE || GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0)
+ continue;
+ if (gBitTable[i] & sentIn)
+ viaSentIn++;
+
+ item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+
+ if (item == ITEM_ENIGMA_BERRY)
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(item);
+
+ if (holdEffect == HOLD_EFFECT_EXP_SHARE)
+ viaExpShare++;
+ }
+
+ calculatedExp = gBaseStats[gBattleMons[gBattlerFainted].species].expYield * gBattleMons[gBattlerFainted].level / 7;
+
+ if (viaExpShare) // at least one mon is getting exp via exp share
+ {
+ *exp = calculatedExp / 2 / viaSentIn;
+ if (*exp == 0)
+ *exp = 1;
+
+ gExpShareExp = calculatedExp / 2 / viaExpShare;
+ if (gExpShareExp == 0)
+ gExpShareExp = 1;
+ }
+ else
+ {
+ *exp = calculatedExp / viaSentIn;
+ if (*exp == 0)
+ *exp = 1;
+ gExpShareExp = 0;
+ }
+
+ gBattleScripting.getexpState++;
+ gBattleStruct->expGetterMonId = 0;
+ gBattleStruct->sentInPokes = sentIn;
+ }
+ // fall through
+ case 2: // set exp value to the poke in expgetter_id and print message
+ if (gBattleControllerExecFlags == 0)
+ {
+ item = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HELD_ITEM);
+
+ if (item == ITEM_ENIGMA_BERRY)
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(item);
+
+ if (holdEffect != HOLD_EFFECT_EXP_SHARE && !(gBattleStruct->sentInPokes & 1))
+ {
+ *(&gBattleStruct->sentInPokes) >>= 1;
+ gBattleScripting.getexpState = 5;
+ gBattleMoveDamage = 0; // used for exp
+ }
+ else if (GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL) == MAX_LEVEL)
+ {
+ *(&gBattleStruct->sentInPokes) >>= 1;
+ gBattleScripting.getexpState = 5;
+ gBattleMoveDamage = 0; // used for exp
+ }
+ else
+ {
+ // music change in wild battle after fainting a poke
+ if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && gBattleMons[0].hp && !gBattleStruct->wildVictorySong)
+ {
+ BattleStopLowHpSound();
+ PlayBGM(MUS_KACHI2);
+ gBattleStruct->wildVictorySong++;
+ }
+
+ if (GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP))
+ {
+ if (gBattleStruct->sentInPokes & 1)
+ gBattleMoveDamage = *exp;
+ else
+ gBattleMoveDamage = 0;
+
+ if (holdEffect == HOLD_EFFECT_EXP_SHARE)
+ gBattleMoveDamage += gExpShareExp;
+ if (holdEffect == HOLD_EFFECT_LUCKY_EGG)
+ gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
``` \ No newline at end of file