From 88620ca9af1fa9570ba012da5b95df78e729fede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 16 Nov 2020 15:19:49 +0100 Subject: ksys/act: Add several more InfoData functions --- src/KingSystem/ActorSystem/actInfoData.cpp | 321 +++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) (limited to 'src/KingSystem/ActorSystem/actInfoData.cpp') diff --git a/src/KingSystem/ActorSystem/actInfoData.cpp b/src/KingSystem/ActorSystem/actInfoData.cpp index 54499e40..af03b8a3 100644 --- a/src/KingSystem/ActorSystem/actInfoData.cpp +++ b/src/KingSystem/ActorSystem/actInfoData.cpp @@ -1,6 +1,8 @@ #include "KingSystem/ActorSystem/actInfoData.h" +#include #include #include +#include "KingSystem/Event/evtManager.h" #include "KingSystem/Utils/Byaml/Byaml.h" #include "KingSystem/Utils/Byaml/ByamlArrayIter.h" #include "KingSystem/Utils/Byaml/ByamlData.h" @@ -63,6 +65,58 @@ void InfoData::init(u8* data, sead::Heap* heap, sead::Heap* debug_heap) { mSystemSameGroupActorNameIdx = mRootIter->getKeyIndex("systemSameGroupActorName"); } +void InfoData::getModelInfo(const char* actor, InfoData::ModelInfo& info) const { + const char** ptr; + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) { + static_cast(logFailure(actor)); + ptr = &info.bfres; + } else { + const auto getFloat = [&](f32* value, const char* key, float default_) { + if (!iter.tryGetFloatByKey(value, key)) + *value = default_; + }; + + getFloat(&info.baseScale.x, "baseScaleX", 1.0); + getFloat(&info.baseScale.y, "baseScaleY", 1.0); + getFloat(&info.baseScale.z, "baseScaleZ", 1.0); + + getFloat(&info.addColor.r, "addColorR", 0.0); + getFloat(&info.addColor.g, "addColorG", 0.0); + getFloat(&info.addColor.b, "addColorB", 0.0); + getFloat(&info.addColor.a, "addColorA", 0.0); + + getFloat(&info.mulColor.r, "mulColorR", 1.0); + getFloat(&info.mulColor.g, "mulColorG", 1.0); + getFloat(&info.mulColor.b, "mulColorB", 1.0); + getFloat(&info.mulColor.a, "mulColorA", 1.0); + + if (!iter.tryGetStringByKey(&info.bfres, "bfres")) + info.bfres = nullptr; + + if (!iter.tryGetStringByKey(&info.mainModel, "mainModel")) + info.mainModel = nullptr; + + if (!info.bfres) + return; + + if (info.mainModel) { + const char* model_resource = + res::ModelResourceDivide::instance()->getModelResource(info.bfres, info.mainModel); + if (model_resource) + info.bfres = model_resource; + } + + if (!info.bfres || sead::SafeString(info.bfres) != "dammy_data") + return; + + info.bfres = nullptr; + ptr = &info.mainModel; + } + + *ptr = nullptr; +} + bool InfoData::getActorIter(al::ByamlIter* iter, const char* actor, bool x) const { const u32 hash = sead::HashCRC32::calcStringHash(actor); @@ -193,6 +247,93 @@ void InfoData::getHomeAreas(const char* actor, HomeAreas& info) const { } } +void InfoData::getInvalidLifeConditions(const char* actor, InvalidLifeConditions& info) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) + return; + + al::ByamlData data; + al::ByamlHashIter hash_iter{iter.getRootNode()}; + + if (hash_iter.getDataByKey(&data, mInvalidTimesIdx)) { + al::ByamlIter it{iter.getData(), iter.getData() + data.getValue()}; + for (s32 i = 0, n = it.getSize(); i < n; ++i) { + const char* time = nullptr; + if (!it.tryGetStringByIndex(&time, i)) + continue; + + info.times[info.num_times] = time; + ++info.num_times; + } + } + + if (hash_iter.getDataByKey(&data, mInvalidWeathersIdx)) { + al::ByamlIter it{iter.getData(), iter.getData() + data.getValue()}; + for (s32 i = 0, n = it.getSize(); i < n; ++i) { + const char* weather = nullptr; + if (!it.tryGetStringByIndex(&weather, i)) + continue; + + info.weathers[info.num_weathers] = weather; + ++info.num_weathers; + } + } +} + +bool InfoData::hasTag(const char* actor, const char* tag) const { + al::ByamlIter iter; + return getActorIter(&iter, actor) && hasTag(iter, sead::HashCRC32::calcStringHash(tag)); +} + +bool InfoData::hasTag(const al::ByamlIter& actor_iter, u32 tag) const { + al::ByamlHashIter tags_iter{actor_iter.getRootNode()}; + al::ByamlData data; + if (!tags_iter.getDataByKey(&data, mTagsIdx)) + return false; + + al::ByamlIter iter{actor_iter.getData(), actor_iter.getData() + data.getValue()}; + if (!iter.isValid()) + return false; + + // Binary search. + + s32 a = 0; + s32 b = iter.getSize(); + if (b <= 0) + return false; + + al::ByamlHashIter hash_iter{iter.getRootNode()}; + const auto pair_table = hash_iter.getPairTable(); + + while (a < b) { + const s32 idx = (a + b) / 2; + + const auto* pair = &pair_table[idx]; + if (!pair) + break; + + al::ByamlData hash_data{pair}; + u32 hash; + if (!iter.tryConvertUInt(&hash, &hash_data)) + break; + + if (hash == tag) + return true; + + if (hash >= tag) + b = idx; + else + a = idx + 1; + } + + return false; +} + +bool InfoData::hasTag(const char* actor, u32 tag_hash) const { + al::ByamlIter iter; + return getActorIter(&iter, actor) && hasTag(iter, tag_hash); +} + const char* InfoData::getSameGroupActorName(const char* actor) const { al::ByamlIter iter; return [&] { @@ -209,6 +350,52 @@ const char* InfoData::getSameGroupActorName(const char* actor) const { }(); } +const char* InfoData::getSameGroupActorName(const al::ByamlIter& iter) const { + al::ByamlHashIter hash_iter{iter.getRootNode()}; + al::ByamlData data; + if (hash_iter.getDataByKey(&data, mSystemSameGroupActorNameIdx)) { + const char* name; + if (iter.tryConvertString(&name, &data)) + return name; + } + return sead::SafeString::cEmptyString.cstr(); +} + +s32 InfoData::getTerrainTextures(const char* actor, InfoData::TerrainTextures& info) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) + return 0; + + al::ByamlIter textures_iter; + if (!iter.tryGetIterByKey(&textures_iter, "terrainTextures")) + return 0; + + s32 count = 0; + for (s32 i = 0; i < textures_iter.getSize(); ++i) { + u32 value; + textures_iter.tryGetUIntByIndex(&value, i); + + if (u8(value) != 0xFF) + info.textures[count++] = u8(value); + if (u8(value >> 8) != 0xFF) + info.textures[count++] = u8(value >> 8); + if (u8(value >> 16) != 0xFF) + info.textures[count++] = u8(value >> 16); + if (u8(value >> 24) != 0xFF) + info.textures[count++] = u8(value >> 24); + } + return count; +} + +bool InfoData::getDrops(al::ByamlIter* drops_iter, const char* actor) const { + al::ByamlIter iter; + return getActorIter(&iter, actor) && iter.tryGetIterByKey(drops_iter, "drops"); +} + +const char* InfoData::getName(const char* actor) const { + return getString(actor, "name", ""); +} + const char* InfoData::getString(const char* actor, const char* key, const sead::SafeString& default_, bool x) const { al::ByamlIter iter; @@ -218,6 +405,10 @@ const char* InfoData::getString(const char* actor, const char* key, return getStringByKey(iter, key, default_); } +const char* InfoData::getUnknown(const char* actor, u32) const { + return actor; +} + const char* InfoData::getSLinkUser(const char* actor) const { al::ByamlIter iter; if (!getActorIter(&iter, actor)) @@ -255,6 +446,15 @@ bool InfoData::getActorProfile(const char** profile, const char* actor) const { return false; } +bool InfoData::getActorProfile(const char** profile, const al::ByamlIter& iter) const { + al::ByamlHashIter hash_iter{iter.getRootNode()}; + al::ByamlData data; + if (hash_iter.getDataByKey(&data, mProfileIdx)) + return iter.tryConvertString(profile, &data); + *profile = "Dummy"; + return false; +} + s32 InfoData::getInt(const char* actor, const char* key, s32 default_, bool x) const { al::ByamlIter iter; if (!getActorIter(&iter, actor, x)) @@ -289,8 +489,129 @@ bool InfoData::getBoolByKey(const al::ByamlIter& iter, const char* key, bool def return iter.tryGetBoolByKey(&value, key) ? value != 0 : default_; } +bool InfoData::getActorIter(al::ByamlIter* iter, u32 hash, bool x) const { + // Perform a binary search. + s32 a = 0; + s32 b = mNumActors; + while (a < b) { + const s32 idx = (a + b) / 2; + const u32 hash_i = mHashes[idx]; + + if (hash_i == hash) { + *iter = al::ByamlIter(mActorsBytes, mActorsBytes + mActorOffsets[idx]); + return true; + } + + if (hash_i >= hash) + b = idx; + else + a = idx + 1; + } + + if (x) + static_cast(evt::Manager::instance()->getActiveEvent()); + + return false; +} + +bool InfoData::hasBurnableParam(const al::ByamlIter& iter) { + al::ByamlIter chemical_it; + if (!iter.tryGetIterByKey(&chemical_it, "Chemical")) + return false; + s32 dummy = 0; + return chemical_it.tryGetIntByKey(&dummy, "Burnable"); +} + +bool InfoData::hasCapaciterParam(const al::ByamlIter& iter) { + al::ByamlIter chemical_it; + if (!iter.tryGetIterByKey(&chemical_it, "Chemical")) + return false; + s32 dummy = 0; + return chemical_it.tryGetIntByKey(&dummy, "Capaciter"); +} + +bool InfoData::hasCapaciterParam(const char* actor) const { + al::ByamlIter iter; + return getActorIter(&iter, actor) && hasCapaciterParam(iter); +} + f32 InfoData::getScale(const char* actor) const { return getFloat(actor, "actorScale", 1.0); } +f32 InfoData::getAdjustedLookAtOffsetY(const char* actor) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) + return 0.0; + + return iter.getFloatByKey("lookAtOffsetY") + iter.getFloatByKey("rigidBodyCenterY"); +} + +f32 InfoData::getCursorOffsetY(const char* actor) const { + return getFloat(actor, "cursorOffsetY", 0.0, false); +} + +f32 InfoData::getTraverseDist(const char* actor) const { + return getFloat(actor, "traverseDist", 0.0); +} + +bool InfoData::getYLimitAlgorithm(const char** algorithm, const char* actor) const { + *algorithm = getString(actor, "yLimitAlgorithm", "NoLimit"); + return algorithm != nullptr; +} + +f32 InfoData::getAabbNorm(const char* actor, bool x) const { + sead::Vector3f min, max; + if (getAAbbMinMax(actor, &min, &max, x)) + return sead::norm2(max - min); + return 0.0; +} + +bool InfoData::getAAbbMinMax(const char* actor, sead::Vector3f* min, sead::Vector3f* max, + bool x) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor, x)) + return false; + + bool min_ok, max_ok; + + if (al::tryGetByamlV3f(min, iter, "aabbMin")) { + min_ok = true; + } else { + *min = sead::Vector3f::zero; + min_ok = false; + } + + if (al::tryGetByamlV3f(max, iter, "aabbMax")) { + max_ok = true; + } else { + *max = sead::Vector3f::zero; + max_ok = false; + } + + return min_ok && max_ok; +} + +s32 InfoData::getSortKey(const char* actor) const { + return getInt(actor, "sortKey", 0, false); +} + +f32 InfoData::getBoundingForTraverse(const char* actor) const { + return getFloat(actor, "boundingForTraverse", 0, false); +} + +f32 InfoData::getAabbNormHalf(const char* actor) const { + return getAabbNorm(actor, true) * 0.5f; +} + +bool InfoData::isHasFar(const char* actor) const { + return getBool(actor, "isHasFar", false, false); +} + +bool InfoData::hasDropEntry(const char* actor, const char* key) const { + al::ByamlIter iter; + getDrops(&iter, actor); + return iter.isExistKey(key); +} + } // namespace ksys::act -- cgit v1.2.3