#ifndef D_CS_GAME_H #define D_CS_GAME_H #include "common.h" #include "d/d_cs.h" #include "d/d_cursor_hit_check.h" #include "d/lyt/d2d.h" #include "m/m2d.h" #include "m/m_vec.h" #include "nw4r/lyt/lyt_pane.h" #include "s/s_FStateID.hpp" #include "s/s_State.hpp" #include "s/s_StateID.hpp" #include "toBeSorted/d_emitter.h" #include "toBeSorted/d_emitter_callbacks.h" /** A variant of the cursor position getter for dCsGame_c */ class dCursorInterfaceGame_c : public dCursorInterface_c { public: dCursorInterfaceGame_c() {} virtual ~dCursorInterfaceGame_c() {} virtual mVec2_c &getCursorPos(); private: /* 0x14 */ mVec2_c field_0x14; }; // TODO - these could also be in the dCsGame_c namespace // TODO - rename these class dCsGameLytBase1_c { public: virtual ~dCsGameLytBase1_c() {} /* 0x0C */ virtual void setPosition(const mVec2_c &pos) { mPosition = pos; } /* 0x10 */ virtual bool init() = 0; /* 0x14 */ virtual bool remove() = 0; /* 0x18 */ virtual bool execute() = 0; /* 0x1C */ virtual bool draw() = 0; protected: /* 0x04 */ mVec2_c mPosition; }; class dCsGameLytBase2_c : public dCsGameLytBase1_c { public: virtual ~dCsGameLytBase2_c() {} /* 0x10 */ virtual bool init(); /* 0x14 */ virtual bool remove() = 0; /* 0x18 */ virtual bool execute(); /* 0x1C */ virtual bool draw(); /* 0x20 */ virtual void loadResAcc() = 0; /* 0x24 */ virtual void build() = 0; /* 0x28 */ virtual d2d::LytBase_c *getLyt() = 0; protected: }; class dCsGameLyt1_c : public dCsGameLytBase2_c { public: dCsGameLyt1_c() : mpResAcc(nullptr) {} virtual ~dCsGameLyt1_c() {} virtual bool init() override; virtual bool remove() override; virtual void loadResAcc() override; virtual void build() override; virtual d2d::LytBase_c *getLyt() override { return &mLyt; } void setResAcc(m2d::ResAccIf_c *resAcc) { mpResAcc = resAcc; } void setPriorityDraw(u8 priority) { mLyt.setPriority(priority); } private: /* 0x0C */ m2d::ResAccIf_c *mpResAcc; /* 0x10 */ d2d::LytBase_c mLyt; }; class dCsGameLyt2_c : public dCsGameLytBase2_c { public: dCsGameLyt2_c() : mpResAcc(nullptr) {} virtual ~dCsGameLyt2_c() {} virtual bool init() override; virtual bool remove() override; virtual void loadResAcc() override; virtual void build() override; virtual d2d::LytBase_c *getLyt() override { return &mLyt; } void setResAcc(m2d::ResAccIf_c *resAcc) { mpResAcc = resAcc; } void setPriorityDraw(u8 priority) { mLyt.setPriority(priority); } private: /* 0x0C */ m2d::ResAccIf_c *mpResAcc; /* 0x10 */ d2d::LytBase_c mLyt; }; /// @brief Game cursor. class dCsGame_c : public dCs_c { public: enum CursorType_e { CS_NONE = 0, /** Default pointer */ CS_POINTER_DEF = 1, /** Grab pointer */ CS_POINTER_CAT = 2, CS_BOW = 6, CS_DOWSING = 7, CS_VACUUM = 8, CS_PACHINKO = 9, CS_HOOKSHOT = 10, CS_PLAYERCAM = 14, }; dCsGame_c(); virtual ~dCsGame_c(); virtual int create() override; virtual int doDelete() override; virtual int execute() override; virtual int draw() override; static dCsGame_c *GetInstance() { return sInstance; } bool shouldDraw() const; /// @brief Item cursor. class lytItemCursor_c : public dCsGameLytBase2_c { friend class dCsGame_c; public: /// @brief Bow cursor. class lytBowCsr_c { public: lytBowCsr_c(d2d::AnmGroups g, d2d::LytBase_c *lyt) : mAnm(g), mpLyt(lyt), mStateMgr(*this), field_0x50(0.0f), field_0x54(0.0f) {} virtual ~lytBowCsr_c() {} void init(); void enter(); inline void select() { // TODO this function might be breaking vtable order mStateMgr.changeState(StateID_Select); } void execute(); void startDrawOrCharge(f32 f1, f32 f2); void aimStart(); void ready(); private: STATE_FUNC_DECLARE(lytBowCsr_c, Invisible); STATE_FUNC_DECLARE(lytBowCsr_c, Select); STATE_FUNC_DECLARE(lytBowCsr_c, Ready); STATE_FUNC_DECLARE(lytBowCsr_c, ToAimStart); STATE_FUNC_DECLARE(lytBowCsr_c, AimStart); STATE_FUNC_DECLARE(lytBowCsr_c, Draw); STATE_FUNC_DECLARE(lytBowCsr_c, Charge); /* 0x04 */ UI_STATE_MGR_DECLARE(lytBowCsr_c); /* 0x40 */ d2d::AnmGroups mAnm; /* 0x4C */ d2d::LytBase_c *mpLyt; /* 0x50 */ f32 field_0x50; /* 0x54 */ f32 field_0x54; /* 0x58 */ nw4r::lyt::Pane *mpPanesArrowRing[4]; }; /// @brief Dowsing cursor. class lytDowsingCsr_c { public: lytDowsingCsr_c(d2d::AnmGroups g, d2d::LytBase_c *lyt) : mAnm(g), mpLyt(lyt), mStateMgr(*this), mpRingAllPane(nullptr), mpDowsingPane(nullptr), field_0xC0(0.0f), field_0xC4(0), mRotZ(0), field_0xCC(0.0f), field_0xD0(0.0f), mAlpha(0) {} virtual ~lytDowsingCsr_c() {} void init(); void enter(); void execute(); void setParams(const mAng &rot, f32 v1, f32 v2); void setUnkWord(UNKWORD v); void moveEffectsIn(); void moveEffectsOut(); void updateEffects(); private: STATE_FUNC_DECLARE(lytDowsingCsr_c, NotFind); STATE_FUNC_DECLARE(lytDowsingCsr_c, ToFind); STATE_FUNC_DECLARE(lytDowsingCsr_c, Find); STATE_FUNC_DECLARE(lytDowsingCsr_c, FindMinimum); STATE_FUNC_DECLARE(lytDowsingCsr_c, ToNotFind); /* 0x04 */ UI_STATE_MGR_DECLARE(lytDowsingCsr_c); /* 0x40 */ d2d::AnmGroups mAnm; /* 0x4C */ d2d::LytBase_c *mpLyt; /* 0x50 */ dEmitter_c mEffects1; /* 0x84 */ dEmitter_c mEffects2; /* 0xB8 */ nw4r::lyt::Pane *mpRingAllPane; /* 0xBC */ nw4r::lyt::Pane *mpDowsingPane; /* 0xC0 */ f32 field_0xC0; /* 0xC4 */ UNKWORD field_0xC4; /* 0xC8 */ mAng mRotZ; /* 0xCC */ f32 field_0xCC; /* 0xD0 */ f32 field_0xD0; /* 0xD4 */ u32 mAlpha; }; /// @brief Slingshot cursor. class lytPachinkoCsr_c { public: lytPachinkoCsr_c(d2d::AnmGroups g, d2d::LytBase_c *lyt) : mAnm(g), mpLyt(lyt), mStateMgr(*this), mIsCharging(false), mDrawProgress(0.0f), mSavedOnProgress(0.0f) {} virtual ~lytPachinkoCsr_c() {} void init(); // void enter(); void execute(); void setCharging(bool charging, f32 progress); private: STATE_FUNC_DECLARE(lytPachinkoCsr_c, Invisible); STATE_FUNC_DECLARE(lytPachinkoCsr_c, Select); STATE_FUNC_DECLARE(lytPachinkoCsr_c, ToDraw); STATE_FUNC_DECLARE(lytPachinkoCsr_c, Draw); STATE_FUNC_DECLARE(lytPachinkoCsr_c, Out); STATE_FUNC_DECLARE(lytPachinkoCsr_c, Charge); STATE_FUNC_DECLARE(lytPachinkoCsr_c, ChargeFull); /* 0x04 */ UI_STATE_MGR_DECLARE(lytPachinkoCsr_c); /* 0x40 */ d2d::AnmGroups mAnm; /* 0x4C */ d2d::LytBase_c *mpLyt; /* 0x50 */ bool mIsCharging; /* 0x54 */ f32 mDrawProgress; /* 0x58 */ f32 mSavedOnProgress; }; /// @brief Clawshots cursor. class lytCrawShotCsr_c { public: lytCrawShotCsr_c(d2d::AnmGroups g, d2d::LytBase_c *lyt) : mAnm(g), mpLyt(lyt), mStateMgr(*this), mLocked(false) {} virtual ~lytCrawShotCsr_c() {} void init(); void enter(); void execute(); void setLocked(bool locked); void setRotate(f32 rot); private: STATE_FUNC_DECLARE(lytCrawShotCsr_c, Normal); STATE_FUNC_DECLARE(lytCrawShotCsr_c, ToLock); STATE_FUNC_DECLARE(lytCrawShotCsr_c, Lock); STATE_FUNC_DECLARE(lytCrawShotCsr_c, ToNormal); /* 0x04 */ UI_STATE_MGR_DECLARE(lytCrawShotCsr_c); /* 0x40 */ d2d::AnmGroups mAnm; /* 0x4C */ d2d::LytBase_c *mpLyt; /* 0x50 */ u8 field_0x50[0x54 - 0x50]; /* 0x54 */ bool mLocked; /* 0x58 */ nw4r::lyt::Pane *mpPaneCrawFix; /* 0x5C */ nw4r::lyt::Pane *mpPaneCraws[3]; /* 0x68 */ f32 field_0x68; }; /// @brief Gust Bellows cursor. class lytVacuumCsr_c { public: lytVacuumCsr_c(d2d::AnmGroups g, d2d::LytBase_c *lyt) : mAnm(g), mpLyt(lyt), mStateMgr(*this), mLocked(false) {} virtual ~lytVacuumCsr_c() {} void init(); void enter(); void execute(); void setUnkFloat(f32 f); void setLocked(bool locked); private: STATE_FUNC_DECLARE(lytVacuumCsr_c, Normal); STATE_FUNC_DECLARE(lytVacuumCsr_c, ToLock); STATE_FUNC_DECLARE(lytVacuumCsr_c, Lock); STATE_FUNC_DECLARE(lytVacuumCsr_c, ToNormal); /* 0x04 */ UI_STATE_MGR_DECLARE(lytVacuumCsr_c); /* 0x40 */ d2d::AnmGroups mAnm; /* 0x4C */ d2d::LytBase_c *mpLyt; /* 0x50 */ u8 field_0x50[0x54 - 0x50]; /* 0x54 */ f32 field_0x54; /* 0x58 */ u8 field_0x58[0x5C - 0x58]; /* 0x5C */ bool mLocked; }; public: lytItemCursor_c() : mStateMgr(*this), mAnm(mAnmGroups.tmp.mAnmGroups, 0x17), mBow(mAnm, &mLyt), mDowsing(mAnm, &mLyt), mPachinko(mAnm, &mLyt), mCrawShot(mAnm, &mLyt), mVacuum(mAnm, &mLyt) {} virtual ~lytItemCursor_c() {} virtual bool init() override; virtual bool remove() override; virtual bool execute() override; virtual void loadResAcc() override; virtual void build() override; virtual d2d::LytBase_c *getLyt() override { return &mLyt; } void setResAcc(m2d::ResAccIf_c *resAcc) { mpResAcc = resAcc; } void setPriorityDraw(u8 priority) { mLyt.setPriority(priority); } void changeState(const sFStateID_c &newState); void pachinkoSetCharging(bool charging, f32 progress); void dowsingSetParams(const mAng &rot, f32 v1, f32 v2); void dowsingSetUnkWord(UNKWORD v); void vacuumSetUnkFloat(f32 v); void vacuumSetLocked(bool locked); void clawshotsSetLocked(bool locked); void bowStartDrawOrCharge(f32 f1, f32 f2); void bowAimStart(); void bowReady(); private: STATE_FUNC_DECLARE(lytItemCursor_c, Invisible); STATE_FUNC_DECLARE(lytItemCursor_c, Bow); STATE_FUNC_DECLARE(lytItemCursor_c, Dowsing); STATE_FUNC_DECLARE(lytItemCursor_c, Vacuum); STATE_FUNC_DECLARE(lytItemCursor_c, Pachinko); STATE_FUNC_DECLARE(lytItemCursor_c, HookShot); STATE_FUNC_DECLARE(lytItemCursor_c, PlayerCam); /* 0x00C */ UI_STATE_MGR_DECLARE(lytItemCursor_c); template class Tmp { public: d2d::AnmGroup_c mAnmGroups[N]; }; class dCsGameAnmGroups_c { public: dCsGameAnmGroups_c() {} virtual ~dCsGameAnmGroups_c() {} d2d::AnmGroup_c &operator[](int idx) { return tmp.mAnmGroups[idx]; } Tmp<0x17> tmp; }; /* 0x048 */ dEmitter_c mEffects; /* 0x07C */ dEmitterCallbackCursorTrail_c mTrailCb; /* 0x0B0 */ mVec3_c mPositionThisFrame; /* 0x0BC */ mVec3_c mPositionLastFrame; /* 0x0C8 */ m2d::ResAccIf_c *mpResAcc; /* 0x0CC */ d2d::LytBase_c mLyt; /* 0x15C */ dCsGameAnmGroups_c mAnmGroups; /* 0x720 */ d2d::AnmGroups mAnm; /* 0x72C */ lytBowCsr_c mBow; /* 0x794 */ lytDowsingCsr_c mDowsing; /* 0x86C */ lytPachinkoCsr_c mPachinko; /* 0x8C8 */ lytCrawShotCsr_c mCrawShot; /* 0x934 */ lytVacuumCsr_c mVacuum; /* 0x994 */ u8 field_0x994[0x99C - 0x994]; // seemingly not used /* 0x99C */ bool mDrawCursorTrailThisFrame; /* 0x99D */ u8 field_0x99D[0x9A0 - 0x99D]; // Havent seen this range be set }; void setNextCursorType(CursorType_e); void noneSet(); void pointerDefSet(); void pointerCatSet(); void pachinkoSetCharging(bool charging, f32 progress); void dowsingSetParams(const mAng &rot, f32 v1, f32 v2); void dowsingSetUnkWord(UNKWORD v); void vacuumSetNotLocked(f32 v); void vacuumSetLocked(); void clawshotsSetLocked(bool locked); void bowStartDrawOrCharge(f32 f1, f32 f2); void bowAimStart(); void bowReady(); void setCursorTypePlayerCam(); bool isCursorActive() const { return mCursorActive; } void setField_0x9A2(bool value) { field_0x9A2 = value; } void offNextCursor() { mNextCursorActive = false; } dCursorHitCheck_c *getCursorHit() const { return mCursorIf.getHit(); } dCursorInterfaceGame_c *getCursorIf() { return &mCursorIf; } void setPriorityDraw(u8 priority) { mLyt1.setPriorityDraw(priority); mLyt2.setPriorityDraw(priority); mCursor.setPriorityDraw(priority); } private: static dCsGame_c *sInstance; bool isForcedHidden() const; /* 0x068 */ m2d::ResAccIf_c mCursorResAcc; /* 0x11C */ m2d::ResAccIf_c mMain2DResAcc; /* 0x1D0 */ dCursorInterfaceGame_c mCursorIf; /* 0x1EC */ CursorType_e mCursorType; /* 0x1F0 */ dCsGameLyt1_c mLyt1; /* 0x290 */ dCsGameLyt2_c mLyt2; /* 0x330 */ lytItemCursor_c mCursor; /* 0xCD0 */ bool mCursorActive; /* 0xCD1 */ bool field_0x9A1; // Compares to mCursorActive to change state /* 0xCD2 */ bool field_0x9A2; // A way of signalling Lyt non-normal state. /* 0xCD4 */ CursorType_e mActiveCursorType; /* 0xCD8 */ bool mNextCursorActive; /* 0xCDC */ CursorType_e mNextCursorType; }; #endif