1#include <game/bases/d_wm_enemy.hpp>
2#include <game/bases/d_wm_lib.hpp>
3#include <game/bases/d_wm_se_manager.hpp>
4#include <game/bases/d_wm_effect_manager.hpp>
5#include <game/bases/d_a_wm_map.hpp>
6#include <game/bases/d_a_wm_player.hpp>
7#include <game/bases/d_s_world_map_static.hpp>
8#include <game/bases/d_cs_seq_manager.hpp>
9#include <game/bases/d_game_com.hpp>
10#include <game/bases/d_info.hpp>
12const char *dWmEnemy_c::smc_PathPointA[WORLD_USED_COUNT] = {
13 "Fa00",
"Fa01",
"Fa02",
"Fa03",
"Fa04",
14 "Fa05",
"Fa06",
"Fa07",
"Fa08"
16const char *dWmEnemy_c::smc_PathPointB[WORLD_USED_COUNT] = {
17 "Fb00",
"Fb01",
"Fb02",
"Fb03",
"Fb04",
18 "Fb05",
"Fb06",
"Fb07",
"Fb08"
20const char *dWmEnemy_c::smc_PathPointC[WORLD_USED_COUNT] = {
21 "Fc00",
"Fc01",
"Fc02",
"Fc03",
"Fc04",
22 "Fc05",
"Fc06",
"Fc07",
"Fc08"
36 int courseType = dWmLib::GetCourseTypeFromCourseNo(dInfo_c::m_instance->m_54);
37 if (dScWMap_c::m_WorldNo == dScWMap_c::m_PrevWorldNo &&
38 dScWMap_c::m_SceneNo == dScWMap_c::m_PrevSceneNo &&
39 dWmLib::GetCurrentPlayResultStatus() != 0 &&
40 dWmLib::GetCurrentPlayResultStatus() != 9 &&
41 courseType != dWmLib::COURSE_TYPE_KINOKO_START &&
42 courseType != dWmLib::COURSE_TYPE_PEACH_CASTLE &&
43 courseType != dWmLib::COURSE_TYPE_INVALID &&
44 courseType != dWmLib::COURSE_TYPE_KINOKO &&
45 courseType != dWmLib::COURSE_TYPE_CANNON
54dWmEnemy_c::~dWmEnemy_c() {
55 if (mpBgmSync !=
nullptr) {
60void dWmEnemy_c::initializeBase(
const char **names,
int count,
bool cyclic) {
61 daWmMap_c *wmMap = daWmMap_c::m_instance;
62 dInfo_c::enemy_s enData;
63 dInfo_c::m_instance->GetMapEnemyInfo(dScWMap_c::m_WorldNo, ACTOR_PARAM(enemyNo), enData);
64 dWmConnect_c *connect = &wmMap->mWmConnect[wmMap->currIdx];
68 mPath.init(names, count, connect, cyclic, enData.mWalkDirection);
69 mPath.SetStartPoint(getStartPoint());
70 dWmConnect_c::Point_s *point = connect->GetPointFromIndex(mPath.mpCurrentPoint->mPointIndex);
71 mPos = point->pos + getPointOffset(mPath.mpCurrentPoint->mIndex);
73 if (dWmEnemy::isEnemyWalk() && dWmLib::getEnemyRevivalCount(dScWMap_c::m_WorldNo, ACTOR_PARAM(enemyNo)) == 0) {
78 dWmBgmSync_c *bgmSync =
new dWmBgmSync_c();
80 bgmSync->mAngle = &mpUnkData->mAngle2;
81 bgmSync->m_04 = bgmSync->mAngle->
x.
mAngle - 1;
82 bgmSync->m_08 = bgmSync->mAngle->
y.
mAngle;
86 float scale = mpUnkData->m_04;
90 mArrivedAtTarget =
true;
94int dWmEnemy_c::getStartPoint() {
95 return ACTOR_PARAM(startPoint);
98mVec3_c dWmEnemy_c::getPointOffset(
int index) {
103 if (mpBgmSync !=
nullptr) {
104 mpBgmSync->execute();
105 if (mpBgmSync->m_0c) {
109 setCutEndSpecific(dCsSeqMng_c::ms_instance->GetCutName(), dCsSeqMng_c::ms_instance->m_164);
110 if (IsExecEnable() || dCsSeqMng_c::ms_instance->GetCutName() == 0x57) {
111 static const ProcFunc ProcTbl[PROC_COUNT] = {
118 (this->*ProcTbl[mCurrProc])();
125void dWmEnemy_c::updateBgmAnimRate() {}
127void dWmEnemy_c::calculateEffect() {}
129void dWmEnemy_c::calc() {}
131void dWmEnemy_c::init_exec() {
132 mCurrProc = PROC_TYPE_EXEC;
135void dWmEnemy_c::mode_exec() {
136 if (IsExecEnable() && mNotAnger && mpBgmSync->m_0d) {
139 if (IsNeedChasePlayer()) {
145void dWmEnemy_c::init_lose() {
147 mCurrProc = PROC_TYPE_LOSE;
150void dWmEnemy_c::initDemoStarLose() {
154void dWmEnemy_c::mode_lose() {
155 if (procDemoStarLose()) {
160bool dWmEnemy_c::procDemoStarLose() {
161 return procDemoLose();
164void dWmEnemy_c::init_bgmDance() {
165 mCurrProc = PROC_TYPE_BGM_DANCE;
166 mBgmDanceRelated = 1;
170void dWmEnemy_c::initDemoBgmDance() {}
172void dWmEnemy_c::mode_bgmDance() {
173 if (procDemoBgmDance()) {
178bool dWmEnemy_c::procDemoBgmDance() {
182void dWmEnemy_c::init_DemoContinue() {
183 mCurrProc = PROC_TYPE_DEMO_CONTINUE;
184 mDemoContinueRelated = 2;
188void dWmEnemy_c::mode_DemoContinue() {
192void dWmEnemy_c::init_waitWalk() {
193 mCurrProc = PROC_TYPE_WAIT_WALK;
194 mWalkWaitTimer = GetWalkWaitFrame() + 1;
197void dWmEnemy_c::mode_waitWalk() {
199 if (mWalkWaitTimer > 0) {
200 if (mWalkWaitTimer == 1) {
201 mPath.mAdvancePoint = IsRandomMove();
202 PATH_DIRECTION_e dir;
203 bool randomWalk = IsRandomWalk();
205 mPath.mDir2 = mPath.mDir1;
208 dir = mPath.mDir1 == PATH_DIR_NORMAL ? PATH_DIR_REVERSE : PATH_DIR_NORMAL;
217 if (doWalk() && mCurrProc == PROC_TYPE_WAIT_WALK) {
220 mPath.mAdvancePoint =
true;
221 mPath.mDir1 = mPath.mDir2;
223 if (!daWmPlayer_c::checkWalkPlayers()) {
231void dWmEnemy_c::initWalk(
float f) {
232 mNextPoint = getNextPointInfo();
237 mArrivedAtTarget =
false;
238 mDemoAngle.y = (getNextPointInfo() -
mPos).xzAng();
239 if (isNextThroughPoint()) {
246bool dWmEnemy_c::doWalk() {
247 if (!mArrivedAtTarget) {
249 sLib::addCalcAngle(&
mAngle3D.y.mAngle, mDemoAngle.y, 10, 0x2000, 0x400);
253 dWmSeManager_c *seManager = dWmSeManager_c::m_pInstance;
254 mSeID = seManager->
playSound(getEnemyWalkSeID(), 0,
mPos, ACTOR_PARAM(enemyNo) + 1, 1);
256 setWalkAnm(getWalkAnmRate());
259 adjustHeightBase(mPrevPoint, mNextPoint, -1);
260 bool hitToPlayer =
false;
261 if (CheckIsHitToPlayer()) {
264 if (!mArrivedAtTarget && checkArriveTargetXYZ(mPrevPoint, mNextPoint)) {
271 mArrivedAtTarget =
true;
272 updatePathInfo(!tmp);
279 if (mArrivedAtTarget) {
283 mDemoAngle.y = getWaitAngle();
284 sLib::addCalcAngle(&
mAngle3D.y.mAngle, mDemoAngle.y, 10, 0x2000, 0x400);
300mVec3_c dWmEnemy_c::getNextPointInfo() {
301 daWmMap_c *wmMap = daWmMap_c::m_instance;
302 dWmConnect_c *connect = &wmMap->mWmConnect[wmMap->currIdx];
303 dWmConnect_c::Point_s *point = connect->GetPointFromIndex(mPath.GetNextPointIdx());
304 int idx = mPath.GetNextPointInfo(
false)->mIndex;
305 return point->pos + getPointOffset(idx);
308mVec3_c dWmEnemy_c::getCurrentPointInfo() {
309 daWmMap_c *wmMap = daWmMap_c::m_instance;
310 dWmConnect_c *connect = &wmMap->mWmConnect[wmMap->currIdx];
311 dWmConnect_c::Point_s *point = connect->GetPointFromIndex(mPath.mpCurrentPoint->mPointIndex);
312 return point->pos + getPointOffset(mPath.mpCurrentPoint->mIndex);
315void dWmEnemy_c::initShapeAngle() {
316 short angle = getWaitAngle();
322 dWmDemoActor_c *actor = dCsSeqMng_c::ms_instance->m_1ac;
362 isEnd = !procDemoAnger();
369 isEnd = !procDemoLose();
375 if (mHitPlayer && dScWMap_c::m_WorldNo != WORLD_4) {
377 if (mRotateTimer > 0) {
381 if (mArrivedAtTarget || mRotateTimer == 0) {
382 if (!mArrivedAtTarget) {
383 updatePathInfo(
true);
389 mPath.mAdvancePoint =
true;
390 mPath.mDir1 = mPath.mDir2;
399void dWmEnemy_c::initDemoAnger() {
400 mVec3_c playerPos = daWmPlayer_c::ms_instance->mPos;
401 mDemoAngle.
y = (playerPos -
mPos).xzAng();
406bool dWmEnemy_c::procDemoAnger() {
408 if (mCurrProc != PROC_TYPE_BGM_DANCE) {
409 if (mRotateTimer > 0) {
412 sLib::addCalcAngle(&
mAngle3D.y.mAngle, mDemoAngle.y, 100, 0x4000, 0x800);
422void dWmEnemy_c::initDemoLose() {}
425 _initDemoJumpBase(pos, 0,
426 jumpData.mFrames, jumpData.mJumpSpeed,
427 jumpData.mStartScale * scale, jumpData.mEndScale * scale,
432bool dWmEnemy_c::procDemoLose() {
436void dWmEnemy_c::procDemoLoseEnd() {
438 dInfo_c::enemy_s enData;
439 dInfo_c::m_instance->GetMapEnemyInfo(dScWMap_c::m_WorldNo, ACTOR_PARAM(enemyNo), enData);
440 enData.mPathIndex = -1;
443bool dWmEnemy_c::procDemoLoseBase(
short angle) {
445 rotDirectionX(angle,
false);
446 if (_procDemoJumpBase()) {
447 dWmEffectManager_c::m_pInstance->
playEffect(dWmEffectManager_c::WM_EFFECT_ENEMY_DEATH, &
mPos,
nullptr,
nullptr);
448 dWmSeManager_c::m_pInstance->
playSound(dWmSeManager_c::WM_SE_EMY_CS_ENEMY_BYE,
mPos, 1);
456bool dWmEnemy_c::isNextThroughPoint() {
457 return isThroughPoint(mPath.GetNextPointIdx());
460bool dWmEnemy_c::isThroughPoint(
int idx) {
461 daWmMap_c *wmMap = daWmMap_c::m_instance;
462 return wmMap->mCsvData[wmMap->currIdx].GetPointName(idx)[0] ==
'K';
466 return dInfo_c::m_instance->m_9c == ACTOR_PARAM(enemyNo);
469bool dWmEnemy_c::isDead() {
470 return dWmLib::getEnemyRevivalCount(dScWMap_c::m_WorldNo, ACTOR_PARAM(enemyNo)) != 0;
473void dWmEnemy_c::ModelCalc(
m3d::mdl_c *mdl,
float yOffset,
float shadowYOffset,
float shadowScale) {
475 mVec3_c selfPos =
mPos;
477 selfPos.y += yOffset;
478 mMatrix.trans(selfPos).ZXYrotM(ang);
479 mMatrix.concat(mMtx_c::createTrans(mVec3_c(0.0f, -yOffset, 0.0f)));
483 CalcShadow(shadowYOffset, shadowScale);
486void dWmEnemy_c::updatePathInfo(
bool b) {
487 dInfo_c *info = dInfo_c::m_instance;
489 mDemoAngle.y = (getNextPointInfo() -
mPos).xzAng();
491 int wNo = dScWMap_c::m_WorldNo;
492 int sNo = dScWMap_c::m_SceneNo;
493 int param = ACTOR_PARAM(enemyNo);
494 int v =
vfc4(mPath.GetPathPointNo(mPath.mpCurrentPoint->mpName));
495 info->SetMapEnemyInfo(wNo, param, sNo, v);
496 info->FUN_800bbc40(wNo, param, mPath.mDir1);
500void dWmEnemy_c::deleteSound() {
504 dWmSeManager_c::m_pInstance->endSound(mSeID);
508void dWmEnemy_c::deleteEffect() {
512 dWmEffectManager_c::m_pInstance->
endEffect(mEfID);
516int dWmEnemy_c::getEnemyWalkSeID() {
517 switch (dScWMap_c::m_WorldNo) {
519 return dWmSeManager_c::WM_SE_EMY_CS_MOVE_W1_KURIBO;
521 return dWmSeManager_c::WM_SE_EMY_CS_MOVE_W3_ICEBROS;
523 return dWmSeManager_c::WM_SE_EMY_CS_MOVE_W5_PAKKUN;
525 return dWmSeManager_c::WM_SE_EMY_CS_MOVE_W7_JUGEM;
527 return dWmSeManager_c::WM_SE_INVALID;
531bool dWmEnemy_c::IsExecEnable() {
532 static const int cutsceneIDs[] = {
538bool dWmEnemy_c::IsPlayerComingCore() {
539 int point = daWmPlayer_c::ms_instance->m_234;
540 if (point >= 0 && mPath.isPointIn(point) && !isThroughPoint(point)) {
544 if (GetIndex() != point) {
551bool dWmEnemy_c::IsNeedChasePlayer() {
553 if (!mHitPlayer && !isDead() && IsPlayerComing()) {
559bool dWmEnemy_c::IsRandomWalk() {
560 int count = dGameCom::rndInt(100);
561 int randomNumber = 0;
563 randomNumber = dGameCom::rndInt(100);
566 bool randomWalk =
false;
567 if (mCurrProc == PROC_TYPE_WAIT_WALK && randomNumber <= GetChangeDirRate()) {
573bool dWmEnemy_c::IsHitToWaitPlayer() {
578 int nextPointIdx = daWmPlayer_c::ms_instance->m_22c;
579 if (mPath.GetNextPointIdx() == nextPointIdx && !daWmPlayer_c::ms_instance->m_18c) {
583 if (
mPos.distTo(daWmPlayer_c::ms_instance->mPos) < GetTerritory()) {
594bool dWmEnemy_c::IsHitToMovePlayer() {
599 int nextPointIdx = daWmPlayer_c::ms_instance->m_230;
600 if (mPath.GetNextPointIdx() == nextPointIdx && daWmPlayer_c::ms_instance->m_18c) {
604 if (
mPos.distTo(daWmPlayer_c::ms_instance->mPos) < GetTerritory() * 2.0f) {
615bool dWmEnemy_c::CheckIsHitToPlayer() {
616 bool hitWait = IsHitToWaitPlayer();
617 bool hitMove = IsHitToMovePlayer();
618 if (hitWait || hitMove) {
620 if (daWmPlayer_c::isPlayerStarMode()) {
621 daWmPlayer_c::ms_instance->setEnemyDieByStar(
this);
627 daWmPlayer_c::ms_instance->m_2fc =
true;
628 dCsSeqMng_c::ms_instance->
FUN_801017c0(0x29,
this, 0, 0x80);
633 dCsSeqMng_c::ms_instance->
FUN_801017c0(0x29,
this, 0, 0x80);
643bool dWmEnemy_c::isAllEnemyMoveEnd(
void) {
646 for (
int i = 0; i < ARRAY_SIZE(dWmEnemy::sc_EnemyProfName); i++) {
649 while (en !=
nullptr) {
650 res &= en->isWaitWalkEnd();
bool mVisible
Whether the actor should be visible or not. Defaults to true .
mAng3_c mAngle3D
The actor's rotation (for 3D actors).
mMtx_c mMatrix
The actor's partial transformation matrix. See makeMtx for details.
mVec3_c mScale
The actor's scale (defaults to 1).
mVec3_c mPos
The actor's position.
float mSpeedF
The actor's horizontal speed.
void posMove()
Moves the actor by its speed.
float mMaxFallSpeed
The actor's maximum fall speed.
void calcSpeed()
Updates the actor's speed (3D actors). See here for details.
mAng3_c mAngle
The actor's rotation (for 2D actors).
float mAccelY
The actor's vertical acceleration.
void FUN_801017c0(int, dWmEnemy_c *, int, int)
bool isCutscenePlaying(const int *csList, int csCount)
virtual void setCutEndSpecific(int cutsceneId, bool param2)
int playEffect(int, const mVec3_c *, const mAng3_c *, const mVec3_c *)
virtual int execute()
do method for the execute operation.
virtual int vfc4(int pointNo)
POINT_TYPE_e mNextPointType
0 = stop point, 1 = through point
bool csCommand(int id, bool b)
void demoJump(const mVec3_c &pos, JumpData_s &jumpData, float scale)
int playSound(int id, int, const mVec3_c &pos, int, int)
@ SUCCEEDED
The step was completed successfully.
static fBase_c * searchBaseByProfName(ProfileName profID, const fBase_c *parent)
Searches for a base with a given profile name, optionally under a given parent.
mAng y
The rotation on the Y axis.
mAng x
The rotation on the X axis.
A three-dimensional floating point vector.
static mVec3_c Ey
The unit vector for the Y axis.
static mVec3_c Zero
The null vector.
u16 ProfileName
The name of a profile. Value is a fProfile::PROFILE_NAME_e.