mirror of
https://github.com/zeldaret/ss
synced 2026-08-19 22:02:02 -04:00
Merge pull request #50 from robojumper/state_system
Port and match the NSMBW state system, match 1½ RELs with that state system
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
#include <d/tg/d_t_rock_boat.h>
|
||||
#include <d/a/obj/d_a_obj_base.h>
|
||||
|
||||
SPECIAL_ACTOR_PROFILE(TAG_ROCK_BOAT, dTgRockBoat_c, fProfile::TAG_ROCK_BOAT, 0x173, 0, 3);
|
||||
|
||||
STATE_DEFINE(dTgRockBoat_c, Wait);
|
||||
|
||||
int dTgRockBoat_c::create() {
|
||||
mStateMgr.changeState(StateID_Wait);
|
||||
cooldown = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dTgRockBoat_c::doDelete() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dTgRockBoat_c::actorExecute() {
|
||||
mStateMgr.executeState();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dTgRockBoat_c::draw() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dTgRockBoat_c::initializeState_Wait() {}
|
||||
void dTgRockBoat_c::executeState_Wait() {
|
||||
if (cooldown > 0 && --cooldown == 0) {
|
||||
dAcObjBase_c::create(fProfile::OBJ_ROCK_BOAT, roomid, (boatNum << 0x1c) | 0xff, &position, 0, 0, -1);
|
||||
cooldown = 0x259;
|
||||
if (++boatNum == 0xf) {
|
||||
boatNum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
void dTgRockBoat_c::finalizeState_Wait() {}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
#include <c/c_math.h>
|
||||
#include <d/tg/d_t_tumble_weed.h>
|
||||
#include <m/m_vec.h>
|
||||
|
||||
SPECIAL_ACTOR_PROFILE(TAG_TUMBLE_WEED, dTgTumbleWeed_c, fProfile::TUMBLE_WEED_TAG, 0x0244, 0, 0);
|
||||
|
||||
STATE_DEFINE(dTgTumbleWeed_c, AreaOut);
|
||||
STATE_DEFINE(dTgTumbleWeed_c, AreaIn);
|
||||
STATE_DEFINE(dTgTumbleWeed_c, Wind);
|
||||
|
||||
int dTgTumbleWeed_c::create() {
|
||||
tumbleweedTimer = 0;
|
||||
windTimer = 0x96;
|
||||
mStateMgr.changeState(StateID_AreaOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
u16 decr(u16 *num);
|
||||
|
||||
int dTgTumbleWeed_c::doDelete() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dTgTumbleWeed_c::actorExecute() {
|
||||
mStateMgr.executeState();
|
||||
decr(&tumbleweedTimer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
u16 decr(u16 *num) {
|
||||
if (*num != 0) {
|
||||
(*num)--;
|
||||
}
|
||||
return *num;
|
||||
}
|
||||
|
||||
int dTgTumbleWeed_c::draw() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dTgTumbleWeed_c::initializeState_AreaOut() {}
|
||||
void dTgTumbleWeed_c::executeState_AreaOut() {
|
||||
if (decr(&windTimer) == 0) {
|
||||
windTimer = 0x96;
|
||||
if (shouldDoWind()) {
|
||||
mStateMgr.changeState(StateID_Wind);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isWithinPlayerRadius(scale.x)) {
|
||||
mStateMgr.changeState(StateID_AreaIn);
|
||||
}
|
||||
}
|
||||
void dTgTumbleWeed_c::finalizeState_AreaOut() {}
|
||||
|
||||
void dTgTumbleWeed_c::initializeState_AreaIn() {}
|
||||
void dTgTumbleWeed_c::executeState_AreaIn() {
|
||||
if (tumbleweedTimer == 0) {
|
||||
if (shouldSpawnTumbleweed()) {
|
||||
doSpawnTumbleweed();
|
||||
}
|
||||
tumbleweedTimer = 600;
|
||||
}
|
||||
if (decr(&windTimer) == 0) {
|
||||
windTimer = 0x96;
|
||||
if (shouldDoWind()) {
|
||||
mStateMgr.changeState(StateID_Wind);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isWithinPlayerRadius(scale.x)) {
|
||||
mStateMgr.changeState(StateID_AreaOut);
|
||||
}
|
||||
}
|
||||
void dTgTumbleWeed_c::finalizeState_AreaIn() {}
|
||||
|
||||
extern "C" void fn_475_1B00(fBase_c *, mVec3_c&);
|
||||
void dTgTumbleWeed_c::initializeState_Wind() {
|
||||
mVec3_c vec;
|
||||
getWind(&vec);
|
||||
if (childTumbleweed.p_owner != nullptr) {
|
||||
fn_475_1B00(childTumbleweed.p_owner, vec);
|
||||
}
|
||||
}
|
||||
|
||||
void dTgTumbleWeed_c::executeState_Wind() {
|
||||
if (isWithinPlayerRadius(scale.x)) {
|
||||
mStateMgr.changeState(StateID_AreaIn);
|
||||
} else {
|
||||
mStateMgr.changeState(StateID_AreaOut);
|
||||
}
|
||||
}
|
||||
void dTgTumbleWeed_c::finalizeState_Wind() {}
|
||||
|
||||
bool dTgTumbleWeed_c::shouldSpawnTumbleweed() {
|
||||
bool spawnAllowed = false;
|
||||
if (childTumbleweed.p_owner == nullptr && cM::rnd() <= 0.8f) {
|
||||
spawnAllowed = true;
|
||||
}
|
||||
|
||||
if (spawnAllowed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool dTgTumbleWeed_c::shouldDoWind() {
|
||||
return childTumbleweed.p_owner != nullptr && cM::rnd() <= 0.5f;
|
||||
}
|
||||
void dTgTumbleWeed_c::doSpawnTumbleweed() {
|
||||
}
|
||||
void dTgTumbleWeed_c::getWind(mVec3_c*) {}
|
||||
|
||||
+2
-3
@@ -24,7 +24,6 @@ void (*fBase_c::sUnloadCallback)();
|
||||
fBase_c::fBase_c()
|
||||
: unique_ID(m_rootUniqueID), params(m_tmpCtData.params), profile_name(m_tmpCtData.prof_name),
|
||||
group_type(m_tmpCtData.group_type), manager(this) {
|
||||
fManager_c *mgr = &manager;
|
||||
|
||||
m_rootUniqueID = (fBaseID_e)(m_rootUniqueID + 1);
|
||||
if (m_rootUniqueID == INVALID) {
|
||||
@@ -33,8 +32,8 @@ fBase_c::fBase_c()
|
||||
}
|
||||
}
|
||||
|
||||
fManager_c::m_connectManage.addTreeNode(&mgr->connect_node, m_tmpCtData.connect_parent);
|
||||
int searchTableIdx = mgr->getSearchTableNum();
|
||||
fManager_c::m_connectManage.addTreeNode(&manager.connect_node, m_tmpCtData.connect_parent);
|
||||
int searchTableIdx = manager.getSearchTableNum();
|
||||
fManager_c::m_searchManage[searchTableIdx].prepend(&manager.search_node);
|
||||
|
||||
const fProfile::fBaseProfile_c *profile = (*fProfile::sProfileList)[profile_name];
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <s/s_Phase.hpp>
|
||||
|
||||
// Note: Ported from https://github.com/NSMBW-Community/NSMBW-Decomp/tree/master/include/dol/sLib
|
||||
// See include/s/README.txt for changes made
|
||||
|
||||
sPhase_c::sPhase_c(phaseMethod **methodList, int count) {
|
||||
mpMethodList = methodList;
|
||||
mPhaseLength = count;
|
||||
mCurrMethod = 0;
|
||||
}
|
||||
|
||||
sPhase_c::METHOD_RESULT_e sPhase_c::callMethod(void *thisPtr) {
|
||||
if (mCurrMethod >= mPhaseLength) {
|
||||
return DONE;
|
||||
}
|
||||
|
||||
METHOD_RESULT_e result = OK;
|
||||
while (result == OK) {
|
||||
result = (mpMethodList[mCurrMethod])(thisPtr);
|
||||
|
||||
if (result == OK) {
|
||||
// Go to the next method
|
||||
mCurrMethod++;
|
||||
if (mCurrMethod >= mPhaseLength) {
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <common.h>
|
||||
#include <s/s_StateInterfaces.hpp>
|
||||
#include <s/s_StateID.hpp>
|
||||
#include <s/s_StateMethodUsr_FI.hpp>
|
||||
#include <s/s_StateIDChk.hpp>
|
||||
|
||||
// Note: Ported from https://github.com/NSMBW-Community/NSMBW-Decomp/tree/master/include/dol/sLib
|
||||
// See include/s/README.txt for changes made
|
||||
|
||||
sStateID_c::NumberMemo_c sStateID_c::sm_numberMemo;
|
||||
sStateID_c sStateID::null(nullptr);
|
||||
|
||||
sStateID_c::sStateID_c(const char *name) {
|
||||
mpName = name;
|
||||
mNumber = (name != nullptr) ? sm_numberMemo.get() : 0;
|
||||
}
|
||||
|
||||
sStateID_c::~sStateID_c() {}
|
||||
|
||||
bool sStateID_c::isNull() const {
|
||||
return mNumber == 0;
|
||||
}
|
||||
|
||||
bool sStateID_c::isEqual(const sStateIDIf_c &other) const {
|
||||
return number() == other.number();
|
||||
}
|
||||
|
||||
bool sStateID_c::operator==(const sStateIDIf_c &other) const {
|
||||
return isEqual(other);
|
||||
}
|
||||
|
||||
bool sStateID_c::operator!=(const sStateIDIf_c &other) const {
|
||||
return !isEqual(other);
|
||||
}
|
||||
|
||||
bool sStateID_c::isSameName(const char *name) const {
|
||||
// Just return false, the full implementation is in sFStateID_c
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *sStateID_c::name() const {
|
||||
return mpName;
|
||||
}
|
||||
|
||||
unsigned int sStateID_c::number() const {
|
||||
return mNumber;
|
||||
}
|
||||
|
||||
sStateFctIf_c::~sStateFctIf_c() {}
|
||||
sStateIDChkIf_c::~sStateIDChkIf_c() {}
|
||||
sStateIDChk_c::~sStateIDChk_c() {}
|
||||
sStateIDIf_c::~sStateIDIf_c() {}
|
||||
sStateIf_c::~sStateIf_c() {}
|
||||
sStateMethodIf_c::~sStateMethodIf_c() {}
|
||||
sStateMethodUsr_FI_c::~sStateMethodUsr_FI_c() {}
|
||||
sStateMgrIf_c::~sStateMgrIf_c() {}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <common.h>
|
||||
#include <s/s_StateInterfaces.hpp>
|
||||
#include <s/s_StateMethod.hpp>
|
||||
#include <s/s_StateID.hpp>
|
||||
|
||||
// Note: Ported from https://github.com/NSMBW-Community/NSMBW-Decomp/tree/master/include/dol/sLib
|
||||
// See include/s/README.txt for changes made
|
||||
|
||||
sStateMethod_c::sStateMethod_c(sStateIDChkIf_c &checker, sStateFctIf_c &factory, const sStateIDIf_c &initialState) :
|
||||
mpStateChk(checker),
|
||||
mpStateFct(factory),
|
||||
mInitFinalizeLock(false),
|
||||
mExecutionLock(false),
|
||||
mIsValid(false),
|
||||
mStateChanged(false),
|
||||
mRefreshStateMethod(false),
|
||||
mpNewStateID(&initialState),
|
||||
mpOldStateID(&sStateID::null),
|
||||
mpStateID(&initialState),
|
||||
mpState(nullptr) {
|
||||
}
|
||||
|
||||
sStateMethod_c::~sStateMethod_c() {}
|
||||
|
||||
void sStateMethod_c::initializeStateMethod() {
|
||||
if (!mpNewStateID->isNull() && !mInitFinalizeLock && !mIsValid) {
|
||||
mInitFinalizeLock = true;
|
||||
|
||||
mpStateID = mpNewStateID;
|
||||
int ret = initializeStateLocalMethod();
|
||||
if (ret != 0) {
|
||||
mIsValid = true;
|
||||
} else {
|
||||
mIsValid = false;
|
||||
}
|
||||
|
||||
mInitFinalizeLock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void sStateMethod_c::executeStateMethod() {
|
||||
if (!mExecutionLock) {
|
||||
// Skyward Sword change: Prevent runaway state changes?
|
||||
int i = 2;
|
||||
do {
|
||||
if (mRefreshStateMethod) {
|
||||
i--;
|
||||
}
|
||||
mRefreshStateMethod = false;
|
||||
// We only want to execute if we have a valid next state
|
||||
if (!mpNewStateID->isNull()) {
|
||||
mExecutionLock = true;
|
||||
executeStateLocalMethod();
|
||||
mExecutionLock = false;
|
||||
}
|
||||
} while (mRefreshStateMethod && mStateChanged && i);
|
||||
}
|
||||
}
|
||||
|
||||
void sStateMethod_c::finalizeStateMethod() {
|
||||
if (!mpNewStateID->isNull() && mIsValid && !mInitFinalizeLock) {
|
||||
mInitFinalizeLock = true;
|
||||
|
||||
mpOldStateID = mpStateID;
|
||||
finalizeStateLocalMethod();
|
||||
mIsValid = false;
|
||||
|
||||
mInitFinalizeLock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void sStateMethod_c::changeStateMethod(const sStateIDIf_c &newID) {
|
||||
if (!newID.isNull()) {
|
||||
mpNewStateID = &newID;
|
||||
changeStateLocalMethod(newID);
|
||||
mStateChanged = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <common.h>
|
||||
#include <s/s_StateMethodUsr_FI.hpp>
|
||||
|
||||
// Note: Ported from https://github.com/NSMBW-Community/NSMBW-Decomp/tree/master/include/dol/sLib
|
||||
// See include/s/README.txt for changes made
|
||||
|
||||
sStateMethodUsr_FI_c::sStateMethodUsr_FI_c(sStateIDChkIf_c &check, sStateFctIf_c &factory, const sStateIDIf_c &state) :
|
||||
sStateMethod_c(check, factory, state) {
|
||||
}
|
||||
|
||||
int sStateMethodUsr_FI_c::initializeStateLocalMethod() {
|
||||
mpState = mpStateFct.build(*getNewStateID()); // Create new state holder with the next state ID
|
||||
mpState->initialize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sStateMethodUsr_FI_c::executeStateLocalMethod() {
|
||||
initializeStateMethod(); // Ensure we are in a valid state (this only actually initializes the state if !mIsValid)
|
||||
mpState->execute();
|
||||
}
|
||||
|
||||
void sStateMethodUsr_FI_c::finalizeStateLocalMethod() {
|
||||
mpState->finalize();
|
||||
mpStateFct.dispose(mpState);
|
||||
}
|
||||
|
||||
void sStateMethodUsr_FI_c::changeStateLocalMethod(const sStateIDIf_c &newID) {
|
||||
finalizeStateMethod(); // Terminate the current state
|
||||
initializeStateMethod(); // Initialize the new state
|
||||
}
|
||||
Reference in New Issue
Block a user