summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrián <38050447+oxixes@users.noreply.github.com>2026-11-03 03:47:18 +0100
committerGitHub <noreply@github.com>2026-11-03 02:47:18 +0000
commitdcad8b499e1397fa145d3348a387b6339c00bb34 (patch)
treed7b7b5aba5df46ebdc2f560a836e6cf1b6588855 /src
parentd7a8694143c2677534ffaffe5ab130764bc76d31 (diff)
Match ksys::eco::LevelSensor::scaleActor and scaleWeapon (#222)
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/Ecosystem/ecoLevelSensor.cpp235
-rw-r--r--src/KingSystem/Ecosystem/ecoLevelSensor.h8
2 files changed, 242 insertions, 1 deletions
diff --git a/src/KingSystem/Ecosystem/ecoLevelSensor.cpp b/src/KingSystem/Ecosystem/ecoLevelSensor.cpp
index 201efafc..e326f933 100644
--- a/src/KingSystem/Ecosystem/ecoLevelSensor.cpp
+++ b/src/KingSystem/Ecosystem/ecoLevelSensor.cpp
@@ -1,7 +1,12 @@
#include "KingSystem/Ecosystem/ecoLevelSensor.h"
+
+#include "KingSystem/ActorSystem/actActor.h"
+#include "KingSystem/ActorSystem/actInstParamPack.h"
+#include "KingSystem/Ecosystem/ecoSystem.h"
#include "KingSystem/GameData/gdtManager.h"
#include "KingSystem/Resource/resLoadRequest.h"
#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/World/worldManager.h"
namespace ksys::eco {
@@ -21,6 +26,236 @@ void LevelSensor::init(sead::Heap* heap) {
mRootIter = new (heap) al::ByamlIter(res->getRawData());
}
+bool LevelSensor::isScalingAllowed(const sead::Vector3f& position) const {
+ const auto* world_mgr = world::Manager::instance();
+ if (world_mgr->getStageType() == StageType::OpenWorld &&
+ world_mgr->getFieldType() == world::FieldType::AocField &&
+ world_mgr->getScalingMode() == world::ScalingMode::Disabled) {
+ return false;
+ }
+
+ return Ecosystem::instance()->getFieldMapArea(position.x, position.z) != 28;
+}
+
+bool LevelSensor::isScalingAllowed(const act::Actor& actor) const {
+ if (const auto* map_obj = actor.getMapObject()) {
+ const sead::Vector3f position = map_obj->getTranslate();
+ return isScalingAllowed(position);
+ }
+
+ sead::Vector3f position;
+ actor.getMtx().getTranslation(position);
+ return isScalingAllowed(position);
+}
+
+bool LevelSensor::scaleWeapon(const sead::SafeString& weapon, WeaponModifier min_modifier,
+ const char** scaled_weapon, WeaponModifier* scaled_modifier,
+ const act::Actor* actor) const {
+ if (actor && !isScalingAllowed(*actor))
+ return false;
+
+ al::ByamlIter weapons_iter;
+ if (!mRootIter->tryGetIterByKey(&weapons_iter, "weapon"))
+ return false;
+
+ for (s32 i = 0; i < weapons_iter.getSize(); ++i) {
+ al::ByamlIter weapon_iter;
+ if (!weapons_iter.tryGetIterByIndex(&weapon_iter, i))
+ return false;
+
+ al::ByamlIter actors_iter;
+ if (!weapon_iter.tryGetIterByKey(&actors_iter, "actors"))
+ return false;
+
+ for (s32 j = 0; j < actors_iter.getSize() - 1; ++j) {
+ al::ByamlIter actor_iter;
+ if (!actors_iter.tryGetIterByIndex(&actor_iter, j))
+ return false;
+
+ const char* actor_name;
+ if (!actor_iter.tryGetStringByKey(&actor_name, "name"))
+ return false;
+
+ f32 actor_value;
+ if (!actor_iter.tryGetFloatByKey(&actor_value, "value"))
+ return false;
+
+ s32 actor_plus;
+ if (!actor_iter.tryGetIntByKey(&actor_plus, "plus"))
+ return false;
+
+ bool modifier_matches = false;
+ if (min_modifier == WeaponModifier::None) {
+ if (actor_plus == -1)
+ modifier_matches = true;
+ } else if (min_modifier == WeaponModifier::Blue) {
+ if (actor_plus == 0)
+ modifier_matches = true;
+ } else if (min_modifier == WeaponModifier::Yellow) {
+ if (actor_plus == 1)
+ modifier_matches = true;
+ }
+
+ if (modifier_matches && actor_value < mWeaponPoints && weapon == actor_name) {
+ bool not_rank_up = false;
+ if (!weapon_iter.tryGetBoolByKey(&not_rank_up, "not_rank_up"))
+ return false;
+
+ al::ByamlIter next_iter;
+ f32 next_value = 0.0f;
+ s32 found_index = -1;
+ for (s32 k = j + 1; k < actors_iter.getSize(); ++k) {
+ if (!actors_iter.tryGetIterByIndex(&next_iter, k) ||
+ !next_iter.tryGetFloatByKey(&next_value, "value")) {
+ return false;
+ }
+
+ const char* next_name;
+ bool same_weapon = true;
+ if (not_rank_up) {
+ if (!next_iter.tryGetStringByKey(&next_name, "name"))
+ return false;
+
+ same_weapon = weapon == next_name;
+ }
+
+ if (same_weapon) {
+ found_index = k;
+ if (mWeaponPoints <= next_value)
+ break;
+ }
+ }
+
+ if (found_index < 0)
+ return false;
+
+ const char* found_name;
+ const char* series;
+ const char* actor_type;
+ s32 found_plus;
+ if (!actors_iter.tryGetIterByIndex(&next_iter, found_index) ||
+ !next_iter.tryGetStringByKey(&found_name, "name") ||
+ !weapon_iter.tryGetStringByKey(&series, "series") ||
+ !weapon_iter.tryGetStringByKey(&actor_type, "actorType") ||
+ !next_iter.tryGetIntByKey(&found_plus, "plus")) {
+ return false;
+ }
+
+ *scaled_weapon = found_name;
+ switch (found_plus) {
+ case 0:
+ *scaled_modifier = WeaponModifier::Blue;
+ break;
+ case 1:
+ *scaled_modifier = WeaponModifier::Yellow;
+ break;
+ default:
+ *scaled_modifier = WeaponModifier::None;
+ break;
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool LevelSensor::scaleActor(const sead::SafeString& name, map::Object* obj,
+ const char** scaled_weapon, act::InstParamPack* pack,
+ const sead::Vector3f& position) const {
+ if (!isScalingAllowed(position))
+ return false;
+
+ if (name.startsWith("Enemy")) {
+ const auto& mubin_iter = obj->getMubinIter();
+ s32 mode = 0;
+ if (mubin_iter.tryGetParamIntByKey(&mode, "LevelSensorMode") && mode >= 1) {
+ al::ByamlIter enemies_iter;
+ if (!mRootIter->tryGetIterByKey(&enemies_iter, "enemy"))
+ return false;
+
+ for (s32 i = 0; i < enemies_iter.getSize(); ++i) {
+ al::ByamlIter enemy_iter;
+ if (!enemies_iter.tryGetIterByIndex(&enemy_iter, i))
+ return false;
+
+ al::ByamlIter actors_iter;
+ if (!enemy_iter.tryGetIterByKey(&actors_iter, "actors"))
+ return false;
+
+ for (s32 j = 0; j < actors_iter.getSize() - 1; ++j) {
+ al::ByamlIter actor_iter;
+ if (!actors_iter.tryGetIterByIndex(&actor_iter, j))
+ return false;
+
+ const char* actor_name;
+ if (!actor_iter.tryGetStringByKey(&actor_name, "name"))
+ return false;
+
+ f32 actor_value;
+ if (!actor_iter.tryGetFloatByKey(&actor_value, "value"))
+ return false;
+
+ if (actor_value < mEnemyPoints && name == actor_name) {
+ al::ByamlIter next_actor_iter;
+ f32 next_actor_value;
+ for (s32 k = j + 1; k < actors_iter.getSize(); ++k) {
+ if (!actors_iter.tryGetIterByIndex(&next_actor_iter, k))
+ return false;
+
+ if (!next_actor_iter.tryGetFloatByKey(&next_actor_value, "value"))
+ return false;
+
+ if (mEnemyPoints <= next_actor_value)
+ break;
+ }
+
+ const char* next_actor_name;
+ if (!next_actor_iter.tryGetStringByKey(&next_actor_name, "name"))
+ return false;
+
+ const char* enemy_species;
+ if (!enemy_iter.tryGetStringByKey(&enemy_species, "species"))
+ return false;
+
+ *scaled_weapon = next_actor_name;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ if (name.startsWith("Weapon")) {
+ const auto& mubin_iter = obj->getMubinIter();
+ WeaponModifier scaled_modifier;
+ s32 mode = 0;
+ s32 sharp_weapon_judge_type;
+ if (mubin_iter.tryGetParamIntByKey(&mode, "LevelSensorMode") && mode >= 1) {
+ sharp_weapon_judge_type = 0;
+ if (!mubin_iter.tryGetParamIntByKey(&sharp_weapon_judge_type, "SharpWeaponJudgeType"))
+ return false;
+
+ const char* scaled_weapon_result;
+ WeaponModifier weapon_modifier =
+ getRandomWeaponModifier(sharp_weapon_judge_type, obj->getUnitConfigName());
+ if (!scaleWeapon(obj->getUnitConfigName(), weapon_modifier, &scaled_weapon_result,
+ &scaled_modifier, nullptr)) {
+ return false;
+ }
+
+ auto val = int(scaled_modifier);
+ pack->getBuffer().add(val, "SharpWeaponJudgeType");
+
+ *scaled_weapon = scaled_weapon_result;
+ return true;
+ }
+ }
+
+ return false;
+}
+
void LevelSensor::calculatePoints() {
if (mDefaultPoints >= 0) {
mPoints = mDefaultPoints;
diff --git a/src/KingSystem/Ecosystem/ecoLevelSensor.h b/src/KingSystem/Ecosystem/ecoLevelSensor.h
index 6d6d3fbb..54169e81 100644
--- a/src/KingSystem/Ecosystem/ecoLevelSensor.h
+++ b/src/KingSystem/Ecosystem/ecoLevelSensor.h
@@ -30,6 +30,9 @@ enum class WeaponModifier {
NoneForced = 4,
};
+// TODO Find out where this goes. It is currently used by ksys::eco::LevelSensor::scaleActor.
+WeaponModifier getRandomWeaponModifier(s32 judge_type, const sead::SafeString& unit_config_name);
+
class LevelSensor {
public:
LevelSensor();
@@ -39,7 +42,7 @@ public:
bool scaleWeapon(const sead::SafeString& weapon, WeaponModifier min_modifier,
const char** scaled_weapon, WeaponModifier* scaled_modifier,
- act::Actor* actor) const;
+ const act::Actor* actor) const;
bool scaleActor(const sead::SafeString& name, map::Object* obj, const char** scaled_weapon,
act::InstParamPack* pack, const sead::Vector3f& position) const;
@@ -47,6 +50,9 @@ public:
void calculatePoints();
private:
+ bool isScalingAllowed(const sead::Vector3f& position) const;
+ bool isScalingAllowed(const act::Actor& actor) const;
+
f32 mPoints{};
f32 mWeaponPoints{};
f32 mEnemyPoints{};