summaryrefslogtreecommitdiff
path: root/src/toBeSorted/salvage_mgr.cpp
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2026-09-13 15:14:22 +0200
committerGitHub <noreply@github.com>2026-09-13 15:14:22 +0200
commit83a06ced84253a3136210f4d43f1e50f1f1303b2 (patch)
tree486b09ac0bb9da838dcb3b6cbbb1b1118118d00f /src/toBeSorted/salvage_mgr.cpp
parent9481f3ab62d690bd6534cb0adf7e02db5579b333 (diff)
parentae87d5a5b1f99fa73b3541f8d01dbdc51a99eb10 (diff)
Merge pull request #338 from robojumper/salvage_mgrHEADmain
Salvage mgr 99%
Diffstat (limited to 'src/toBeSorted/salvage_mgr.cpp')
-rw-r--r--src/toBeSorted/salvage_mgr.cpp451
1 files changed, 451 insertions, 0 deletions
diff --git a/src/toBeSorted/salvage_mgr.cpp b/src/toBeSorted/salvage_mgr.cpp
new file mode 100644
index 00000000..0a972c38
--- /dev/null
+++ b/src/toBeSorted/salvage_mgr.cpp
@@ -0,0 +1,451 @@
+
+#include "toBeSorted/salvage_mgr.h"
+
+#include "common.h"
+#include "d/d_sc_game.h"
+#include "d/flag/storyflag_manager.h"
+#include "toBeSorted/event_manager.h"
+
+dSalvageMgr_c *dSalvageMgr_c::sInstance;
+
+void dSalvageMgr_c::create() {
+ if (sInstance == nullptr) {
+ sInstance = new dSalvageMgr_c();
+ if (sInstance != nullptr) {
+ sInstance->init();
+ }
+ }
+}
+
+void dSalvageMgr_c::remove() {
+ delete sInstance;
+ sInstance = nullptr;
+}
+
+void dSalvageMgr_c::init() {
+ mCurrentPickupIdx = -1;
+ mCurrentPickupMaskBit = 0;
+ for (int i = 0; i < SALVAGE_OBJ_MAX; i++) {
+ s32 it = i;
+ if (!checkDeliveredStoryflag(it) && checkPickupStoryflag(it)) {
+ mCurrentPickupIdx = it;
+ mCurrentPickupMaskBit |= 1 << it;
+ }
+ }
+ field_0x2C = 10;
+ setupDeliverToTarget();
+}
+
+void dSalvageMgr_c::execute() {
+ handlePickupIndex();
+ setupDeliverToTarget();
+}
+
+void dSalvageMgr_c::handlePickupIndex() {
+ if (mCurrentPickupIdx != -1 && checkDeliveredStoryflag(mCurrentPickupIdx)) {
+ mCurrentPickupIdx = -1;
+ }
+
+ s32 target = -1;
+ for (int i = 0; i < SALVAGE_OBJ_MAX; i++) {
+ s32 it = i;
+ if (!checkDeliveredStoryflag(it) && checkPickupStoryflag(it)) {
+ // TODO instruction swap
+ if (target == -1 && it != mCurrentPickupIdx && !checkPickupMask(it)) {
+ target = it;
+ }
+ mCurrentPickupMaskBit |= 1 << it;
+ } else {
+ mCurrentPickupMaskBit &= ~(1 << it);
+ }
+ }
+
+ if (target != -1) {
+ setPickupIndex(target);
+ }
+}
+
+void dSalvageMgr_c::setupDeliverToTarget() {
+ if (checkIsOnDeliveryStage2() && field_0x2C > 0) {
+ // TODO wrong registers
+ if (!mDeliverToRef.isLinked() || mDeliverToRef.get()->mProfileName != getDeliverToActorId(mCurrentPickupIdx)) {
+ dAcObjBase_c *deliverTo = findDeliveryTarget();
+ if (deliverTo == nullptr) {
+ mDeliverToRef.unlink();
+ field_0x2C = field_0x2C - 1 < 0 ? 0 : field_0x2C - 1;
+ } else {
+ mDeliverToRef.link(deliverTo);
+ field_0x2C = 10;
+ }
+ }
+ } else {
+ mDeliverToRef.unlink();
+ }
+}
+
+struct SalvageMgrObjTransform {
+ ~SalvageMgrObjTransform() {}
+
+ /* 0x00 */ mVec3_c offset;
+ /* 0x0C */ mAng3_c rotation;
+};
+
+#define deg_ang(x, y, z) mAng3_c(mAng::fromDeg(x), mAng::fromDeg(y), mAng::fromDeg(z))
+
+static const SalvageMgrObjTransform sTransforms[SALVAGE_OBJ_MAX] = {
+ { mVec3_c(29.22f, 4.51f, -46.36f), deg_ang(81.83f, 56.65f, -12.683f)},
+ { mVec3_c(37.05f, -65.41f, -10.07f), deg_ang(4.149f, 21.983f, 134.444f)},
+ {mVec3_c(-28.28f, -27.73f, -5.12f), deg_ang(16.224f, 5.528f, -73.192f)},
+ { mVec3_c(-44.5f, -37.32f, -7.17f), deg_ang(4.237f, 15.61f, -90.026f)},
+ {mVec3_c(-26.64f, -8.95f, -95.21f), deg_ang(83.418f, 19.082f, -73.081f)},
+ {mVec3_c(-97.98f, -194.72f, 0.119f), deg_ang(-1.184f, 1.26f, -52.992f)},
+ {mVec3_c(-97.98f, -194.72f, 0.119f), deg_ang(-1.184f, 1.26f, -52.992f)},
+};
+
+#undef deg_ang
+
+struct SalvageMgrObjDef {
+ /* 0x00 */ u16 profileId;
+ /* 0x02 */ u16 deliverToProfileId;
+ /* 0x04 */ const char *fayCallEvnt;
+ /* 0x08 */ const char *deliveryEvnt;
+ /* 0x0C */ const char *postDeliveryEvnt;
+ /* 0x10 */ const char *stage;
+ /* 0x14 */ s32 questStartedStoryflag;
+ /* 0x18 */ s32 pickedUpStoryFlag;
+ /* 0x1C */ s32 additionalPickupUnsetFlag;
+ /* 0x20 */ s32 deliveredStoryflag;
+};
+
+// TODO - the docs for the plant species flags might be wrong
+// clang-format off
+static const SalvageMgrObjDef sDefs[SALVAGE_OBJ_MAX] = {
+ { fProfile::OBJ_PROPERA, fProfile::NPC_SORAJIMA_FATHER, "SalbageFayCall", "DelivaryPropera", "RepearPropera", "F000", STORYFLAG_SCRAPPER_UNLOCKED, STORYFLAG_PROPERA_PICKUP, -1, STORYFLAG_WINDMILL_REPAIRED },
+ { fProfile::OBJ_ROULETTE, fProfile::NPC_DIVE_GAME_JUDGE, "SalbageFayCall", "DelivaryRoulette", "DefaultTalk", "F020", STORYFLAG_PARTY_WHEEL_QUEST_STARTED, STORYFLAG_PARTY_WHEEL_PICKUP, -1, STORYFLAG_PARTY_WHEEL_DELIVERED },
+ {fProfile::OBJ_DIVINER_CRYSTAL, fProfile::NPC_SHA, "SalbageFayCall", "DelivarySuisho", "DefaultTalk", "F013r", STORYFLAG_CRYSTAL_QUEST_STARTED, STORYFLAG_CRYSTAL_PICKUP, -1, STORYFLAG_CRYSTAL_DELIVERED },
+ { fProfile::NPC_SALBAGE_MORRY, fProfile::NPC_SKN, "SalbageFayCall", "DelivaryKyui", "RepearPropera", "F001r", STORYFLAG_PLANT_SPECIES_QUEST_STARTED, STORYFLAG_480, -1, STORYFLAG_481 },
+ { fProfile::NPC_MOLE_ELDER, fProfile::NPC_PDU, "SalbageFayCall", "DelivaryMole", "DefaultTalk", "F020", STORYFLAG_MOLE_ELDER_QUEST_STARTED, STORYFLAG_MOLE_ELDER_PICKUP, -1, STORYFLAG_MOLE_ELDER_DELIVERED },
+ { fProfile::OBJ_WATER_JAR, fProfile::NPC_SORAJIMA_FATHER, "SalbageFayCall", "DelivaryPot", "DefaultTalk", "F000", STORYFLAG_WATER_BASIN_QUEST_STARTED, STORYFLAG_SCRAPPER_HAS_WATER_BASIN, -1, STORYFLAG_SUMMIT_BIG_FROG_WATERED },
+ { fProfile::OBJ_POT_SAL, fProfile::NPC_SORAJIMA_FATHER, "SalbageFayCall", "DelivaryPumpPot", "DefaultTalk", "F023", STORYFLAG_SPIRAL_CHARGE_UNLOCKED, STORYFLAG_PUMPKIN_SOUP_PICKUP, -1, STORYFLAG_LEVIAS_FIGHT_STARTED },
+};
+// clang-format on
+
+struct SalvageMgrObjEntrypoints {
+ /* 0x00 */ u16 talkEntrypoint1;
+ /* 0x02 */ u16 talkEntrypoint2;
+ /* 0x04 */ u16 talkEntrypoint3;
+ /* 0x06 */ u16 talkEntrypoint4; // unused
+};
+
+// clang-format off
+static const SalvageMgrObjEntrypoints sEntrypoints[SALVAGE_OBJ_MAX] = {
+ {
+ 51001, // 510_01: This is the Windmill Propeller...
+ 51004, // 510_04: Master, I suggest that we also return...
+ 51005, // 510_05: Hey! Master Shortpants! You're in my may...
+ 11818, // 118_18: Here's that windmill propeller, zzzazt!
+ },
+ {
+ 45101, // 451_01: I have identified the item that the... highly unusual man...
+ 45104, // 451_04: Master, I suggest that we also return...
+ 45105, // 451_05: OK, OK, zrrft... You just sit tight there
+ 11005, // 110_05: Here's your wheel thing, bzzzrrrt!
+ },
+ {
+ 35101, // 351_01: I have located a substance that closely resembles...
+ 35104, // 351_04: Master, I suggest we also return...
+ 35105, // 351_05: Hey, Master Shortpants! How come...
+ 11820, // 118_20: Here's that bright and shiny crystal ball, BZZAT!
+ },
+ {
+ 25106, // 251_06: I can verify with only 40% accuracy that this person is a plant...
+ 25104, // 251_04: Master, I suggest we also return...
+ 25105, // 251_05: Move it! Move it! Zrrppt! Forcing me...
+ 11821, // 118_21: I have come bearing the unusual Kikwi...
+ },
+ {
+ 51001, // (?) 510_01: This is the Windmill Propeller...
+ 35111, // 351_11: Master, I suggest that we also return...
+ 35112, // 351_12: You don't have to tell me twice, zrrbt!
+ 11820, // (?) 118_20: Here's that bright and shiny crystal ball, BZZAT!
+ },
+ {
+ 51001, // (?) 510_01: This is the Windmill Propeller...
+ -1, // <nothing>
+ -1, // <nothing>
+ 11790, // Does not exist?
+ },
+ {
+ 51001, // (?) 510_01: This is the Windmill Propeller...
+ -1, // <nothing>
+ -1, // <nothing>
+ 12020, // 120_20: I'm unloading this cargo of pumpkin soup...
+ },
+};
+// clang-format off
+
+mMtx_c dSalvageMgr_c::getCarryRotMtx(const s32 &id) const {
+ SalvageMgrObjTransform tf = sTransforms[id];
+ mMtx_c result;
+ result.transS(tf.offset);
+ result.ZYXrotM(tf.rotation);
+ return result;
+}
+
+void dSalvageMgr_c::setPickupIndex(const s32 &id) {
+ for (int i = 0; i < SALVAGE_OBJ_MAX; i++) {
+ if (i != id) {
+ unsetPickupStoryflag(i);
+ }
+ }
+
+ if (!checkDeliveredStoryflag(id)) {
+ mCurrentPickupIdx = id;
+ }
+}
+
+void dSalvageMgr_c::deleteObjAndSlb() {
+ dAcObjBase_c *slb = mSlbRef.get();
+ dAcObjBase_c *obj = mObjRef.get();
+
+ if (obj != nullptr) {
+ obj->deleteRequest();
+ }
+ if (slb != nullptr) {
+ slb->deleteRequest();
+ }
+}
+
+bool dSalvageMgr_c::checkIsOnDeliveryStage2() const {
+ if (mCurrentPickupIdx == -1) {
+ return false;
+ }
+ return checkIsOnDeliveryStage();
+}
+
+bool dSalvageMgr_c::hasStartedQuestForSalvageObj(const dAcSalbageObj_c *obj) const {
+ s32 id = obj->getSalvageIf()->getSalvageObjId();
+ if (id < 0) {
+ return false;
+ }
+ s32 it = id;
+ return hasStartedQuestForId(it);
+}
+
+bool dSalvageMgr_c::hasStartedQuestForId(const s32 &id) const {
+ if (id == -1) {
+ return false;
+ } else if (sDefs[id].questStartedStoryflag == -1) {
+ return false;
+ } else {
+ return StoryflagManager::sInstance->getFlag(sDefs[id].questStartedStoryflag) != 0;
+ }
+}
+
+bool dSalvageMgr_c::hasDowsingForSalvageObj(const dAcSalbageObj_c *obj) const {
+ s32 id = obj->getSalvageIf()->getSalvageObjId();
+ if (id < 0) {
+ return false;
+ }
+ s32 it = id;
+ return hasDowsingForId(it);
+}
+
+bool dSalvageMgr_c::hasDowsingForId(const s32 &id) const {
+ if (id == -1) {
+ return false;
+ } else if (checkDeliveredStoryflag(id)) {
+ return false;
+ } else {
+ bool ret = false;
+ switch (id) {
+ case SALVAGE_OBJ_PROPERA: {
+ ret = DowsingTarget::hasPropellerDowsing();
+ break;
+ }
+ case SALVAGE_OBJ_ROULETTE: {
+ ret = DowsingTarget::hasPartyWheelDowsing();
+ break;
+ }
+ case SALVAGE_OBJ_DIVINER_CRYSTAL: {
+ ret = DowsingTarget::hasCrystalBallDowsing();
+ break;
+ }
+ case SALVAGE_OBJ_SALVAGE_MORRY: {
+ ret = DowsingTarget::hasNewPlantSpeciesDowsing();
+ break;
+ }
+ case SALVAGE_OBJ_MOLE_ELDER: {
+ ret = DowsingTarget::hasPumpkinDowsing();
+ break;
+ }
+ case SALVAGE_OBJ_WATER_JAR: {
+ ret = DowsingTarget::hasWaterBasinDowsing();
+ break;
+ }
+ }
+ return ret;
+ }
+}
+
+u16 dSalvageMgr_c::getDeliverToActorId(s32 id) {
+ return sDefs[id].deliverToProfileId;
+}
+
+void dSalvageMgr_c::noop() {}
+
+s32 dSalvageMgr_c::getCurrentSalvageObjId() const {
+ return mCurrentPickupIdx;
+}
+
+bool dSalvageMgr_c::checkDeliveredStoryflag(const s32 &id) const {
+ if (id == -1) {
+ return false;
+ } else if (sDefs[id].deliveredStoryflag == -1) {
+ return false;
+ } else {
+ return StoryflagManager::sInstance->getFlag(sDefs[id].deliveredStoryflag) != 0;
+ }
+}
+
+void dSalvageMgr_c::unsetPickupStoryflag(const s32 &id) {
+ if (id == -1) {
+ return;
+ } else if (checkDeliveredStoryflag(id)) {
+ return;
+ } else {
+ // TODO - ???
+ s32 alsoUnsetFlag = sDefs[id].additionalPickupUnsetFlag;
+ if (sDefs[id].pickedUpStoryFlag != -1) {
+ StoryflagManager::sInstance->unsetFlag(sDefs[id].pickedUpStoryFlag);
+ }
+ if (alsoUnsetFlag != -1) {
+ StoryflagManager::sInstance->unsetFlag(sDefs[id].additionalPickupUnsetFlag);
+ }
+ }
+}
+
+bool dSalvageMgr_c::checkPickupStoryflag(const s32 &id) const {
+ if (id == -1) {
+ return false;
+ } else if (sDefs[id].pickedUpStoryFlag == -1) {
+ return false;
+ } else {
+ return StoryflagManager::sInstance->getFlag(sDefs[id].pickedUpStoryFlag) != 0;
+ }
+}
+
+bool dSalvageMgr_c::checkIsOnDeliveryStage() const {
+ if (mCurrentPickupIdx >= 0 && dScGame_c::currentSpawnInfo.stageName == sDefs[mCurrentPickupIdx].stage) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+dAcObjBase_c *dSalvageMgr_c::findDeliveryTarget() {
+ if (mDeliverToRef.isLinked()) {
+ return mDeliverToRef.get();
+ } else if (mCurrentPickupIdx == -1) {
+ return nullptr;
+ } else {
+ return (dAcObjBase_c *)fManager_c::searchBaseByProfName(
+ (ProfileName)sDefs[mCurrentPickupIdx].deliverToProfileId, nullptr
+ );
+ }
+}
+
+bool dSalvageMgr_c::triggerDeliveryEvent() {
+ if (mCurrentPickupIdx == -1) {
+ return false;
+ } else {
+ dAcNpcSlb_c *slb = mSlbRef.get();
+ dAcSalbageObj_c *obj = mObjRef.get();
+ dAcObjBase_c *deliverTo = mDeliverToRef.get();
+ if (slb == nullptr || obj == nullptr || deliverTo == nullptr) {
+ return false;
+ } else {
+ Event ev(sDefs[mCurrentPickupIdx].deliveryEvnt, 100, 0x100001, nullptr, nullptr);
+ EventManager::alsoSetAsCurrentEvent(slb, &ev, deliverTo);
+ return true;
+ }
+ }
+}
+
+u16 dSalvageMgr_c::getTalkEntryPoint1ForPickup(dAcObjBase_c *obj) {
+ SalvageObj_e id = SALVAGE_OBJ_NONE;
+ if (obj != nullptr) {
+ if (obj->mProfileName == fProfile::OBJ_PROPERA) {
+ id = SALVAGE_OBJ_PROPERA;
+ } else if (obj->mProfileName == fProfile::OBJ_ROULETTE) {
+ id = SALVAGE_OBJ_ROULETTE;
+ } else if (obj->mProfileName == fProfile::OBJ_DIVINER_CRYSTAL) {
+ id = SALVAGE_OBJ_DIVINER_CRYSTAL;
+ } else if (obj->mProfileName == fProfile::NPC_SALBAGE_MORRY) {
+ id = SALVAGE_OBJ_SALVAGE_MORRY;
+ } else if (obj->mProfileName == fProfile::NPC_MOLE_ELDER) {
+ id = SALVAGE_OBJ_MOLE_ELDER;
+ } else if (obj->mProfileName == fProfile::OBJ_WATER_JAR) {
+ id = SALVAGE_OBJ_WATER_JAR;
+ } else {
+ id = SALVAGE_OBJ_PROPERA;
+ }
+ }
+
+ if (id == SALVAGE_OBJ_NONE) {
+ return -1;
+ }
+ return sEntrypoints[id].talkEntrypoint1;
+}
+
+u16 dSalvageMgr_c::getTalkEntryPoint2ForPickup(dAcObjBase_c *obj) {
+ SalvageObj_e id = SALVAGE_OBJ_NONE;
+ if (obj != nullptr) {
+ if (obj->mProfileName == fProfile::OBJ_PROPERA) {
+ id = SALVAGE_OBJ_PROPERA;
+ } else if (obj->mProfileName == fProfile::OBJ_ROULETTE) {
+ id = SALVAGE_OBJ_ROULETTE;
+ } else if (obj->mProfileName == fProfile::OBJ_DIVINER_CRYSTAL) {
+ id = SALVAGE_OBJ_DIVINER_CRYSTAL;
+ } else if (obj->mProfileName == fProfile::NPC_SALBAGE_MORRY) {
+ id = SALVAGE_OBJ_SALVAGE_MORRY;
+ } else if (obj->mProfileName == fProfile::NPC_MOLE_ELDER) {
+ id = SALVAGE_OBJ_MOLE_ELDER;
+ } else if (obj->mProfileName == fProfile::OBJ_WATER_JAR) {
+ id = SALVAGE_OBJ_WATER_JAR;
+ } else {
+ id = SALVAGE_OBJ_PROPERA;
+ }
+ }
+
+ if (id == SALVAGE_OBJ_NONE) {
+ return -1;
+ }
+ return sEntrypoints[id].talkEntrypoint2;
+}
+
+u16 dSalvageMgr_c::getTalkEntryPoint3ForPickup(dAcObjBase_c *obj) {
+ SalvageObj_e id = SALVAGE_OBJ_NONE;
+ if (obj != nullptr) {
+ if (obj->mProfileName == fProfile::OBJ_PROPERA) {
+ id = SALVAGE_OBJ_PROPERA;
+ } else if (obj->mProfileName == fProfile::OBJ_ROULETTE) {
+ id = SALVAGE_OBJ_ROULETTE;
+ } else if (obj->mProfileName == fProfile::OBJ_DIVINER_CRYSTAL) {
+ id = SALVAGE_OBJ_DIVINER_CRYSTAL;
+ } else if (obj->mProfileName == fProfile::NPC_SALBAGE_MORRY) {
+ id = SALVAGE_OBJ_SALVAGE_MORRY;
+ } else if (obj->mProfileName == fProfile::NPC_MOLE_ELDER) {
+ id = SALVAGE_OBJ_MOLE_ELDER;
+ } else if (obj->mProfileName == fProfile::OBJ_WATER_JAR) {
+ id = SALVAGE_OBJ_WATER_JAR;
+ } else {
+ id = SALVAGE_OBJ_PROPERA;
+ }
+ }
+
+ if (id == SALVAGE_OBJ_NONE) {
+ return -1;
+ }
+ return sEntrypoints[id].talkEntrypoint3;
+}