[GameInteractor] Game Hooks (#2481)

This commit is contained in:
David Chavez 2023-02-15 20:30:34 +01:00 committed by GitHub
parent 2c10bca615
commit 8934274c67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 230 additions and 121 deletions

View File

@ -258,8 +258,14 @@ set(Header_Files__soh__Enhancements__item_tables
source_group("Header Files\\soh\\Enhancements\\item-tables" FILES ${Header_Files__soh__Enhancements__item_tables})
set(Header_Files__soh__Enhancements__mods
"soh/Enhancements/mods/modhooks.h"
)
source_group("Header Files\\soh\\Enhancements\\mods" FILES ${Header_Files__soh__Enhancements__mods})
set(Header_Files__soh__Enhancements__game_interactor
"soh/Enhancements/game-interactor/GameInteractor.h"
"soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
"soh/Enhancements/game-interactor/GameInteractionEffect.h"
)
source_group("Header Files\\soh\\Enhancements\\game-interactor" FILES ${Header_Files__soh__Enhancements__game_interactor})
@ -609,9 +615,15 @@ set(Source_Files__soh__Enhancements__item_tables
source_group("Source Files\\soh\\Enhancements\\item-tables" FILES ${Source_Files__soh__Enhancements__item_tables})
set(Source_Files__soh__Enhancements__mods
"soh/Enhancements/mods/modhooks.cpp"
)
source_group("Source Files\\soh\\Enhancements\\mods" FILES ${Source_Files__soh__Enhancements__mods})
set(Source_Files__soh__Enhancements__game_interactor
"soh/Enhancements/game-interactor/GameInteractor.cpp"
"soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp"
"soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp"
"soh/Enhancements/game-interactor/GameInteractor_State.cpp"
"soh/Enhancements/game-interactor/GameInteractionEffect.cpp"
)
@ -1835,6 +1847,7 @@ set(ALL_FILES
${Header_Files__soh__Enhancements__randomizer__3drando}
${Header_Files__soh__Enhancements__item_tables}
${Header_Files__soh__Enhancements__custom_message}
${Header_Files__soh__Enhancements__mods}
${Header_Files__soh__Enhancements__game_interactor}
${Header_Files__soh__Enhancements__crowd_control}
${Source_Files__soh}
@ -1849,6 +1862,7 @@ set(ALL_FILES
${Source_Files__soh__Enhancements__randomizer__3drando__location_access}
${Source_Files__soh__Enhancements__item_tables}
${Source_Files__soh__Enhancements__custom_message}
${Source_Files__soh__Enhancements__mods}
${Source_Files__soh__Enhancements__game_interactor}
${Source_Files__soh__Enhancements__crowd_control}
${Source_Files__src__boot}

View File

@ -4,6 +4,7 @@
#define GameInteractor_h
#include "GameInteractionEffect.h"
#include "z64.h"
typedef enum {
/* 0x00 */ GI_LINK_SIZE_NORMAL,
@ -39,6 +40,15 @@ GIGravityLevel GameInteractor_GravityLevel();
#ifdef __cplusplus
#include <vector>
#include <functional>
#define DEFINE_HOOK(name, type) \
struct name { \
typedef std::function<type> fn; \
}
class GameInteractor {
public:
static GameInteractor* Instance;
@ -65,6 +75,23 @@ public:
static GameInteractionEffectQueryResult ApplyEffect(GameInteractionEffectBase* effect);
static GameInteractionEffectQueryResult RemoveEffect(GameInteractionEffectBase* effect);
// Game Hooks
template <typename H> struct RegisteredGameHooks { inline static std::vector<typename H::fn> functions; };
template <typename H> void RegisterGameHook(typename H::fn h) { RegisteredGameHooks<H>::functions.push_back(h); }
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
for (auto& fn : RegisteredGameHooks<H>::functions) {
fn(std::forward<Args>(args)...);
}
}
DEFINE_HOOK(OnReceiveItem, void(u8 item));
DEFINE_HOOK(OnSceneInit, void(s16 sceneNum));
DEFINE_HOOK(OnSaveFile, void(int fileNum));
DEFINE_HOOK(OnLoadFile, void(int fileNum));
DEFINE_HOOK(OnDeleteFile, void(int fileNum));
// Helpers
static bool IsSaveLoaded();
static bool IsGameplayPaused();

View File

@ -0,0 +1,29 @@
#include "GameInteractor_Hooks.h"
extern "C" {
extern PlayState* gPlayState;
}
// MARK: - Gameplay
void GameInteractor_ExecuteOnReceiveItemHooks(u8 item) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnReceiveItem>(item);
}
void GameInteractor_ExecuteOnSceneInitHooks(s16 sceneNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneNum);
}
// MARK: - Save Files
void GameInteractor_ExecuteOnSaveFile(int fileNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
}
void GameInteractor_ExecuteOnLoadFile(int fileNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
}
void GameInteractor_ExecuteOnDeleteFile(int fileNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnDeleteFile>(fileNum);
}

View File

@ -0,0 +1,10 @@
#include "GameInteractor.h"
// MARK: - Gameplay
extern "C" void GameInteractor_ExecuteOnReceiveItemHooks(u8 item);
extern "C" void GameInteractor_ExecuteOnSceneInit(s16 sceneNum);
// MARK: - Save Files
extern "C" void GameInteractor_ExecuteOnSaveFile(int fileNum);
extern "C" void GameInteractor_ExecuteOnLoadFile(int fileNum);
extern "C" void GameInteractor_ExecuteOnDeleteFile(int fileNum);

View File

@ -0,0 +1,68 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include <libultraship/bridge.h>
extern "C" {
#include <z64.h>
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
extern void Play_PerformSave(PlayState* play);
}
void RegisterAutoSaveOnReceiveItem() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnReceiveItem>([](u8 item) {
if (CVarGetInteger("gAutosave", 0) && (gPlayState != NULL) && (gPlayState->sceneNum != SCENE_KENJYANOMA) && (gSaveContext.pendingSale == ITEM_NONE) && (gPlayState->sceneNum != SCENE_GANON_DEMO)) {
if (CVarGetInteger("gAutosaveAllItems", 0)) {
Play_PerformSave(gPlayState);
} else if (CVarGetInteger("gAutosaveMajorItems", 1)) {
switch (item) {
case ITEM_STICK:
case ITEM_NUT:
case ITEM_BOMB:
case ITEM_BOW:
case ITEM_SEEDS:
case ITEM_FISHING_POLE:
case ITEM_MAGIC_SMALL:
case ITEM_MAGIC_LARGE:
case ITEM_INVALID_4:
case ITEM_INVALID_5:
case ITEM_INVALID_6:
case ITEM_INVALID_7:
case ITEM_HEART:
case ITEM_RUPEE_GREEN:
case ITEM_RUPEE_BLUE:
case ITEM_RUPEE_RED:
case ITEM_RUPEE_PURPLE:
case ITEM_RUPEE_GOLD:
case ITEM_INVALID_8:
case ITEM_STICKS_5:
case ITEM_STICKS_10:
case ITEM_NUTS_5:
case ITEM_NUTS_10:
case ITEM_BOMBS_5:
case ITEM_BOMBS_10:
case ITEM_BOMBS_20:
case ITEM_BOMBS_30:
case ITEM_ARROWS_SMALL:
case ITEM_ARROWS_MEDIUM:
case ITEM_ARROWS_LARGE:
case ITEM_SEEDS_30:
break;
case ITEM_BOMBCHU:
case ITEM_BOMBCHUS_5:
case ITEM_BOMBCHUS_20:
if (!CVarGetInteger("gBombchuDrops", 0)) {
Play_PerformSave(gPlayState);
}
break;
default:
Play_PerformSave(gPlayState);
break;
}
}
}
});
}
extern "C" void RegisterModHooks() {
RegisterAutoSaveOnReceiveItem();
}

View File

@ -0,0 +1,5 @@
#ifdef __cplusplus
extern "C" {
void RegisterModHooks(void);
}
#endif

View File

@ -73,8 +73,9 @@
CrowdControl* CrowdControl::Instance;
#endif
#include "Enhancements/mods/modhooks.h"
#include "Enhancements/game-interactor/GameInteractor.h"
#include "libultraship/libultraship.h"
#include <libultraship/libultraship.h>
// Resource Types/Factories
#include "soh/resource/type/Animation.h"
@ -584,6 +585,8 @@ extern "C" void InitOTR() {
OTRExtScanner();
VanillaItemTable_Init();
RegisterModHooks();
time_t now = time(NULL);
tm *tm_now = localtime(&now);
if (tm_now->tm_mon == 11 && tm_now->tm_mday >= 24 && tm_now->tm_mday <= 25) {

View File

@ -1,5 +1,6 @@
#include "SaveManager.h"
#include "OTRGlobals.h"
#include "Enhancements/game-interactor/GameInteractor.h"
#include "z64.h"
#include "functions.h"
@ -693,6 +694,7 @@ void SaveManager::SaveFile(int fileNum) {
#endif
InitMeta(fileNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
}
void SaveManager::SaveGlobal() {
@ -754,6 +756,7 @@ void SaveManager::LoadFile(int fileNum) {
break;
}
InitMeta(fileNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
}
bool SaveManager::SaveFile_Exist(int fileNum) {
@ -1680,6 +1683,7 @@ void SaveManager::DeleteZeldaFile(int fileNum) {
}
fileMetaInfo[fileNum].valid = false;
fileMetaInfo[fileNum].randoSave = false;
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnDeleteFile>(fileNum);
}
bool SaveManager::IsRandoFile() {

View File

@ -2,6 +2,7 @@
#include <ResourceMgr.h>
#include "soh/resource/type/Scene.h"
#include <Utils/StringHelper.h>
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "global.h"
#include "vt.h"
#include <Vertex.h>
@ -81,6 +82,8 @@ void OTRPlay_InitScene(PlayState* play, s32 spawn) {
.get());
auto data2 = ResourceMgr_LoadVtxByCRC(0x68d4ea06044e228f);*/
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(play->sceneNum);
volatile int a = 0;
}

View File

@ -1738,7 +1738,7 @@ u8 Item_Give(PlayState* play, u8 item) {
func_8006D0AC(play);
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_SONG_MINUET) && (item <= ITEM_SONG_STORMS)) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_SONG_MINUET + QUEST_SONG_MINUET];
@ -1750,7 +1750,7 @@ u8 Item_Give(PlayState* play, u8 item) {
gBitFlags[item - ITEM_SONG_MINUET + QUEST_SONG_MINUET], gBitFlags[item - ITEM_SONG_MINUET]);
osSyncPrintf(VT_RST);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_KOKIRI_EMERALD) && (item <= ITEM_ZORA_SAPPHIRE)) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD];
@ -1759,7 +1759,7 @@ u8 Item_Give(PlayState* play, u8 item) {
osSyncPrintf("精霊石 = %x\n", gSaveContext.inventory.questItems); // "Spiritual Stones = %x"
osSyncPrintf(VT_RST);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item == ITEM_STONE_OF_AGONY) || (item == ITEM_GERUDO_CARD)) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_STONE_OF_AGONY + QUEST_STONE_OF_AGONY];
@ -1768,7 +1768,7 @@ u8 Item_Give(PlayState* play, u8 item) {
osSyncPrintf("アイテム = %x\n", gSaveContext.inventory.questItems); // "Items = %x"
osSyncPrintf(VT_RST);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_SKULL_TOKEN) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_SKULL_TOKEN + QUEST_SKULL_TOKEN];
@ -1779,7 +1779,7 @@ u8 Item_Give(PlayState* play, u8 item) {
osSyncPrintf("Nコイン = %x(%d)\n", gSaveContext.inventory.questItems, gSaveContext.inventory.gsTokens);
osSyncPrintf(VT_RST);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) {
gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD];
@ -1811,19 +1811,19 @@ u8 Item_Give(PlayState* play, u8 item) {
}
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_SHIELD_DEKU) && (item <= ITEM_SHIELD_MIRROR)) {
gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_SHIELD]);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_TUNIC_KOKIRI) && (item <= ITEM_TUNIC_ZORA)) {
gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_TUNIC_KOKIRI] << gEquipShifts[EQUIP_TUNIC]);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_BOOTS_KOKIRI) && (item <= ITEM_BOOTS_HOVER)) {
gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_BOOTS_KOKIRI] << gEquipShifts[EQUIP_BOOTS]);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) {
// Boss Key, Compass, and Dungeon Map exceptions for rando.
@ -1840,7 +1840,7 @@ u8 Item_Give(PlayState* play, u8 item) {
} else {
gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS];
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_KEY_SMALL) {
// Small key exceptions for rando with keysanity off.
@ -1851,11 +1851,11 @@ u8 Item_Give(PlayState* play, u8 item) {
gSaveContext.sohStats.dungeonKeys[13]++;
if (gSaveContext.inventory.dungeonKeys[13] < 0) {
gSaveContext.inventory.dungeonKeys[13] = 1;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[13]++;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
}
@ -1864,11 +1864,11 @@ u8 Item_Give(PlayState* play, u8 item) {
gSaveContext.sohStats.dungeonKeys[6]++;
if (gSaveContext.inventory.dungeonKeys[6] < 0) {
gSaveContext.inventory.dungeonKeys[6] = 1;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[6]++;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
}
@ -1876,11 +1876,11 @@ u8 Item_Give(PlayState* play, u8 item) {
gSaveContext.sohStats.dungeonKeys[gSaveContext.mapIndex]++;
if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
} else if ((item == ITEM_QUIVER_30) || (item == ITEM_BOW)) {
@ -1888,7 +1888,7 @@ u8 Item_Give(PlayState* play, u8 item) {
Inventory_ChangeUpgrade(UPG_QUIVER, 1);
INV_CONTENT(ITEM_BOW) = ITEM_BOW;
AMMO(ITEM_BOW) = CAPACITY(UPG_QUIVER, 1);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
AMMO(ITEM_BOW)++;
@ -1899,29 +1899,29 @@ u8 Item_Give(PlayState* play, u8 item) {
} else if (item == ITEM_QUIVER_40) {
Inventory_ChangeUpgrade(UPG_QUIVER, 2);
AMMO(ITEM_BOW) = CAPACITY(UPG_QUIVER, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_QUIVER_50) {
Inventory_ChangeUpgrade(UPG_QUIVER, 3);
AMMO(ITEM_BOW) = CAPACITY(UPG_QUIVER, 3);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BULLET_BAG_40) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 2);
AMMO(ITEM_SLINGSHOT) = CAPACITY(UPG_BULLET_BAG, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BULLET_BAG_50) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 3);
AMMO(ITEM_SLINGSHOT) = CAPACITY(UPG_BULLET_BAG, 3);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BOMB_BAG_20) {
if (CUR_UPG_VALUE(UPG_BOMB_BAG) == 0) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 1);
INV_CONTENT(ITEM_BOMB) = ITEM_BOMB;
AMMO(ITEM_BOMB) = CAPACITY(UPG_BOMB_BAG, 1);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
AMMO(ITEM_BOMB)++;
@ -1932,46 +1932,46 @@ u8 Item_Give(PlayState* play, u8 item) {
} else if (item == ITEM_BOMB_BAG_30) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 2);
AMMO(ITEM_BOMB) = CAPACITY(UPG_BOMB_BAG, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BOMB_BAG_40) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 3);
AMMO(ITEM_BOMB) = CAPACITY(UPG_BOMB_BAG, 3);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BRACELET) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 1);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_GAUNTLETS_SILVER) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_GAUNTLETS_GOLD) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 3);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_SCALE_SILVER) {
Inventory_ChangeUpgrade(UPG_SCALE, 1);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_SCALE_GOLDEN) {
Inventory_ChangeUpgrade(UPG_SCALE, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_WALLET_ADULT) {
Inventory_ChangeUpgrade(UPG_WALLET, 1);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) {
Rupees_ChangeBy(200);
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_WALLET_GIANT) {
Inventory_ChangeUpgrade(UPG_WALLET, 2);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) {
Rupees_ChangeBy(500);
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_STICK_UPGRADE_20) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
@ -1979,7 +1979,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
Inventory_ChangeUpgrade(UPG_STICKS, 2);
AMMO(ITEM_STICK) = CAPACITY(UPG_STICKS, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_STICK_UPGRADE_30) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
@ -1987,7 +1987,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
Inventory_ChangeUpgrade(UPG_STICKS, 3);
AMMO(ITEM_STICK) = CAPACITY(UPG_STICKS, 3);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_NUT_UPGRADE_30) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
@ -1995,7 +1995,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
Inventory_ChangeUpgrade(UPG_NUTS, 2);
AMMO(ITEM_NUT) = CAPACITY(UPG_NUTS, 2);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_NUT_UPGRADE_40) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
@ -2003,7 +2003,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
Inventory_ChangeUpgrade(UPG_NUTS, 3);
AMMO(ITEM_NUT) = CAPACITY(UPG_NUTS, 3);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_LONGSHOT) {
INV_CONTENT(item) = item;
@ -2037,7 +2037,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
}
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_STICK) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
@ -2090,40 +2090,40 @@ u8 Item_Give(PlayState* play, u8 item) {
if ((AMMO(ITEM_BOMB) += 1) > CUR_CAPACITY(UPG_BOMB_BAG)) {
AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG);
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item >= ITEM_BOMBS_5) && (item <= ITEM_BOMBS_30)) {
if ((AMMO(ITEM_BOMB) += sAmmoRefillCounts[item - ITEM_BOMBS_5]) > CUR_CAPACITY(UPG_BOMB_BAG)) {
AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG);
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BOMBCHU) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
AMMO(ITEM_BOMBCHU) = 10;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
AMMO(ITEM_BOMBCHU) += 10;
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
} else if ((item == ITEM_BOMBCHUS_5) || (item == ITEM_BOMBCHUS_20)) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
AMMO(ITEM_BOMBCHU) += sAmmoRefillCounts[item - ITEM_BOMBCHUS_5 + 8];
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else {
AMMO(ITEM_BOMBCHU) += sAmmoRefillCounts[item - ITEM_BOMBCHUS_5 + 8];
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
} else if ((item >= ITEM_ARROWS_SMALL) && (item <= ITEM_ARROWS_LARGE)) {
@ -2135,13 +2135,13 @@ u8 Item_Give(PlayState* play, u8 item) {
osSyncPrintf("%d本 Item_MaxGet=%d\n", AMMO(ITEM_BOW), CUR_CAPACITY(UPG_QUIVER));
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_BOW;
} else if (item == ITEM_SLINGSHOT) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 1);
INV_CONTENT(ITEM_SLINGSHOT) = ITEM_SLINGSHOT;
AMMO(ITEM_SLINGSHOT) = 30;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_SEEDS) {
AMMO(ITEM_SLINGSHOT) += 5;
@ -2152,11 +2152,11 @@ u8 Item_Give(PlayState* play, u8 item) {
if (!(gSaveContext.itemGetInf[1] & 8)) {
gSaveContext.itemGetInf[1] |= 8;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_SEEDS;
} else if (item == ITEM_SEEDS_30) {
AMMO(ITEM_SLINGSHOT) += 30;
@ -2167,15 +2167,15 @@ u8 Item_Give(PlayState* play, u8 item) {
if (!(gSaveContext.itemGetInf[1] & 8)) {
gSaveContext.itemGetInf[1] |= 8;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_SEEDS;
} else if (item == ITEM_OCARINA_FAIRY) {
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_OCARINA_TIME) {
INV_CONTENT(ITEM_OCARINA_TIME) = ITEM_OCARINA_TIME;
@ -2208,7 +2208,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
}
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BEAN) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
@ -2219,25 +2219,25 @@ u8 Item_Give(PlayState* play, u8 item) {
AMMO(ITEM_BEAN)++;
BEANS_BOUGHT++;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if ((item == ITEM_HEART_PIECE_2) || (item == ITEM_HEART_PIECE)) {
gSaveContext.inventory.questItems += 1 << (QUEST_HEART_PIECE + 4);
gSaveContext.sohStats.heartPieces++;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_HEART_CONTAINER) {
gSaveContext.healthCapacity += 0x10;
gSaveContext.health += 0x10;
gSaveContext.sohStats.heartContainers++;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_HEART) {
osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart"
if (play != NULL) {
Health_ChangeBy(play, 0x10);
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return item;
} else if (item == ITEM_MAGIC_SMALL) {
if (gSaveContext.magicState != 10) {
@ -2252,11 +2252,11 @@ u8 Item_Give(PlayState* play, u8 item) {
if (!(gSaveContext.infTable[25] & 0x100)) {
gSaveContext.infTable[25] |= 0x100;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return item;
} else if (item == ITEM_MAGIC_LARGE) {
if (gSaveContext.magicState != 10) {
@ -2270,15 +2270,15 @@ u8 Item_Give(PlayState* play, u8 item) {
if (!(gSaveContext.infTable[25] & 0x100)) {
gSaveContext.infTable[25] |= 0x100;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return item;
} else if ((item >= ITEM_RUPEE_GREEN) && (item <= ITEM_INVALID_8)) {
Rupees_ChangeBy(sAmmoRefillCounts[item - ITEM_RUPEE_GREEN + 10]);
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
} else if (item == ITEM_BOTTLE) {
temp = SLOT(item);
@ -2286,7 +2286,7 @@ u8 Item_Give(PlayState* play, u8 item) {
for (i = 0; i < 4; i++) {
if (gSaveContext.inventory.items[temp + i] == ITEM_NONE) {
gSaveContext.inventory.items[temp + i] = item;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
}
@ -2318,7 +2318,7 @@ u8 Item_Give(PlayState* play, u8 item) {
}
gSaveContext.inventory.items[temp + i] = item;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
}
@ -2326,7 +2326,7 @@ u8 Item_Give(PlayState* play, u8 item) {
for (i = 0; i < 4; i++) {
if (gSaveContext.inventory.items[temp + i] == ITEM_NONE) {
gSaveContext.inventory.items[temp + i] = item;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
}
@ -2354,13 +2354,13 @@ u8 Item_Give(PlayState* play, u8 item) {
} else {
gSaveContext.equips.buttonItems[i] = ITEM_NONE;
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
}
}
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return ITEM_NONE;
}
@ -2368,7 +2368,7 @@ u8 Item_Give(PlayState* play, u8 item) {
osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, temp);
INV_CONTENT(item) = item;
PerformAutosave(play, item);
GameInteractor_ExecuteOnReceiveItemHooks(item);
return temp;
}
@ -2721,60 +2721,6 @@ u8 Item_CheckObtainability(u8 item) {
return gSaveContext.inventory.items[slot];
}
// Save when receiving an item, unless it's purchased from a shop
void PerformAutosave(PlayState* play, u8 item) {
if (CVarGetInteger("gAutosave", 0) && (play != NULL) && (play->sceneNum != SCENE_KENJYANOMA) && (gSaveContext.pendingSale == ITEM_NONE) && (play->sceneNum != SCENE_GANON_DEMO)) {
if (CVarGetInteger("gAutosaveAllItems", 0)) {
Play_PerformSave(play);
} else if (CVarGetInteger("gAutosaveMajorItems", 1)) {
switch (item) {
case ITEM_STICK:
case ITEM_NUT:
case ITEM_BOMB:
case ITEM_BOW:
case ITEM_SEEDS:
case ITEM_FISHING_POLE:
case ITEM_MAGIC_SMALL:
case ITEM_MAGIC_LARGE:
case ITEM_INVALID_4:
case ITEM_INVALID_5:
case ITEM_INVALID_6:
case ITEM_INVALID_7:
case ITEM_HEART:
case ITEM_RUPEE_GREEN:
case ITEM_RUPEE_BLUE:
case ITEM_RUPEE_RED:
case ITEM_RUPEE_PURPLE:
case ITEM_RUPEE_GOLD:
case ITEM_INVALID_8:
case ITEM_STICKS_5:
case ITEM_STICKS_10:
case ITEM_NUTS_5:
case ITEM_NUTS_10:
case ITEM_BOMBS_5:
case ITEM_BOMBS_10:
case ITEM_BOMBS_20:
case ITEM_BOMBS_30:
case ITEM_ARROWS_SMALL:
case ITEM_ARROWS_MEDIUM:
case ITEM_ARROWS_LARGE:
case ITEM_SEEDS_30:
break;
case ITEM_BOMBCHU:
case ITEM_BOMBCHUS_5:
case ITEM_BOMBCHUS_20:
if (!CVarGetInteger("gBombchuDrops", 0)) {
Play_PerformSave(play);
}
break;
default:
Play_PerformSave(play);
break;
}
}
}
}
void Inventory_DeleteItem(u16 item, u16 invSlot) {
s16 i;
@ -6300,7 +6246,7 @@ void Interface_Update(PlayState* play) {
if (gSaveContext.rupeeAccumulator == 0) {
u16 tempSaleItem = gSaveContext.pendingSale;
gSaveContext.pendingSale = ITEM_NONE;
PerformAutosave(play, tempSaleItem);
GameInteractor_ExecuteOnReceiveItemHooks(tempSaleItem);
}
} else {
gSaveContext.rupeeAccumulator = 0;