Adds rough ability to differentiate between rando and vanilla items.merge stashed changes from before develop-zhora merge

This commit is contained in:
Christopher Leggett 2022-08-03 23:15:52 -04:00
parent 1da655adb5
commit 95d439bb30
No known key found for this signature in database
GPG Key ID: 7093AE5FF7037D79
14 changed files with 316 additions and 143 deletions

View File

@ -10,6 +10,7 @@ extern "C"
#endif
#include "../../libultraship/libultraship/luslog.h"
#include <soh/Enhancements/item-tables/ItemTableTypes.h>
#if defined(INCLUDE_GAME_PRINTF) && !defined(NDEBUG)
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__)
@ -1045,6 +1046,7 @@ void Interface_LoadItemIcon1(GlobalContext* globalCtx, u16 button);
void Interface_LoadItemIcon2(GlobalContext* globalCtx, u16 button);
void func_80084BF4(GlobalContext* globalCtx, u16 flag);
u8 Item_Give(GlobalContext* globalCtx, u8 item);
u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry);
u8 Item_CheckObtainability(u8 item);
void Inventory_DeleteItem(u16 item, u16 invSlot);
s32 Inventory_ReplaceItem(GlobalContext* globalCtx, u16 oldItem, u16 newItem);

View File

@ -626,6 +626,6 @@ typedef struct Player {
/* 0x0A87 */ u8 unk_A87;
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
/* 0x0A94 */ PendingFlag pendingFlag;
} Player; // size = 0xAA0
} Player; // size = 0xA94
#endif

View File

@ -949,6 +949,7 @@
<ClCompile Include="soh\Enhancements\randomizer\randomizer.h" />
<ClInclude Include="soh\Enhancements\gfx.h" />
<ClInclude Include="soh\Enhancements\item-tables\ItemTableManager.h" />
<ClInclude Include="soh\Enhancements\item-tables\ItemTableTypes.h" />
<ClInclude Include="soh\Enhancements\randomizer\3drando\category.hpp" />
<ClInclude Include="soh\Enhancements\randomizer\3drando\cosmetics.hpp" />
<ClInclude Include="soh\Enhancements\randomizer\3drando\custom_messages.hpp" />

View File

@ -4086,7 +4086,10 @@
<Filter>Header Files\soh\Enhancements\randomizer</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\item-tables\ItemTableManager.h">
<Filter>Header Files</Filter>
<Filter>Header Files\soh\Enhancements\item-tables</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\item-tables\ItemTableTypes.h">
<Filter>Header Files\soh\Enhancements\item-tables</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>

View File

@ -1,30 +1,16 @@
#pragma once
#include <ultra64/gbi.h>
#include "ItemTableTypes.h"
#define CHEST_ANIM_SHORT 0
#define CHEST_ANIM_LONG 1
typedef struct {
/* 0x00 */ uint8_t itemId;
/* 0x01 */ uint8_t field; // various bit-packed data
/* 0x02 */ int8_t gi; // defines the draw id and chest opening animation
/* 0x03 */ uint8_t textId;
/* 0x04 */ uint16_t objectId;
/* 0x06 */ uint16_t modIndex; // 0 = Vanilla, 1 = Randomizer, future mods will increment up?
} GetItemEntry; // size = 0x06
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim) \
{ itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId }
#define GET_ITEM_NONE \
{ ITEM_NONE, 0, 0, 0, OBJECT_INVALID }
#ifdef __cplusplus
{ 0, 0, 0, 0, 0 }
#include <unordered_map>
#include "z64item.h"
#include "z64object.h"
typedef std::unordered_map<uint8_t, GetItemEntry> ItemTable;
@ -44,5 +30,3 @@ class ItemTableManager {
ItemTable* RetrieveItemTable(std::string tableID);
};
#endif

View File

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
#include <stdint.h>
#endif
typedef struct {
/* 0x00 */ uint8_t itemId;
/* 0x01 */ uint8_t field; // various bit-packed data
/* 0x02 */ int8_t gi; // defines the draw id and chest opening animation
/* 0x03 */ uint8_t textId;
/* 0x04 */ uint16_t objectId;
/* 0x06 */ uint16_t modIndex; // 0 = Vanilla, 1 = Randomizer, future mods will increment up?
} GetItemEntry; // size = 0x06

View File

