Project/Action: Implement ActionFlagCtrl (#783)

This commit is contained in:
Narr the Reg 2025-11-22 08:05:55 -06:00 committed by GitHub
parent ca8e7eb87a
commit 5539b5a52c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 208 additions and 29 deletions

View file

@ -288330,13 +288330,13 @@ Project/Action/ActionFlagCtrl.o:
label:
- _ZN2al20ActionSensorCtrlInfoC1Ev
- _ZN2al20ActionSensorCtrlInfoC2Ev
status: NotDecompiled
status: Matching
- offset: 0xa377b0
size: 12
label:
- _ZN2al18ActionFlagCtrlInfoC1Ev
- _ZN2al18ActionFlagCtrlInfoC2Ev
status: NotDecompiled
status: Matching
- offset: 0xa377bc
size: 276
label: _ZN2al14ActionFlagCtrl9tryCreateEPNS_9LiveActorEPKc
@ -288344,7 +288344,7 @@ Project/Action/ActionFlagCtrl.o:
- offset: 0xa378d0
size: 1180
label: _ZN2al14ActionFlagCtrl8initPostEv
status: NotDecompiled
status: Matching
- offset: 0xa37d6c
size: 144
label: _ZN2al14ActionFlagCtrl5startEPKc
@ -288356,11 +288356,11 @@ Project/Action/ActionFlagCtrl.o:
- offset: 0xa37e64
size: 472
label: _ZN2al14ActionFlagCtrl13startCtrlFlagEv
status: NotDecompiled
status: NonMatchingMajor
- offset: 0xa3803c
size: 192
label: _ZN2al14ActionFlagCtrl15startCtrlSensorEv
status: NotDecompiled
status: Matching
- offset: 0xa380fc
size: 36
label: _ZN2al14ActionFlagCtrl6updateEfffb
@ -288368,7 +288368,7 @@ Project/Action/ActionFlagCtrl.o:
- offset: 0xa38120
size: 240
label: _ZN2al14ActionFlagCtrl16updateCtrlSensorEfffb
status: NotDecompiled
status: Matching
- offset: 0xa38210
size: 56
label:
@ -288378,11 +288378,11 @@ Project/Action/ActionFlagCtrl.o:
- offset: 0xa38248
size: 44
label: _ZNK2al14ActionFlagCtrl13isFlagValidOnEib
status: NotDecompiled
status: Matching
- offset: 0xa38274
size: 40
label: _ZNK2al14ActionFlagCtrl14isFlagValidOffEib
status: NotDecompiled
status: Matching
Project/Action/ActionFunction.o:
'.text':
- offset: 0xa3829c

View file

@ -1,12 +1,25 @@
#include "Project/Action/ActionFlagCtrl.h"
#include "Library/Base/StringUtil.h"
#include "Library/HitSensor/HitSensorKeeper.h"
#include "Library/LiveActor/ActorClippingFunction.h"
#include "Library/LiveActor/ActorCollisionFunction.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorModelFunction.h"
#include "Library/LiveActor/ActorResourceFunction.h"
#include "Library/LiveActor/ActorSensorUtil.h"
#include "Library/LiveActor/LiveActor.h"
#include "Library/Yaml/ByamlIter.h"
#include "Library/Yaml/ByamlUtil.h"
#include "Project/Action/InitResourceDataActionAnim.h"
#include "Project/HitSensor/HitSensor.h"
namespace al {
ActionSensorCtrlInfo::ActionSensorCtrlInfo() = default;
ActionFlagCtrlInfo::ActionFlagCtrlInfo() = default;
ActionFlagCtrl::ActionFlagCtrl(LiveActor* actor, const char* name)
: mParentActor(actor), mName(createStringIfInStack(name)) {}
: mParentActor(actor), mArchiveName(createStringIfInStack(name)) {}
ActionFlagCtrl* ActionFlagCtrl::tryCreate(LiveActor* actor, const char* name) {
if (!isExistModelResource(actor))
@ -22,10 +35,64 @@ ActionFlagCtrl* ActionFlagCtrl::tryCreate(LiveActor* actor, const char* name) {
return new ActionFlagCtrl(actor, name);
}
inline CtrlFlag getCtrlFlagByKey(ByamlIter iter, const char* name) {
bool isValid = false;
if (!iter.tryGetBoolByKey(&isValid, name))
return CtrlFlag::NotFound;
return isValid ? CtrlFlag::ValidOn : CtrlFlag::ValidOff;
}
void ActionFlagCtrl::initPost() {
mHitSensorKeeper = mParentActor->getHitSensorKeeper();
sead::FixedSafeString<128> initFileName;
tryGetActorInitFileName(&initFileName, mParentActor, "ActionFlagCtrl", mArchiveName);
ByamlIter fileIter;
tryGetActorInitFileIter(&fileIter, mParentActor, initFileName.cstr(), mArchiveName);
mInfoCount = fileIter.getSize();
mCtrlInfoArray = new ActionFlagCtrlInfo*[mInfoCount];
for (s32 i = 0; i < mInfoCount; i++) {
ByamlIter iter;
fileIter.tryGetIterByIndex(&iter, i);
ActionFlagCtrlInfo* flagCtrlInfo = new ActionFlagCtrlInfo();
mCtrlInfoArray[i] = flagCtrlInfo;
iter.tryGetStringByKey(&flagCtrlInfo->actionName, "ActionName");
flagCtrlInfo->ctrlFlags = new CtrlFlag[5];
flagCtrlInfo->ctrlFlags[0] = getCtrlFlagByKey(iter, "ShowModel");
flagCtrlInfo->ctrlFlags[1] = getCtrlFlagByKey(iter, "CollisionParts");
flagCtrlInfo->ctrlFlags[2] = getCtrlFlagByKey(iter, "Collider");
flagCtrlInfo->ctrlFlags[3] = getCtrlFlagByKey(iter, "ClippingOff");
flagCtrlInfo->ctrlFlags[4] = getCtrlFlagByKey(iter, "FaceCtrl");
ByamlIter sensorListIter;
if (iter.tryGetIterByKey(&sensorListIter, "SensorList") && mHitSensorKeeper) {
flagCtrlInfo->sensorCtrlInfoArray =
new ActionSensorCtrlInfo[mHitSensorKeeper->getSensorNum()];
for (s32 j = 0; j < mHitSensorKeeper->getSensorNum(); j++) {
ActionSensorCtrlInfo* sensorInfoArray = flagCtrlInfo->sensorCtrlInfoArray;
sensorInfoArray[j].name = mHitSensorKeeper->getSensor(j)->getName();
ByamlIter sensorIter;
if (sensorListIter.tryGetIterByKey(&sensorIter, sensorInfoArray[j].name)) {
sensorInfoArray[j].state = getCtrlFlagByKey(sensorIter, "State");
tryGetByamlS16(&sensorInfoArray[j].startFrame, sensorIter, "StartFrame");
tryGetByamlS16(&sensorInfoArray[j].endFrame, sensorIter, "EndFrame");
}
}
}
}
}
void ActionFlagCtrl::start(const char* name) {
mLastFlag = findFlagInfo(name);
mIsBool = false;
if (!mLastFlag)
mCurrentCtrlInfo = findFlagInfo(name);
mIsUpdateNeeded = false;
if (!mCurrentCtrlInfo)
return;
startCtrlFlag();
@ -34,19 +101,100 @@ void ActionFlagCtrl::start(const char* name) {
ActionFlagCtrlInfo* ActionFlagCtrl::findFlagInfo(const char* name) const {
for (s32 i = 0; i < mInfoCount; i++) {
ActionFlagCtrlInfo* flagInfo = mInfos[i];
if (isEqualStringCase(flagInfo->name, name))
ActionFlagCtrlInfo* flagInfo = mCtrlInfoArray[i];
if (isEqualStringCase(flagInfo->actionName, name))
return flagInfo;
}
return nullptr;
}
void ActionFlagCtrl::update(f32 frame, f32 frameRate, f32 frameMax, bool isStop) {
if (!mLastFlag || !mIsBool)
// NON_MATCHING: Wrong compiler optimization https://decomp.me/scratch/3VkWo
void ActionFlagCtrl::startCtrlFlag() {
if (isFlagValidOn(0, !isHideModel(mParentActor)))
showModel(mParentActor);
else if (isFlagValidOff(0, !isHideModel(mParentActor)))
hideModel(mParentActor);
if (mParentActor->getCollisionParts()) {
if (isFlagValidOn(1, isValidCollisionParts(mParentActor)))
validateCollisionParts(mParentActor);
else if (isFlagValidOff(1, isValidCollisionParts(mParentActor)))
invalidateCollisionParts(mParentActor);
}
if (mParentActor->getCollider()) {
if (isFlagValidOn(2, !isNoCollide(mParentActor)))
onCollide(mParentActor);
else if (isFlagValidOff(2, !isNoCollide(mParentActor)))
offCollide(mParentActor);
}
if (isFlagValidOn(3, isInvalidClipping(mParentActor)))
invalidateClipping(mParentActor);
else if (isFlagValidOff(3, isInvalidClipping(mParentActor)))
validateClipping(mParentActor);
}
void ActionFlagCtrl::startCtrlSensor() {
if (!mHitSensorKeeper)
return;
for (s32 i = 0; i < mHitSensorKeeper->getSensorNum(); i++) {
ActionSensorCtrlInfo* sensor = mCurrentCtrlInfo->sensorCtrlInfoArray;
if (sensor[i].startFrame > 0) {
mIsUpdateNeeded = true;
continue;
}
if (sensor[i].endFrame > 0)
mIsUpdateNeeded = true;
switch (sensor[i].state) {
case CtrlFlag::ValidOn:
validateHitSensor(mParentActor, sensor[i].name);
break;
case CtrlFlag::ValidOff:
invalidateHitSensor(mParentActor, sensor[i].name);
break;
default:
break;
}
}
}
void ActionFlagCtrl::update(f32 frame, f32 frameRateMax, f32 frameRate, bool isStop) {
if (!mCurrentCtrlInfo || !mIsUpdateNeeded)
return;
if (!mHitSensorKeeper)
return;
updateCtrlSensor(frame, frameRate, frameMax, isStop);
updateCtrlSensor(frame, frameRateMax, frameRate, isStop);
}
void ActionFlagCtrl::updateCtrlSensor(f32 frame, f32 frameRateMax, f32 frameRate, bool isStop) {
for (s32 i = 0; i < mHitSensorKeeper->getSensorNum(); i++) {
ActionSensorCtrlInfo* ctrlInfo = mCurrentCtrlInfo->sensorCtrlInfoArray;
f32 startFrame = ctrlInfo[i].startFrame;
if (startFrame > 0 &&
alAnimFunction::checkPass(frame, frameRateMax, frameRate, isStop, startFrame))
validateHitSensor(mParentActor, ctrlInfo[i].name);
f32 endFrame = ctrlInfo[i].endFrame;
if (endFrame > 0 &&
alAnimFunction::checkPass(frame, frameRateMax, frameRate, isStop, endFrame))
invalidateHitSensor(mParentActor, ctrlInfo[i].name);
}
}
bool ActionFlagCtrl::isFlagValidOn(s32 index, bool isEnabled) const {
return mCurrentCtrlInfo && mCurrentCtrlInfo->ctrlFlags[index] == CtrlFlag::ValidOn &&
!isEnabled;
}
bool ActionFlagCtrl::isFlagValidOff(s32 index, bool isEnabled) const {
return mCurrentCtrlInfo && mCurrentCtrlInfo->ctrlFlags[index] == CtrlFlag::ValidOff &&
isEnabled;
}
} // namespace al

View file

@ -9,35 +9,58 @@ struct ActionAnimDataInfo;
class HitSensorKeeper;
class LiveActor;
struct ActionFlagCtrlInfo {
const char* name;
void* _8;
void* _10;
enum class CtrlFlag : s16 {
NotFound = 0,
ValidOff = 2,
ValidOn = 3,
};
struct ActionSensorCtrlInfo {
ActionSensorCtrlInfo();
const char* name = nullptr;
CtrlFlag state = CtrlFlag::NotFound;
s16 startFrame = -1;
s16 endFrame = -1;
};
static_assert(sizeof(ActionSensorCtrlInfo) == 0x10);
struct ActionFlagCtrlInfo {
ActionFlagCtrlInfo();
const char* actionName = nullptr;
CtrlFlag* ctrlFlags = nullptr;
ActionSensorCtrlInfo* sensorCtrlInfoArray = nullptr;
};
static_assert(sizeof(ActionFlagCtrlInfo) == 0x18);
class ActionFlagCtrl {
public:
static ActionFlagCtrl* tryCreate(LiveActor* actor, const char* name);
ActionFlagCtrl(LiveActor* actor, const char* name);
ActionFlagCtrlInfo* findFlagInfo(const char* name) const;
void initPost();
void start(const char* name);
ActionFlagCtrlInfo* findFlagInfo(const char* name) const;
void startCtrlFlag();
void startCtrlSensor();
void update(f32 frame, f32 frameRateMax, f32 frameRate, bool isStop);
void updateCtrlSensor(f32, f32, f32, bool);
bool isFlagValidOn(s32, bool);
bool isFlagValidOff(s32, bool);
void updateCtrlSensor(f32 frame, f32 frameRateMax, f32 frameRate, bool isStop);
bool isFlagValidOn(s32 index, bool isEnabled) const;
bool isFlagValidOff(s32 index, bool isEnabled) const;
private:
LiveActor* mParentActor;
const char* mName;
const char* mArchiveName;
HitSensorKeeper* mHitSensorKeeper = nullptr;
s32 mInfoCount = 0;
ActionFlagCtrlInfo** mInfos = nullptr;
ActionFlagCtrlInfo* mLastFlag = nullptr;
bool mIsBool = false;
ActionFlagCtrlInfo** mCtrlInfoArray = nullptr;
ActionFlagCtrlInfo* mCurrentCtrlInfo = nullptr;
bool mIsUpdateNeeded = false;
};
static_assert(sizeof(ActionFlagCtrl) == 0x38);
} // namespace al

View file

@ -3,6 +3,7 @@
#include <basis/seadTypes.h>
namespace al {
class AnimInfoTable;
struct ActionAnimCtrlInfo;
class InitResourceDataAnim;
class Resource;
@ -20,3 +21,8 @@ private:
ActionAnimCtrlInfo** mAnimInfos = nullptr;
};
} // namespace al
namespace alAnimFunction {
bool checkPass(f32, f32, f32, bool, f32);
al::AnimInfoTable* createAnimInfoTableIfNeed(const al::AnimInfoTable*, const al::AnimInfoTable*);
} // namespace alAnimFunction

View file

@ -56,6 +56,8 @@ public:
void update();
void addHitSensor(HitSensor* sensor);
const char* getName() const { return mName; }
void clearSensors() { mSensorCount = 0; }
const sead::Vector3f& getFollowPosOffset() const { return mFollowPosOffset; }