#ifndef D_A_FORMATION_MNG_H #define D_A_FORMATION_MNG_H #include "d/d_com_inf_game.h" #include "d/d_path.h" #include "d/actor/d_a_player.h" #include "d/d_kankyo.h" #include "SSystem/SComponent/c_math.h" struct daFmtMng_Path_c { bool checkPathEnd(cXyz, f32); bool checkPoint(cXyz, f32); bool isPathClose() { return dPath_ChkClose(mPath); } s8 getArg0() { return mPath->m_points[field_0x4].mArg0; } s8 getArg1() { return mPath->m_points[field_0x4].mArg1; } void chgDir() { int dir; if (field_0xc > 0) { dir = -1; } else { dir = 1; } field_0xc = dir; } void setPath(int param_1, int param_2, cXyz* param_3) { mPath = dPath_GetRoomPath(param_1, param_2); field_0x4 = 0; field_0xc = 1; field_0x8 = param_3->abs(dPath_GetPnt(mPath, field_0x4)->m_position); } void getStartPoint(Vec* param_1, SVec* param_2) { *param_1 = dPath_GetPnt(mPath, 0)->m_position; Vec local_2c = dPath_GetPnt(mPath, 1)->m_position; cXyz cStack_38(param_1->x, param_1->y + 200.0f, param_1->z); if (fopAcM_gc_c::gndCheck(&cStack_38)) { param_1->y = fopAcM_gc_c::getGroundY(); } param_2->x = 0; param_2->y = cLib_targetAngleY(param_1, &local_2c); param_2->z = 0; } void getTargetPoint(Vec* param_1) { *param_1 = dPath_GetPnt(mPath, field_0x4)->m_position; } int decIndex(int param_1) { param_1--; if (param_1 < 0) { if (isPathClose()) { param_1 = mPath->m_num - 1; } else { param_1 = 0; } } return param_1; } int incIndex(int param_1) { param_1++; if (param_1 >= mPath->m_num) { if (isPathClose()) { param_1 = 0; } else { param_1--; } } return param_1; } void setNextPoint() { if (field_0xc > 0) { field_0x4 = incIndex(field_0x4); } else { field_0x4 = decIndex(field_0x4); } field_0x8 = G_CM3D_F_INF; } void setNextPoint(cXyz *param_1) { setNextPoint(); field_0x8 = param_1->abs(dPath_GetPnt(mPath, field_0x4)->m_position); } /* 0x0 */ dPath* mPath; /* 0x4 */ int field_0x4; /* 0x8 */ f32 field_0x8; /* 0xC */ s8 field_0xc; }; struct FmtPos_c : public daFmtMng_Path_c { /* 0x10 */ cXyz field_0x10; /* 0x1C */ s16 field_0x1c; /* 0x1E */ s16 field_0x1e; }; struct FmtMember_c { /* 0x00 */ u32 mNpcId; /* 0x04 */ cXyz field_0x04; /* 0x10 */ cXyz field_0x10; /* 0x1C */ s16 field_0x1c; /* 0x1E */ u16 field_0x1e; }; enum FmtMngAction { MODE_0_e, MODE_1_e, MODE_2_e, MODE_3_e, MODE_4_e, MODE_MAX_e, }; struct FmtMngAttributes { /* 0x00 */ int field_0x00; /* 0x04 */ f32 field_0x04; /* 0x08 */ f32 field_0x08; /* 0x0C */ f32 field_0x0c; /* 0x10 */ f32 field_0x10; /* 0x14 */ s16 field_0x14; /* 0x16 */ s16 field_0x16; }; struct daFmtMng_c : public fopAc_ac_c { void initWait(); void initMemberPos(); void executeWait(); void initWalk(); void executeWalk(); void setMovePath(FmtPos_c*, int); void initReverse(); void executeReverse(); void initMotion(); void executeMotion(); void initFight(); void executeFight(); int create(); void create_init(); ~daFmtMng_c() { FmtMember_c* member = mMember; for (int i = 0; i < mFormationLine * mFormationRow; i++, member++) { fopAcM_delete(member->mNpcId); } delete [] mPos; delete [] mMember; } int getTimeHour() { if (dKy_darkworld_check()) { return dKy_getDarktime_hour(); } return dKy_getdaytime_hour(); } int getTimeMinute() { if (dKy_darkworld_check()) { return dKy_getDarktime_minute(); } return dKy_getdaytime_minute(); } int getTime() { return getTimeHour() * 60 + getTimeMinute(); } u8 getPathID() { return shape_angle.x; } u8 getFormationLine() { return fopAcM_GetParam(this) & 0xff; } u8 getFormationRow() { return (fopAcM_GetParam(this) >> 8) & 0xff; } int getStartTime() { return (fopAcM_GetParam(this) >> 16) & 0xff; } int getEndTime() { return (fopAcM_GetParam(this) >> 24) & 0xff; } void callExecute() { JUT_ASSERT(680, mAction != NULL); (this->*(mAction[1]))(); } bool checkEmergency() { if (dKy_darkworld_check() || !daPy_py_c::checkNowWolf()) { return false; } FmtMember_c* member = mMember; fopAc_ac_c* npcFgd = NULL; for (int i = 0; i < mFormationRow * mFormationLine; i++, member++) { fopAcM_SearchByID(member->mNpcId, &npcFgd); if (npcFgd != NULL) { cXyz* iVar6 = fopAcM_GetPosition_p(daPy_getPlayerActorClass()); f32 dVar10 = iVar6->y; cXyz* this_01 = fopAcM_GetPosition_p(npcFgd); if (this_01->y - dVar10 < 200.0f) { f32 maxDist = pow(500.0, 2.0); if (fopAcM_searchPlayerDistanceXZ2(npcFgd) < maxDist) { return true; } } } } return false; } void callInit() { JUT_ASSERT(667, mAction != NULL) (this->*(*mAction))(); } void setAction(int i_action) { JUT_ASSERT(633, i_action < MODE_MAX_e); mPrevAction = mCurrentAction; mCurrentAction = i_action; mAction = &((ActionFunc*)ActionTable)[mCurrentAction * 2]; callInit(); } int execute() { callExecute(); if (mCurrentAction != MODE_4_e && checkEmergency()) { setAction(MODE_4_e); } return 1; } bool isAllMemberCulling() { FmtMember_c* member = mMember; bool memberCulling; fopAc_ac_c* npcFgd = NULL; for (int i = 0; i < mFormationRow * mFormationLine; i++, member++) { memberCulling = false; if (member->mNpcId != -1) { fopAcM_SearchByID(member->mNpcId, &npcFgd); if (npcFgd != NULL) { memberCulling = fopAcM_CheckCondition(npcFgd, 4); } if (!memberCulling) { return false; } } } return true; } void setMoveSpeed() { speedF += attr().field_0x08; if (speedF > attr().field_0x04) { speedF = attr().field_0x04; } } void setMoveAngle(FmtPos_c* member) { if (speedF <= 0.0f) { return; } cXyz acStack_28; member->getTargetPoint(&acStack_28); cLib_addCalcAngleS2(&member->field_0x1c, cLib_targetAngleY(&member->field_0x10, &acStack_28), attr().field_0x14, attr().field_0x16); } void setMovePos(cXyz* param_1, s16* param_2) { param_1->x += speedF * cM_ssin(*param_2); param_1->z += speedF * cM_scos(*param_2); } void correctFormation() { FmtPos_c* pos = mPos + 1; for (int i = 1; i < mFormationRow; i++, pos++) { if (cLib_distanceAngleS(pos[-1].field_0x1c, pos[0].field_0x1c) <= attr().field_0x00) { pos[0].field_0x10.set(0.0f, 0.0f, -attr().field_0x10); mDoMtx_stack_c::transS(pos[-1].field_0x10); mDoMtx_stack_c::YrotM(pos[-1].field_0x1c); mDoMtx_stack_c::multVec(&pos[0].field_0x10, &pos[0].field_0x10); } } } void setMemberPos() { int j; FmtPos_c* pos; fopAc_ac_c* npcFgd; FmtMember_c* member; int i; pos = mPos; member = mMember; for (i = 0; i < mFormationRow; i++, pos++) { f32 dVar13 = (mFormationLine - 1) * attr().field_0x0c * 0.5f; mDoMtx_stack_c::transS(pos->field_0x10); mDoMtx_stack_c::YrotM(pos->field_0x1c); for (j = 0; j < mFormationLine; j++, member++) { member->field_0x10.set(member->field_0x04); member->field_0x04.set(dVar13, 0.0f, 0.0f); mDoMtx_stack_c::multVec(&member->field_0x04, &member->field_0x04); dVar13 -= attr().field_0x0c; npcFgd = NULL; fopAcM_SearchByID(member->mNpcId, &npcFgd); if (npcFgd != NULL) { cXyz* npcPos = fopAcM_GetPosition_p(npcFgd); csXyz* npcAngle = fopAcM_GetShapeAngle_p(npcFgd); npcPos->x = member->field_0x04.x; npcPos->z = member->field_0x04.z; cLib_addCalcAngleS2(&npcAngle->y, cLib_targetAngleY(&member->field_0x10, &member->field_0x04), attr().field_0x14, attr().field_0x16); fopAcM_SetSpeedF(npcFgd, member->field_0x10.abs(member->field_0x04)); } } } } static FmtMngAttributes const& attr() { return M_attr; } static FmtMngAttributes const M_attr; typedef void (daFmtMng_c::*ActionFunc)(); static daFmtMng_c::ActionFunc ActionTable[10]; /* 0x568 */ FmtPos_c* mPos; /* 0x56C */ FmtMember_c* mMember; /* 0x570 */ dPath* mRoomPath; /* 0x574 */ ActionFunc* mAction; /* 0x578 */ int mCurrentAction; /* 0x57C */ int mPrevAction; /* 0x580 */ int field_0x580; /* 0x584 */ int mFormationLine; /* 0x588 */ int mFormationRow; /* 0x58C */ int mStartTime; /* 0x590 */ int mEndTime; /* 0x594 */ int mDayOfWeek; /* 0x598 */ int field_0x598; /* 0x59C */ int field_0x59c; /* 0x5A0 */ int field_0x5a0; }; #endif /* D_A_FORMATION_MNG_H */