ksys/act: Implement more ActorUtil functions

This commit is contained in:
Léo Lam
2020-12-02 23:33:33 +01:00
parent bfbe2db425
commit 5b523db03b
7 changed files with 316 additions and 50 deletions
+15 -3
View File
@@ -1,5 +1,6 @@
#pragma once
#include <prim/seadTypedBitFlag.h>
#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<StasisFlag>& 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<StasisFlag> mStasisFlags;
/* 0x714 */ u8 TEMP_0x714[0x838 - 0x714]; // FIXME
};
KSYS_CHECK_SIZE_NX150(Actor, 0x838);
@@ -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);
+254 -3
View File
@@ -1,4 +1,5 @@
#include "KingSystem/ActorSystem/actActorUtil.h"
#include <container/seadSafeArray.h>
#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<const char*, 6> 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
+10 -8
View File
@@ -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
@@ -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.
@@ -20,13 +20,13 @@ public:
bool needsParse() const override { return true; }
template <GParamListObjType Type>
const auto& get() const {
const auto* get() const {
using Traits = GParamListObjTypeTraits<Type>;
return *reinterpret_cast<typename Traits::type*>(mObjects[Traits::index]);
return reinterpret_cast<const typename Traits::type*>(mObjects[Traits::index]);
}
#define KSYS_GPARAM_DEFINE_GETTER_(NAME) \
const auto& get##NAME() const { return get<GParamListObjType::NAME>(); }
const auto* get##NAME() const { return get<GParamListObjType::NAME>(); }
KSYS_GPARAM_DEFINE_GETTER_(System)
KSYS_GPARAM_DEFINE_GETTER_(General)