summaryrefslogtreecommitdiff
path: root/src/toBeSorted/dowsing_target.cpp
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2024-09-12 22:23:11 +0200
committerGitHub <noreply@github.com>2024-09-12 16:23:11 -0400
commite2c4bb7be7fa731a335bce4bc22283d899133e39 (patch)
tree91152d84cae384b376f4ce4c87e9e247255ec954 /src/toBeSorted/dowsing_target.cpp
parent9aa30ee4995be938e1ea05f6d476d63fcb8cc67e (diff)
Dowsing (#17)
* Dowsing. * d_t_dowsing * d_t_holy_water OK
Diffstat (limited to 'src/toBeSorted/dowsing_target.cpp')
-rw-r--r--src/toBeSorted/dowsing_target.cpp272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/toBeSorted/dowsing_target.cpp b/src/toBeSorted/dowsing_target.cpp
new file mode 100644
index 00000000..84eea947
--- /dev/null
+++ b/src/toBeSorted/dowsing_target.cpp
@@ -0,0 +1,272 @@
+#include <c/c_math.h>
+#include <m/m_mtx.h>
+#include <nw4r/ut/ut_LinkList.h>
+#include <toBeSorted/dowsing_target.h>
+#include <toBeSorted/item_story_flag_manager.h>
+#include <toBeSorted/tlist.h>
+
+typedef TList<DowsingTarget, 0> DowsingList;
+
+DowsingList DOWSING_LISTS[8];
+
+static const int DOWSING_TARGET_STORY_FLAGS[8] = {
+ 100,
+ 105,
+ 100,
+ 104,
+ 108,
+ 110,
+ 109,
+ 102,
+};
+
+DowsingTarget::~DowsingTarget() {
+ doUnregister();
+}
+
+void DowsingTarget::initialize(DowsingSlot type, u16 unk, const mVec3_c *offset, f32 unk2) {
+ reinitialize(type);
+ field_0x0E = unk;
+ if (offset != nullptr) {
+ mOffset = *offset;
+ }
+}
+
+static bool insertDowsingTarget(DowsingTarget *target);
+static bool removeDowsingTarget(DowsingTarget *target);
+
+bool DowsingTarget::doRegister() {
+ return insertDowsingTarget(this);
+}
+
+bool DowsingTarget::doUnregister() {
+ return removeDowsingTarget(this);
+}
+
+void DowsingTarget::reinitialize(DowsingSlot type) {
+ bool res = doUnregister();
+ mDowsingSlot = type;
+ if (res) {
+ doRegister();
+ }
+}
+
+void DowsingTarget::getPosition(mVec3_c &position) {
+ mMtx_c mtx;
+ mMtx_c mtx2;
+ PSMTXTrans(mtx.m, mpActor->position.x, mpActor->position.y, mpActor->position.z);
+ mtx.YrotM(mpActor->rotation.y);
+ PSMTXScale(mtx2.m, mpActor->scale.x, mpActor->scale.y, mpActor->scale.z);
+ PSMTXConcat(mtx.m, mtx2.m, mtx.m);
+ PSMTXMultVec(mtx.m, mOffset, position);
+}
+
+bool DowsingTarget::hasZeldaDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(100);
+}
+
+bool DowsingTarget::hasKikwiDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(56) && !StoryFlagManager::sInstance->getCounterOrFlag(57);
+}
+
+bool DowsingTarget::hasKeyPieceDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(106) && !StoryFlagManager::sInstance->getCounterOrFlag(120);
+}
+
+bool DowsingTarget::hasDesertNodeDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(107) && !StoryFlagManager::sInstance->getCounterOrFlag(8);
+}
+
+bool DowsingTarget::hasAnyTrialDowsing() {
+ // TODO more complicated code
+ return ItemFlagManager::sInstance->getFlag(187) && !StoryFlagManager::sInstance->getCounterOrFlag(93) ||
+ ItemFlagManager::sInstance->getFlag(188) && !StoryFlagManager::sInstance->getCounterOrFlag(97) ||
+ ItemFlagManager::sInstance->getFlag(189) && !StoryFlagManager::sInstance->getCounterOrFlag(98) ||
+ ItemFlagManager::sInstance->getFlag(193) && !StoryFlagManager::sInstance->getCounterOrFlag(99);
+}
+
+bool DowsingTarget::hasSacredWaterDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(64) && !StoryFlagManager::sInstance->getCounterOrFlag(65);
+}
+
+bool DowsingTarget::hasSandshipDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(271) && !StoryFlagManager::sInstance->getCounterOrFlag(14);
+}
+
+bool DowsingTarget::hasTadtoneDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(81) && !StoryFlagManager::sInstance->getCounterOrFlag(18);
+}
+
+bool DowsingTarget::hasPropellerDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(668);
+}
+
+bool DowsingTarget::hasWaterBasinDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(669);
+}
+
+bool DowsingTarget::hasCrystalBallDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(670);
+}
+
+bool DowsingTarget::hasPumpkinDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(680);
+}
+
+bool DowsingTarget::hasNewPlantSpeciesDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(681);
+}
+
+bool DowsingTarget::hasPartyWheelDowsing() {
+ return StoryFlagManager::sInstance->getCounterOrFlag(682);
+}
+
+bool DowsingTarget::hasDowsingInSlot(int slot) {
+ if (slot >= 8) {
+ return false;
+ }
+
+ if (slot == 6) {
+ return true;
+ }
+
+ if (slot == 0) {
+ return hasZeldaDowsing() || hasAnyTrialDowsing() || hasSacredWaterDowsing() || hasSandshipDowsing() ||
+ hasTadtoneDowsing() || hasPropellerDowsing() || hasWaterBasinDowsing();
+ } else if (slot == 2) {
+ return hasCrystalBallDowsing() || hasPumpkinDowsing() || hasNewPlantSpeciesDowsing() || hasKikwiDowsing() ||
+ hasKeyPieceDowsing() || hasDesertNodeDowsing() || hasPartyWheelDowsing();
+ } else if (StoryFlagManager::sInstance->getCounterOrFlag(DOWSING_TARGET_STORY_FLAGS[slot])) {
+ // TODO small instruction shuffle
+ return true;
+ }
+
+ return false;
+}
+
+#define MYCLAMP(low, high, x) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
+
+DowsingTarget *DowsingTarget::getDowsingInfo(const mVec3_c &playerPosition, const mVec3_c &dowsingDirection, f32 *p3,
+ f32 *p4, f32 *intensity, int slot) {
+ if (slot >= 8) {
+ return nullptr;
+ }
+ mVec3_c dwsDir = dowsingDirection;
+ dwsDir.normalize();
+ DowsingList *list = &DOWSING_LISTS[slot];
+ DowsingTarget *best = nullptr;
+
+ for (DowsingList::Iterator node = list->GetBeginIter(); node != list->GetEndIter(); ++node) {
+ mVec3_c targetPos;
+ node->getPosition(targetPos);
+ mVec3_c targetDir = mVec3_c(targetPos - playerPosition);
+ f32 proximity = nw4r::ut::Max(10000.0f - targetDir.mag(), 0.0f);
+
+ targetDir.normalize();
+
+ f32 dot = dwsDir.dot(targetDir);
+ dot = MYCLAMP(-1.0f, 1.0f, dot);
+ f32 a = 1.0f - dot * dot <= 0.0f ? 0.0f : nw4r::math::FrSqrt(1.0f - dot * dot) * (1.0f - dot * dot);
+
+ f32 f9 = (5461 - labs(cM::atan2s(a, dot))) * (1.0f / 5461.0f);
+ if (!(f9 < 0.0f)) {
+ f32 val;
+ f32 f10 = MYCLAMP(0.0f, 0.9f, proximity * 0.0001f) * 1.1111112f;
+ if (f9 > 0.85f) {
+ f9 = 0.85f;
+ }
+
+ f9 = f9 * 1.1764705f;
+ f9 *= f9;
+ if (f9 > 1.0f) {
+ f9 = 1.0f;
+ }
+
+ val = f9 * f10;
+ if (val > *intensity) {
+ *intensity = val;
+ *p3 = f10;
+ *p4 = f9;
+ best = &*node;
+ }
+ }
+ }
+ return best;
+}
+
+void DowsingTarget::init() {}
+
+void DowsingTarget::execute() {}
+
+// Not sure what this is
+inline static TListNode *getNode(u8 slot, DowsingTarget *t) {
+ if (t->mLink.mpNext == nullptr || t->mLink.mpPrev == nullptr) {
+ return &DOWSING_LISTS[slot].mNode;
+ } else {
+ return &t->mLink;
+ }
+}
+
+static bool insertDowsingTarget(DowsingTarget *target) {
+ u8 slot = target->getSlot();
+ if (slot == DowsingTarget::SLOT_NONE) {
+ return false;
+ }
+
+ if (getNode(slot, target) != &DOWSING_LISTS[slot].mNode) {
+ return false;
+ }
+ DOWSING_LISTS[slot].insert(target);
+ return true;
+}
+
+static bool removeDowsingTarget(DowsingTarget *target) {
+ u8 slot = target->getSlot();
+ if (slot == DowsingTarget::SLOT_NONE) {
+ return false;
+ }
+
+ if (getNode(slot, target) != &DOWSING_LISTS[slot].mNode) {
+ DOWSING_LISTS[slot].remove(target);
+ return true;
+ }
+ return false;
+}
+
+u8 DowsingTarget::getTopDowsingIcon() {
+ if (hasZeldaDowsing()) {
+ return 19;
+ } else if (hasAnyTrialDowsing()) {
+ return 20;
+ } else if (hasSacredWaterDowsing()) {
+ return 5;
+ } else if (hasSandshipDowsing()) {
+ return 18;
+ } else if (hasTadtoneDowsing()) {
+ return 17;
+ } else if (hasPropellerDowsing()) {
+ return 10;
+ } else if (hasWaterBasinDowsing()) {
+ return 14;
+ }
+ return 19;
+}
+
+u8 DowsingTarget::getLeftDowsingIcon() {
+ if (hasCrystalBallDowsing()) {
+ return 15;
+ } else if (hasPumpkinDowsing()) {
+ return 12;
+ } else if (hasNewPlantSpeciesDowsing()) {
+ return 21;
+ } else if (hasPartyWheelDowsing()) {
+ return 13;
+ } else if (hasKikwiDowsing()) {
+ return 8;
+ } else if (hasKeyPieceDowsing()) {
+ return 11;
+ } else if (hasDesertNodeDowsing()) {
+ return 7;
+ }
+ return 15;
+}