@ -2030,8 +2030,8 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_MAGIC_BEAN_PACK:
return GI_BEAN; //todo make it 10 of them
case RG_DOUBLE_DEFENSE:
return GI_DOUBLE_DEFENSE;
/*case RG_DOUBLE_DEFENSE:
return GI_DOUBLE_DEFENSE;*/
case RG_WEIRD_EGG:
return GI_WEIRD_EGG;
@ -2160,9 +2160,9 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_PROGRESSIVE_MAGIC_METER:
switch (gSaveContext.magicLevel) {
case 0:
return GI_SINGLE_MAGIC;
return (GetItemID)RG_MAGIC_SINGLE;
case 1:
return GI_DOUBLE_MAGIC;
return (GetItemID)RG_MAGIC_DOUBLE;
}
return GI_RUPEE_BLUE;
@ -2182,7 +2182,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
return GI_BOTTLE;
case RG_BOTTLE_WITH_MILK:
return GI_MILK_BOTTLE;
case RG_BOTTLE_WITH_RED_POTION:
/*case RG_BOTTLE_WITH_RED_POTION:
return GI_BOTTLE_WITH_RED_POTION;
case RG_BOTTLE_WITH_GREEN_POTION:
return GI_BOTTLE_WITH_GREEN_POTION;
@ -2227,7 +2227,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_NOCTURNE_OF_SHADOW:
return GI_NOCTURNE_OF_SHADOW;
case RG_PRELUDE_OF_LIGHT:
return GI_PRELUDE_OF_LIGHT;
return GI_PRELUDE_OF_LIGHT;*/
// todo implement dungeon-specific maps/compasses
case RG_DEKU_TREE_MAP:
@ -2290,7 +2290,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_GANONS_CASTLE_KEY_RING:
return GI_RUPEE_BLUE;
case RG_KOKIRI_EMERALD:
/*case RG_KOKIRI_EMERALD:
return GI_STONE_KOKIRI;
case RG_GORON_RUBY:
return GI_STONE_GORON;
@ -2308,7 +2308,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_SHADOW_MEDALLION:
return GI_MEDALLION_SHADOW;
case RG_LIGHT_MEDALLION:
return GI_MEDALLION_LIGHT;
return GI_MEDALLION_LIGHT;*/
case RG_RECOVERY_HEART:
return GI_HEART;
@ -2387,11 +2387,60 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_HINT:
return GI_RUPEE_BLUE; //todo
default:
default: {
if (IsGetItemRandoExclusive(randoGet)) {
return (GetItemID)randoGet;
}
return ogItemId;
}
}
}
bool Randomizer::IsGetItemRandoExclusive(RandomizerGet randoGet) {
switch (randoGet) {
case RG_LIGHT_MEDALLION:
case RG_FOREST_MEDALLION:
case RG_FIRE_MEDALLION:
case RG_WATER_MEDALLION:
case RG_SHADOW_MEDALLION:
case RG_SPIRIT_MEDALLION:
case RG_KOKIRI_EMERALD:
case RG_GORON_RUBY:
case RG_ZORA_SAPPHIRE:
case RG_ZELDAS_LULLABY:
case RG_SUNS_SONG:
case RG_EPONAS_SONG:
case RG_SONG_OF_STORMS:
case RG_SONG_OF_TIME:
case RG_SARIAS_SONG:
case RG_MINUET_OF_FOREST:
case RG_BOLERO_OF_FIRE:
case RG_SERENADE_OF_WATER:
case RG_NOCTURNE_OF_SHADOW:
case RG_REQUIEM_OF_SPIRIT:
case RG_PRELUDE_OF_LIGHT:
case RG_PROGRESSIVE_MAGIC_METER:
case RG_DOUBLE_DEFENSE:
case RG_BOTTLE_WITH_RED_POTION:
case RG_BOTTLE_WITH_GREEN_POTION:
case RG_BOTTLE_WITH_BLUE_POTION:
case RG_BOTTLE_WITH_FAIRY:
case RG_BOTTLE_WITH_FISH:
case RG_BOTTLE_WITH_BLUE_FIRE:
case RG_BOTTLE_WITH_BUGS:
case RG_BOTTLE_WITH_POE:
case RG_BOTTLE_WITH_BIG_POE:
return true;
default:
return false;
}
}
bool Randomizer::CheckContainsRandoItem(RandomizerCheck randoCheck) {
RandomizerGet randoGet = this->itemLocations[randoCheck];
return IsGetItemRandoExclusive(randoGet);
}
std::string Randomizer::GetAdultAltarText() const {
return this->adultAltarText;
}
@ -4732,31 +4781,34 @@ void DrawRandoEditor(bool& open) {
void InitRandoItemTable() {
GetItemEntry getItemTable[] = {
GET_ITEM(RG_LIGHT_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_FOREST_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_FIRE_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_WATER_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SHADOW_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SPIRIT_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG),
// The first several entries have ItemIDs from vanilla, but not GetItemIDs or entries in sGetItemTable
GET_ITEM(ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_ZELDAS_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SUNS_SONG, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_EPONAS_SONG, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SONG_OF_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SONG_OF_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SARIAS_SONG, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_MINUET_OF_FOREST, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_BOLERO_OF_FIRE, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_SERENADE_OF_WATER, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_NOCTURNE_OF_SHADOW, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_REQUIEM_OF_SPIRIT, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_PRELUDE_OF_LIGHT, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG),
// Starting here, these do not have ItemIDs or GetItemIDs from vanilla, so I'm using their
// RandomizerGet enum values for both.
GET_ITEM(RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG),
GET_ITEM(RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG),
@ -4773,14 +4825,92 @@ void InitRandoItemTable() {
};
ItemTableManager::Instance->AddItemTable("Randomizer");
for (int i = 0; i < ARRAY_SIZE(getItemTable); i++) {
getItemTable[i].modIndex = MOD_RANDOMIZER;
ItemTableManager::Instance->AddItemEntry("Randomizer", getItemTable[i].itemId, getItemTable[i]);
if (i < 21) {
// We want to use vanilla Give_Item code for indices 0-20 since
// vanilla already handles that.
getItemTable[i].modIndex = MOD_VANILLA;
} else {
// Mark these as randomizer items so we use the rando exclusive
// Give_Item_Randomizer for these.
getItemTable[i].modIndex = MOD_RANDOMIZER;
}
uint8_t getItemID;
switch (getItemTable[i].itemId) {
case ITEM_MEDALLION_LIGHT:
getItemID = RG_LIGHT_MEDALLION;
break;
case ITEM_MEDALLION_FOREST:
getItemID = RG_FOREST_MEDALLION;
break;
case ITEM_MEDALLION_FIRE:
getItemID = RG_FIRE_MEDALLION;
break;
case ITEM_MEDALLION_WATER:
getItemID = RG_WATER_MEDALLION;
break;
case ITEM_MEDALLION_SHADOW:
getItemID = RG_SHADOW_MEDALLION;
break;
case ITEM_MEDALLION_SPIRIT:
getItemID = RG_SPIRIT_MEDALLION;
break;
case ITEM_KOKIRI_EMERALD:
getItemID = RG_KOKIRI_EMERALD;
break;
case ITEM_GORON_RUBY:
getItemID = RG_GORON_RUBY;
break;
case ITEM_ZORA_SAPPHIRE:
getItemID = RG_ZORA_SAPPHIRE;
break;
case ITEM_SONG_LULLABY:
getItemID = RG_ZELDAS_LULLABY;
break;
case ITEM_SONG_SUN:
getItemID = RG_SUNS_SONG;
break;
case ITEM_SONG_EPONA:
getItemID = RG_EPONAS_SONG;
break;
case ITEM_SONG_STORMS:
getItemID = RG_SONG_OF_STORMS;
break;
case ITEM_SONG_TIME:
getItemID = RG_SONG_OF_TIME;
break;
case ITEM_SONG_SARIA:
getItemID = RG_SARIAS_SONG;
break;
case ITEM_SONG_MINUET:
getItemID = RG_MINUET_OF_FOREST;
break;
case ITEM_SONG_BOLERO:
getItemID = RG_BOLERO_OF_FIRE;
break;
case ITEM_SONG_SERENADE:
getItemID = RG_SERENADE_OF_WATER;
break;
case ITEM_SONG_NOCTURNE:
getItemID = RG_NOCTURNE_OF_SHADOW;
break;
case ITEM_SONG_REQUIEM:
getItemID = RG_REQUIEM_OF_SPIRIT;
break;
case ITEM_SONG_PRELUDE:
getItemID = RG_PRELUDE_OF_LIGHT;
break;
default:
getItemID = getItemTable[i].itemId;
break;
}
ItemTableManager::Instance->AddItemEntry("Randomizer", getItemID, getItemTable[i]);
}
}
void InitRando() {
SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor);
InitRandoItemTable();
}
extern "C" {

View File

@ -24,6 +24,8 @@ class Randomizer {
void ParseRandomizerSettingsFile(const char* spoilerFileName);
void ParseHintLocationsFile(const char* spoilerFileName);
void ParseItemLocationsFile(const char* spoilerFileName, bool silent);
bool IsGetItemRandoExclusive(RandomizerGet randoGet);
public:
Randomizer();
@ -37,7 +39,7 @@ class Randomizer {
void LoadHintLocations(const char* spoilerFileName);
void LoadItemLocations(const char* spoilerFileName, bool silent);
u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey);
RandomizerCheck GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum);
RandomizerCheck GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams);
std::string GetChildAltarText() const;
std::string GetAdultAltarText() const;
std::string GetGanonText() const;
@ -45,6 +47,7 @@ class Randomizer {
std::string GetHintFromCheck(RandomizerCheck check);
GetItemID GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
GetItemID GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
bool CheckContainsRandoItem(RandomizerCheck randoCheck);
};
#ifdef __cplusplus

View File

@ -1648,10 +1648,20 @@ extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer,
}
extern "C" s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) {
if (OTRGlobals::Instance->gRandomizer->CheckContainsRandoItem(OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams))) {
OTRGlobals::Instance->getItemModIndex = MOD_RANDOMIZER;
} else {
OTRGlobals::Instance->getItemModIndex = MOD_VANILLA;
}
return OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum);
}
extern "C" s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) {
if (OTRGlobals::Instance->gRandomizer->CheckContainsRandoItem(randomizerCheck)) {
OTRGlobals::Instance->getItemModIndex = MOD_RANDOMIZER;
} else {
OTRGlobals::Instance->getItemModIndex = MOD_VANILLA;
}
return OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId);
}
@ -1660,5 +1670,14 @@ extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetIte
}
extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) {
return ItemTableManager::Instance->RetrieveItemEntry("Vanilla", getItemID);
}
std::string itemTableID;
if (OTRGlobals::Instance->getItemModIndex == MOD_VANILLA) {
itemTableID = "Vanilla";
} else {
itemTableID = "Randomizer";
getItemID++; // counteracts the - 1 offset used for vanilla table
}
return ItemTableManager::Instance->RetrieveItemEntry(itemTableID, getItemID);
}

