diff --git a/data/uking_functions.csv b/data/uking_functions.csv index c99ea488..13ff54dd 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -80202,38 +80202,38 @@ 0x0000007100ede158,PlacementObj::shouldSkipSpawnFairy,188,_ZN4ksys3act20shouldSkipSpawnFairyEPNS_3map6ObjectE 0x0000007100ede214,sub_7100EDE214,208,_ZN4ksys3act20shouldSkipSpawnFairyERKN4sead14SafeStringBaseIcEE 0x0000007100ede2e4,PlacementMgr::setSomeGlobalPlacementFlags,180,_ZN4ksys3act31initSpawnConditionGameDataFlagsEv -0x0000007100ede398,act::hasAnyRevivalTag,328, -0x0000007100ede4e0,hasStopTimerMiddleTag,28, -0x0000007100ede4fc,hasStopTimerShortTag,28, +0x0000007100ede398,act::hasAnyRevivalTag,328,_ZN4ksys3act16hasAnyRevivalTagERKN4sead14SafeStringBaseIcEE? +0x0000007100ede4e0,hasStopTimerMiddleTag,28,_ZN4ksys3act21hasStopTimerMiddleTagEPNS0_5ActorE +0x0000007100ede4fc,hasStopTimerShortTag,28,_ZN4ksys3act20hasStopTimerShortTagEPNS0_5ActorE 0x0000007100ede518,Actor::canBeStasised,296, 0x0000007100ede640,powerupRuneStuff,316, -0x0000007100ede77c,getArrowTypeName,28, -0x0000007100ede798,getArrowTypeNumberByName,296, -0x0000007100ede8c0,getZukanType,212, -0x0000007100ede994,Actor::getPictureBookType,200, +0x0000007100ede77c,getArrowTypeName,28,_ZN4ksys3act17arrowTypeToStringENS0_9ArrowTypeE! +0x0000007100ede798,getArrowTypeNumberByName,296,_ZN4ksys3act19arrowTypeFromStringERKN4sead14SafeStringBaseIcEE +0x0000007100ede8c0,getZukanType,212,_ZN4ksys3act12getZukanTypeEPN2al9ByamlIterE +0x0000007100ede994,Actor::getPictureBookType,200,_ZN4ksys3act12getZukanTypeEPNS0_5ActorE 0x0000007100edea5c,sub_7100EDEA5C,80, -0x0000007100edeaac,act::acc::isPlayerClass,168, -0x0000007100edeb54,act::isPlayerClass,204, -0x0000007100edec20,BaseProcLink::isPlayerClass,196, -0x0000007100edece4,act::isCamera,204, -0x0000007100ededb0,act::acc::isNPCClass,168, -0x0000007100edee58,act::isNPCClass,204, -0x0000007100edef24,BaseProcLink::isNPCClass,196, -0x0000007100edefe8,act::npcGparamStuff,76, -0x0000007100edf034,act::isDemoNPC,204, -0x0000007100edf100,act::acc::isEnemyClass,1180, -0x0000007100edf59c,act::isEnemyClass,84, -0x0000007100edf5f0,BaseProcLink::isEnemyClass,76, -0x0000007100edf63c,BaseProcLink::isGuardianClass,304, -0x0000007100edf76c,act::acc::isLargeEnemy,544, -0x0000007100edf98c,act::isLargeEnemy,84, -0x0000007100edf9e0,act::acc::isGanonBeast,168, -0x0000007100edfa88,BaseProcLink::isGanonBeast,196, -0x0000007100edfb4c,sub_7100EDFB4C,84, -0x0000007100edfba0,sub_7100EDFBA0,624, -0x0000007100edfe10,sub_7100EDFE10,76, -0x0000007100edfe5c,sub_7100EDFE5C,188, -0x0000007100edff18,isWeaponActorProfile,168, +0x0000007100edeaac,act::acc::isPlayerClass,168,_ZN4ksys3act15isPlayerProfileERKNS0_20ActorConstDataAccessE +0x0000007100edeb54,act::isPlayerClass,204,_ZN4ksys3act15isPlayerProfileEPNS0_5ActorE +0x0000007100edec20,BaseProcLink::isPlayerClass,196,_ZN4ksys3act15isPlayerProfileEPNS0_12BaseProcLinkE +0x0000007100edece4,act::isCamera,204,_ZN4ksys3act15isCameraProfileEPNS0_5ActorE +0x0000007100ededb0,act::acc::isNPCClass,168,_ZN4ksys3act12isNPCProfileERKNS0_20ActorConstDataAccessE +0x0000007100edee58,act::isNPCClass,204,_ZN4ksys3act12isNPCProfileEPNS0_5ActorE +0x0000007100edef24,BaseProcLink::isNPCClass,196,_ZN4ksys3act12isNPCProfileEPNS0_12BaseProcLinkE +0x0000007100edefe8,act::npcGparamStuff,76,_ZN4ksys3act21isNPCOffPodFromWeaponEPNS0_5ActorE +0x0000007100edf034,act::isDemoNPC,204,_ZN4ksys3act16isDemoNPCProfileEPNS0_5ActorE +0x0000007100edf100,act::acc::isEnemyClass,1180,_ZN4ksys3act14isEnemyProfileERKNS0_20ActorConstDataAccessE +0x0000007100edf59c,act::isEnemyClass,84,_ZN4ksys3act14isEnemyProfileEPNS0_5ActorE +0x0000007100edf5f0,BaseProcLink::isEnemyClass,76,_ZN4ksys3act14isEnemyProfileEPNS0_12BaseProcLinkE +0x0000007100edf63c,BaseProcLink::isGuardianClass,304,_ZN4ksys3act17isGuardianProfileEPNS0_12BaseProcLinkE +0x0000007100edf76c,act::acc::isLargeEnemy,544,_ZN4ksys3act12isLargeEnemyERKNS0_20ActorConstDataAccessE +0x0000007100edf98c,act::isLargeEnemy,84,_ZN4ksys3act12isLargeEnemyEPNS0_5ActorE +0x0000007100edf9e0,act::acc::isGanonBeast,168,_ZN4ksys3act12isGanonBeastERKNS0_20ActorConstDataAccessE +0x0000007100edfa88,BaseProcLink::isGanonBeast,196,_ZN4ksys3act12isGanonBeastEPNS0_12BaseProcLinkE +0x0000007100edfb4c,sub_7100EDFB4C,84,_ZN4ksys3act19isNotLivingCreatureEPNS0_5ActorE +0x0000007100edfba0,sub_7100EDFBA0,624,_ZN4ksys3act19isNotLivingCreatureERKNS0_20ActorConstDataAccessE +0x0000007100edfe10,sub_7100EDFE10,76,_ZN4ksys3act19isNotLivingCreatureEPNS0_12BaseProcLinkE +0x0000007100edfe5c,sub_7100EDFE5C,188,_ZN4ksys3act15isWeaponProfileERKNS0_20ActorConstDataAccessE +0x0000007100edff18,isWeaponActorProfile,168,_ZN4ksys3act15isWeaponProfileERKN4sead14SafeStringBaseIcEE 0x0000007100edffc0,Actor::isWeaponActorProfile,224, 0x0000007100ee00a0,sub_7100EE00A0,216, 0x0000007100ee0178,act::acc::isWeaponOrArmor,332, @@ -80241,7 +80241,7 @@ 0x0000007100ee0318,act::acc::isBulletClass,168, 0x0000007100ee03c0,sub_7100EE03C0,204, 0x0000007100ee048c,sub_7100EE048C,196, -0x0000007100ee0550,act::acc::isHorseClass,168, +0x0000007100ee0550,act::acc::isHorseClass,168,_ZN4ksys3act14isHorseProfileERKNS0_20ActorConstDataAccessE 0x0000007100ee05f8,sub_7100EE05F8,204, 0x0000007100ee06c4,BaseProcLink::isHorseClass,196, 0x0000007100ee0788,sub_7100EE0788,24, @@ -80249,7 +80249,7 @@ 0x0000007100ee0814,sub_7100EE0814,100, 0x0000007100ee0878,sub_7100EE0878,28, 0x0000007100ee0894,sub_7100EE0894,100, -0x0000007100ee08f8,sub_7100EE08F8,260, +0x0000007100ee08f8,sub_7100EE08F8,260,_ZN4ksys3act13isPreyOrSwarmERKNS0_20ActorConstDataAccessE 0x0000007100ee09fc,isPreyOrSwarm,312, 0x0000007100ee0b34,BaseProcLink::isPreyClass,304, 0x0000007100ee0c64,sub_7100EE0C64,92, @@ -80397,7 +80397,7 @@ 0x0000007100ee72c8,PlacementObj::getNameAndUniqueName,1376, 0x0000007100ee7828,Actor::getPlacementNameAndUniqueName,44, 0x0000007100ee7854,sub_7100EE7854,44, -0x0000007100ee7880,getDefaultTBoxDropActor,12, +0x0000007100ee7880,getDefaultTBoxDropActor,12,_ZN4ksys3act19getDefaultDropActorEv 0x0000007100ee788c,Actor::createDrops,36, 0x0000007100ee78b0,eco::getEcosystemActorName,1192, 0x0000007100ee7d58,eco::sub_7100EE7D58,344, diff --git a/src/KingSystem/ActorSystem/actActor.h b/src/KingSystem/ActorSystem/actActor.h index 83315c02..71608780 100644 --- a/src/KingSystem/ActorSystem/actActor.h +++ b/src/KingSystem/ActorSystem/actActor.h @@ -1,5 +1,6 @@ #pragma once +#include #include "KingSystem/ActorSystem/actBaseProc.h" namespace ksys { @@ -11,6 +12,12 @@ class ActorParam; class Actor : public BaseProc { public: + enum class StasisFlag { + _1 = 1, + _2 = 2, + _4 = 4, + }; + Actor(); // FIXME ~Actor() override; @@ -27,10 +34,15 @@ public: void nullsub_4649(); // Some kind of logging which has been excluded from the build? + const sead::TypedBitFlag& getStasisFlags() const { return mStasisFlags; } + protected: - u8 TEMP1[0x3F4]; // FIXME - ActorParam* mActorParam; - u8 TEMP2[0x2C0]; // FIXME + /* 0x008 */ u8 TEMP_0x008[0x3F4]; // FIXME + /* 0x570 */ ActorParam* mActorParam; + /* 0x578 */ u8 TEMP_0x578[0x710 - 0x578]; + // The name could be incorrect. + /* 0x710 */ sead::TypedBitFlag mStasisFlags; + /* 0x714 */ u8 TEMP_0x714[0x838 - 0x714]; // FIXME }; KSYS_CHECK_SIZE_NX150(Actor, 0x838); diff --git a/src/KingSystem/ActorSystem/actActorConstDataAccess.h b/src/KingSystem/ActorSystem/actActorConstDataAccess.h index b5125a03..ba4c4ed5 100644 --- a/src/KingSystem/ActorSystem/actActorConstDataAccess.h +++ b/src/KingSystem/ActorSystem/actActorConstDataAccess.h @@ -9,6 +9,7 @@ namespace ksys::act { class ActorConstDataAccess : public ActorLinkConstDataAccess { public: ActorConstDataAccess() = default; + explicit ActorConstDataAccess(BaseProc* proc) : ActorLinkConstDataAccess(proc) {} bool acquireActor(const ActorLinkConstDataAccess& other); diff --git a/src/KingSystem/ActorSystem/actActorUtil.cpp b/src/KingSystem/ActorSystem/actActorUtil.cpp index f7e37ebe..095d7500 100644 --- a/src/KingSystem/ActorSystem/actActorUtil.cpp +++ b/src/KingSystem/ActorSystem/actActorUtil.cpp @@ -1,4 +1,5 @@ #include "KingSystem/ActorSystem/actActorUtil.h" +#include #include "KingSystem/ActorSystem/actActor.h" #include "KingSystem/ActorSystem/actActorConstDataAccess.h" #include "KingSystem/ActorSystem/actActorParam.h" @@ -8,7 +9,10 @@ #include "KingSystem/GameData/gdtManager.h" #include "KingSystem/Map/mapObject.h" #include "KingSystem/Map/mapPlacementMgr.h" +#include "KingSystem/Resource/GeneralParamList/resGParamListObjectNpc.h" #include "KingSystem/Resource/resResourceActorLink.h" +#include "KingSystem/Resource/resResourceGParamList.h" +#include "KingSystem/Utils/Byaml/Byaml.h" #include "KingSystem/World/worldManager.h" namespace ksys::act { @@ -21,9 +25,20 @@ ActorConstDataAccess getAccessor(BaseProcLink* link) { return accessor; } -const char* sArrowTypes[] = { - "NormalArrow", "BombArrow_A", "AncientArrow", "FireArrow", "IceArrow", "ElectricArrow", -}; +ActorConstDataAccess getAccessor(Actor* actor) { + ActorConstDataAccess accessor{actor}; + return accessor; +} + +sead::SafeString sDefaultDropActor = "Item_Fruit_A"; +sead::SafeArray sArrowTypes{{ + "NormalArrow", + "BombArrow_A", + "AncientArrow", + "FireArrow", + "IceArrow", + "ElectricArrow", +}}; gdt::FlagHandle sAnimalMasterAppearanceHandle = gdt::InvalidHandle; gdt::FlagHandle sFairyCountCheckHandle = gdt::InvalidHandle; gdt::FlagHandle sIsGetStopTimerLv2Handle = gdt::InvalidHandle; @@ -160,4 +175,240 @@ auto initSpawnConditionGameDataFlags_dummy() { return sIsGetStopTimerLv2Handle; } +// NON_MATCHING: redundant branches in the original code. +bool hasAnyRevivalTag(const sead::SafeString& actor) { + auto* info = InfoData::instance(); + al::ByamlIter iter; + if (!info || !info->getActorIter(&iter, actor.cstr())) + return false; + + for (auto tag : { + tags::RevivalBloodyMoon, + tags::RevivalRandom, + tags::RevivalNone, + tags::RevivalNoneForUsed, + tags::RevivalRandomForDrop, + tags::RevivalNoneForDrop, + tags::RevivalUnderGodTime, + }) { + if (info->hasTag(iter, tag)) + return true; + } + return false; +} + +bool hasStopTimerMiddleTag(Actor* actor) { + return hasTag(actor, tags::StopTimerMiddle); +} + +bool hasStopTimerShortTag(Actor* actor) { + return hasTag(actor, tags::StopTimerShort); +} + +// NON_MATCHING: ??? +const char* arrowTypeToString(ArrowType idx) { + return sArrowTypes[u32(idx)]; +} + +ArrowType arrowTypeFromString(const sead::SafeString& name) { + for (s32 i = 0; i < sArrowTypes.size(); ++i) { + if (name == sArrowTypes[i]) + return ArrowType(i); + } + return ArrowType::Invalid; +} + +ZukanType getZukanType(al::ByamlIter* iter) { + if (!iter) + return ZukanType::Invalid; + + auto* info = InfoData::instance(); + + if (info->hasTag(*iter, tags::ZukanAnimal)) + return ZukanType::Animal; + + if (info->hasTag(*iter, tags::ZukanEnemy)) + return ZukanType::Enemy; + + if (info->hasTag(*iter, tags::ZukanSozai)) + return ZukanType::Sozai; + + if (info->hasTag(*iter, tags::ZukanWeapon)) + return ZukanType::Weapon; + + if (info->hasTag(*iter, tags::ZukanOther)) + return ZukanType::Other; + + return ZukanType::Invalid; +} + +ZukanType getZukanType(Actor* actor) { + if (!actor) + return ZukanType::Invalid; + + if (hasTag(actor, tags::ZukanAnimal)) + return ZukanType::Animal; + + if (hasTag(actor, tags::ZukanEnemy)) + return ZukanType::Enemy; + + if (hasTag(actor, tags::ZukanSozai)) + return ZukanType::Sozai; + + if (hasTag(actor, tags::ZukanWeapon)) + return ZukanType::Weapon; + + if (hasTag(actor, tags::ZukanOther)) + return ZukanType::Other; + + return ZukanType::Invalid; +} + +static bool isProfile(const ActorConstDataAccess& accessor, const sead::SafeString& profile) { + return accessor.hasProc() && accessor.getProfile() == profile; +} + +bool isPlayerProfile(const ActorConstDataAccess& accessor) { + return isProfile(accessor, "Player"); +} + +bool isPlayerProfile(Actor* actor) { + return isPlayerProfile(getAccessor(actor)); +} + +bool isPlayerProfile(BaseProcLink* link) { + return isPlayerProfile(getAccessor(link)); +} + +const sead::SafeString& getDefaultDropActor() { + return sDefaultDropActor; +} + +bool isCameraProfile(Actor* actor) { + return isProfile(getAccessor(actor), "Camera"); +} + +bool isNPCProfile(const ActorConstDataAccess& accessor) { + return isProfile(accessor, "NPC"); +} + +bool isNPCProfile(Actor* actor) { + return isNPCProfile(getAccessor(actor)); +} + +bool isNPCProfile(BaseProcLink* link) { + return isNPCProfile(getAccessor(link)); +} + +bool isNPCOffPodFromWeapon(Actor* actor) { + if (!actor) + return false; + + auto* gparam = actor->getParam()->getRes().mGParamList; + if (!gparam) + return false; + + const auto* npc_param = gparam->getNpc(); + return npc_param && npc_param->mIsOffPodFromWeapon.ref(); +} + +bool isDemoNPCProfile(Actor* actor) { + return isProfile(getAccessor(actor), "DemoNPC"); +} + +bool isEnemyProfile(const ActorConstDataAccess& accessor) { + if (!accessor.hasProc()) + return false; + + const auto& profile = accessor.getProfile(); + + return profile == "Enemy" || profile == "GiantEnemy" || profile == "Guardian" || + profile == "GuardianComponent" || profile == "LastBoss" || profile == "GelEnemy" || + profile == "EnemySwarm" || profile == "SiteBoss" || profile == "Sandworm" || + profile == "Dragon"; +} + +bool isEnemyProfile(Actor* actor) { + return isEnemyProfile(getAccessor(actor)); +} + +bool isEnemyProfile(BaseProcLink* link) { + return isEnemyProfile(getAccessor(link)); +} + +bool isGuardianProfile(BaseProcLink* link) { + const auto accessor = getAccessor(link); + if (!accessor.hasProc()) + return false; + + const auto& profile = accessor.getProfile(); + return profile == "Guardian" || profile == "GuardianComponent"; +} + +bool isLargeEnemy(const ActorConstDataAccess& accessor) { + if (!accessor.hasProc()) + return false; + + const auto& profile = accessor.getProfile(); + return profile == "GiantEnemy" || profile == "LastBoss" || profile == "SiteBoss" || + profile == "Sandworm" || profile == "Dragon"; +} + +bool isLargeEnemy(Actor* actor) { + return isLargeEnemy(getAccessor(actor)); +} + +bool isGanonBeast(const ActorConstDataAccess& accessor) { + return accessor.hasProc() && accessor.getName() == "Enemy_GanonBeast"; +} + +bool isGanonBeast(BaseProcLink* link) { + return isGanonBeast(getAccessor(link)); +} + +bool isNotLivingCreature(Actor* actor) { + return isNotLivingCreature(getAccessor(actor)); +} + +bool isNotLivingCreature(const ActorConstDataAccess& accessor) { + if (isPlayerProfile(accessor)) + return false; + if (isNPCProfile(accessor)) + return false; + if (isEnemyProfile(accessor)) + return false; + if (isHorseProfile(accessor)) + return false; + if (isPreyOrSwarm(accessor)) + return false; + return true; +} + +bool isNotLivingCreature(BaseProcLink* link) { + return isNotLivingCreature(getAccessor(link)); +} + +bool isWeaponProfile(const ActorConstDataAccess& accessor) { + if (!accessor.hasProc()) + return false; + return isWeaponProfile(accessor.getName()); +} + +bool isWeaponProfile(const sead::SafeString& actor) { + const char* profile = nullptr; + InfoData::instance()->getActorProfile(&profile, actor.cstr()); + return sead::SafeString(profile).startsWith("Weapon"); +} + +bool isHorseProfile(const ActorConstDataAccess& accessor) { + return isProfile(accessor, "Horse"); +} + +bool isPreyOrSwarm(const ActorConstDataAccess& accessor) { + if (!accessor.hasProc()) + return false; + const auto& profile = accessor.getProfile(); + return profile == "Prey" || profile == "Swarm"; +} + } // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorUtil.h b/src/KingSystem/ActorSystem/actActorUtil.h index 1841c55f..f13b8cbc 100644 --- a/src/KingSystem/ActorSystem/actActorUtil.h +++ b/src/KingSystem/ActorSystem/actActorUtil.h @@ -73,7 +73,7 @@ bool hasAnyRevivalTag(const sead::SafeString& actor); bool hasStopTimerMiddleTag(Actor* actor); bool hasStopTimerShortTag(Actor* actor); -bool canBeStasised(Actor* actor); +bool canBeStasised(Actor* actor, bool force); void highlightStasisableActors(bool on); @@ -108,14 +108,14 @@ bool isLargeEnemy(Actor* actor); bool isGanonBeast(const ActorConstDataAccess& accessor); bool isGanonBeast(BaseProcLink* link); -bool isHumanOrOtherAnimal(Actor* actor); -bool isHumanOrOtherAnimal(const ActorConstDataAccess& accessor); -bool isHumanOrOtherAnimal(BaseProcLink* link); +bool isNotLivingCreature(Actor* actor); +bool isNotLivingCreature(const ActorConstDataAccess& accessor); +bool isNotLivingCreature(BaseProcLink* link); -bool isWeaponName(const ActorConstDataAccess& accessor); -bool isWeaponName(const sead::SafeString& actor); -bool isWeaponName(Actor* actor); -bool isWeaponName(BaseProcLink* link); +bool isWeaponProfile(const ActorConstDataAccess& accessor); +bool isWeaponProfile(const sead::SafeString& actor); +bool isWeaponProfile(Actor* actor); +bool isWeaponProfile(BaseProcLink* link); bool isWeaponOrArmor(const ActorConstDataAccess& accessor); bool isWeaponOrArmor(Actor* actor); @@ -154,4 +154,6 @@ bool isAlive(BaseProcLink* link); bool isAirOctaPlatform(const sead::SafeString& name); bool isAirOctaPlatformDlc(const sead::SafeString& name); +const sead::SafeString& getDefaultDropActor(); + } // namespace ksys::act diff --git a/src/KingSystem/Damage/dmgDamageManagerBase.cpp b/src/KingSystem/Damage/dmgDamageManagerBase.cpp index 76c82d15..51b1e68a 100644 --- a/src/KingSystem/Damage/dmgDamageManagerBase.cpp +++ b/src/KingSystem/Damage/dmgDamageManagerBase.cpp @@ -106,7 +106,7 @@ void DamageManagerBase::removeDamageCallback(DamageCallback* callback) { bool DamageManagerBase::applyDamage(s32& life) { auto* param_list = mActor->getParam()->getRes().mGParamList; - const res::GParamListObjectGeneral& params = param_list->getGeneral(); + const res::GParamListObjectGeneral& params = *param_list->getGeneral(); if (params.mIsLifeInfinite.ref()) { // Since life is infinite, we don't need to modify the damage or life. // But we still call the "callback" as if damage was done. diff --git a/src/KingSystem/Resource/resResourceGParamList.h b/src/KingSystem/Resource/resResourceGParamList.h index c421fe2d..5294575d 100644 --- a/src/KingSystem/Resource/resResourceGParamList.h +++ b/src/KingSystem/Resource/resResourceGParamList.h @@ -20,13 +20,13 @@ public: bool needsParse() const override { return true; } template - const auto& get() const { + const auto* get() const { using Traits = GParamListObjTypeTraits; - return *reinterpret_cast(mObjects[Traits::index]); + return reinterpret_cast(mObjects[Traits::index]); } #define KSYS_GPARAM_DEFINE_GETTER_(NAME) \ - const auto& get##NAME() const { return get(); } + const auto* get##NAME() const { return get(); } KSYS_GPARAM_DEFINE_GETTER_(System) KSYS_GPARAM_DEFINE_GETTER_(General)