From d29c7c377e2808686d915992ef149a8652009e98 Mon Sep 17 00:00:00 2001 From: Aetias Date: Thu, 29 May 2025 12:24:19 +0200 Subject: [PATCH] `ActorSpawner` 99% --- config/eur/arm9/overlays/ov000/delinks.txt | 3 + config/eur/arm9/overlays/ov000/symbols.txt | 2 +- config/usa/arm9/overlays/ov000/delinks.txt | 3 + config/usa/arm9/overlays/ov000/symbols.txt | 2 +- include/Actor/Actor.hpp | 7 +- include/Actor/ActorSpawner.hpp | 19 +++- src/00_Core/Actor/ActorSpawner.cpp | 104 +++++++++++++++++++-- 7 files changed, 123 insertions(+), 17 deletions(-) diff --git a/config/eur/arm9/overlays/ov000/delinks.txt b/config/eur/arm9/overlays/ov000/delinks.txt index 4e7c7c37..5ef9d228 100644 --- a/config/eur/arm9/overlays/ov000/delinks.txt +++ b/config/eur/arm9/overlays/ov000/delinks.txt @@ -16,6 +16,9 @@ src/00_Core/Actor/ActorManager.cpp: .text start:0x020c33d4 end:0x020c3e54 .data start:0x020e72a8 end:0x020e72f4 +src/00_Core/Actor/ActorSpawner.cpp: + .text start:0x020c3f9c end:0x020c42d8 + src/00_Core/Actor/Dungeon/ActorSwitchObject.cpp: .text start:0x0208fa70 end:0x020903a8 .init start:0x020df678 end:0x020df6b8 diff --git a/config/eur/arm9/overlays/ov000/symbols.txt b/config/eur/arm9/overlays/ov000/symbols.txt index 7748f1a0..4d1e7b98 100644 --- a/config/eur/arm9/overlays/ov000/symbols.txt +++ b/config/eur/arm9/overlays/ov000/symbols.txt @@ -2868,7 +2868,7 @@ _ZN12ActorSpawnerD1Ev kind:function(arm,size=0x4) addr:0x20c4010 _ZN12ActorSpawner19func_ov000_020c4014Ev kind:function(arm,size=0x4) addr:0x20c4014 _ZN12ActorSpawner19func_ov000_020c4018Ev kind:function(arm,size=0x4) addr:0x20c4018 _ZN12ActorSpawner11CreateActorEj kind:function(arm,size=0x2c) addr:0x20c401c -_ZN12ActorSpawner5SpawnEjP5Vec3pPvP8ActorRef kind:function(arm,size=0x290) addr:0x20c4048 +_ZN12ActorSpawner5SpawnEjP5Vec3pP17ActorSpawnOptionsP8ActorRef kind:function(arm,size=0x290) addr:0x20c4048 func_ov000_020c42d8 kind:function(arm,size=0x14) addr:0x20c42d8 func_ov000_020c42ec kind:function(arm,size=0x30) addr:0x20c42ec func_ov000_020c431c kind:function(arm,size=0x6c) addr:0x20c431c diff --git a/config/usa/arm9/overlays/ov000/delinks.txt b/config/usa/arm9/overlays/ov000/delinks.txt index d0fd0130..5d8f5cc3 100644 --- a/config/usa/arm9/overlays/ov000/delinks.txt +++ b/config/usa/arm9/overlays/ov000/delinks.txt @@ -16,6 +16,9 @@ src/00_Core/Actor/ActorManager.cpp: .text start:0x020c3374 end:0x020c3df4 .data start:0x020e7248 end:0x020e7294 +src/00_Core/Actor/ActorSpawner.cpp: + .text start:0x020c3f3c end:0x020c4278 + src/00_Core/Actor/Dungeon/ActorSwitchObject.cpp: .text start:0x0208fa10 end:0x02090348 .init start:0x020df618 end:0x020df658 diff --git a/config/usa/arm9/overlays/ov000/symbols.txt b/config/usa/arm9/overlays/ov000/symbols.txt index d8d0c8c9..6d11f24b 100644 --- a/config/usa/arm9/overlays/ov000/symbols.txt +++ b/config/usa/arm9/overlays/ov000/symbols.txt @@ -2868,7 +2868,7 @@ _ZN12ActorSpawnerD1Ev kind:function(arm,size=0x4) addr:0x20c3fb0 _ZN12ActorSpawner19func_ov000_020c4014Ev kind:function(arm,size=0x4) addr:0x20c3fb4 _ZN12ActorSpawner19func_ov000_020c4018Ev kind:function(arm,size=0x4) addr:0x20c3fb8 _ZN12ActorSpawner11CreateActorEj kind:function(arm,size=0x2c) addr:0x20c3fbc -_ZN12ActorSpawner5SpawnEjP5Vec3pPvP8ActorRef kind:function(arm,size=0x290) addr:0x20c3fe8 +_ZN12ActorSpawner5SpawnEjP5Vec3pP17ActorSpawnOptionsP8ActorRef kind:function(arm,size=0x290) addr:0x20c3fe8 func_ov000_020c42d8 kind:function(arm,size=0x14) addr:0x20c4278 func_ov000_020c42ec kind:function(arm,size=0x30) addr:0x20c428c func_ov000_020c431c kind:function(arm,size=0x6c) addr:0x20c42bc diff --git a/include/Actor/Actor.hpp b/include/Actor/Actor.hpp index f82d34ab..4d40a080 100644 --- a/include/Actor/Actor.hpp +++ b/include/Actor/Actor.hpp @@ -35,8 +35,8 @@ struct Actor_UnkStruct_020 { /* 08 */ u8 mUnk_08[2]; /* 0a */ u8 mUnk_0a[2]; /* 0c */ unk8 mUnk_0c; - /* 0d */ unk8 mUnk_0d; - /* 0e */ unk8 mUnk_0e; + /* 0d */ u8 mUnk_0d; + /* 0e */ u8 mUnk_0e; /* 0f */ unk8 mUnk_0f; /* 10 */ unk32 mUnk_10; /* 14 */ @@ -110,8 +110,7 @@ public: /* 012 */ unk16 mUnk_012; /* 014 */ Vec3p mUnk_014; /* 020 */ Actor_UnkStruct_020 mUnk_020; - /* 034 */ unk32 mUnk_034; - /* 038 */ unk32 mUnk_038; + /* 034 */ ActorRef mUnk_034; /* 03c */ unk32 mUnk_03c; /* 040 */ ActorRef mUnk_040; /* 048 */ Vec3p mPos; diff --git a/include/Actor/ActorSpawner.hpp b/include/Actor/ActorSpawner.hpp index 94047e10..e99bafb3 100644 --- a/include/Actor/ActorSpawner.hpp +++ b/include/Actor/ActorSpawner.hpp @@ -5,10 +5,23 @@ #include "global.h" #include "types.h" +#include "Actor/Actor.hpp" #include "Actor/ActorRef.hpp" #include "Actor/ActorType.hpp" +#include "System/SysNew.hpp" -class ActorSpawner { +struct ActorSpawnOptions { + /* 00 */ Actor_UnkStruct_020 mUnk_00; + /* 14 */ s16 mAngle; + /* 16 */ unk8 mUnk_16[0x2]; + /* 18 */ unk32 mUnk_18; + /* 1c */ ActorRef mUnk_1c; + /* 24 */ unk32 mUnk_24; + /* 28 */ unk32 mUnk_28; + /* 2c */ +}; + +class ActorSpawner : public SysObject { public: /* 0 (empty) */ @@ -18,8 +31,8 @@ public: ~ActorSpawner(); void func_ov000_020c4014(); void func_ov000_020c4018(); - Actor *CreateActor(ActorTypeId type); - s32 Spawn(ActorTypeId type, Vec3p *pos, void *param3, ActorRef *ref); + Actor *CreateActor(ActorTypeId typeId); + s32 Spawn(ActorTypeId type, Vec3p *pos, ActorSpawnOptions *param3, ActorRef *ref); }; extern ActorSpawner *gActorSpawner; diff --git a/src/00_Core/Actor/ActorSpawner.cpp b/src/00_Core/Actor/ActorSpawner.cpp index 76b4ae74..c23babf2 100644 --- a/src/00_Core/Actor/ActorSpawner.cpp +++ b/src/00_Core/Actor/ActorSpawner.cpp @@ -1,10 +1,98 @@ #include "Actor/ActorSpawner.hpp" +#include "Actor/ActorManager.hpp" +#include "Map/MapManager.hpp" -ActorSpawner *ActorSpawner::Create() {} -void ActorSpawner::Destroy() {} -ActorSpawner::ActorSpawner() {} -ActorSpawner::~ActorSpawner() {} -void ActorSpawner::func_ov000_020c4014() {} -void ActorSpawner::func_ov000_020c4018() {} -Actor *ActorSpawner::CreateActor(ActorTypeId type) {} -s32 ActorSpawner::Spawn(ActorTypeId type, Vec3p *pos, void *param3, ActorRef *ref) {} +extern u32 *data_027e0ce0[]; +ARM ActorSpawner *ActorSpawner::Create() { + gActorSpawner = new(data_027e0ce0[1], 4) ActorSpawner(); +} + +ARM void ActorSpawner::Destroy() { + delete gActorSpawner; + gActorSpawner = NULL; +} + +ARM ActorSpawner::ActorSpawner() {} + +ARM ActorSpawner::~ActorSpawner() {} + +ARM void ActorSpawner::func_ov000_020c4014() {} + +ARM void ActorSpawner::func_ov000_020c4018() {} + +ARM Actor *ActorSpawner::CreateActor(ActorTypeId typeId) { + Actor *actor = NULL; + ActorType *type = ActorType::Find(typeId); + if (type != NULL) { + actor = type->create(); + } + return actor; +} + +extern "C" unk32 GetCardinal(s16 angle); +ARM s32 ActorSpawner::Spawn(ActorTypeId type, Vec3p *pos, ActorSpawnOptions *options, ActorRef *ref) { + ActorManager *actorManager = gActorManager; + u16 maxActors = actorManager->mMaxActors; + Actor **actorSlot = actorManager->mActorTable; + ActorRef actorRef; + actorRef.id = -1; + for (actorRef.index = 0; actorRef.index < maxActors; actorRef.index++, actorSlot++) { + if (*actorSlot != NULL) { + continue; + } + + Actor *actor = this->CreateActor(type); + *actorSlot = actor; + if (actor == NULL) { + if (ref != NULL) { + ref->Reset(); + } + return -1; + } + actor->mType = type; + (*actorSlot)->mRef.id = actorManager->mNextActorId; + (*actorSlot)->mRef.index = actorRef.index; + (*actorSlot)->mUnk_014 = *pos; + (*actorSlot)->mUnk_020 = options->mUnk_00; + (*actorSlot)->mAngle = options->mAngle; + (*actorSlot)->mUnk_012 = options->mAngle; + (*actorSlot)->mUnk_074 = GetCardinal(options->mAngle); + if (options->mUnk_18 >= 0xffff) { + (*actorSlot)->mUnk_03c = -1; + } else { + (*actorSlot)->mUnk_03c = options->mUnk_18; + } + (*actorSlot)->mUnk_034 = options->mUnk_1c; + (*actorSlot)->mUnk_140 = options->mUnk_24; + (*actorSlot)->mUnk_144 = options->mUnk_28; + Actor *actor2 = *actorSlot; + actor2->mPos = *pos; + actor2->mPrevPos = *pos; + (*actorSlot)->mUnk_010 = gMapManager->GetCourseData_Unk_1c(); + (*actorSlot)->mUnk_011 = gMapManager->GetCourseData_Unk_1d(); + u16 nextIndex = actorRef.index + 1; + if (actorManager->mMaxActorIndex < nextIndex) { + actorManager->mMaxActorIndex = nextIndex; + } + actorManager->mCacheEmptyActorIndex = actorRef.index; + + actorRef.id = actorManager->mNextActorId; + if (ref != NULL) { + *ref = actorRef; + } + actorManager->mNextActorId += 1; + actorManager->mNumActors += 1; + if (!(*actorSlot)->vfunc_08()) { + (*actorSlot)->mAlive = false; + if (ref != NULL) { + ref->Reset(); + } + return -1; + } + break; + } + if ((actorRef.id == -1) && (ref != NULL)) { + ref->Reset(); + } + return actorRef.id; +}