View File

@ -5,7 +5,7 @@
#include "GlobalCtx2.h"
#include "SaveManager.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h>
#include <soh/Enhancements/item-tables/ItemTableTypes.h>
#ifdef __cplusplus
#include "Enhancements/savestates.h"
@ -19,6 +19,7 @@ public:
std::shared_ptr<Ship::GlobalCtx2> context;
std::shared_ptr<SaveStateMgr> gSaveStateMgr;
std::shared_ptr<Randomizer> gRandomizer;
uint16_t getItemModIndex;
OTRGlobals();
~OTRGlobals();

View File

@ -1578,70 +1578,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
osSyncPrintf("item_get_setting=%d pt=%d z=%x\n", item, slot, gSaveContext.inventory.items[slot]);
osSyncPrintf(VT_RST);
if (item == ITEM_SINGLE_MAGIC) {
gSaveContext.magicAcquired = true;
gSaveContext.unk_13F6 = 0x30;
Magic_Fill(globalCtx);
return ITEM_NONE;
} else if (item == ITEM_DOUBLE_MAGIC) {
if (!gSaveContext.magicAcquired) {
gSaveContext.magicAcquired = true;
}
gSaveContext.doubleMagic = true;
gSaveContext.unk_13F6 = 0x60;
gSaveContext.magicLevel = 0;
Magic_Fill(globalCtx);
return ITEM_NONE;
}
if (item == ITEM_DOUBLE_DEFENSE) {
gSaveContext.doubleDefense = true;
gSaveContext.inventory.defenseHearts = 20;
gSaveContext.healthAccumulator = 0x140;
return ITEM_NONE;
}
if (item >= ITEM_BOTTLE_WITH_RED_POTION &&
item <= ITEM_BOTTLE_WITH_BIG_POE) {
temp = SLOT(ITEM_BOTTLE);
for (i = 0; i < 4; i++) {
if (gSaveContext.inventory.items[temp + i] == ITEM_NONE) {
switch (item) {
case ITEM_BOTTLE_WITH_RED_POTION:
item = ITEM_POTION_RED;
break;
case ITEM_BOTTLE_WITH_GREEN_POTION:
item = ITEM_POTION_GREEN;
break;
case ITEM_BOTTLE_WITH_BLUE_POTION:
item = ITEM_POTION_BLUE;
break;
case ITEM_BOTTLE_WITH_FAIRY:
item = ITEM_FAIRY;
break;
case ITEM_BOTTLE_WITH_FISH:
item = ITEM_FISH;
break;
case ITEM_BOTTLE_WITH_BLUE_FIRE:
item = ITEM_BLUE_FIRE;
break;
case ITEM_BOTTLE_WITH_BUGS:
item = ITEM_BUG;
break;
case ITEM_BOTTLE_WITH_POE:
item = ITEM_POE;
break;
case ITEM_BOTTLE_WITH_BIG_POE:
item = ITEM_BIG_POE;
break;
}
gSaveContext.inventory.items[temp + i] = item;
return ITEM_NONE;
}
}
}
if ((item >= ITEM_MEDALLION_FOREST) && (item <= ITEM_MEDALLION_LIGHT)) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST];
@ -2179,6 +2115,84 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return temp;
}
u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
uint16_t item = giEntry.itemId;
uint16_t temp;
uint16_t i;
uint16_t slot;
slot = SLOT(item);
if (item == RG_MAGIC_SINGLE) {
gSaveContext.magicAcquired = true;
gSaveContext.unk_13F6 = 0x30;
Magic_Fill(globalCtx);
return RG_NONE;
} else if (item == RG_MAGIC_DOUBLE) {
if (!gSaveContext.magicAcquired) {
gSaveContext.magicAcquired = true;
}
gSaveContext.doubleMagic = true;
gSaveContext.unk_13F6 = 0x60;
gSaveContext.magicLevel = 0;
Magic_Fill(globalCtx);
return RG_NONE;
}
if (item == RG_DOUBLE_DEFENSE) {
gSaveContext.doubleDefense = true;
gSaveContext.inventory.defenseHearts = 20;
gSaveContext.healthAccumulator = 0x140;
return RG_NONE;
}
if (item >= RG_BOTTLE_WITH_RED_POTION && item <= RG_BOTTLE_WITH_BIG_POE) {
temp = SLOT(ITEM_BOTTLE);
for (i = 0; i < 4; i++) {
if (gSaveContext.inventory.items[temp + i] == RG_NONE) {
switch (item) {
case RG_BOTTLE_WITH_RED_POTION:
item = ITEM_POTION_RED;
break;
case RG_BOTTLE_WITH_GREEN_POTION:
item = ITEM_POTION_GREEN;
break;
case RG_BOTTLE_WITH_BLUE_POTION:
item = ITEM_POTION_BLUE;
break;
case RG_BOTTLE_WITH_FAIRY:
item = ITEM_FAIRY;
break;
case RG_BOTTLE_WITH_FISH:
item = ITEM_FISH;
break;
case RG_BOTTLE_WITH_BLUE_FIRE:
item = ITEM_BLUE_FIRE;
break;
case RG_BOTTLE_WITH_BUGS:
item = ITEM_BUG;
break;
case RG_BOTTLE_WITH_POE:
item = ITEM_POE;
break;
case RG_BOTTLE_WITH_BIG_POE:
item = ITEM_BIG_POE;
break;
}
gSaveContext.inventory.items[temp + i] = item;
return RG_NONE;
}
}
}
temp = gSaveContext.inventory.items[slot];
osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, temp);
INV_CONTENT(item) = item;
return temp;
}
u8 Item_CheckObtainability(u8 item) {
s16 i;
s16 slot = SLOT(item);

View File

@ -367,43 +367,43 @@ void GiveLinkSong(GetItemID getItemId) {
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkDungeonReward(GetItemID getItemId) {
void GiveLinkDungeonReward(uint16_t getItemId) {
s16 item;
u8 medallion = 0;
switch (getItemId) {
case GI_MEDALLION_FOREST:
case RG_FOREST_MEDALLION:
item = ITEM_MEDALLION_FOREST;
medallion = 1;
break;
case GI_MEDALLION_FIRE:
case RG_FIRE_MEDALLION:
item = ITEM_MEDALLION_FIRE;
medallion = 1;
break;
case GI_MEDALLION_WATER:
case RG_WATER_MEDALLION:
item = ITEM_MEDALLION_WATER;
medallion = 1;
break;
case GI_MEDALLION_SHADOW:
case RG_SHADOW_MEDALLION:
item = ITEM_MEDALLION_SHADOW;
medallion = 1;
break;
case GI_MEDALLION_SPIRIT:
case RG_SPIRIT_MEDALLION:
item = ITEM_MEDALLION_SPIRIT;
medallion = 1;
break;
case GI_MEDALLION_LIGHT:
case RG_LIGHT_MEDALLION:
item = ITEM_MEDALLION_LIGHT;
medallion = 1;
break;
case GI_STONE_KOKIRI:
case RG_KOKIRI_EMERALD:
item = ITEM_KOKIRI_EMERALD;
break;
case GI_STONE_GORON:
case RG_GORON_RUBY:
item = ITEM_GORON_RUBY;
break;
case GI_STONE_ZORA:
case RG_ZORA_SAPPHIRE:
item = ITEM_ZORA_SAPPHIRE;
break;
}

View File

@ -70,6 +70,7 @@ static InitChainEntry sInitChain[] = {
};
static UNK_TYPE sUnused;
int32_t sItem;
void EnBox_SetupAction(EnBox* this, EnBoxActionFunc actionFunc) {
this->actionFunc = actionFunc;
@ -445,40 +446,40 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) {
int32_t item = Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum);
sItem = Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum);
// RANDOTODO treasure chest game rando
if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) {
if (gSaveContext.n64ddFlag && globalCtx->sceneNum == 16 && (this->dyna.actor.params & 0x60) != 0x20) {
if((this->dyna.actor.params & 0xF) < 2) {
if(Flags_GetCollectible(globalCtx, 0x1B)) {
item = GI_RUPEE_BLUE;
sItem = GI_RUPEE_BLUE;
}
}
if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) {
if(Flags_GetCollectible(globalCtx, 0x1C)) {
item = GI_RUPEE_BLUE;
sItem = GI_RUPEE_BLUE;
}
}
if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) {
if(Flags_GetCollectible(globalCtx, 0x1D)) {
item = GI_RUPEE_BLUE;
sItem = GI_RUPEE_BLUE;
}
}
if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) {
if(Flags_GetCollectible(globalCtx, 0x1E)) {
item = GI_RUPEE_BLUE;
sItem = GI_RUPEE_BLUE;
}
}
if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) {
if(Flags_GetCollectible(globalCtx, 0x1F)) {
item = GI_RUPEE_BLUE;
sItem = GI_RUPEE_BLUE;
}
}
}
}
func_8002F554(&this->dyna.actor, globalCtx, 0 - item);
func_8002F554(&this->dyna.actor, globalCtx, 0 - sItem);
}
if (Flags_GetTreasure(globalCtx, this->dyna.actor.params & 0x1F)) {
EnBox_SetupAction(this, EnBox_Open);
@ -590,9 +591,7 @@ void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) {
}
if (((!gSaveContext.n64ddFlag && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) ||
(gSaveContext.n64ddFlag && Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F,
this->dyna.actor.id, this->dyna.actor.params,
globalCtx->sceneNum) == GI_ICE_TRAP)) &&
(gSaveContext.n64ddFlag && sItem == GI_ICE_TRAP)) &&
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 &&
this->iceSmokeTimer < 100) EnBox_SpawnIceSmoke(this, globalCtx);
}

View File

@ -12715,9 +12715,13 @@ s32 func_8084DFF4(GlobalContext* globalCtx, Player* this) {
gSaveContext.swordHealth = 8;
}
Message_StartTextbox(globalCtx, giEntry->textId, &this->actor);
Item_Give(globalCtx, giEntry->itemId);
Message_StartTextbox(globalCtx, giEntry.textId, &this->actor);
if (giEntry.modIndex == 0) {
Item_Give(globalCtx, giEntry.itemId);
}
else {
Randomizer_Item_Give(globalCtx, giEntry);
}
Player_SetPendingFlag(this, globalCtx);
if (((this->getItemId >= GI_RUPEE_GREEN) && (this->getItemId <= GI_RUPEE_RED)) ||