From fdf9086b2a900e0539f68952f01cc81fd7c6cd86 Mon Sep 17 00:00:00 2001 From: Rozelette Date: Thu, 1 Jun 2023 20:39:50 -0500 Subject: [PATCH] Dynamic Actor IDs (#1729) * Add dynamic actor IDs * Convert Ivan to use new actor system * attempt to fix linux build * attempt to fix linux build * merge * Cleanup * Fix missing math functions on Windows. * Removes a stubbed function to fix non-windows builds. * Update soh/soh/ActorDB.cpp Co-authored-by: Adam Bird --------- Co-authored-by: Christopher Leggett Co-authored-by: Adam Bird --- soh/CMakeLists.txt | 4 +- soh/include/fp.h | 2 - soh/include/functions.h | 12 - soh/include/global.h | 2 + soh/include/tables/actor_table.h | 3 +- soh/include/variables.h | 2 - soh/include/z64actor.h | 14 +- soh/soh/ActorDB.cpp | 617 ++++++++++++++++++ soh/soh/ActorDB.h | 81 +++ soh/soh/Enhancements/debugconsole.cpp | 16 +- soh/soh/Enhancements/debugger/actorViewer.cpp | 452 +------------ soh/soh/OTRGlobals.cpp | 5 +- soh/src/code/z_actor.c | 194 ++---- soh/src/code/z_actor_dlftbls.c | 97 --- soh/src/code/z_play.c | 5 +- soh/src/code/z_scene.c | 3 +- .../actors/ovl_En_Heishi1/z_en_heishi1.c | 2 +- .../actors/ovl_En_Partner/z_en_partner.c | 13 - .../actors/ovl_En_Partner/z_en_partner.h | 11 + 19 files changed, 786 insertions(+), 749 deletions(-) create mode 100644 soh/soh/ActorDB.cpp create mode 100644 soh/soh/ActorDB.h delete mode 100644 soh/src/code/z_actor_dlftbls.c diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 23e657f0d..177a7027b 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -665,7 +665,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") "version;" "setupapi" ) - elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32") + elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32") set(ADDITIONAL_LIBRARY_DEPENDENCIES "libultraship;" "ZAPDUtils;" @@ -752,7 +752,7 @@ nx_generate_nacp(Ship.nacp AUTHOR "${PROJECT_TEAM}" VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" ) - + nx_create_nro(soh NACP Ship.nacp ICON ${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg diff --git a/soh/include/fp.h b/soh/include/fp.h index 7ea6a7670..b87c6a709 100644 --- a/soh/include/fp.h +++ b/soh/include/fp.h @@ -28,7 +28,5 @@ s32 lnearbyint(f64 x); f32 roundf(f32 x); f64 round(f64 x); -s32 lroundf(f32 x); -s32 lround(f64 x); #endif diff --git a/soh/include/functions.h b/soh/include/functions.h index bb794c9df..aae6a423f 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -20,13 +20,6 @@ extern "C" #define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__) #endif -f32 fabsf(f32 f); -//#pragma intrinsic(fabsf) -f32 sqrtf(f32 f); -//#pragma intrinsic(sqrtf) -f64 sqrt(f64 d); -//#pragma intrinsic(sqrt) - void gSPSegment(void* value, int segNum, uintptr_t target); void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target); void gDPSetTextureImage(Gfx* pkt, u32 f, u32 s, u32 w, uintptr_t i); @@ -567,9 +560,6 @@ void Flags_SetRandomizerInf(RandomizerInf flag); u16 func_80037C30(PlayState* play, s16 arg1); s32 func_80037D98(PlayState* play, Actor* actor, s16 arg2, s32* arg3); s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4); -void ActorOverlayTable_LogPrint(void); -void ActorOverlayTable_Init(void); -void ActorOverlayTable_Cleanup(void); // ? func_80038600(?); u16 DynaSSNodeList_GetNextNodeIdx(DynaSSNodeList*); void func_80038A28(CollisionPoly* poly, f32 tx, f32 ty, f32 tz, MtxF* dest); @@ -2296,7 +2286,6 @@ s32 JpegDecoder_ParseNextSymbol(JpegHuffmanTable* hTable, s16* outCoeff, s8* out u16 JpegDecoder_ReadBits(u8 len); s32 osPfsFreeBlocks(OSPfs* pfs, s32* leftoverBytes); void guScale(Mtx* m, f32 x, f32 y, f32 z); -f32 sinf(f32); s16 sins(u16); OSTask* _VirtualToPhysicalTask(OSTask* intp); void osSpTaskLoad(OSTask* task); @@ -2361,7 +2350,6 @@ s32 osPfsDeleteFile(OSPfs* pfs, u16 companyCode, u32 gameCode, u8* gameName, u8* s32 __osPfsReleasePages(OSPfs* pfs, __OSInode* inode, u8 initialPage, u8 bank, __OSInodeUnit* finalPage); void guOrthoF(f32[4][4], f32, f32, f32, f32, f32, f32, f32); void guOrtho(Mtx*, f32, f32, f32, f32, f32, f32, f32); -f32 cosf(f32); s16 coss(u16); void osViSetEvent(OSMesgQueue* mq, OSMesg m, u32 retraceCount); s32 osPfsIsPlug(OSMesgQueue* mq, u8* pattern); diff --git a/soh/include/global.h b/soh/include/global.h index 3d989cacc..43f56ed0e 100644 --- a/soh/include/global.h +++ b/soh/include/global.h @@ -3,6 +3,8 @@ #ifndef GLOBAL_H #define GLOBAL_H +#include "math.h" + #include "functions.h" #include "variables.h" #include "macros.h" diff --git a/soh/include/tables/actor_table.h b/soh/include/tables/actor_table.h index 64d9099e8..d05085f4d 100644 --- a/soh/include/tables/actor_table.h +++ b/soh/include/tables/actor_table.h @@ -480,5 +480,4 @@ /* 0x01D3 */ DEFINE_ACTOR(En_Zl4, ACTOR_EN_ZL4, ALLOCTYPE_NORMAL) /* 0x01D4 */ DEFINE_ACTOR(En_Mm2, ACTOR_EN_MM2, ALLOCTYPE_NORMAL) /* 0x01D5 */ DEFINE_ACTOR(Bg_Jya_Block, ACTOR_BG_JYA_BLOCK, ALLOCTYPE_NORMAL) -/* 0x01D6 */ DEFINE_ACTOR(Obj_Warp2block, ACTOR_OBJ_WARP2BLOCK, ALLOCTYPE_NORMAL) -/* 0x01D7 */ DEFINE_ACTOR(En_Partner, ACTOR_EN_PARTNER, ALLOCTYPE_NORMAL) \ No newline at end of file +/* 0x01D6 */ DEFINE_ACTOR(Obj_Warp2block, ACTOR_OBJ_WARP2BLOCK, ALLOCTYPE_NORMAL) \ No newline at end of file diff --git a/soh/include/variables.h b/soh/include/variables.h index 55adf0d2e..853cb3a17 100644 --- a/soh/include/variables.h +++ b/soh/include/variables.h @@ -68,8 +68,6 @@ extern "C" extern u64 gJpegUCode[]; extern EffectSsOverlay gEffectSsOverlayTable[EFFECT_SS_TYPE_MAX]; extern Gfx D_80116280[]; - extern ActorOverlay gActorOverlayTable[ACTOR_ID_MAX]; // original name: "actor_dlftbls" 801162A0 - extern s32 gMaxActorId; // original name: "MaxProfile" extern s32 gDbgCamEnabled; extern GameStateOverlay gGameStateOverlayTable[6]; extern u8 gWeatherMode; diff --git a/soh/include/z64actor.h b/soh/include/z64actor.h index c0664f79e..09e6a64ed 100644 --- a/soh/include/z64actor.h +++ b/soh/include/z64actor.h @@ -5,6 +5,7 @@ #include "z64animation.h" #include "z64math.h" #include "z64collision_check.h" +#include "z64bgcheck.h" #include "soh/Enhancements/item-tables/ItemTableTypes.h" #define ACTOR_NUMBER_MAX 2000 @@ -47,18 +48,6 @@ typedef enum { /* 2 */ ALLOCTYPE_PERMANENT } AllocType; -typedef struct { - /* 0x00 */ uintptr_t vromStart; - /* 0x04 */ uintptr_t vromEnd; - /* 0x08 */ void* vramStart; - /* 0x0C */ void* vramEnd; - /* 0x10 */ void* loadedRamAddr; // original name: "allocp" - /* 0x14 */ ActorInit* initInfo; - /* 0x18 */ char* name; - /* 0x1C */ u16 allocType; - /* 0x1E */ s8 numLoaded; // original name: "clients" -} ActorOverlay; // size = 0x20 - typedef struct { u8 table[32]; } DamageTable; @@ -188,7 +177,6 @@ typedef struct Actor { /* 0x130 */ ActorFunc update; // Update Routine. Called by `Actor_UpdateAll` /* 0x134 */ ActorFunc draw; // Draw Routine. Called by `Actor_Draw` /* 0x138 */ ActorResetFunc reset; - /* 0x138 */ ActorOverlay* overlayEntry; // Pointer to the overlay table entry for this actor /* 0x13C */ char dbgPad[0x10]; // Padding that only exists in the debug rom } Actor; // size = 0x14C diff --git a/soh/soh/ActorDB.cpp b/soh/soh/ActorDB.cpp new file mode 100644 index 000000000..2cf4d8fe7 --- /dev/null +++ b/soh/soh/ActorDB.cpp @@ -0,0 +1,617 @@ +#include "ActorDB.h" + +#include + +ActorDB* ActorDB::Instance; + + +#define DEFINE_ACTOR(name, _1, _2) extern "C" ActorInit name##_InitVars; +#define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern "C" ActorInit name##_InitVars; +#define DEFINE_ACTOR_UNSET(_0) + +#include "tables/actor_table.h" + +#undef DEFINE_ACTOR +#undef DEFINE_ACTOR_INTERNAL +#undef DEFINE_ACTOR_UNSET + +struct AddPair { + std::string name; + ActorInit& init; +}; + +#define DEFINE_ACTOR_INTERNAL(name, _1, allocType) { #name, name##_InitVars }, +#define DEFINE_ACTOR(name, _1, allocType) { #name, name##_InitVars }, +#define DEFINE_ACTOR_UNSET(_0) + +static const std::vector initialActorTable = { +#include "tables/actor_table.h" +}; + +#undef DEFINE_ACTOR_INTERNAL +#undef DEFINE_ACTOR_UNSET +#undef DEFINE_ACTOR + +// https://wiki.cloudmodding.com/oot/Actor_List_(Variables) +static std::unordered_map actorDescriptions = { + { ACTOR_PLAYER, "Link" }, + { ACTOR_EN_TEST, "Stalfos" }, + { ACTOR_EN_GIRLA, "Shop Items" }, + { ACTOR_EN_PART, "Body Parts" }, + { ACTOR_EN_LIGHT, "Decorative Flames" }, + { ACTOR_EN_DOOR, "Door" }, + { ACTOR_EN_BOX, "Treasure Chest" }, + { ACTOR_BG_DY_YOSEIZO, "Great Fairy" }, + { ACTOR_BG_HIDAN_FIREWALL, "Proximity activated Fire Wall" }, + { ACTOR_EN_POH, "Poe" }, + { ACTOR_EN_OKUTA, "Octorok" }, + { ACTOR_BG_YDAN_SP, "Webs" }, + { ACTOR_EN_BOM, "Bomb" }, + { ACTOR_EN_WALLMAS, "Wallmaster" }, + { ACTOR_EN_DODONGO, "Dodongo" }, + { ACTOR_EN_FIREFLY, "Keese" }, + { ACTOR_EN_HORSE, "Rideable Horse" }, + { ACTOR_EN_ITEM00, "Collectibles" }, + { ACTOR_EN_ARROW, "Arrow" }, + { ACTOR_EN_ELF, "Fairy" }, + { ACTOR_EN_NIW, "Cucco" }, + { ACTOR_EN_TITE, "Tektite" }, + { ACTOR_EN_REEBA, "Leever" }, + { ACTOR_EN_PEEHAT, "Peahat and Larva" }, + { ACTOR_EN_BUTTE, "Butterfly" }, + { ACTOR_EN_INSECT, "Bugs" }, + { ACTOR_EN_FISH, "Fish" }, + { ACTOR_EN_HOLL, "Room changing plane" }, + { ACTOR_EN_SCENE_CHANGE, "ovl_En_Scene_Change (broken)" }, + { ACTOR_EN_ZF, "Lizalfos and Dinolfos" }, + { ACTOR_EN_HATA, "Wooden Flagpole with Red Cloth" }, + { ACTOR_BOSS_DODONGO, "King Dodongo" }, + { ACTOR_BOSS_GOMA, "Gohma" }, + { ACTOR_EN_ZL1, "Child Princess Zelda (at window)" }, + { ACTOR_EN_VIEWER, "Cutscene Actors" }, + { ACTOR_EN_GOMA, "Gohma Larva" }, + { ACTOR_BG_PUSHBOX, "Cube" }, + { ACTOR_EN_BUBBLE, "Shabom" }, + { ACTOR_DOOR_SHUTTER, "Shutter Door" }, + { ACTOR_EN_DODOJR, "Baby Dodongo" }, + { ACTOR_EN_BDFIRE, "Empty" }, + { ACTOR_EN_BOOM, "Boomerang" }, + { ACTOR_EN_TORCH2, "Dark Link" }, + { ACTOR_EN_BILI, "Biri" }, + { ACTOR_EN_TP, "Electric Tailpasaran" }, + { ACTOR_EN_ST, "Skulltula" }, + { ACTOR_EN_BW, "Torch Slug" }, + { ACTOR_EN_A_OBJ, "Gameplay_keep items" }, + { ACTOR_EN_EIYER, "Stinger (Land)" }, + { ACTOR_EN_RIVER_SOUND, "Ambient Sound Effects" }, + { ACTOR_EN_HORSE_NORMAL, "Horse" }, + { ACTOR_EN_OSSAN, "Shopkeeper" }, + { ACTOR_BG_TREEMOUTH, "Great Deku Tree's Jaw" }, + { ACTOR_BG_DODOAGO, "Dodongo's Cavern Mega Dodongo" }, + { ACTOR_BG_HIDAN_DALM, "Megaton Hammer Statue" }, + { ACTOR_BG_HIDAN_HROCK, "Huge stone spike platform (Fire Temple)" }, + { ACTOR_EN_HORSE_GANON, "Ganondorf's Horse" }, + { ACTOR_BG_HIDAN_ROCK, "Stone Blocks (Fire Temple)" }, + { ACTOR_BG_HIDAN_RSEKIZOU, "Spinning Stone Flamethrower (Fire Temple)" }, + { ACTOR_BG_HIDAN_SEKIZOU, "Stationary Flamethrower Statue (Fire Temple)" }, + { ACTOR_BG_HIDAN_SIMA, "Stone Platform (Fire Temple)" }, + { ACTOR_BG_HIDAN_SYOKU, "Stone Elevator (Fire Temple)" }, + { ACTOR_EN_XC, "Sheik" }, + { ACTOR_BG_HIDAN_CURTAIN, "Flame Circle" }, + { ACTOR_BG_SPOT00_HANEBASI, "Drawbridge Objects" }, + { ACTOR_EN_MB, "Moblins" }, + { ACTOR_EN_BOMBF, "Bombflower" }, + { ACTOR_EN_ZL2, "Adult Zelda (Cutscenes)" }, + { ACTOR_BG_HIDAN_FSLIFT, "Hookshot Elevator Platform (Fire Temple)" }, + { ACTOR_EN_OE2, "Unused NPC" }, + { ACTOR_BG_YDAN_HASI, "Deku Tree Puzzle elements" }, + { ACTOR_BG_YDAN_MARUTA, "Rotating Spiked Log (Deku Tree)" }, + { ACTOR_BOSS_GANONDROF, "Phantom Ganon" }, + { ACTOR_EN_AM, "Armos Statue" }, + { ACTOR_EN_DEKUBABA, "Deku Baba" }, + { ACTOR_EN_M_FIRE1, "Thrown Deku Nut" }, + { ACTOR_EN_M_THUNDER, "Spin Attack" }, + { ACTOR_BG_DDAN_JD, "Rising Stone Platform (Dodongo's Cavern)" }, + { ACTOR_BG_BREAKWALL, "Bombable Wall" }, + { ACTOR_EN_JJ, "Lord Jabu-Jabu" }, + { ACTOR_EN_HORSE_ZELDA, "Zelda's Horse" }, + { ACTOR_BG_DDAN_KD, "Stone Stairs (Dodongo's Cavern)" }, + { ACTOR_DOOR_WARP1, "Warp Portal" }, + { ACTOR_OBJ_SYOKUDAI, "Torch" }, + { ACTOR_ITEM_B_HEART, "Heart container" }, + { ACTOR_EN_DEKUNUTS, "Mad Scrub" }, + { ACTOR_BG_MENKURI_KAITEN, "Rotating Stone Ring Platform" }, + { ACTOR_BG_MENKURI_EYE, "Eye Statue" }, + { ACTOR_EN_VALI, "Bari" }, + { ACTOR_BG_MIZU_MOVEBG, "Water Temple Background Actors" }, + { ACTOR_BG_MIZU_WATER, "Water Plane (Water Temple)" }, + { ACTOR_ARMS_HOOK, "Hookshot" }, + { ACTOR_EN_FHG, "Phantom Ganon's Horse" }, + { ACTOR_BG_MORI_HINERI, "Twisted Hallway Rooms" }, + { ACTOR_EN_BB, "Bubble" }, + { ACTOR_BG_TOKI_HIKARI, "Windows (Temple of Time)" }, + { ACTOR_EN_YUKABYUN, "Flying Floor Tile" }, + { ACTOR_BG_TOKI_SWD, "Master Sword" }, + { ACTOR_EN_FHG_FIRE, "Empty" }, + { ACTOR_BG_MJIN, "Warp Song Pad" }, + { ACTOR_BG_HIDAN_KOUSI, "Sliding Metal Gate" }, + { ACTOR_DOOR_TOKI, "Door of Time Collision" }, + { ACTOR_BG_HIDAN_HAMSTEP, "Stone Steps and Platforms (Fire Temple)" }, + { ACTOR_EN_BIRD, "Brown Bird" }, + { ACTOR_EN_WOOD02, "Trees and Bushes" }, + { ACTOR_EN_LIGHTBOX, "Large noisy stone" }, + { ACTOR_EN_PU_BOX, "Stone cube" }, + { ACTOR_EN_TRAP, "Metal Spike Trap" }, + { ACTOR_EN_AROW_TRAP, "Arrow Trap" }, + { ACTOR_EN_VASE, "Orange Pot" }, + { ACTOR_EN_TA, "Talon" }, + { ACTOR_EN_TK, "Dampe (Alive)" }, + { ACTOR_BG_MORI_BIGST, "Large Round Platform (Forest Temple)" }, + { ACTOR_BG_MORI_ELEVATOR, "Elevator (Forest Temple)" }, + { ACTOR_BG_MORI_KAITENKABE, "Rotatable Walls (Forest Temple)" }, + { ACTOR_BG_MORI_RAKKATENJO, "Falling Ceiling (Forest Temple)" }, + { ACTOR_EN_VM, "Beamos" }, + { ACTOR_DEMO_EFFECT, "Spiritual Stones, Medallions, Triforce" }, + { ACTOR_DEMO_KANKYO, "Temple of Time Objects" }, + { ACTOR_BG_HIDAN_FWBIG, "Large Fire Wall (Fire Temple)" }, + { ACTOR_EN_FLOORMAS, "Floormaster" }, + { ACTOR_EN_HEISHI1, "Castle Courtyard Guards" }, + { ACTOR_EN_RD, "Redead and Gibdo" }, + { ACTOR_EN_PO_SISTERS, "Poe Sisters" }, + { ACTOR_BG_HEAVY_BLOCK, "Golden Gauntlets Pillar" }, + { ACTOR_BG_PO_EVENT, "Poe Sisters' Paintings and Puzzle Block" }, + { ACTOR_OBJ_MURE, "Fish, Bugs, Butterflies Group Spawner" }, + { ACTOR_EN_SW, "Skullwalltula and Gold Skulltulas" }, + { ACTOR_BOSS_FD, "Volvagia (Flying)" }, + { ACTOR_OBJECT_KANKYO, "Environmental Effects" }, + { ACTOR_EN_DU, "Darunia" }, + { ACTOR_EN_FD, "Flare Dancer" }, + { ACTOR_EN_HORSE_LINK_CHILD, "Young Epona" }, + { ACTOR_DOOR_ANA, "Grotto Entrance" }, + { ACTOR_BG_SPOT02_OBJECTS, "Graveyard Actors" }, + { ACTOR_BG_HAKA, "Gravestone" }, + { ACTOR_MAGIC_WIND, "Farore's Wind" }, + { ACTOR_MAGIC_FIRE, "Din's Fire" }, + { ACTOR_EN_RU1, "Ruto (Child)" }, + { ACTOR_BOSS_FD2, "Volvagia (Hole Form)" }, + { ACTOR_EN_FD_FIRE, "Flare Dancer Fire Attack" }, + { ACTOR_EN_DH, "Dead Hand" }, + { ACTOR_EN_DHA, "Dead Hand's Hand" }, + { ACTOR_EN_RL, "Rauru" }, + { ACTOR_EN_ENCOUNT1, "Enemy Spawner" }, + { ACTOR_DEMO_DU, "Darunia (Cutscenes)" }, + { ACTOR_DEMO_IM, "Impa (Cutscenes)" }, + { ACTOR_DEMO_TRE_LGT, "Treasure Chest Light" }, + { ACTOR_EN_FW, "Flare Dancer Core" }, + { ACTOR_BG_VB_SIMA, "Volvagia Platform" }, + { ACTOR_EN_VB_BALL, "Volvagia Rocks and Bones" }, + { ACTOR_BG_HAKA_MEGANE, "Shadow Temple Fake Walls" }, + { ACTOR_BG_HAKA_MEGANEBG, "Platforms (Shadow Temple)" }, + { ACTOR_BG_HAKA_SHIP, "River Boat (Shadow Temple)" }, + { ACTOR_BG_HAKA_SGAMI, "Spinning Scythe Trap" }, + { ACTOR_EN_HEISHI2, "Hyrulian Guards" }, + { ACTOR_EN_ENCOUNT2, "Falling Rock Spawner" }, + { ACTOR_EN_FIRE_ROCK, "Falling Burning Rocks" }, + { ACTOR_EN_BROB, "Flobbery Muscle Block (Jabu-Jabu's Belly)" }, + { ACTOR_MIR_RAY, "Reflectable Light Beam" }, + { ACTOR_BG_SPOT09_OBJ, "Gerudo Valley Objects" }, + { ACTOR_BG_SPOT18_OBJ, "Statue (Darunia's Room)" }, + { ACTOR_BOSS_VA, "Barinade" }, + { ACTOR_BG_HAKA_TUBO, "Giant Skull Jar (Shadow Temple)" }, + { ACTOR_BG_HAKA_TRAP, "Shadow Temple Traps" }, + { ACTOR_BG_HAKA_HUTA, "Coffin Lid" }, + { ACTOR_BG_HAKA_ZOU, "Bird Statue and Wall (Shadow Temple)" }, + { ACTOR_BG_SPOT17_FUNEN, "Smoke Cone (Death Mountain Crater)" }, + { ACTOR_EN_SYATEKI_ITM, "Shooting Gallery Game" }, + { ACTOR_EN_SYATEKI_MAN, "Shooting Gallery Man" }, + { ACTOR_EN_TANA, "Shop Shelves" }, + { ACTOR_EN_NB, "Nabooru" }, + { ACTOR_BOSS_MO, "Morpha" }, + { ACTOR_EN_SB, "Shell Blade" }, + { ACTOR_EN_BIGOKUTA, "Big Octo" }, + { ACTOR_EN_KAREBABA, "Withered Deku Baba" }, + { ACTOR_BG_BDAN_OBJECTS, "Inside Jabu-Jabu's Belly Objects" }, + { ACTOR_DEMO_SA, "Saria (Cutscenes)" }, + { ACTOR_DEMO_GO, "Gorons (Cutscene)" }, + { ACTOR_EN_IN, "Ingo" }, + { ACTOR_EN_TR, "Koume and Kotake" }, + { ACTOR_BG_SPOT16_BOMBSTONE, "Dodongo's Cavern Entrance Blocking Rock" }, + { ACTOR_BG_HIDAN_KOWARERUKABE, "Bombable Walls (Fire Temple)" }, + { ACTOR_BG_BOMBWALL, "2D Bombable Wall" }, + { ACTOR_BG_SPOT08_ICEBLOCK, "Ice Platform (Zora's Fountain)" }, + { ACTOR_EN_RU2, "Ruto (Adult)" }, + { ACTOR_OBJ_DEKUJR, "Deku Tree Sprout" }, + { ACTOR_BG_MIZU_UZU, "Water Vortex Effect (Water Temple)" }, + { ACTOR_BG_SPOT06_OBJECTS, "Lake Hylia Objects" }, + { ACTOR_BG_ICE_OBJECTS, "Pushable Ice Block (Ice Cavern)" }, + { ACTOR_BG_HAKA_WATER, "Bottom of the Well Water Level Changer" }, + { ACTOR_EN_MA2, "Malon (Adult, Ingo's Ranch)" }, + { ACTOR_EN_BOM_CHU, "Bombchu" }, + { ACTOR_EN_HORSE_GAME_CHECK, "Horseback Minigames" }, + { ACTOR_BOSS_TW, "Twinrova" }, + { ACTOR_EN_RR, "Like-Like" }, + { ACTOR_EN_BA, "Tentacle (Inside Jabu-Jabu's Belly)" }, + { ACTOR_EN_BX, "Electrified Tentacle (Inside Jabu-Jabu's Belly)" }, + { ACTOR_EN_ANUBICE, "Anubis (Body)" }, + { ACTOR_EN_ANUBICE_FIRE, "Anubis Fire Attack" }, + { ACTOR_BG_MORI_HASHIGO, "Ladder (Forest Temple)" }, + { ACTOR_BG_MORI_HASHIRA4, "Forest Temple Objects" }, + { ACTOR_BG_MORI_IDOMIZU, "Well Water (Forest Temple)" }, + { ACTOR_BG_SPOT16_DOUGHNUT, "Cloud Ring (Death Mountain)" }, + { ACTOR_BG_BDAN_SWITCH, "Switches (Inside Lord Jabu-Jabu)" }, + { ACTOR_EN_MA1, "Malon (Child)" }, + { ACTOR_BOSS_GANON, "Ganondorf" }, + { ACTOR_BOSS_SST, "Bongo Bongo" }, + { ACTOR_EN_NY, "Spike (Enemy)" }, + { ACTOR_EN_FR, "Frog Song Spot and Frogs" }, + { ACTOR_ITEM_SHIELD, "Deku Shield" }, + { ACTOR_BG_ICE_SHELTER, "Red Ice" }, + { ACTOR_EN_ICE_HONO, "Blue Fire Flames" }, + { ACTOR_ITEM_OCARINA, "Ocarina of Time" }, + { ACTOR_MAGIC_DARK, "Nayru's Love" }, + { ACTOR_DEMO_6K, "Sages, Balls of Light (Cutscene)" }, + { ACTOR_EN_ANUBICE_TAG, "Anubis Spawn" }, + { ACTOR_BG_HAKA_GATE, "Truth Spinner Puzzle (Shadow Temple)" }, + { ACTOR_BG_SPOT15_SAKU, "Hyrule Castle Gate" }, + { ACTOR_BG_JYA_GOROIWA, "Rolling Boulder (Spirit Temple)" }, + { ACTOR_BG_JYA_ZURERUKABE, "Sliding, Climbable Brick Wall (Spirit Temple)" }, + { ACTOR_BG_JYA_COBRA, "Rotatable Cobra Mirror (Spirit Temple)" }, + { ACTOR_BG_JYA_KANAAMI, "Climbable Metal Grating Bridge (Spirit Temple)" }, + { ACTOR_FISHING, "Fishing Pond Man and Fish" }, + { ACTOR_OBJ_OSHIHIKI, "Pushable Block" }, + { ACTOR_BG_GATE_SHUTTER, "Gate to Death Mountain Trail" }, + { ACTOR_EFF_DUST, "Dust Effects" }, + { ACTOR_BG_SPOT01_FUSYA, "Windmill Sails (Kakariko Village)" }, + { ACTOR_BG_SPOT01_IDOHASHIRA, "Well Crossbeam (Kakariko Village)" }, + { ACTOR_BG_SPOT01_IDOMIZU, "Well Water (Kakariko Village)" }, + { ACTOR_BG_PO_SYOKUDAI, "Golden Torch (Poe Sisters)" }, + { ACTOR_BG_GANON_OTYUKA, "Falling Platform (Ganondorf Fight)" }, + { ACTOR_BG_SPOT15_RRBOX, "Milk Crate" }, + { ACTOR_BG_UMAJUMP, "Obstacle Fence (Lon Lon Ranch)" }, + { ACTOR_ARROW_FIRE, "Fire Arrow" }, + { ACTOR_ARROW_ICE, "Ice Arrow" }, + { ACTOR_ARROW_LIGHT, "Light Arrow" }, + { ACTOR_ITEM_ETCETERA, "Collectible Items" }, + { ACTOR_OBJ_KIBAKO, "Small Liftable Crate" }, + { ACTOR_OBJ_TSUBO, "Breakable Pot" }, + { ACTOR_EN_WONDER_ITEM, "Invisible Collectible" }, + { ACTOR_EN_IK, "Iron Knuckle" }, + { ACTOR_DEMO_IK, "Iron Knuckle armor pieces (Spirit Temple Nabooru fight)" }, + { ACTOR_EN_SKJ, "Skullkid" }, + { ACTOR_EN_SKJNEEDLE, "Skullkid Needle Attack" }, + { ACTOR_EN_G_SWITCH, "Silver Rupee" }, + { ACTOR_DEMO_EXT, "Magic Vortex" }, + { ACTOR_DEMO_SHD, "Bongo Bongo's Shadow" }, + { ACTOR_EN_DNS, "Business Scrub" }, + { ACTOR_ELF_MSG, "Navi Message" }, + { ACTOR_EN_HONOTRAP, "Stone Eye (Fire Trap) and Flame" }, + { ACTOR_EN_TUBO_TRAP, "Flying Pot" }, + { ACTOR_OBJ_ICE_POLY, "Ice spawned by red ice? frozen actors" }, + { ACTOR_BG_SPOT03_TAKI, "Zora's River Waterfall" }, + { ACTOR_BG_SPOT07_TAKI, "Zora's Domain Waterfall and Ice" }, + { ACTOR_EN_FZ, "Frezzard" }, + { ACTOR_EN_PO_RELAY, "Dampe's Ghost" }, + { ACTOR_BG_RELAY_OBJECTS, "Windmill Objects" }, + { ACTOR_EN_DIVING_GAME, "Zora Diving Game" }, + { ACTOR_EN_KUSA, "Bush/Grass" }, + { ACTOR_OBJ_BEAN, "Bean Plant Spot" }, + { ACTOR_OBJ_BOMBIWA, "Brown Bombable Boulder" }, + { ACTOR_OBJ_SWITCH, "Switches" }, + { ACTOR_OBJ_ELEVATOR, "Huge Stone Elevator" }, + { ACTOR_OBJ_LIFT, "Square Collapsing Platform" }, + { ACTOR_OBJ_HSBLOCK, "Stone Hookshot Target" }, + { ACTOR_EN_OKARINA_TAG, "Ocarina Music Staff Spot" }, + { ACTOR_EN_YABUSAME_MARK, "Horseback Archery Target" }, + { ACTOR_EN_GOROIWA, "Rolling Boulder" }, + { ACTOR_EN_EX_RUPPY, "Sparkling Rupee" }, + { ACTOR_EN_TORYO, "Boss Carpenter" }, + { ACTOR_EN_DAIKU, "Carpenters" }, + { ACTOR_EN_NWC, "Cucco Chick" }, + { ACTOR_EN_BLKOBJ, "Dark Link's Illusion Room" }, + { ACTOR_ITEM_INBOX, "Zelda's Magic to Open Gates" }, + { ACTOR_EN_GE1, "White Clothed Gerudo" }, + { ACTOR_OBJ_BLOCKSTOP, "Pushblock Stop" }, + { ACTOR_EN_SDA, "Dynamic Shadow" }, + { ACTOR_EN_CLEAR_TAG, "Arwing" }, + { ACTOR_EN_NIW_LADY, "Cucco Lady" }, + { ACTOR_EN_GM, "Medigoron" }, + { ACTOR_EN_MS, "Bean Salesman" }, + { ACTOR_EN_HS, "Carpenter's Son" }, + { ACTOR_BG_INGATE, "Ingo's Gates (Lon Lon Ranch)" }, + { ACTOR_EN_KANBAN, "Square Signpost" }, + { ACTOR_EN_HEISHI3, "Hyrule Castle Guard" }, + { ACTOR_EN_SYATEKI_NIW, "Cucco (Minigames)" }, + { ACTOR_EN_ATTACK_NIW, "Cucco (Attacking)" }, + { ACTOR_BG_SPOT01_IDOSOKO, "Stone Blocking Entrance to Bottom of the Well" }, + { ACTOR_EN_SA, "Saria" }, + { ACTOR_EN_WONDER_TALK, "Checkable Spot (Green Navi)" }, + { ACTOR_BG_GJYO_BRIDGE, "Rainbow Bridge to Ganon's Castle" }, + { ACTOR_EN_DS, "Potion Shop Granny" }, + { ACTOR_EN_MK, "Lakeside Professor" }, + { ACTOR_EN_BOM_BOWL_MAN, "Bombchu Bowling Alley Lady" }, + { ACTOR_EN_BOM_BOWL_PIT, "Bombchu Bowling Alley Final Target" }, + { ACTOR_EN_OWL, "Kaepora Gaebora" }, + { ACTOR_EN_ISHI, "Liftable Rock" }, + { ACTOR_OBJ_HANA, "Uninteractable Flowers, Rocks, Grass" }, + { ACTOR_OBJ_LIGHTSWITCH, "Sun Emblem Switch (Spirit Temple)" }, + { ACTOR_OBJ_MURE2, "Rock/Bush groups" }, + { ACTOR_EN_GO, "Gorons 1" }, + { ACTOR_EN_FU, "Windmill Man" }, + { ACTOR_EN_CHANGER, "Treasure Box Shop Minigame" }, + { ACTOR_BG_JYA_MEGAMI, "Statue Face (Spirit Temple)" }, + { ACTOR_BG_JYA_LIFT, "Chain Platform (Spirit Temple)" }, + { ACTOR_BG_JYA_BIGMIRROR, "Large Circular Mirror (Spirt Temple)" }, + { ACTOR_BG_JYA_BOMBCHUIWA, "Light Blocking Rock (Spirit Temple)" }, + { ACTOR_BG_JYA_AMISHUTTER, "Sliding Circular Metal Grate (Spirit Temple)" }, + { ACTOR_BG_JYA_BOMBIWA, "Bombable Rock Wall (Spirit Temple)" }, + { ACTOR_BG_SPOT18_BASKET, "Big Goron Pot" }, + { ACTOR_EN_GANON_ORGAN, "Ganon's Organ and surroundings" }, + { ACTOR_EN_SIOFUKI, "Water Spout" }, + { ACTOR_EN_STREAM, "Water Vortex" }, + { ACTOR_EN_MM, "Running Man (Child Era)" }, + { ACTOR_EN_KO, "Kokiri Children" }, + { ACTOR_EN_KZ, "King Zora" }, + { ACTOR_EN_WEATHER_TAG, "Proximity Weather Effects" }, + { ACTOR_BG_SST_FLOOR, "Bongo Bongo's Drum" }, + { ACTOR_EN_ANI, "Kakariko Village Rooftop Man" }, + { ACTOR_EN_EX_ITEM, "Minigame Displayed Items" }, + { ACTOR_BG_JYA_IRONOBJ, "Iron Knuckles Room Stuff (Spirit Temple)" }, + { ACTOR_EN_JS, "Magic Carpet Man" }, + { ACTOR_EN_JSJUTAN, "Magic Carpet Man Carpet" }, + { ACTOR_EN_CS, "Graveyard Boy" }, + { ACTOR_EN_MD, "Mido" }, + { ACTOR_EN_HY, "Market NPCs" }, + { ACTOR_EN_GANON_MANT, "Ganondorf's Cape" }, + { ACTOR_EN_OKARINA_EFFECT, "Song of Storms Storm Manager" }, + { ACTOR_EN_MAG, "Title Screen Manager" }, + { ACTOR_DOOR_GERUDO, "Cell Door (Gerudo Fortress)" }, + { ACTOR_ELF_MSG2, "Navi Information Spot (Targetable, Green)" }, + { ACTOR_DEMO_GT, "Ganon's Tower Collapsing (Cutscene Objects)" }, + { ACTOR_EN_PO_FIELD, "Big/Small Poe Spawn Point" }, + { ACTOR_EFC_ERUPC, "Lava Particle Fountain (Death Mountain panorama)" }, + { ACTOR_BG_ZG, "Metal Bars (Ganon's Castle)" }, + { ACTOR_EN_HEISHI4, "Hyrule Guard" }, + { ACTOR_EN_ZL3, "Adult Zelda" }, + { ACTOR_BOSS_GANON2, "Ganon" }, + { ACTOR_EN_KAKASI, "Pierre the Scarecrow" }, + { ACTOR_EN_TAKARA_MAN, "Treasure Box Shop Man" }, + { ACTOR_OBJ_MAKEOSHIHIKI, "Push Block Puzzles" }, + { ACTOR_OCEFF_SPOT, "Sun's Song Effect" }, + { ACTOR_END_TITLE, "The End message" }, + { ACTOR_EN_TORCH, "Grotto Treasure Chest" }, + { ACTOR_DEMO_EC, "Credits Revelers in Lon Lon" }, + { ACTOR_SHOT_SUN, "Lake Hylia Sun Hitbox, Big Fairy Spawner" }, + { ACTOR_EN_DY_EXTRA, "Spiral Beams (Great Fairy Fountains)" }, + { ACTOR_EN_WONDER_TALK2, "Dialog Spot" }, + { ACTOR_EN_GE2, "Patrolling Gerudo" }, + { ACTOR_OBJ_ROOMTIMER, "Room Timer" }, + { ACTOR_EN_SSH, "Cursed Skulltula People" }, + { ACTOR_EN_STH, "Uncursed Skulltula People" }, + { ACTOR_OCEFF_WIPE, "Zelda's Lullaby and Song of Time Ocarina Effect" }, + { ACTOR_OCEFF_STORM, "Song of Storm Ocarina Effect" }, + { ACTOR_EN_WEIYER, "Stinger (Water)" }, + { ACTOR_BG_SPOT05_SOKO, "Sacred Forest Meadow Objects" }, + { ACTOR_BG_JYA_1FLIFT, "Stone Elevator (Spirit Temple)" }, + { ACTOR_BG_JYA_HAHENIRON, "Chunks of Iron Knucle Chair and Pillar" }, + { ACTOR_BG_SPOT12_GATE, "Gerudo Fortress Wooden Gate" }, + { ACTOR_BG_SPOT12_SAKU, "Gerudo Fortress Training Area Gate" }, + { ACTOR_EN_HINTNUTS, "Hint Deku Scrubs (Deku Tree)" }, + { ACTOR_EN_NUTSBALL, "Deku Scrub Nut Attack" }, + { ACTOR_BG_SPOT00_BREAK, "Broken Drawbridge, Fences" }, + { ACTOR_EN_SHOPNUTS, "Grounded Sales Scrub" }, + { ACTOR_EN_IT, "Dampe's Minigame Collectibles" }, + { ACTOR_EN_GELDB, "Gerudo Fighter" }, + { ACTOR_OCEFF_WIPE2, "Epona's Song Ocarina Effect" }, + { ACTOR_OCEFF_WIPE3, "Saria's Song Ocarina Effect" }, + { ACTOR_EN_NIW_GIRL, "Girl Chasing Cucco" }, + { ACTOR_EN_DOG, "Dog" }, + { ACTOR_EN_SI, "Gold Skulltula Token" }, + { ACTOR_BG_SPOT01_OBJECTS2, "Kakariko Village Objects" }, + { ACTOR_OBJ_COMB, "Beehive" }, + { ACTOR_BG_SPOT11_BAKUDANKABE, "Destructible Wall (Desert Colossus)" }, + { ACTOR_OBJ_KIBAKO2, "Large Crate" }, + { ACTOR_EN_DNT_DEMO, "Deku Mask Panel Trigger" }, + { ACTOR_EN_DNT_JIJI, "Deku Mask Panel Head Judge" }, + { ACTOR_EN_DNT_NOMAL, "Deku Game?" }, + { ACTOR_EN_GUEST, "Happy Mask Shop Customer" }, + { ACTOR_BG_BOM_GUARD, "Bombchu Bowling Alley Aiming Area" }, + { ACTOR_EN_HS2, "Carpenter's Son (Child Era)" }, + { ACTOR_DEMO_KEKKAI, "Ganon's Tower Magic Barriers" }, + { ACTOR_BG_SPOT08_BAKUDANKABE, "Destructible Wall (Zora's Fountain)" }, + { ACTOR_BG_SPOT17_BAKUDANKABE, "Destructible Wall (Death Mountain Crater)" }, + { ACTOR_OBJ_MURE3, "Rupee Patterns" }, + { ACTOR_EN_TG, "Entwined Lovers (Honey & Darling)" }, + { ACTOR_EN_MU, "Haggling Townspeople" }, + { ACTOR_EN_GO2, "Gorons 2" }, + { ACTOR_EN_WF, "Wolfos" }, + { ACTOR_EN_SKB, "Stalchild" }, + { ACTOR_DEMO_GJ, "Ganon Battle Rubble" }, + { ACTOR_DEMO_GEFF, "Ganon's Tower Rubble Fragment" }, + { ACTOR_BG_GND_FIREMEIRO, "Sinking Lava Platform (Ganon's Castle)" }, + { ACTOR_BG_GND_DARKMEIRO, "Clear block" }, + { ACTOR_BG_GND_SOULMEIRO, "Web-Blocked Ceiling Hole (Inside Ganon's Castle)" }, + { ACTOR_BG_GND_NISEKABE, "Ganon's Castle Fake Walls" }, + { ACTOR_BG_GND_ICEBLOCK, "Pushable Square Ice Block (Inside Ganon's Castle)" }, + { ACTOR_EN_GB, "Poe Collector and Surroundings" }, + { ACTOR_EN_GS, "Gossip Stone" }, + { ACTOR_BG_MIZU_BWALL, "Bombable Stone Wall" }, + { ACTOR_BG_MIZU_SHUTTER, "Metal Gate (Water Temple)" }, + { ACTOR_EN_DAIKU_KAKARIKO, "Carpenters (Kakariko)" }, + { ACTOR_BG_BOWL_WALL, "Bombchu Bowling Alley Wall" }, + { ACTOR_EN_WALL_TUBO, "Bombchu Bowling Alley Bullseyes" }, + { ACTOR_EN_PO_DESERT, "Poe Guide (Desert Wasteland)" }, + { ACTOR_EN_CROW, "Guay" }, + { ACTOR_DOOR_KILLER, "Fake Door" }, + { ACTOR_BG_SPOT11_OASIS, "Oasis (Desert Colossus)" }, + { ACTOR_BG_SPOT18_FUTA, "Goron Jar Lid" }, + { ACTOR_BG_SPOT18_SHUTTER, "Sliding Doors (Goron City)" }, + { ACTOR_EN_MA3, "Malon (Adult, Lon Lon Ranch)" }, + { ACTOR_EN_COW, "Cow" }, + { ACTOR_BG_ICE_TURARA, "Icicles" }, + { ACTOR_BG_ICE_SHUTTER, "Vertical Ice Bars (Ice Cavern)" }, + { ACTOR_EN_KAKASI2, "Pierre the Scarecrow Spawn" }, + { ACTOR_EN_KAKASI3, "Bonooru the Scarecrow" }, + { ACTOR_OCEFF_WIPE4, "Scarecrow's Song Ocarina Effect" }, + { ACTOR_EN_EG, "Void-out Trigger (Tower Collapse)" }, + { ACTOR_BG_MENKURI_NISEKABE, "False Stone Walls (Gerudo Training Grounds)" }, + { ACTOR_EN_ZO, "Zora" }, + { ACTOR_OBJ_MAKEKINSUTA, "Skulltula Sprouting from Bean Spot" }, + { ACTOR_EN_GE3, "Gerudo Fortress Leader" }, + { ACTOR_OBJ_TIMEBLOCK, "Time Block" }, + { ACTOR_OBJ_HAMISHI, "Bronze Boulder" }, + { ACTOR_EN_ZL4, "Zelda (Child)" }, + { ACTOR_EN_MM2, "Running Man (Adult Era)" }, + { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, + { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" } +}; + +ActorDB::ActorDB() { + db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each + for (const AddPair& pair : initialActorTable) { + Entry& entry = AddEntry(pair.name, actorDescriptions[pair.init.id], pair.init); + } +} + +// Adds an actor at the given index. The name must be unique. +ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, size_t index) { + assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling for mods that try to declare the same actor. + + if (db.size() < (index + 1)) { + db.resize(index + 1); + } + Entry& newEntry = db.at(index); + newEntry.entry.id = index; + + assert(!newEntry.entry.valid); + + nextFreeId = std::max(nextFreeId, index + 1); + + nameTable[name] = newEntry.entry.id; + newEntry.SetName(name); + newEntry.SetDesc(desc); + + newEntry.entry.valid = true; + + return newEntry; +} + +// Adds an actor with the legacy ActorInit struct. The id is provided in it. +ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, const ActorInit& init) { + Entry& entry = AddEntry(name, desc, init.id); + + entry.entry.category = init.category; + entry.entry.flags = init.flags; + entry.entry.objectId = init.objectId; + entry.entry.instanceSize = init.instanceSize; + entry.entry.init = init.init; + entry.entry.destroy = init.destroy; + entry.entry.update = init.update; + entry.entry.draw = init.draw; + entry.entry.reset = init.reset; + + return entry; +} + +// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or RetrieveId to get it. +ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) { + Entry& entry = AddEntry(init.name, init.desc, nextFreeId); + + entry.entry.category = init.category; + entry.entry.flags = init.flags; + entry.entry.objectId = init.objectId; + entry.entry.instanceSize = init.instanceSize; + entry.entry.init = init.init; + entry.entry.destroy = init.destroy; + entry.entry.update = init.update; + entry.entry.draw = init.draw; + entry.entry.reset = init.reset; + + return entry; +} + +// Get the ActorDB::Entry for the given actor id. +ActorDB::Entry& ActorDB::RetrieveEntry(const int id) { + static Entry invalid; + if ((id < 0) || (id >= db.size())) { + return invalid; + } + return db[id]; +} + +// Get the id for a given actor by name. +int ActorDB::RetrieveId(const std::string& name) { + auto entry = nameTable.find(name); + if (entry == nameTable.end()) { + return -1; + } + + return entry->second; +} + +ActorDB::Entry::Entry() { + entry.name = nullptr; + entry.desc = nullptr; + entry.valid = false; + entry.id = 0; + entry.category = 0; + entry.flags = 0; + entry.objectId = 0; + entry.instanceSize = 0; + entry.init = nullptr; + entry.destroy = nullptr; + entry.update = nullptr; + entry.draw = nullptr; + entry.reset = nullptr; + entry.numLoaded = 0; +} + +ActorDB::Entry::Entry(const Entry& other) { + entry = other.entry; + SetName(other.name); + SetDesc(other.desc); +} + +ActorDB::Entry& ActorDB::Entry::operator=(const Entry& other) { + entry = other.entry; + SetName(other.name); + SetDesc(other.desc); + return *this; +} + +void ActorDB::Entry::SetName(const std::string& newName) { + name = newName; + entry.name = name.c_str(); +} + +void ActorDB::Entry::SetDesc(const std::string& newDesc) { + desc = newDesc; + entry.desc = desc.c_str(); +} + +#include "src/overlays/actors/ovl_En_Partner/z_en_partner.h" +static ActorDBInit EnPartnerInit = { + "En_Partner", + "Ivan", + ACTORCAT_ITEMACTION, + (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_DRAGGED_BY_HOOKSHOT | ACTOR_FLAG_CAN_PRESS_SWITCH), + OBJECT_GAMEPLAY_KEEP, + sizeof(EnPartner), + (ActorFunc)EnPartner_Init, + (ActorFunc)EnPartner_Destroy, + (ActorFunc)EnPartner_Update, + (ActorFunc)EnPartner_Draw, + nullptr, +}; +extern "C" s16 gEnPartnerId; + +void ActorDB::AddBuiltInCustomActors() { + gEnPartnerId = ActorDB::Instance->AddEntry(EnPartnerInit).entry.id; +} + +extern "C" ActorDBEntry* ActorDB_Retrieve(const int id) { + return &ActorDB::Instance->RetrieveEntry(id).entry; +} + +extern "C" int ActorDB_RetrieveId(const char* name) { + return ActorDB::Instance->RetrieveId(name); +} diff --git a/soh/soh/ActorDB.h b/soh/soh/ActorDB.h new file mode 100644 index 000000000..afb033a2f --- /dev/null +++ b/soh/soh/ActorDB.h @@ -0,0 +1,81 @@ +#pragma once +#include "z64actor.h" + +typedef struct { + const char* name; + const char* desc; + u32 valid; + s32 id; + s32 category; + u32 flags; + s32 objectId; + size_t instanceSize; + ActorFunc init; + ActorFunc destroy; + ActorFunc update; + ActorFunc draw; + ActorResetFunc reset; + s32 numLoaded; +} ActorDBEntry; + +#ifdef __cplusplus + +#include +#include +#include + +struct ActorDBInit { + std::string name; + std::string desc; + int category = 0; + u32 flags = 0; + int objectId = 0; + size_t instanceSize = sizeof(Actor); + ActorFunc init = nullptr; + ActorFunc destroy = nullptr; + ActorFunc update = nullptr; + ActorFunc draw = nullptr; + ActorResetFunc reset = nullptr; +}; + +class ActorDB { +public: + static ActorDB* Instance; + + ActorDB(); + + // Wrapper around ActorDBEntry so we get C++isms for the entries + struct Entry { + Entry(); + Entry(const Entry& other); + Entry& operator=(const Entry& other); + + void SetName(const std::string& newName); + void SetDesc(const std::string& newDesc); + + std::string name; + std::string desc; + ActorDBEntry entry; + }; + Entry& AddEntry(const ActorDBInit& init); + + Entry& RetrieveEntry(const int id); + int RetrieveId(const std::string& name); + + static void AddBuiltInCustomActors(); + +private: + Entry& AddEntry(const std::string& name, const std::string& desc, size_t index); + Entry& AddEntry(const std::string& name, const std::string& desc, const ActorInit& init); + + std::vector db; + std::unordered_map nameTable; + size_t nextFreeId = 0; +}; + +#else + +ActorDBEntry* ActorDB_Retrieve(const int id); +int ActorDB_RetrieveId(const char* name); + +#endif diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 29047a216..37feb8dbf 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -3,6 +3,7 @@ #include #include "savestates.h" #include +#include "soh/ActorDB.h" #include #include @@ -47,7 +48,18 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std:: Player* player = GET_PLAYER(gPlayState); PosRot spawnPoint; - const s16 actorId = std::stoi(args[1]); + const s16 nameId = ActorDB::Instance->RetrieveId(args[1]); + s16 actorId = 0; + if (nameId == -1) { + try { + actorId = std::stoi(args[1]); + } catch (std::invalid_argument const& ex) { + LUS::GetConsole()->SendErrorMessage("Invalid actor ID"); + return CMD_FAILED; + } + } else { + actorId = nameId; + } const s16 params = std::stoi(args[2]); spawnPoint = player->actor.world; @@ -1428,7 +1440,7 @@ void DebugConsole_Init(void) { { "Item ID", LUS::ArgumentType::NUMBER } }}); - CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor_id", LUS::ArgumentType::NUMBER }, + CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor name/id", LUS::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type { "data", LUS::ArgumentType::NUMBER }, { "x", LUS::ArgumentType::PLAYER_POS, true }, { "y", LUS::ArgumentType::PLAYER_POS, true }, diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index 0e92806b3..31725bbb2 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -2,6 +2,7 @@ #include "../../util.h" #include "../../UIWidgets.hpp" #include +#include "soh/ActorDB.h" #include #include @@ -50,441 +51,8 @@ std::array acMapping = { "Chest" }; -// https://wiki.cloudmodding.com/oot/Actor_List_(Variables) -std::map actorDescriptions = { - { ACTOR_PLAYER, "Link" }, - { ACTOR_EN_TEST, "Stalfos" }, - { ACTOR_EN_GIRLA, "Shop Items" }, - { ACTOR_EN_PART, "Body Parts" }, - { ACTOR_EN_LIGHT, "Decorative Flames" }, - { ACTOR_EN_DOOR, "Door" }, - { ACTOR_EN_BOX, "Treasure Chest" }, - { ACTOR_BG_DY_YOSEIZO, "Great Fairy" }, - { ACTOR_BG_HIDAN_FIREWALL, "Proximity activated Fire Wall" }, - { ACTOR_EN_POH, "Poe" }, - { ACTOR_EN_OKUTA, "Octorok" }, - { ACTOR_BG_YDAN_SP, "Webs" }, - { ACTOR_EN_BOM, "Bomb" }, - { ACTOR_EN_WALLMAS, "Wallmaster" }, - { ACTOR_EN_DODONGO, "Dodongo" }, - { ACTOR_EN_FIREFLY, "Keese" }, - { ACTOR_EN_HORSE, "Rideable Horse" }, - { ACTOR_EN_ITEM00, "Collectibles" }, - { ACTOR_EN_ARROW, "Arrow" }, - { ACTOR_EN_ELF, "Fairy" }, - { ACTOR_EN_NIW, "Cucco" }, - { ACTOR_EN_TITE, "Tektite" }, - { ACTOR_EN_REEBA, "Leever" }, - { ACTOR_EN_PEEHAT, "Peahat and Larva" }, - { ACTOR_EN_BUTTE, "Butterfly" }, - { ACTOR_EN_INSECT, "Bugs" }, - { ACTOR_EN_FISH, "Fish" }, - { ACTOR_EN_HOLL, "Room changing plane" }, - { ACTOR_EN_SCENE_CHANGE, "ovl_En_Scene_Change (broken)" }, - { ACTOR_EN_ZF, "Lizalfos and Dinolfos" }, - { ACTOR_EN_HATA, "Wooden Flagpole with Red Cloth" }, - { ACTOR_BOSS_DODONGO, "King Dodongo" }, - { ACTOR_BOSS_GOMA, "Gohma" }, - { ACTOR_EN_ZL1, "Child Princess Zelda (at window)" }, - { ACTOR_EN_VIEWER, "Cutscene Actors" }, - { ACTOR_EN_GOMA, "Gohma Larva" }, - { ACTOR_BG_PUSHBOX, "Cube" }, - { ACTOR_EN_BUBBLE, "Shabom" }, - { ACTOR_DOOR_SHUTTER, "Shutter Door" }, - { ACTOR_EN_DODOJR, "Baby Dodongo" }, - { ACTOR_EN_BDFIRE, "Empty" }, - { ACTOR_EN_BOOM, "Boomerang" }, - { ACTOR_EN_TORCH2, "Dark Link" }, - { ACTOR_EN_BILI, "Biri" }, - { ACTOR_EN_TP, "Electric Tailpasaran" }, - { ACTOR_EN_ST, "Skulltula" }, - { ACTOR_EN_BW, "Torch Slug" }, - { ACTOR_EN_A_OBJ, "Play_keep items" }, - { ACTOR_EN_EIYER, "Stinger (Land)" }, - { ACTOR_EN_RIVER_SOUND, "Ambient Sound Effects" }, - { ACTOR_EN_HORSE_NORMAL, "Horse" }, - { ACTOR_EN_OSSAN, "Shopkeeper" }, - { ACTOR_BG_TREEMOUTH, "Great Deku Tree's Jaw" }, - { ACTOR_BG_DODOAGO, "Dodongo's Cavern Mega Dodongo" }, - { ACTOR_BG_HIDAN_DALM, "Megaton Hammer Statue" }, - { ACTOR_BG_HIDAN_HROCK, "Huge stone spike platform (Fire Temple)" }, - { ACTOR_EN_HORSE_GANON, "Ganondorf's Horse" }, - { ACTOR_BG_HIDAN_ROCK, "Stone Blocks (Fire Temple)" }, - { ACTOR_BG_HIDAN_RSEKIZOU, "Spinning Stone Flamethrower (Fire Temple)" }, - { ACTOR_BG_HIDAN_SEKIZOU, "Stationary Flamethrower Statue (Fire Temple)" }, - { ACTOR_BG_HIDAN_SIMA, "Stone Platform (Fire Temple)" }, - { ACTOR_BG_HIDAN_SYOKU, "Stone Elevator (Fire Temple)" }, - { ACTOR_EN_XC, "Sheik" }, - { ACTOR_BG_HIDAN_CURTAIN, "Flame Circle" }, - { ACTOR_BG_SPOT00_HANEBASI, "Drawbridge Objects" }, - { ACTOR_EN_MB, "Moblins" }, - { ACTOR_EN_BOMBF, "Bombflower" }, - { ACTOR_EN_ZL2, "Adult Zelda (Cutscenes)" }, - { ACTOR_BG_HIDAN_FSLIFT, "Hookshot Elevator Platform (Fire Temple)" }, - { ACTOR_EN_OE2, "Unused NPC" }, - { ACTOR_BG_YDAN_HASI, "Deku Tree Puzzle elements" }, - { ACTOR_BG_YDAN_MARUTA, "Rotating Spiked Log (Deku Tree)" }, - { ACTOR_BOSS_GANONDROF, "Phantom Ganon" }, - { ACTOR_EN_AM, "Armos Statue" }, - { ACTOR_EN_DEKUBABA, "Deku Baba" }, - { ACTOR_EN_M_FIRE1, "Thrown Deku Nut" }, - { ACTOR_EN_M_THUNDER, "Spin Attack" }, - { ACTOR_BG_DDAN_JD, "Rising Stone Platform (Dodongo's Cavern)" }, - { ACTOR_BG_BREAKWALL, "Bombable Wall" }, - { ACTOR_EN_JJ, "Lord Jabu-Jabu" }, - { ACTOR_EN_HORSE_ZELDA, "Zelda's Horse" }, - { ACTOR_BG_DDAN_KD, "Stone Stairs (Dodongo's Cavern)" }, - { ACTOR_DOOR_WARP1, "Warp Portal" }, - { ACTOR_OBJ_SYOKUDAI, "Torch" }, - { ACTOR_ITEM_B_HEART, "Heart container" }, - { ACTOR_EN_DEKUNUTS, "Mad Scrub" }, - { ACTOR_BG_MENKURI_KAITEN, "Rotating Stone Ring Platform" }, - { ACTOR_BG_MENKURI_EYE, "Eye Statue" }, - { ACTOR_EN_VALI, "Bari" }, - { ACTOR_BG_MIZU_MOVEBG, "Water Temple Background Actors" }, - { ACTOR_BG_MIZU_WATER, "Water Plane (Water Temple)" }, - { ACTOR_ARMS_HOOK, "Hookshot" }, - { ACTOR_EN_FHG, "Phantom Ganon's Horse" }, - { ACTOR_BG_MORI_HINERI, "Twisted Hallway Rooms" }, - { ACTOR_EN_BB, "Bubble" }, - { ACTOR_BG_TOKI_HIKARI, "Windows (Temple of Time)" }, - { ACTOR_EN_YUKABYUN, "Flying Floor Tile" }, - { ACTOR_BG_TOKI_SWD, "Master Sword" }, - { ACTOR_EN_FHG_FIRE, "Empty" }, - { ACTOR_BG_MJIN, "Warp Song Pad" }, - { ACTOR_BG_HIDAN_KOUSI, "Sliding Metal Gate" }, - { ACTOR_DOOR_TOKI, "Door of Time Collision" }, - { ACTOR_BG_HIDAN_HAMSTEP, "Stone Steps and Platforms (Fire Temple)" }, - { ACTOR_EN_BIRD, "Brown Bird" }, - { ACTOR_EN_WOOD02, "Trees and Bushes" }, - { ACTOR_EN_LIGHTBOX, "Large noisy stone" }, - { ACTOR_EN_PU_BOX, "Stone cube" }, - { ACTOR_EN_TRAP, "Metal Spike Trap" }, - { ACTOR_EN_AROW_TRAP, "Arrow Trap" }, - { ACTOR_EN_VASE, "Orange Pot" }, - { ACTOR_EN_TA, "Talon" }, - { ACTOR_EN_TK, "Dampe (Alive)" }, - { ACTOR_BG_MORI_BIGST, "Large Round Platform (Forest Temple)" }, - { ACTOR_BG_MORI_ELEVATOR, "Elevator (Forest Temple)" }, - { ACTOR_BG_MORI_KAITENKABE, "Rotatable Walls (Forest Temple)" }, - { ACTOR_BG_MORI_RAKKATENJO, "Falling Ceiling (Forest Temple)" }, - { ACTOR_EN_VM, "Beamos" }, - { ACTOR_DEMO_EFFECT, "Spiritual Stones, Medallions, Triforce" }, - { ACTOR_DEMO_KANKYO, "Temple of Time Objects" }, - { ACTOR_BG_HIDAN_FWBIG, "Large Fire Wall (Fire Temple)" }, - { ACTOR_EN_FLOORMAS, "Floormaster" }, - { ACTOR_EN_HEISHI1, "Castle Courtyard Guards" }, - { ACTOR_EN_RD, "Redead and Gibdo" }, - { ACTOR_EN_PO_SISTERS, "Poe Sisters" }, - { ACTOR_BG_HEAVY_BLOCK, "Golden Gauntlets Pillar" }, - { ACTOR_BG_PO_EVENT, "Poe Sisters' Paintings and Puzzle Block" }, - { ACTOR_OBJ_MURE, "Fish, Bugs, Butterflies Group Spawner" }, - { ACTOR_EN_SW, "Skullwalltula and Gold Skulltulas" }, - { ACTOR_BOSS_FD, "Volvagia (Flying)" }, - { ACTOR_OBJECT_KANKYO, "Environmental Effects" }, - { ACTOR_EN_DU, "Darunia" }, - { ACTOR_EN_FD, "Flare Dancer" }, - { ACTOR_EN_HORSE_LINK_CHILD, "Young Epona" }, - { ACTOR_DOOR_ANA, "Grotto Entrance" }, - { ACTOR_BG_SPOT02_OBJECTS, "Graveyard Actors" }, - { ACTOR_BG_HAKA, "Gravestone" }, - { ACTOR_MAGIC_WIND, "Farore's Wind" }, - { ACTOR_MAGIC_FIRE, "Din's Fire" }, - { ACTOR_EN_RU1, "Ruto (Child)" }, - { ACTOR_BOSS_FD2, "Volvagia (Hole Form)" }, - { ACTOR_EN_FD_FIRE, "Flare Dancer Fire Attack" }, - { ACTOR_EN_DH, "Dead Hand" }, - { ACTOR_EN_DHA, "Dead Hand's Hand" }, - { ACTOR_EN_RL, "Rauru" }, - { ACTOR_EN_ENCOUNT1, "Enemy Spawner" }, - { ACTOR_DEMO_DU, "Darunia (Cutscenes)" }, - { ACTOR_DEMO_IM, "Impa (Cutscenes)" }, - { ACTOR_DEMO_TRE_LGT, "Treasure Chest Light" }, - { ACTOR_EN_FW, "Flare Dancer Core" }, - { ACTOR_BG_VB_SIMA, "Volvagia Platform" }, - { ACTOR_EN_VB_BALL, "Volvagia Rocks and Bones" }, - { ACTOR_BG_HAKA_MEGANE, "Shadow Temple Fake Walls" }, - { ACTOR_BG_HAKA_MEGANEBG, "Platforms (Shadow Temple)" }, - { ACTOR_BG_HAKA_SHIP, "River Boat (Shadow Temple)" }, - { ACTOR_BG_HAKA_SGAMI, "Spinning Scythe Trap" }, - { ACTOR_EN_HEISHI2, "Hyrulian Guards" }, - { ACTOR_EN_ENCOUNT2, "Falling Rock Spawner" }, - { ACTOR_EN_FIRE_ROCK, "Falling Burning Rocks" }, - { ACTOR_EN_BROB, "Flobbery Muscle Block (Jabu-Jabu's Belly)" }, - { ACTOR_MIR_RAY, "Reflectable Light Beam" }, - { ACTOR_BG_SPOT09_OBJ, "Gerudo Valley Objects" }, - { ACTOR_BG_SPOT18_OBJ, "Statue (Darunia's Room)" }, - { ACTOR_BOSS_VA, "Barinade" }, - { ACTOR_BG_HAKA_TUBO, "Giant Skull Jar (Shadow Temple)" }, - { ACTOR_BG_HAKA_TRAP, "Shadow Temple Traps" }, - { ACTOR_BG_HAKA_HUTA, "Coffin Lid" }, - { ACTOR_BG_HAKA_ZOU, "Bird Statue and Wall (Shadow Temple)" }, - { ACTOR_BG_SPOT17_FUNEN, "Smoke Cone (Death Mountain Crater)" }, - { ACTOR_EN_SYATEKI_ITM, "Shooting Gallery Game" }, - { ACTOR_EN_SYATEKI_MAN, "Shooting Gallery Man" }, - { ACTOR_EN_TANA, "Shop Shelves" }, - { ACTOR_EN_NB, "Nabooru" }, - { ACTOR_BOSS_MO, "Morpha" }, - { ACTOR_EN_SB, "Shell Blade" }, - { ACTOR_EN_BIGOKUTA, "Big Octo" }, - { ACTOR_EN_KAREBABA, "Withered Deku Baba" }, - { ACTOR_BG_BDAN_OBJECTS, "Inside Jabu-Jabu's Belly Objects" }, - { ACTOR_DEMO_SA, "Saria (Cutscenes)" }, - { ACTOR_DEMO_GO, "Gorons (Cutscene)" }, - { ACTOR_EN_IN, "Ingo" }, - { ACTOR_EN_TR, "Koume and Kotake" }, - { ACTOR_BG_SPOT16_BOMBSTONE, "Dodongo's Cavern Entrance Blocking Rock" }, - { ACTOR_BG_HIDAN_KOWARERUKABE, "Bombable Walls (Fire Temple)" }, - { ACTOR_BG_BOMBWALL, "2D Bombable Wall" }, - { ACTOR_BG_SPOT08_ICEBLOCK, "Ice Platform (Zora's Fountain)" }, - { ACTOR_EN_RU2, "Ruto (Adult)" }, - { ACTOR_OBJ_DEKUJR, "Deku Tree Sprout" }, - { ACTOR_BG_MIZU_UZU, "Water Vortex Effect (Water Temple)" }, - { ACTOR_BG_SPOT06_OBJECTS, "Lake Hylia Objects" }, - { ACTOR_BG_ICE_OBJECTS, "Pushable Ice Block (Ice Cavern)" }, - { ACTOR_BG_HAKA_WATER, "Bottom of the Well Water Level Changer" }, - { ACTOR_EN_MA2, "Malon (Adult, Ingo's Ranch)" }, - { ACTOR_EN_BOM_CHU, "Bombchu" }, - { ACTOR_EN_HORSE_GAME_CHECK, "Horseback Minigames" }, - { ACTOR_BOSS_TW, "Twinrova" }, - { ACTOR_EN_RR, "Like-Like" }, - { ACTOR_EN_BA, "Tentacle (Inside Jabu-Jabu's Belly)" }, - { ACTOR_EN_BX, "Electrified Tentacle (Inside Jabu-Jabu's Belly)" }, - { ACTOR_EN_ANUBICE, "Anubis (Body)" }, - { ACTOR_EN_ANUBICE_FIRE, "Anubis Fire Attack" }, - { ACTOR_BG_MORI_HASHIGO, "Ladder (Forest Temple)" }, - { ACTOR_BG_MORI_HASHIRA4, "Forest Temple Objects" }, - { ACTOR_BG_MORI_IDOMIZU, "Well Water (Forest Temple)" }, - { ACTOR_BG_SPOT16_DOUGHNUT, "Cloud Ring (Death Mountain)" }, - { ACTOR_BG_BDAN_SWITCH, "Switches (Inside Lord Jabu-Jabu)" }, - { ACTOR_EN_MA1, "Malon (Child)" }, - { ACTOR_BOSS_GANON, "Ganondorf" }, - { ACTOR_BOSS_SST, "Bongo Bongo" }, - { ACTOR_EN_NY, "Spike (Enemy)" }, - { ACTOR_EN_FR, "Frog Song Spot and Frogs" }, - { ACTOR_ITEM_SHIELD, "Deku Shield" }, - { ACTOR_BG_ICE_SHELTER, "Red Ice" }, - { ACTOR_EN_ICE_HONO, "Blue Fire Flames" }, - { ACTOR_ITEM_OCARINA, "Ocarina of Time" }, - { ACTOR_MAGIC_DARK, "Nayru's Love" }, - { ACTOR_DEMO_6K, "Sages, Balls of Light (Cutscene)" }, - { ACTOR_EN_ANUBICE_TAG, "Anubis Spawn" }, - { ACTOR_BG_HAKA_GATE, "Truth Spinner Puzzle (Shadow Temple)" }, - { ACTOR_BG_SPOT15_SAKU, "Hyrule Castle Gate" }, - { ACTOR_BG_JYA_GOROIWA, "Rolling Boulder (Spirit Temple)" }, - { ACTOR_BG_JYA_ZURERUKABE, "Sliding, Climbable Brick Wall (Spirit Temple)" }, - { ACTOR_BG_JYA_COBRA, "Rotatable Cobra Mirror (Spirit Temple)" }, - { ACTOR_BG_JYA_KANAAMI, "Climbable Metal Grating Bridge (Spirit Temple)" }, - { ACTOR_FISHING, "Fishing Pond Man and Fish" }, - { ACTOR_OBJ_OSHIHIKI, "Pushable Block" }, - { ACTOR_BG_GATE_SHUTTER, "Gate to Death Mountain Trail" }, - { ACTOR_EFF_DUST, "Dust Effects" }, - { ACTOR_BG_SPOT01_FUSYA, "Windmill Sails (Kakariko Village)" }, - { ACTOR_BG_SPOT01_IDOHASHIRA, "Well Crossbeam (Kakariko Village)" }, - { ACTOR_BG_SPOT01_IDOMIZU, "Well Water (Kakariko Village)" }, - { ACTOR_BG_PO_SYOKUDAI, "Golden Torch (Poe Sisters)" }, - { ACTOR_BG_GANON_OTYUKA, "Falling Platform (Ganondorf Fight)" }, - { ACTOR_BG_SPOT15_RRBOX, "Milk Crate" }, - { ACTOR_BG_UMAJUMP, "Obstacle Fence (Lon Lon Ranch)" }, - { ACTOR_ARROW_FIRE, "Fire Arrow" }, - { ACTOR_ARROW_ICE, "Ice Arrow" }, - { ACTOR_ARROW_LIGHT, "Light Arrow" }, - { ACTOR_ITEM_ETCETERA, "Collectible Items" }, - { ACTOR_OBJ_KIBAKO, "Small Liftable Crate" }, - { ACTOR_OBJ_TSUBO, "Breakable Pot" }, - { ACTOR_EN_WONDER_ITEM, "Invisible Collectible" }, - { ACTOR_EN_IK, "Iron Knuckle" }, - { ACTOR_DEMO_IK, "Iron Knuckle armor pieces (Spirit Temple Nabooru fight)" }, - { ACTOR_EN_SKJ, "Skullkid" }, - { ACTOR_EN_SKJNEEDLE, "Skullkid Needle Attack" }, - { ACTOR_EN_G_SWITCH, "Silver Rupee" }, - { ACTOR_DEMO_EXT, "Magic Vortex" }, - { ACTOR_DEMO_SHD, "Bongo Bongo's Shadow" }, - { ACTOR_EN_DNS, "Business Scrub" }, - { ACTOR_ELF_MSG, "Navi Message" }, - { ACTOR_EN_HONOTRAP, "Stone Eye (Fire Trap) and Flame" }, - { ACTOR_EN_TUBO_TRAP, "Flying Pot" }, - { ACTOR_OBJ_ICE_POLY, "Ice spawned by red ice? frozen actors" }, - { ACTOR_BG_SPOT03_TAKI, "Zora's River Waterfall" }, - { ACTOR_BG_SPOT07_TAKI, "Zora's Domain Waterfall and Ice" }, - { ACTOR_EN_FZ, "Frezzard" }, - { ACTOR_EN_PO_RELAY, "Dampe's Ghost" }, - { ACTOR_BG_RELAY_OBJECTS, "Windmill Objects" }, - { ACTOR_EN_DIVING_GAME, "Zora Diving Game" }, - { ACTOR_EN_KUSA, "Bush/Grass" }, - { ACTOR_OBJ_BEAN, "Bean Plant Spot" }, - { ACTOR_OBJ_BOMBIWA, "Brown Bombable Boulder" }, - { ACTOR_OBJ_SWITCH, "Switches" }, - { ACTOR_OBJ_ELEVATOR, "Huge Stone Elevator" }, - { ACTOR_OBJ_LIFT, "Square Collapsing Platform" }, - { ACTOR_OBJ_HSBLOCK, "Stone Hookshot Target" }, - { ACTOR_EN_OKARINA_TAG, "Ocarina Music Staff Spot" }, - { ACTOR_EN_YABUSAME_MARK, "Horseback Archery Target" }, - { ACTOR_EN_GOROIWA, "Rolling Boulder" }, - { ACTOR_EN_EX_RUPPY, "Sparkling Rupee" }, - { ACTOR_EN_TORYO, "Boss Carpenter" }, - { ACTOR_EN_DAIKU, "Carpenters" }, - { ACTOR_EN_NWC, "Cucco Chick" }, - { ACTOR_EN_BLKOBJ, "Dark Link's Illusion Room" }, - { ACTOR_ITEM_INBOX, "Zelda's Magic to Open Gates" }, - { ACTOR_EN_GE1, "White Clothed Gerudo" }, - { ACTOR_OBJ_BLOCKSTOP, "Pushblock Stop" }, - { ACTOR_EN_SDA, "Dynamic Shadow" }, - { ACTOR_EN_CLEAR_TAG, "Arwing" }, - { ACTOR_EN_NIW_LADY, "Cucco Lady" }, - { ACTOR_EN_GM, "Medigoron" }, - { ACTOR_EN_MS, "Bean Salesman" }, - { ACTOR_EN_HS, "Carpenter's Son" }, - { ACTOR_BG_INGATE, "Ingo's Gates (Lon Lon Ranch)" }, - { ACTOR_EN_KANBAN, "Square Signpost" }, - { ACTOR_EN_HEISHI3, "Hyrule Castle Guard" }, - { ACTOR_EN_SYATEKI_NIW, "Cucco (Minigames)" }, - { ACTOR_EN_ATTACK_NIW, "Cucco (Attacking)" }, - { ACTOR_BG_SPOT01_IDOSOKO, "Stone Blocking Entrance to Bottom of the Well" }, - { ACTOR_EN_SA, "Saria" }, - { ACTOR_EN_WONDER_TALK, "Checkable Spot (Green Navi)" }, - { ACTOR_BG_GJYO_BRIDGE, "Rainbow Bridge to Ganon's Castle" }, - { ACTOR_EN_DS, "Potion Shop Granny" }, - { ACTOR_EN_MK, "Lakeside Professor" }, - { ACTOR_EN_BOM_BOWL_MAN, "Bombchu Bowling Alley Lady" }, - { ACTOR_EN_BOM_BOWL_PIT, "Bombchu Bowling Alley Final Target" }, - { ACTOR_EN_OWL, "Kaepora Gaebora" }, - { ACTOR_EN_ISHI, "Liftable Rock" }, - { ACTOR_OBJ_HANA, "Uninteractable Flowers, Rocks, Grass" }, - { ACTOR_OBJ_LIGHTSWITCH, "Sun Emblem Switch (Spirit Temple)" }, - { ACTOR_OBJ_MURE2, "Rock/Bush groups" }, - { ACTOR_EN_GO, "Gorons 1" }, - { ACTOR_EN_FU, "Windmill Man" }, - { ACTOR_EN_CHANGER, "Treasure Box Shop Minigame" }, - { ACTOR_BG_JYA_MEGAMI, "Statue Face (Spirit Temple)" }, - { ACTOR_BG_JYA_LIFT, "Chain Platform (Spirit Temple)" }, - { ACTOR_BG_JYA_BIGMIRROR, "Large Circular Mirror (Spirt Temple)" }, - { ACTOR_BG_JYA_BOMBCHUIWA, "Light Blocking Rock (Spirit Temple)" }, - { ACTOR_BG_JYA_AMISHUTTER, "Sliding Circular Metal Grate (Spirit Temple)" }, - { ACTOR_BG_JYA_BOMBIWA, "Bombable Rock Wall (Spirit Temple)" }, - { ACTOR_BG_SPOT18_BASKET, "Big Goron Pot" }, - { ACTOR_EN_GANON_ORGAN, "Ganon's Organ and surroundings" }, - { ACTOR_EN_SIOFUKI, "Water Spout" }, - { ACTOR_EN_STREAM, "Water Vortex" }, - { ACTOR_EN_MM, "Running Man (Child Era)" }, - { ACTOR_EN_KO, "Kokiri Children" }, - { ACTOR_EN_KZ, "King Zora" }, - { ACTOR_EN_WEATHER_TAG, "Proximity Weather Effects" }, - { ACTOR_BG_SST_FLOOR, "Bongo Bongo's Drum" }, - { ACTOR_EN_ANI, "Kakariko Village Rooftop Man" }, - { ACTOR_EN_EX_ITEM, "Minigame Displayed Items" }, - { ACTOR_BG_JYA_IRONOBJ, "Iron Knuckles Room Stuff (Spirit Temple)" }, - { ACTOR_EN_JS, "Magic Carpet Man" }, - { ACTOR_EN_JSJUTAN, "Magic Carpet Man Carpet" }, - { ACTOR_EN_CS, "Graveyard Boy" }, - { ACTOR_EN_MD, "Mido" }, - { ACTOR_EN_HY, "Market NPCs" }, - { ACTOR_EN_GANON_MANT, "Ganondorf's Cape" }, - { ACTOR_EN_OKARINA_EFFECT, "Song of Storms Storm Manager" }, - { ACTOR_EN_MAG, "Title Screen Manager" }, - { ACTOR_DOOR_GERUDO, "Cell Door (Gerudo Fortress)" }, - { ACTOR_ELF_MSG2, "Navi Information Spot (Targetable, Green)" }, - { ACTOR_DEMO_GT, "Ganon's Tower Collapsing (Cutscene Objects)" }, - { ACTOR_EN_PO_FIELD, "Big/Small Poe Spawn Point" }, - { ACTOR_EFC_ERUPC, "Lava Particle Fountain (Death Mountain panorama)" }, - { ACTOR_BG_ZG, "Metal Bars (Ganon's Castle)" }, - { ACTOR_EN_HEISHI4, "Hyrule Guard" }, - { ACTOR_EN_ZL3, "Adult Zelda" }, - { ACTOR_BOSS_GANON2, "Ganon" }, - { ACTOR_EN_KAKASI, "Pierre the Scarecrow" }, - { ACTOR_EN_TAKARA_MAN, "Treasure Box Shop Man" }, - { ACTOR_OBJ_MAKEOSHIHIKI, "Push Block Puzzles" }, - { ACTOR_OCEFF_SPOT, "Sun's Song Effect" }, - { ACTOR_END_TITLE, "The End message" }, - { ACTOR_EN_TORCH, "Grotto Treasure Chest" }, - { ACTOR_DEMO_EC, "Credits Revelers in Lon Lon" }, - { ACTOR_SHOT_SUN, "Lake Hylia Sun Hitbox, Big Fairy Spawner" }, - { ACTOR_EN_DY_EXTRA, "Spiral Beams (Great Fairy Fountains)" }, - { ACTOR_EN_WONDER_TALK2, "Dialog Spot" }, - { ACTOR_EN_GE2, "Patrolling Gerudo" }, - { ACTOR_OBJ_ROOMTIMER, "Room Timer" }, - { ACTOR_EN_SSH, "Cursed Skulltula People" }, - { ACTOR_EN_STH, "Uncursed Skulltula People" }, - { ACTOR_OCEFF_WIPE, "Zelda's Lullaby and Song of Time Ocarina Effect" }, - { ACTOR_OCEFF_STORM, "Song of Storm Ocarina Effect" }, - { ACTOR_EN_WEIYER, "Stinger (Water)" }, - { ACTOR_BG_SPOT05_SOKO, "Sacred Forest Meadow Objects" }, - { ACTOR_BG_JYA_1FLIFT, "Stone Elevator (Spirit Temple)" }, - { ACTOR_BG_JYA_HAHENIRON, "Chunks of Iron Knucle Chair and Pillar" }, - { ACTOR_BG_SPOT12_GATE, "Gerudo Fortress Wooden Gate" }, - { ACTOR_BG_SPOT12_SAKU, "Gerudo Fortress Training Area Gate" }, - { ACTOR_EN_HINTNUTS, "Hint Deku Scrubs (Deku Tree)" }, - { ACTOR_EN_NUTSBALL, "Deku Scrub Nut Attack" }, - { ACTOR_BG_SPOT00_BREAK, "Broken Drawbridge, Fences" }, - { ACTOR_EN_SHOPNUTS, "Grounded Sales Scrub" }, - { ACTOR_EN_IT, "Dampe's Minigame Collectibles" }, - { ACTOR_EN_GELDB, "Gerudo Fighter" }, - { ACTOR_OCEFF_WIPE2, "Epona's Song Ocarina Effect" }, - { ACTOR_OCEFF_WIPE3, "Saria's Song Ocarina Effect" }, - { ACTOR_EN_NIW_GIRL, "Girl Chasing Cucco" }, - { ACTOR_EN_DOG, "Dog" }, - { ACTOR_EN_SI, "Gold Skulltula Token" }, - { ACTOR_BG_SPOT01_OBJECTS2, "Kakariko Village Objects" }, - { ACTOR_OBJ_COMB, "Beehive" }, - { ACTOR_BG_SPOT11_BAKUDANKABE, "Destructible Wall (Desert Colossus)" }, - { ACTOR_OBJ_KIBAKO2, "Large Crate" }, - { ACTOR_EN_DNT_DEMO, "Deku Mask Panel Trigger" }, - { ACTOR_EN_DNT_JIJI, "Deku Mask Panel Head Judge" }, - { ACTOR_EN_DNT_NOMAL, "Deku Game?" }, - { ACTOR_EN_GUEST, "Happy Mask Shop Customer" }, - { ACTOR_BG_BOM_GUARD, "Bombchu Bowling Alley Aiming Area" }, - { ACTOR_EN_HS2, "Carpenter's Son (Child Era)" }, - { ACTOR_DEMO_KEKKAI, "Ganon's Tower Magic Barriers" }, - { ACTOR_BG_SPOT08_BAKUDANKABE, "Destructible Wall (Zora's Fountain)" }, - { ACTOR_BG_SPOT17_BAKUDANKABE, "Destructible Wall (Death Mountain Crater)" }, - { ACTOR_OBJ_MURE3, "Rupee Patterns" }, - { ACTOR_EN_TG, "Entwined Lovers (Honey & Darling)" }, - { ACTOR_EN_MU, "Haggling Townspeople" }, - { ACTOR_EN_GO2, "Gorons 2" }, - { ACTOR_EN_WF, "Wolfos" }, - { ACTOR_EN_SKB, "Stalchild" }, - { ACTOR_DEMO_GJ, "Ganon Battle Rubble" }, - { ACTOR_DEMO_GEFF, "Ganon's Tower Rubble Fragment" }, - { ACTOR_BG_GND_FIREMEIRO, "Sinking Lava Platform (Ganon's Castle)" }, - { ACTOR_BG_GND_DARKMEIRO, "Clear block" }, - { ACTOR_BG_GND_SOULMEIRO, "Web-Blocked Ceiling Hole (Inside Ganon's Castle)" }, - { ACTOR_BG_GND_NISEKABE, "Ganon's Castle Fake Walls" }, - { ACTOR_BG_GND_ICEBLOCK, "Pushable Square Ice Block (Inside Ganon's Castle)" }, - { ACTOR_EN_GB, "Poe Collector and Surroundings" }, - { ACTOR_EN_GS, "Gossip Stone" }, - { ACTOR_BG_MIZU_BWALL, "Bombable Stone Wall" }, - { ACTOR_BG_MIZU_SHUTTER, "Metal Gate (Water Temple)" }, - { ACTOR_EN_DAIKU_KAKARIKO, "Carpenters (Kakariko)" }, - { ACTOR_BG_BOWL_WALL, "Bombchu Bowling Alley Wall" }, - { ACTOR_EN_WALL_TUBO, "Bombchu Bowling Alley Bullseyes" }, - { ACTOR_EN_PO_DESERT, "Poe Guide (Desert Wasteland)" }, - { ACTOR_EN_CROW, "Guay" }, - { ACTOR_DOOR_KILLER, "Fake Door" }, - { ACTOR_BG_SPOT11_OASIS, "Oasis (Desert Colossus)" }, - { ACTOR_BG_SPOT18_FUTA, "Goron Jar Lid" }, - { ACTOR_BG_SPOT18_SHUTTER, "Sliding Doors (Goron City)" }, - { ACTOR_EN_MA3, "Malon (Adult, Lon Lon Ranch)" }, - { ACTOR_EN_COW, "Cow" }, - { ACTOR_BG_ICE_TURARA, "Icicles" }, - { ACTOR_BG_ICE_SHUTTER, "Vertical Ice Bars (Ice Cavern)" }, - { ACTOR_EN_KAKASI2, "Pierre the Scarecrow Spawn" }, - { ACTOR_EN_KAKASI3, "Bonooru the Scarecrow" }, - { ACTOR_OCEFF_WIPE4, "Scarecrow's Song Ocarina Effect" }, - { ACTOR_EN_EG, "Void-out Trigger (Tower Collapse)" }, - { ACTOR_BG_MENKURI_NISEKABE, "False Stone Walls (Gerudo Training Grounds)" }, - { ACTOR_EN_ZO, "Zora" }, - { ACTOR_OBJ_MAKEKINSUTA, "Skulltula Sprouting from Bean Spot" }, - { ACTOR_EN_GE3, "Gerudo Fortress Leader" }, - { ACTOR_OBJ_TIMEBLOCK, "Time Block" }, - { ACTOR_OBJ_HAMISHI, "Bronze Boulder" }, - { ACTOR_EN_ZL4, "Zelda (Child)" }, - { ACTOR_EN_MM2, "Running Man (Adult Era)" }, - { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, - { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" } -}; - const std::string GetActorDescription(u16 id) { - return actorDescriptions[id] != NULL ? actorDescriptions[id] : "???"; + return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.desc : "???"; } template void DrawGroupWithBorder(T&& drawFunc) { @@ -548,7 +116,6 @@ void DrawActorViewer(bool& open) { static Actor empty{}; static Actor* fetch = NULL; static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}}; - static ActorOverlay* dispOverlay; static bool needs_reset = false; static ImU16 one = 1; static int actor; @@ -563,7 +130,6 @@ void DrawActorViewer(bool& open) { if (needs_reset) { display = ∅ fetch = nullptr; - dispOverlay = nullptr; actor = category = 0; filler = "Please Select"; list.clear(); @@ -587,7 +153,7 @@ void DrawActorViewer(bool& open) { lastSceneId = gPlayState->sceneNum; } for (int i = 0; i < list.size(); i++) { - std::string label = std::to_string(i) + ": " + list[i]->overlayEntry->name; + std::string label = std::to_string(i) + ": " + ActorDB::Instance->RetrieveEntry(list[i]->id).name; std::string description = GetActorDescription(list[i]->id); if (description != "") label += " (" + description + ")"; @@ -604,11 +170,10 @@ void DrawActorViewer(bool& open) { } if (ImGui::TreeNode("Selected Actor")) { - dispOverlay = display->overlayEntry; DrawGroupWithBorder([&]() { - ImGui::Text("Name: %s", dispOverlay != nullptr ? dispOverlay->name : "???"); - ImGui::Text("Description: %s", dispOverlay != nullptr ? GetActorDescription(display->id).c_str() : "???"); - ImGui::Text("Category: %s", dispOverlay != nullptr ? acMapping[display->category] : "???"); + ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str()); + ImGui::Text("Description: %s", GetActorDescription(display->id).c_str()); + ImGui::Text("Category: %s", acMapping[display->category]); ImGui::Text("ID: %d", display->id); ImGui::Text("Parameters: %d", display->params); }); @@ -745,7 +310,7 @@ void DrawActorViewer(bool& open) { } if (ImGui::Button("Spawn")) { - if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && gActorOverlayTable[newActor.id].initInfo != NULL) { + if (ActorDB::Instance->RetrieveEntry(newActor.id).entry.valid) { Actor_Spawn(&gPlayState->actorCtx, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y, newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params, 0); } else { @@ -757,7 +322,7 @@ void DrawActorViewer(bool& open) { Actor* parent = display; if (parent != NULL) { if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && - gActorOverlayTable[newActor.id].initInfo != NULL) { + ActorDB::Instance->RetrieveEntry(newActor.id).entry.valid) { Actor_SpawnAsChild(&gPlayState->actorCtx, parent, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y, newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params); @@ -777,7 +342,6 @@ void DrawActorViewer(bool& open) { ImGui::Text("Global Context needed for actor info!"); if (needs_reset) { fetch = nullptr; - dispOverlay = nullptr; actor = category = 0; filler = "Please Select"; list.clear(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 20972f220..e57d766dc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -74,6 +74,7 @@ #include #include "Enhancements/item-tables/ItemTableManager.h" #include "GameMenuBar.hpp" +#include "ActorDB.h" #ifdef ENABLE_CROWD_CONTROL #include "Enhancements/crowd-control/CrowdControl.h" @@ -754,6 +755,7 @@ extern "C" void InitOTR() { ItemTableManager::Instance = new ItemTableManager(); GameInteractor::Instance = new GameInteractor(); AudioCollection::Instance = new AudioCollection(); + ActorDB::Instance = new ActorDB(); #ifdef __APPLE__ SpeechSynthesizer::Instance = new DarwinSpeechSynthesizer(); SpeechSynthesizer::Instance->Init(); @@ -761,7 +763,7 @@ extern "C" void InitOTR() { SpeechSynthesizer::Instance = new SAPISpeechSynthesizer(); SpeechSynthesizer::Instance->Init(); #endif - + clearMtx = (uintptr_t)&gMtxClear; OTRMessage_Init(); OTRAudio_Init(); @@ -779,6 +781,7 @@ extern "C" void InitOTR() { VanillaItemTable_Init(); InitMods(); + ActorDB::AddBuiltInCustomActors(); time_t now = time(NULL); tm *tm_now = localtime(&now); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index c7db247f4..872752994 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -9,6 +9,7 @@ #include "soh/frame_interpolation.h" #include "soh/Enhancements/enemyrandomizer.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ActorDB.h" #if defined(_MSC_VER) || defined(__GNUC__) #include @@ -1215,18 +1216,12 @@ void Actor_Init(Actor* actor, PlayState* play) { } void Actor_Destroy(Actor* actor, PlayState* play) { - ActorOverlay* overlayEntry; - char* name; - if (actor->destroy != NULL) { actor->destroy(actor, play); actor->destroy = NULL; } else { - overlayEntry = actor->overlayEntry; - name = overlayEntry->name != NULL ? overlayEntry->name : ""; - // "No Actor class destruct [%s]" - osSyncPrintf("Actorクラス デストラクトがありません [%s]\n" VT_RST, name); + osSyncPrintf("Actorクラス デストラクトがありません [%s]\n" VT_RST, ActorDB_Retrieve(actor->id)->name); } } @@ -2441,7 +2436,6 @@ void Actor_DisableLens(PlayState* play) { // Actor_InitContext void func_800304DC(PlayState* play, ActorContext* actorCtx, ActorEntry* actorEntry) { - ActorOverlay* overlayEntry; SavedSceneFlags* savedSceneFlags; s32 i; @@ -2449,17 +2443,9 @@ void func_800304DC(PlayState* play, ActorContext* actorCtx, ActorEntry* actorEnt memset(actorCtx, 0, sizeof(*actorCtx)); - ActorOverlayTable_Init(); Matrix_MtxFCopy(&play->billboardMtxF, &gMtxFClear); Matrix_MtxFCopy(&play->viewProjectionMtxF, &gMtxFClear); - overlayEntry = &gActorOverlayTable[0]; - for (i = 0; i < ARRAY_COUNT(gActorOverlayTable); i++) { - overlayEntry->loadedRamAddr = NULL; - overlayEntry->numLoaded = 0; - overlayEntry++; - } - actorCtx->flags.chest = savedSceneFlags->chest; actorCtx->flags.swch = savedSceneFlags->swch; actorCtx->flags.clear = savedSceneFlags->clear; @@ -2492,11 +2478,6 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { player = GET_PLAYER(play); - if (0) { - // This ASSERT is optimized out but it exists due to its presence in rodata - ASSERT(gMaxActorId == ACTOR_ID_MAX); - } - sp74 = NULL; unkFlag = 0; @@ -2625,16 +2606,15 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { } void Actor_FaultPrint(Actor* actor, char* command) { - ActorOverlay* overlayEntry; char* name; - if ((actor == NULL) || (actor->overlayEntry == NULL)) { + if (actor == NULL) { FaultDrawer_SetCursor(48, 24); FaultDrawer_Printf("ACTOR NAME is NULL"); + return; } - overlayEntry = actor->overlayEntry; - name = overlayEntry->name != NULL ? overlayEntry->name : ""; + name = ActorDB_Retrieve(actor->id)->name; osSyncPrintf("アクターの名前(%08x:%s)\n", actor, name); // "Actor name (%08x:%s)" @@ -2887,8 +2867,7 @@ void func_800315AC(PlayState* play, ActorContext* actorCtx) { actor = actorListEntry->head; while (actor != NULL) { - ActorOverlay* overlayEntry = actor->overlayEntry; - char* actorName = overlayEntry->name != NULL ? overlayEntry->name : ""; + char* actorName = ActorDB_Retrieve(actor->id)->name; gDPNoOpString(POLY_OPA_DISP++, actorName, i); gDPNoOpString(POLY_XLU_DISP++, actorName, i); @@ -3053,7 +3032,6 @@ void func_80031C3C(ActorContext* actorCtx, PlayState* play) { Play_SaveSceneFlags(play); func_80030488(play); - ActorOverlayTable_Cleanup(); } /** @@ -3110,41 +3088,21 @@ Actor* Actor_RemoveFromCategory(PlayState* play, ActorContext* actorCtx, Actor* return newHead; } -void Actor_FreeOverlay(ActorOverlay* actorOverlay) { +void Actor_FreeOverlay(ActorDBEntry* dbEntry) { osSyncPrintf(VT_FGCOL(CYAN)); - if (actorOverlay->numLoaded == 0) { + if (dbEntry->numLoaded == 0) { - if (actorOverlay->initInfo->reset != NULL) { - actorOverlay->initInfo->reset(); + if (dbEntry->reset != NULL) { + dbEntry->reset(); } if (HREG(20) != 0) { osSyncPrintf("アクタークライアントが0になりました\n"); // "Actor client is now 0" } - - if (actorOverlay->loadedRamAddr != NULL) { - if (actorOverlay->allocType & ALLOCTYPE_PERMANENT) { - if (HREG(20) != 0) { - osSyncPrintf("オーバーレイ解放しません\n"); // "Overlay will not be deallocated" - } - } else if (actorOverlay->allocType & ALLOCTYPE_ABSOLUTE) { - if (HREG(20) != 0) { - // "Absolute magic field reserved, so deallocation will not occur" - osSyncPrintf("絶対魔法領域確保なので解放しません\n"); - } - actorOverlay->loadedRamAddr = NULL; - } else { - if (HREG(20) != 0) { - osSyncPrintf("オーバーレイ解放します\n"); // "Overlay deallocated" - } - ZELDA_ARENA_FREE_DEBUG(actorOverlay->loadedRamAddr); - actorOverlay->loadedRamAddr = NULL; - } - } } else if (HREG(20) != 0) { // "%d of actor client remains" - osSyncPrintf("アクタークライアントはあと %d 残っています\n", actorOverlay->numLoaded); + osSyncPrintf("アクタークライアントはあと %d 残っています\n", dbEntry->numLoaded); } osSyncPrintf(VT_RST); @@ -3163,24 +3121,17 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos } } - s32 pad; Actor* actor; - ActorInit* actorInit; s32 objBankIndex; - ActorOverlay* overlayEntry; u32 temp; - char* name; - u32 overlaySize; - overlayEntry = &gActorOverlayTable[actorId]; - ASSERT(actorId < ACTOR_ID_MAX); + ActorDBEntry* dbEntry = ActorDB_Retrieve(actorId); - name = overlayEntry->name != NULL ? overlayEntry->name : ""; - overlaySize = (uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart; + ASSERT(dbEntry->valid); if (HREG(20) != 0) { // "Actor class addition [%d:%s]" - osSyncPrintf("アクタークラス追加 [%d:%s]\n", actorId, name); + osSyncPrintf("アクタークラス追加 [%d:%s]\n", actorId, dbEntry->name); } if (actorCtx->total > ACTOR_NUMBER_MAX) { @@ -3189,112 +3140,55 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos return NULL; } - if (overlayEntry->vramStart == 0) { - if (HREG(20) != 0) { - osSyncPrintf("オーバーレイではありません\n"); // "Not an overlay" - } - - actorInit = overlayEntry->initInfo; - } else { - if (overlayEntry->loadedRamAddr != NULL) { - if (HREG(20) != 0) { - osSyncPrintf("既にロードされています\n"); // "Already loaded" - } - } else { - if (overlayEntry->allocType & ALLOCTYPE_ABSOLUTE) { - ASSERT(overlaySize <= AM_FIELD_SIZE); - - if (actorCtx->absoluteSpace == NULL) { - // "AMF: absolute magic field" - actorCtx->absoluteSpace = ZELDA_ARENA_MALLOC_RDEBUG(AM_FIELD_SIZE); - if (HREG(20) != 0) { - // "Absolute magic field reservation - %d bytes reserved" - osSyncPrintf("絶対魔法領域確保 %d バイト確保\n", AM_FIELD_SIZE); - } - } - - overlayEntry->loadedRamAddr = actorCtx->absoluteSpace; - } else if (overlayEntry->allocType & ALLOCTYPE_PERMANENT) { - overlayEntry->loadedRamAddr = ZELDA_ARENA_MALLOC_RDEBUG(overlaySize); - } else { - overlayEntry->loadedRamAddr = ZELDA_ARENA_MALLOC_DEBUG(overlaySize); - } - - if (overlayEntry->loadedRamAddr == NULL) { - // "Cannot reserve actor program memory" - osSyncPrintf(VT_COL(RED, WHITE) "Actorプログラムメモリが確保できません\n" VT_RST); - return NULL; - } - - Overlay_Load(overlayEntry->vromStart, overlayEntry->vromEnd, overlayEntry->vramStart, overlayEntry->vramEnd, - overlayEntry->loadedRamAddr); - - osSyncPrintf(VT_FGCOL(GREEN)); - osSyncPrintf("OVL(a):Seg:%08x-%08x Ram:%08x-%08x Off:%08x %s\n", overlayEntry->vramStart, - overlayEntry->vramEnd, overlayEntry->loadedRamAddr, - (uintptr_t)overlayEntry->loadedRamAddr + (uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart, - (uintptr_t)overlayEntry->vramStart - (uintptr_t)overlayEntry->loadedRamAddr, name); - osSyncPrintf(VT_RST); - - overlayEntry->numLoaded = 0; - } - - actorInit = (void*)(uintptr_t)((overlayEntry->initInfo != NULL) - ? (void*)((uintptr_t)overlayEntry->initInfo - - ((intptr_t)overlayEntry->vramStart - (intptr_t)overlayEntry->loadedRamAddr)) - : NULL); - } - - objBankIndex = Object_GetIndex(&play->objectCtx, actorInit->objectId); + objBankIndex = Object_GetIndex(&gPlayState->objectCtx, dbEntry->objectId); if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger("gRandomizedEnemies", 0))) { objBankIndex = 0; } if ((objBankIndex < 0) || - ((actorInit->category == ACTORCAT_ENEMY) && Flags_GetClear(play, play->roomCtx.curRoom.num))) { + ((dbEntry->category == ACTORCAT_ENEMY) && Flags_GetClear(play, play->roomCtx.curRoom.num))) { // "No data bank!! (profilep->bank=%d)" osSyncPrintf(VT_COL(RED, WHITE) "データバンク無し!!<データバンク=%d>(profilep->bank=%d)\n" VT_RST, - objBankIndex, actorInit->objectId); - Actor_FreeOverlay(overlayEntry); + objBankIndex, dbEntry->objectId); + Actor_FreeOverlay(dbEntry); return NULL; } - actor = ZELDA_ARENA_MALLOC_DEBUG(actorInit->instanceSize); + actor = ZELDA_ARENA_MALLOC_DEBUG(dbEntry->instanceSize); if (actor == NULL) { // "Actor class cannot be reserved! %s " - osSyncPrintf(VT_COL(RED, WHITE) "Actorクラス確保できません! %s <サイズ=%dバイト>\n", VT_RST, name, - actorInit->instanceSize); - Actor_FreeOverlay(overlayEntry); + osSyncPrintf(VT_COL(RED, WHITE) "Actorクラス確保できません! %s <サイズ=%dバイト>\n", VT_RST, + dbEntry->name, dbEntry->instanceSize); + Actor_FreeOverlay(dbEntry); return NULL; } - ASSERT(overlayEntry->numLoaded < 255); + ASSERT(dbEntry->numLoaded < 255); - overlayEntry->numLoaded++; + dbEntry->numLoaded++; if (HREG(20) != 0) { // "Actor client No. %d" - osSyncPrintf("アクタークライアントは %d 個目です\n", overlayEntry->numLoaded); + osSyncPrintf("アクタークライアントは %d 個目です\n", dbEntry->numLoaded); } - memset((u8*)actor, 0, actorInit->instanceSize); - actor->overlayEntry = overlayEntry; - actor->id = actorInit->id; - actor->flags = actorInit->flags; + memset((u8*)actor, 0, dbEntry->instanceSize); + actor->id = dbEntry->id; + actor->flags = dbEntry->flags; - if (actorInit->id == ACTOR_EN_PART) { + if (dbEntry->id == ACTOR_EN_PART) { actor->objBankIndex = rotZ; rotZ = 0; } else { actor->objBankIndex = objBankIndex; } - actor->init = actorInit->init; - actor->destroy = actorInit->destroy; - actor->update = actorInit->update; - actor->draw = actorInit->draw; + actor->init = dbEntry->init; + actor->destroy = dbEntry->destroy; + actor->update = dbEntry->update; + actor->draw = dbEntry->draw; actor->room = play->roomCtx.curRoom.num; actor->home.pos.x = posX; actor->home.pos.y = posY; @@ -3304,7 +3198,7 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos actor->home.rot.z = rotZ; actor->params = params; - Actor_AddToCategory(actorCtx, actor, actorInit->category); + Actor_AddToCategory(actorCtx, actor, dbEntry->category); temp = gSegments[6]; Actor_Init(actor, play); @@ -3378,18 +3272,16 @@ Actor* Actor_SpawnEntry(ActorContext* actorCtx, ActorEntry* actorEntry, PlayStat } Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) { - char* name; Player* player; Actor* newHead; - ActorOverlay* overlayEntry; + ActorDBEntry* dbEntry; player = GET_PLAYER(play); - overlayEntry = actor->overlayEntry; - name = overlayEntry->name != NULL ? overlayEntry->name : ""; + dbEntry = ActorDB_Retrieve(actor->id); if (HREG(20) != 0) { - osSyncPrintf("アクタークラス削除 [%s]\n", name); // "Actor class deleted [%s]" + osSyncPrintf("アクタークラス削除 [%s]\n", dbEntry->name); // "Actor class deleted [%s]" } if ((player != NULL) && (actor == player->unk_664)) { @@ -3416,16 +3308,8 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) { ZELDA_ARENA_FREE_DEBUG(actor); - /* if (overlayEntry->vramStart == 0) { - if (HREG(20) != 0) { - osSyncPrintf("オーバーレイではありません\n"); // "Not an overlay" - } - } else { */ - //ASSERT(overlayEntry->loadedRamAddr != NULL, "actor_dlftbl->allocp != NULL"); - //ASSERT(overlayEntry->numLoaded > 0, "actor_dlftbl->clients > 0"); - overlayEntry->numLoaded--; - Actor_FreeOverlay(overlayEntry); - //} + dbEntry->numLoaded--; + Actor_FreeOverlay(dbEntry); return newHead; } diff --git a/soh/src/code/z_actor_dlftbls.c b/soh/src/code/z_actor_dlftbls.c deleted file mode 100644 index ee18d9703..000000000 --- a/soh/src/code/z_actor_dlftbls.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "global.h" - -// Linker symbol declarations (used in the table below) -#define DEFINE_ACTOR(name, _1, _2) DECLARE_OVERLAY_SEGMENT(name) -#define DEFINE_ACTOR_INTERNAL(_0, _1, _2) -#define DEFINE_ACTOR_UNSET(_0) - -#include "tables/actor_table.h" - -#undef DEFINE_ACTOR -#undef DEFINE_ACTOR_INTERNAL -#undef DEFINE_ACTOR_UNSET - -// Init Vars declarations (also used in the table below) -#define DEFINE_ACTOR(name, _1, _2) extern ActorInit name##_InitVars; -#define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern ActorInit name##_InitVars; -#define DEFINE_ACTOR_UNSET(_0) - -#include "tables/actor_table.h" - -#undef DEFINE_ACTOR -#undef DEFINE_ACTOR_INTERNAL -#undef DEFINE_ACTOR_UNSET - -// Actor Overlay Table definition -//#define DEFINE_ACTOR(name, _1, allocType) \ -// { (uintptr_t)_ovl_##name##SegmentRomStart, \ -// (uintptr_t)_ovl_##name##SegmentRomEnd, \ -// _ovl_##name##SegmentStart, \ -// _ovl_##name##SegmentEnd, \ -// NULL, \ -// &name##_InitVars, \ -// #name, \ -// allocType, \ -// 0 }, - -#define DEFINE_ACTOR_INTERNAL(name, _1, allocType) { 0, 0, NULL, NULL, NULL, &name##_InitVars, #name, allocType, 0 }, - -#define DEFINE_ACTOR_UNSET(_0) { 0 }, - -#define DEFINE_ACTOR(name, _1, allocType) { 0, 0, NULL, NULL, NULL, &name##_InitVars, #name, allocType, 0 }, - -ActorOverlay gActorOverlayTable[] = { -#include "tables/actor_table.h" -}; - -#undef DEFINE_ACTOR -#undef DEFINE_ACTOR_INTERNAL -#undef DEFINE_ACTOR_UNSET - -s32 gMaxActorId = 0; - -static FaultClient sFaultClient; - -void ActorOverlayTable_LogPrint(void) { - ActorOverlay* overlayEntry; - u32 i; - - osSyncPrintf("actor_dlftbls %u\n", gMaxActorId); - osSyncPrintf("RomStart RomEnd SegStart SegEnd allocp profile segname\n"); - - for (i = 0, overlayEntry = &gActorOverlayTable[0]; i < (u32)gMaxActorId; i++, overlayEntry++) { - osSyncPrintf("%08x %08x %08x %08x %08x %08x %s\n", overlayEntry->vromStart, overlayEntry->vromEnd, - overlayEntry->vramStart, overlayEntry->vramEnd, overlayEntry->loadedRamAddr, - &overlayEntry->initInfo->id, overlayEntry->name != NULL ? overlayEntry->name : "?"); - } -} - -void ActorOverlayTable_FaultPrint(void* arg0, void* arg1) { - ActorOverlay* overlayEntry; - u32 overlaySize; - s32 i; - - FaultDrawer_SetCharPad(-2, 0); - - FaultDrawer_Printf("actor_dlftbls %u\n", gMaxActorId); - FaultDrawer_Printf("No. RamStart- RamEnd cn Name\n"); - - for (i = 0, overlayEntry = &gActorOverlayTable[0]; i < gMaxActorId; i++, overlayEntry++) { - overlaySize = (uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart; - if (overlayEntry->loadedRamAddr != NULL) { - FaultDrawer_Printf("%3d %08x-%08x %3d %s\n", i, overlayEntry->loadedRamAddr, - (uintptr_t)overlayEntry->loadedRamAddr + overlaySize, overlayEntry->numLoaded, - overlayEntry->name != NULL ? overlayEntry->name : ""); - } - } -} - -void ActorOverlayTable_Init(void) { - gMaxActorId = ACTOR_ID_MAX; - Fault_AddClient(&sFaultClient, ActorOverlayTable_FaultPrint, NULL, NULL); -} - -void ActorOverlayTable_Cleanup(void) { - Fault_RemoveClient(&sFaultClient); - gMaxActorId = 0; -} diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 8c5ebb950..44e5442db 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -29,6 +29,8 @@ u64 D_801614D0[0xA00]; PlayState* gPlayState; +s16 gEnPartnerId; + void func_800BC450(PlayState* play) { Camera_ChangeDataIdx(GET_ACTIVE_CAM(play), play->unk_1242B - 1); } @@ -729,7 +731,7 @@ void Play_Init(GameState* thisx) { #endif if (CVarGetInteger("gIvanCoopModeEnabled", 0)) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PARTNER, GET_PLAYER(play)->actor.world.pos.x, + Actor_Spawn(&play->actorCtx, play, gEnPartnerId, GET_PLAYER(play)->actor.world.pos.x, GET_PLAYER(play)->actor.world.pos.y + Player_GetHeight(GET_PLAYER(play)) + 5.0f, GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1, true); } @@ -764,7 +766,6 @@ void Play_Update(PlayState* play) { if ((HREG(81) == 18) && (HREG(82) < 0)) { HREG(82) = 0; - ActorOverlayTable_LogPrint(); } if (CVarGetInteger("gFreeCamera", 0) && Player_InCsMode(play)) { diff --git a/soh/src/code/z_scene.c b/soh/src/code/z_scene.c index d975c08ab..63529e199 100644 --- a/soh/src/code/z_scene.c +++ b/soh/src/code/z_scene.c @@ -1,5 +1,6 @@ #include "global.h" #include "vt.h" +#include "soh/ActorDB.h" RomFile sNaviMsgFiles[]; @@ -193,7 +194,7 @@ void Scene_CommandSpawnList(PlayState* play, SceneCmd* cmd) { linkObjectId = gLinkObjectIds[((void)0, gSaveContext.linkAge)]; - gActorOverlayTable[linkEntry->id].initInfo->objectId = linkObjectId; + ActorDB_Retrieve(linkEntry->id)->objectId = linkObjectId; Object_Spawn(&play->objectCtx, linkObjectId); } diff --git a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c index 2b0cb0d6e..65c6a8cd7 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c +++ b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c @@ -33,7 +33,7 @@ void EnHeishi1_WaitNight(EnHeishi1* this, PlayState* play); s32 sHeishi1PlayerIsCaught = false; const ActorInit En_Heishi1_InitVars = { - 0, + ACTOR_EN_HEISHI1, ACTORCAT_NPC, FLAGS, OBJECT_SD, diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c index c7133f190..29c04b74a 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c @@ -20,19 +20,6 @@ void EnPartner_Update(Actor* thisx, PlayState* play); void EnPartner_Draw(Actor* thisx, PlayState* play); void EnPartner_SpawnSparkles(EnPartner* this, PlayState* play, s32 sparkleLife); -const ActorInit En_Partner_InitVars = { - ACTOR_EN_PARTNER, - ACTORCAT_ITEMACTION, - FLAGS, - OBJECT_GAMEPLAY_KEEP, - sizeof(EnPartner), - (ActorFunc)EnPartner_Init, - (ActorFunc)EnPartner_Destroy, - (ActorFunc)EnPartner_Update, - (ActorFunc)EnPartner_Draw, - NULL, -}; - static InitChainEntry sInitChain[] = { ICHAIN_VEC3F_DIV1000(scale, 8, ICHAIN_STOP), }; diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.h b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.h index 8e3e1cf20..0dc1da405 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.h +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.h @@ -45,4 +45,15 @@ typedef struct EnPartner { Actor* hookshotTarget; } EnPartner; +#ifdef __cplusplus +extern "C" { +#endif +void EnPartner_Init(Actor* thisx, PlayState* play); +void EnPartner_Destroy(Actor* thisx, PlayState* play); +void EnPartner_Update(Actor* thisx, PlayState* play); +void EnPartner_Draw(Actor* thisx, PlayState* play); +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file