BOOL daNpc_zrA_c::wait(void* param_0) { switch (mMode) { case 0: if (field_0x1510 == 0) { if (mPath.getPathInfo() == NULL) { if (mAcch.ChkWaterIn()) { gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; } else { switch (mActionType) { case ACT_TYPE_1: setExpression(EXPR_SADSIT_A, -1.0f); setMotion(MOT_SADSIT_A, -1.0f, false); break; case ACT_TYPE_2: setExpression(EXPR_SADSIT_B, -1.0f); setMotion(MOT_SADSIT_B, -1.0f, false); break; case ACT_TYPE_3: setExpression(EXPR_SADSIT_C, -1.0f); setMotion(MOT_SADSIT_C, -1.0f, false); break; case ACT_TYPE_4: setExpression(EXPR_SADSIT_D, -1.0f); setMotion(MOT_SADSIT_D, -1.0f, false); break; case ACT_TYPE_5: setExpression(EXPR_SADSIT_E, -1.0f); setMotion(MOT_SADSIT_E, -1.0f, false); break; default: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_A, -1.0f, false); break; } } } else { setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WALK_A, -1.0f, false); field_0x1510 = 1; } } else { setMotion(MOT_WALK_A, -1.0f, false); } setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mMode = 2; // fallthrough case 2: if (field_0x1510 != 0) { walkCalc(); } else { waitCalc(); } if (mDamageTimer == 0 && !mTwilight) { BOOL player_attn = mActorMngr[0].getActorP() != NULL; if (chkFindPlayer2(player_attn, shape_angle.y)) { if (!player_attn) { mActorMngr[0].entry(daPy_getPlayerActorClass()); mTurnMode = 0; } } else { if (player_attn) { mActorMngr[0].remove(); mTurnMode = 0; } } if (mActorMngr[0].getActorP() != NULL) { setLookMode(LOOK_PLAYER); } else { setLookMode(LOOK_NONE); if (field_0x1510 == 0 && home.angle.y != mCurAngle.y) { if (mAcch.ChkWaterIn()) { if (step(home.angle.y, -1, -1, 15)) { mMode = 0; } } else { if (step(home.angle.y, EXPR_NONE, MOT_STEP, 15)) { mMode = 0; } } } } } break; case 3: speedF = 0.0f; break; } return true; } void daNpc_zrA_c::walkCalc() { field_0x1550 = false; cXyz next_pnt; if (mPath.getDstPosDstXZ(current.pos, next_pnt)) { mPath.reverse(); mPath.getDstPosDstXZ(current.pos, next_pnt); } s16 target_angle = cLib_targetAngleY(¤t.pos, &next_pnt); speedF = mpHIO->m.mWalkSpeed; mAnm_p->setPlaySpeed(mpHIO->m.mWalkSpeed / mpHIO->m.mWalkAnmRate); cLib_addCalcAngleS2(¤t.angle.y, target_angle, mpHIO->m.mWalkAngleScale, mpHIO->m.mWalkAngleSpeed); mCurAngle = current.angle; shape_angle = mCurAngle; mOldAngle.y = mCurAngle.y; } void daNpc_zrA_c::waitCalc() { if (mAcch.ChkWaterIn()) { if (mMotion != MOT_WAIT_SWIM) { setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_SWIM, -1.0f, false); gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; } field_0x1550 = true; calcModulation(); } else { field_0x1550 = false; if (mMotion == MOT_WAIT_SWIM) { switch (mActionType) { case ACT_TYPE_1: setExpression(EXPR_SADSIT_A, -1.0f); setMotion(MOT_SADSIT_A, -1.0f, false); break; case ACT_TYPE_2: setExpression(EXPR_SADSIT_B, -1.0f); setMotion(MOT_SADSIT_B, -1.0f, false); break; case ACT_TYPE_3: setExpression(EXPR_SADSIT_C, -1.0f); setMotion(MOT_SADSIT_C, -1.0f, false); break; case ACT_TYPE_4: setExpression(EXPR_SADSIT_D, -1.0f); setMotion(MOT_SADSIT_D, -1.0f, false); break; case ACT_TYPE_5: setExpression(EXPR_SADSIT_E, -1.0f); setMotion(MOT_SADSIT_E, -1.0f, false); break; default: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_A, -1.0f, false); } } } } BOOL daNpc_zrA_c::waitSpa(void* param_0) { switch (mMode) { case 0: switch (mActionType) { case ACT_TYPE_2: setExpression(EXPR_SPA_WAIT_A, -1.0f); setMotion(MOT_SPA_WAIT_A, -1.0f, false); field_0x9ea = true; break; case ACT_TYPE_3: setExpression(EXPR_SPA_WAIT_B, -1.0f); setMotion(MOT_SPA_WAIT_B, -1.0f, false); field_0x9ea = true; break; default: setExpression(EXPR_LOOKUP_2, -1.0f); setMotion(MOT_LOOKUP, -1.0f, false); field_0x9ea = true; break; } setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mMode = 2; break; case 2: break; case 3: speedF = 0.0f; break; } return true; } BOOL daNpc_zrA_c::waitLake(void* param_0) { switch (mMode) { case 0: setExpression(EXPR_LOOKING_SP_2, -1.0f); setMotion(MOT_LOOKING_SP, -1.0f, false); setLookMode(LOOK_NONE); mTurnMode = 0; mMode = 2; // fallthrough case 2: if (mDamageTimer == 0 && !mTwilight) { if (mActorMngr[0].getActorP() != NULL) { if (!chkFindPlayer()) { mTurnMode = 0; } } else { if (chkFindPlayer()) { mTurnMode = 0; } } if (mActorMngr[0].getActorP() != NULL) { setLookMode(LOOK_PLAYER); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_A, -1.0f, false); } else { setLookMode(LOOK_NONE); if (home.angle.y != mCurAngle.y) { if (step(home.angle.y, EXPR_NONE, MOT_STEP, 15)) { mMode = 0; } } else { setExpression(EXPR_LOOKING_SP_2, -1.0f); setMotion(MOT_LOOKING_SP, -1.0f, false); } } } case 3: break; } return true; } BOOL daNpc_zrA_c::talk(void* param_0) { BOOL ret = false; BOOL bvar2 = false; switch (mMode) { case 0: if (mDamageTimer != 0) { break; } initTalk(mFlowID, NULL); mTurnMode = 0; mMode = 2; // fallthrough case 2: if (mType != TYPE_SPA) { calcModulation(); } if (field_0x9ea || mTwilight) { bvar2 = true; } else { setLookMode(LOOK_PLAYER_TALK); mActorMngr[0].entry(daPy_getPlayerActorClass()); if (mCurAngle.y == fopAcM_searchPlayerAngleY(this)) { bvar2 = true; } else if (mAcch.ChkWaterIn()) { if (step(fopAcM_searchPlayerAngleY(this), -1, -1, 15)) { mTurnMode = 0; } } else { if (step(fopAcM_searchPlayerAngleY(this), EXPR_NONE, MOT_STEP, 15)) { setMotion(MOT_WAIT_A, -1.0f, false); mTurnMode = 0; } } } if (bvar2 && talkProc(NULL, true, NULL)) { ret = true; } if (ret) { mMode = 3; if (!field_0x9ec) { dComIfGp_event_reset(); setAction(&daNpc_zrA_c::wait); } field_0x9ec = false; } break; case 3: mFlowID = home.angle.x; break; } return ret; } static void* s_subMulti(void* i_proc, void* i_this) { if (fopAc_IsActor(i_proc) && fopAcM_GetName(i_proc) == fpcNm_NPC_ZRA_e) { daNpc_zrA_c* _this = static_cast(i_this); daNpc_zrA_c* other = static_cast(i_proc); if (other != _this && other->getType() == daNpc_zrA_c::TYPE_WAIT && other->getMultiModeFromParam() != 0 && other->getMultiModeFromParam() == _this->getMultiModeFromParam() && other->getMultiNoFromParam() == 2) { return other; } } return NULL; } BOOL daNpc_zrA_c::ECut_talkMulti(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; fopAc_ac_c* actors[2] = {NULL, NULL}; actors[0] = this; actors[1] = mActorMngr[2].getActorP(); int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: mActorMngr[2].remove(); break; case 10: initTalk(mFlowID, actors); break; } } switch (prm) { case 0: if (mActorMngr[2].getActorP() == NULL) { fopAc_ac_c* other = (fopAc_ac_c*)(fpcM_Search(s_subMulti, this)); if (other != NULL) { mActorMngr[2].entry(other); ret = true; } } else { ret = true; } break; case 10: if (talkProc(NULL, false, actors)) { ret = true; } break; default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::swim(void* param_0) { switch (mMode) { case 0: mAcch.SetGrndNone(); mAcch.SetWallNone(); gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; field_0x153d = false; setExpression(EXPR_NONE, -1.0f); if (mSwimMode == SWIM_WAIT) { if (mPath.getPathInfo() == NULL) { setMotion(MOT_WAIT_SWIM, -1.0f, false); field_0x1550 = true; } else { if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mCheckSwimTurnTimer = cLib_getRndValue(3, 3); mSpinTimer = (int)(cM_rnd() * 60.0f) + 90; mSwimMode = SWIM_RAIL; field_0x1521 = true; mScaleFactor = mpHIO->m.mMaxScaleFactor; mCcStts.SetWeight(0); } } else { mSwimMode = SWIM_RAIL; } setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mMode = 2; field_0x153e = false; mSwimAngleCalc = current.angle; if (mSwimMode != SWIM_WAIT) { calcWaistAngleInit(); } // fallthrough case 2: switch (mSwimMode) { case SWIM_WAIT: waitSwim(); break; case SWIM_RAIL: railSwim(); break; case SWIM_TURN: turnSwim(); break; } break; case 3: break; } return true; } BOOL daNpc_zrA_c::railSwim() { s16 ang_step = mpHIO->m.mSwimAngleSpeed; s16 ang_scale = 8; f32 fvar15 = 0.1f; f32 fvar2 = 1.0f; f32 fvar3 = mSwimSpeedScale; f32 water_height = mAcch.m_wtr.GetHeight(); gravity = 0.0f; cXyz vec0, swim_speed, vec1, vec2; csXyz angle; if (field_0x153c) { mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&vec1); mPath.getDstPosDst2(current.pos, vec2); if (field_0x153e) { if (mAnm_p->getFrame() > 13.0f && mAnm_p->getFrame() < 21.0f) { f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 0.3f, 0.7f, 0.3f); mAnm_p->setPlaySpeed(play_speed); } calcBank(ang_step, 8, current.angle.y, current.angle.z); mSwimSpeed.y -= 2.2f; current.pos += mSwimSpeed; if (current.angle.x < 0x2800) { current.angle.x = -cM_atan2s(mSwimSpeed.y, mSwimSpeed.absXZ()); } mCurAngle = current.angle; shape_angle = mCurAngle; if (mIsAboveWater && vec1.y + mSwimSpeed.y <= water_height) { cXyz water_pos = vec1; water_pos.y = water_height; fopKyM_createWpillar(&water_pos, 2.5f, 0); mIsAboveWater = false; mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH, 0, -1); } if (current.pos.y <= water_height - mpHIO->m.mMinDepth) { field_0x153e = false; field_0x153c = false; mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeed.absXZ(); mAnm_p->setPlaySpeed(1.0f); } return true; } angle.x = -0x3000; angle.y = current.angle.y; angle.z = current.angle.z; mSpinTimer = 90; if (!(vec1.y < water_height)) { if (!mIsAboveWater) { cXyz pos = vec1; pos.y = water_height; fopKyM_createWpillar(&pos, 2.5f, 0); mIsAboveWater = true; mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH_OUT, 0, -1); } else { if (mAnm_p->getFrame() > 13.0f && mAnm_p->getFrame() < 17.0f) { f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 0.3f, 0.7f, 0.5f); mAnm_p->setPlaySpeed(play_speed); } if (current.pos.y > water_height && current.angle.x < -0x2000 && mSwimSpeedF > 20.0f) { swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); mSwimSpeed = swim_speed; field_0x153e = true; calcBank(ang_step, 8, angle.y, angle.z); current.angle.z = angle.z; mCurAngle = current.angle; shape_angle = mCurAngle; return true; } } } } else { BOOL ivar9 = mPath.getDstPosDst2(current.pos, vec0); angle.x = cLib_targetAngleX(&vec0, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &vec0); angle.z = current.angle.z; evasionCalc(vec0, angle); if (ivar9) { cXyz next_pos; mPath.getNextPos(next_pos); s16 ang_x = cLib_targetAngleX(&next_pos, &vec0); s16 ang_y = cLib_targetAngleY(&vec0, &next_pos); u32 arg0 = mPath.getArg0(mPath.getIdx()); if (((arg0 == 0 && cM_rnd() < 0.5f) || (u8)arg0 == 1) && mSpinTimer != 0) { mSwimSpeedScale = 1.5f; fvar3 = mSwimSpeedScale; mSpinTimer = 90; field_0x153d = true; } else if (field_0x153d) { field_0x153d = false; field_0x153c = true; angle.x = -0x3000; angle.y = current.angle.y; mCheckSwimTurn = false; } else if ((abs(angle.x - ang_x) > 0x4000 || abs(angle.x - ang_y) > 0x4000) && cM_rnd() < 0.2f && mSpinTimer != 0) { field_0x153c = false; mSwimFastTurnTimer = 60; mSwimSpeedScale = 1.2f; fvar3 = mSwimSpeedScale; mSpinTimer = 90; } else { field_0x153c = false; cLib_calcTimer(&mCheckSwimTurnTimer); } } if (turnSwimCheck()) { return true; } } if (cLib_calcTimer(&mSwimFastTurnTimer) != 0) { ang_scale = 4; ang_step *= 2; } s16 ang_diff_x = angle.x - current.angle.x; s16 ang_diff_y = angle.y - current.angle.y; bool bvar6 = false; if (mActionType != ACT_TYPE_0 && mSpinAngle == 0 && !field_0x153c && !field_0x153d && (abs(ang_diff_x) > 0x3000 || abs(ang_diff_y) > 0x3000) && mSwimSpeedF > 14.0f) { f32 frame = mAnm_p->getFrame(); if ((angle.z <= 0x2000 || ang_diff_y >= 0) && (angle.z >= -0x2000 || ang_diff_y <= 0)) { if (ang_diff_x < -0x3000) { if (frame >= 2.0f && frame <= 4.0f) { bvar6 = true; } } else { if (frame >= 16.0f && frame <= 18.0f) { bvar6 = true; } } } if (bvar6) { calcSwimAngle(angle, mSwimAngleCalc, ang_scale / 2, ang_step); } else { calcSwimAngle(angle, mSwimAngleCalc, ang_scale, ang_step / 2); } } else { calcSwimAngle(angle, mSwimAngleCalc, ang_scale, ang_step); } if (mSwimSpeedF > fvar3 * mpHIO->m.mSwimSpeed) { fvar15 *= 2.0f; fvar2 *= 0.5f; } cLib_addCalc2(&mSwimSpeedF, fvar3 * mpHIO->m.mSwimSpeed, fvar15, fvar2); if (field_0x153c == true && mIsAboveWater == true) { if (mAnm_p->getFrame() > 13.0f && mAnm_p->getFrame() < 21.0f) { f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 0.3f, 0.7f, 0.3f); mAnm_p->setPlaySpeed(play_speed); } } else if (!bvar6) { f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, mSwimSpeedF / mpHIO->m.mSwimAnmRate, 0.2f, 0.1f); mAnm_p->setPlaySpeed(play_speed); } swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (!field_0x153c && mAcch.ChkWaterHit() && current.pos.y > water_height - mpHIO->m.mMinDepth) { current.pos.y = water_height - mpHIO->m.mMinDepth; } if (cLib_calcTimer(&mSpinTimer) == 0) { if (mSpinAngle != 0) { cLib_addCalcAngleS2(&field_0x1518, ang_step, 8, 0x200); if (mSpinAngle > 0) { angle.z += ang_step; mSpinAngle += ang_step; } else { angle.z -= ang_step; mSpinAngle -= ang_step; } if (abs(mSpinAngle) > 0x10000) { mSpinAngle = 0; mSpinTimer = (int)(cM_rnd() * 60.0f) + 90; } } else if (cM_rnd() > 0.9f) { calcBank(ang_step, ang_scale, angle.y, angle.z); field_0x1518 = abs(angle.z - current.angle.z); cLib_addCalcAngleS2(&field_0x1518, ang_step, 8, 0x200); if (angle.z > 0) { angle.z += ang_step; mSpinAngle += ang_step; } else { angle.z -= ang_step; mSpinAngle -= ang_step; } mSwimSpeedScale = 1.0f; } else { mSpinTimer = (int)(cM_rnd() * 60.0f) + 90; mSpinAngle = 0; mSwimSpeedScale = cM_rnd() * (1.0f - mpHIO->m.mMinSwimSpeedScale) + mpHIO->m.mMinSwimSpeedScale; } } if (mSpinAngle == 0) { calcBank(ang_step, ang_scale, angle.y, angle.z); } current.angle.z = angle.z; mCurAngle = current.angle; shape_angle = mCurAngle; return true; } BOOL daNpc_zrA_c::waitSwim() { calcModulation(); if (mDamageTimer == 0) { BOOL player_attn = mActorMngr[0].getActorP() != NULL; if (chkFindPlayer2(player_attn, shape_angle.y)) { if (!player_attn) { mActorMngr[0].entry(daPy_getPlayerActorClass()); mTurnMode = 0; } } else { if (player_attn) { mActorMngr[0].remove(); mTurnMode = 0; } } if (mActorMngr[0].getActorP() != NULL) { setLookMode(LOOK_PLAYER); } else { setLookMode(LOOK_NONE); if (home.angle.y != mCurAngle.y && step(home.angle.y, -1, -1, 15)) { mMode = 0; } } if (home.angle.y == mCurAngle.y) { fopAc_ac_c* actor = getAttnActorP(mActorMngr[0].getActorP() != NULL, srchAttnActor1, mpHIO->m.common.search_distance, mpHIO->m.common.search_height, mpHIO->m.common.search_depth, mpHIO->m.common.fov, shape_angle.y, 120, true); if (actor != NULL) { mActorMngr[1].entry(actor); setLookMode(LOOK_ATTN); } } else { mAttnChangeTimer = 0; } } return true; } BOOL daNpc_zrA_c::turnSwimInit() { mPath.reverse(); mPath.setNextIdxDst(current.pos); mSwimSpeed.set(0.0f, 0.0f, mSwimSpeedF); mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&mSwimSpeed, &mSwimSpeed); mSwimSpeedF = 0.0f; mIsTurning = true; mSwimMode = SWIM_TURN; if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_TURN, -1.0f, false); } else { setMotion(MOT_SWIM_TURN, 4.0f, false); } return true; } BOOL daNpc_zrA_c::turnSwim() { s16 ang_step = mpHIO->m.mSwimAngleSpeed; cXyz pos; csXyz angle; mPath.getDstPosDst2(current.pos, pos); angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 8, ang_step); calcBank(ang_step, 8, current.angle.y, angle.z); current.angle.z = angle.z; mCurAngle = current.angle; shape_angle = mCurAngle; if (mBaseMotionAnm == ANM_SWIM_TURN) { if (mAnm_p->getFrame() < 40.0f) { cXyz zero(0.0f, 0.0f, 0.0f); cLib_chasePos(&mSwimSpeed, zero, 0.7f); current.pos += mSwimSpeed; mAnm_p->setPlaySpeed(0.8f); } else { cXyz swim_speed; mSwimSpeedF = 1.5f * mpHIO->m.mSwimSpeed; swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); mAnm_p->setPlaySpeed(1.0f); } } else if (mBaseMotionAnm == ANM_STILL) { cXyz swim_speed; mSwimSpeedF = 1.5f * mpHIO->m.mSwimSpeed; swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); mAnm_p->setPlaySpeed(1.0f); if (mIsTurning) { mSwimTurnTimer = 10; mIsTurning = false; } else if (cLib_calcTimer(&mSwimTurnTimer) == 0) { mSwimMode = SWIM_RAIL; if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mSpinTimer = 90; mCheckSwimTurn = false; } } if (mAcch.ChkWaterHit() && current.pos.y > mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth) { current.pos.y = mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth; } return true; } BOOL daNpc_zrA_c::turnSwimCheck() { if (mSoldierType != SOLDIER_SPEAR) { if (mCheckSwimTurn) { if (mAnm_p->isLoop()) { turnSwimInit(); turnSwim(); return true; } } else if (mCheckSwimTurnTimer == 0) { mCheckSwimTurnTimer = cLib_getRndValue(6, 6); if (cM_rnd() < 0.5f) { mCheckSwimTurn = true; } } } return false; } BOOL daNpc_zrA_c::evasionCalc(cXyz& param_0, csXyz& param_1) { BOOL ret; daPy_py_c* player = daPy_getPlayerActorClass(); cM3dGLin line; cXyz proj; f32 dist; line.SetStartEnd(current.pos, param_0); if (cM3d_Len3dSqPntAndSegLine(&line, &player->current.pos, &proj, &dist) && dist <= 10000.0f) { fopAcM_searchPlayerAngleY(this); if ((s16)(param_1.y - current.angle.y) > 0) { mEvasionAngle = -0x1800; } else { mEvasionAngle = 0x1800; } param_1.y += mEvasionAngle; mEvasionTimer = 60; mSwimFastTurnTimer = 60; ret = true; } else { cXyz vec(0.0f, 0.0f, 500.0f); csXyz angle(current.angle.x, current.angle.y, 0); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::multVec(&vec, &vec); vec += current.pos; line.SetStartEnd(current.pos, vec); if (cM3d_Len3dSqPntAndSegLine(&line, &player->current.pos, &proj, &dist) && dist <= 10000.0f) { if ((s16)(fopAcM_searchPlayerAngleY(this) - current.angle.y) > 0) { mEvasionAngle = -0x1800; } else { mEvasionAngle = 0x1800; } param_1.y += mEvasionAngle; mEvasionTimer = 60; mSwimFastTurnTimer = 60; ret = true; } else { if (cLib_calcTimer(&mEvasionTimer) != 0) { param_1.y += mEvasionAngle; } ret = true; } } return ret; } void daNpc_zrA_c::calcBank(s16 i_step, s16 i_scale, s16& i_angY, s16& o_angZ) { s16 ang_diff_y = i_angY - current.angle.y; if (ang_diff_y >= 0x4000) { ang_diff_y = 0x4000; } else if (ang_diff_y <= -0x4000) { ang_diff_y = -0x4000; } cLib_addCalcAngleS2(&mSwimAngleCalc.z, ang_diff_y, i_scale * 2, i_step); cLib_addCalcAngleS2(&o_angZ, mSwimAngleCalc.z, (s16)i_scale, i_step); } void daNpc_zrA_c::calcWaistAngle() { if (mResetWaistAngle) { cLib_chaseAngleS(&mWaistAngle.x, 0, mpHIO->m.mSwimAngleSpeed / 2); cLib_chaseAngleS(&mWaistAngle.y, 0, mpHIO->m.mSwimAngleSpeed / 2); cLib_chaseAngleS(&mWaistAngle.z, 0, mpHIO->m.mSwimAngleSpeed / 2); } else { mDoMtx_stack_c::push(); csXyz angle; angle.x = cLib_targetAngleX(&field_0x1578, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &field_0x1578); angle.z = 0; cXyz vec(0.0f, 0.0f, mpHIO->m.field_0x8c); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::multVec(&vec, &field_0x1578); if (mIsTurning) { vec.set(0.0f, 0.0f, mpHIO->m.field_0x90); cXyz vec2; mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&vec, &vec2); field_0x1578 -= vec2; field_0x1578.normalize(); field_0x1578 *= mpHIO->m.field_0x8c; } mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::inverse(); mDoMtx_stack_c::multVec(&field_0x1578, &field_0x1584); field_0x1578 += current.pos; mWaistAngle.x = cM_atan2s(field_0x1584.y, -field_0x1584.z); mWaistAngle.y = cM_atan2s(-field_0x1584.x, -field_0x1584.z); mWaistAngle.z = 0; mDoMtx_stack_c::pop(); } } void daNpc_zrA_c::calcWaistAngleInit() { cXyz vec(0.0f, 0.0f, -mpHIO->m.field_0x8c); mDoMtx_stack_c::ZXYrotS(mCurAngle); mDoMtx_stack_c::transM(vec); mDoMtx_stack_c::multVecZero(&field_0x1578); field_0x1578 += current.pos; mResetWaistAngle = false; } void daNpc_zrA_c::calcWaistAngleStop() { mResetWaistAngle = true; } BOOL daNpc_zrA_c::calcWaistAngleCheck() { if (mSwimMode != SWIM_WAIT && !mResetWaistAngle) { return true; } else { return false; } } void daNpc_zrA_c::calcModulation() { if (mAcch.ChkWaterIn()) { if (mAcch.ChkWaterIn() && current.pos.y < mAcch.m_wtr.GetHeight() - 220.0f) { cLib_chaseF(&mModulationOffset.x, 5.0f - cM_scos(mModulationParam * 0x10000 / 42) * 5.0f, 1.0f); cLib_chaseF(&mModulationOffset.y, 8.0f - cM_scos(mModulationParam * 0x10000 / 70) * 8.0f, 1.0f); cLib_chaseF(&mModulationOffset.z, 4.0f - cM_scos(mModulationParam * 0x10000 / 105) * 4.0f, 1.0f); } else { cLib_chaseF(&mModulationOffset.y, 5.0f - cM_scos(mModulationParam * 0x10000 / 35) * 5.0f, 1.0f); cLib_chaseF(&mModulationOffset.x, 0.0f, 1.0f); cLib_chaseF(&mModulationOffset.z, 0.0f, 1.0f); } mModulationParam--; if (mModulationParam <= 0) { mModulationParam = 210; } } } void daNpc_zrA_c::resetModulation() { cLib_chaseF(&mModulationOffset.y, 0.0f, 1.0f); cLib_chaseF(&mModulationOffset.x, 0.0f, 1.0f); cLib_chaseF(&mModulationOffset.z, 0.0f, 1.0f); mModulationParam = 210; } void daNpc_zrA_c::calcSwimAngle(csXyz& i_target, csXyz& i_calc, s16 i_scale, s16 i_step) { cLib_addCalcAngleS2(&i_calc.x, i_target.x, i_scale, i_step); cLib_addCalcAngleS2(¤t.angle.x, i_calc.x, i_scale, i_step); cLib_addCalcAngleS2(&i_calc.y, i_target.y, i_scale, i_step); cLib_addCalcAngleS2(¤t.angle.y, i_calc.y, i_scale, i_step); } void daNpc_zrA_c::calcSwimPos(cXyz& i_speed) { csXyz angle = current.angle; angle.z = 0; mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::multVec(&i_speed, &i_speed); current.pos += i_speed; } void daNpc_zrA_c::calcWaitSwim(BOOL param_0) { cLib_chaseAngleS(¤t.angle.x, 0, mpHIO->m.mSwimAngleSpeed); cLib_chaseAngleS(¤t.angle.z, 0, mpHIO->m.mSwimAngleSpeed); mCurAngle = current.angle; shape_angle = mCurAngle; cLib_chaseF(&mSwimSpeedF, 0.0f, 2.0f); cLib_chaseF(&mScaleFactor, 1.0f, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); calcModulation(); if (param_0 && mAcch.ChkWaterHit() && current.pos.y > mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth) { current.pos.y = mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth; } } BOOL daNpc_zrA_c::ECut_talkSwim(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: mAcch.ClrGrndNone(); mAcch.ClrWallNone(); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_FLOAT, mpHIO->m.common.morf_frame, true); mTurnMode = 0; mMode = 2; mSwimSpeed.set(0.0f, 0.0f, mSwimSpeedF); mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&mSwimSpeed, &mSwimSpeed); mSwimSpeedF = 0.0f; calcWaistAngleStop(); break; case 1: initTalk(mFlowID, NULL); break; case 2: mSwimAngleCalc = current.angle; break; } } switch (prm) { case 0: { calcModulation(); if (current.angle.x == 0 && current.angle.z == 0 && mSwimSpeed.abs2() < 0.1f && mScaleFactor <= 1.05f && mBaseMotionAnm != ANM_FLOAT) { ret = true; setLookMode(LOOK_PLAYER); break; } cLib_chaseAngleS(¤t.angle.x, 0, mpHIO->m.mSwimAngleSpeed); cLib_chaseAngleS(¤t.angle.z, 0, mpHIO->m.mSwimAngleSpeed); cLib_chaseAngleS(¤t.angle.y, fopAcM_searchPlayerAngleY(this), mpHIO->m.mSwimAngleSpeed); cLib_chaseF(&mScaleFactor, 1.0f, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); cXyz zero(0.0f, 0.0f, 0.0f); cLib_chasePos(&mSwimSpeed, zero, 0.5f); current.pos += mSwimSpeed; f32 water_y; if (fopAcM_getWaterY(¤t.pos, &water_y) && current.pos.y > water_y - mpHIO->m.mMinDepth - 50.0f) { cLib_chaseF(¤t.pos.y, water_y - mpHIO->m.mMinDepth - 50.0f, 20.0f); } mCurAngle = current.angle; shape_angle = mCurAngle; break; } case 1: calcModulation(); if (talkProc(NULL, true, NULL)) { if (mActionType == ACT_TYPE_0) { setMotion(MOT_DIVE_SWIM_B, mpHIO->m.common.morf_frame / 2.0f, true); } else { setMotion(MOT_DIVE_SWIM_A, mpHIO->m.common.morf_frame / 2.0f, true); } mSwimAngleCalc = current.angle; mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; setLookMode(LOOK_NONE); ret = true; } break; case 2: { resetModulation(); s16 swim_angle_speed = mpHIO->m.mSwimAngleSpeed; cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); cXyz vec; csXyz angle; mPath.getDstPosDst2(current.pos, vec); angle.x = cLib_targetAngleX(&vec, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &vec); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 8, swim_angle_speed); mCurAngle = current.angle; shape_angle = mCurAngle; if (mBaseMotionAnm != ANM_DIVE) { ret = true; if (!calcWaistAngleCheck()) { calcWaistAngleInit(); mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; } cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); mAcch.SetGrndNone(); mAcch.SetWallNone(); } if (mAcch.ChkWaterHit() && current.pos.y > mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth) { current.pos.y = mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth; } break; } default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::waitWaterfall(void* param_0) { switch (mMode) { case 0: setExpressionAnm(ANM_NONE, false); if (mMotion != MOT_FLOAT && mMotion != MOT_FLOAT_B) { setMotion(MOT_WAIT_SWIM, -1.0f, false); } gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; mAcch.SetGrndNone(); mAcch.SetWallNone(); setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mSwimMode = SWIM_RAIL; calcWaistAngleStop(); field_0x1550 = true; mCcStts.SetWeight(0xff); mMode = 2; // fallthrough case 2: calcWaitSwim(false); if (mScaleFactor == 1.0f) { mSwimMode = SWIM_WAIT; } if (mDamageTimer == 0 && !mTwilight) { BOOL player_attn = mActorMngr[0].getActorP() != NULL; if (chkFindPlayer2(player_attn, shape_angle.y)) { if (!player_attn) { mActorMngr[0].entry(daPy_getPlayerActorClass()); mTurnMode = 0; } } else { if (player_attn) { mActorMngr[0].remove(); mTurnMode = 0; } } if (mActorMngr[0].getActorP() != NULL) { setLookMode(LOOK_PLAYER); } else { setLookMode(LOOK_NONE); if (home.angle.y != mCurAngle.y && step(home.angle.y, -1, -1, 15)) { mMode = 0; } } } break; case 3: speedF = 0.0f; break; } return true; } BOOL daNpc_zrA_c::swimWaterfall(void* param_0) { s16 angle_step = mpHIO->m.mSwimAngleSpeed * 2; s16 angle_scale = 2; cXyz point, swim_speed; switch (mMode) { case 0: mAcch.SetGrndNone(); mAcch.SetWallNone(); gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; field_0x153d = false; setExpressionAnm(ANM_NONE, false); if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mSwimMode = SWIM_RAIL; mScaleFactor = mpHIO->m.mMaxScaleFactor; mCcStts.SetWeight(0); setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mMode = 2; field_0x153e = false; mSwimAngleCalc = current.angle; calcWaistAngleInit(); // fallthrough case 2: { int idx = mPath.getIdx(); if (mPath.getDstPosDst2(current.pos, point) && idx == 0 && mPath.chkReverse()) { mPath.reverse(); mActionSelect = 0; mSwimSpeedScale = 1.0f; setMotion(MOT_FLOAT_B, -1.0f, false); setAction(&daNpc_zrA_c::waitWaterfall); return false; } csXyz angle; angle.x = cLib_targetAngleX(&point, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &point); angle.z = current.angle.z; cXyz prev_point; mPath.getBeforePos(prev_point); if (cLib_targetAngleX(&point, &prev_point) > 0x3000) { angle.x = 0x4000; angle.y = 0; mSwimSpeedScale = 3.0f; } else { mSwimSpeedScale = 1.0f; } s16 ang_diff_x = angle.x - current.angle.x; s16 ang_diff_y = angle.y - current.angle.y; bool bvar5 = false; if (mActionType != ACT_TYPE_0 && (abs(ang_diff_x) > 0x3000 || abs(ang_diff_y) > 0x3000) && mSwimSpeedF > 14.0f) { f32 frame = mAnm_p->getFrame(); if ((angle.z <= 0x2000 || ang_diff_y >= 0) && (angle.z >= -0x2000 || ang_diff_y <= 0)) { if (ang_diff_x < -0x3000) { if (frame >= 2.0f && frame <= 4.0f) { bvar5 = true; } } else { if (frame >= 16.0f && frame <= 18.0f) { mAnm_p->setFrame(18.0f); mAnm_p->setMorf(4.0f); mAnm_p->setPlaySpeed(0.1f); bvar5 = true; } } } if (bvar5) { calcSwimAngle(angle, mSwimAngleCalc, 1, angle_step); } else { calcSwimAngle(angle, mSwimAngleCalc, 2, angle_step / 2); } } else { calcSwimAngle(angle, mSwimAngleCalc, 2, angle_step); } if (current.angle.x > 0x2000) { mSwimSpeedScale = 3.0f; angle_step *= 2.0f; angle_scale = 2; } else { mSwimSpeedScale = 1.0f; } cLib_addCalc2(&mSwimSpeedF, mSwimSpeedScale * mpHIO->m.mSwimSpeed, 0.1f, 1.0f); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (!bvar5) { f32 play_speed = mAnm_p->getPlaySpeed(); f32 target_speed = cLib_minMaxLimit(mSwimSpeedF / mpHIO->m.mSwimAnmRate, 0.0f, 1.5f); cLib_addCalc2(&play_speed, target_speed, 0.2f, 0.1f); mAnm_p->setPlaySpeed(play_speed); } calcBank(angle_step, angle_scale, angle.y, angle.z); current.angle.z = angle.z; mCurAngle = current.angle; shape_angle = mCurAngle; break; } case 3: break; } return true; } BOOL daNpc_zrA_c::diveWaterfall(void* param_0) { switch (mMode) { case 0: mPath.onReverse(); mPath.setIdx(mPath.getEndIdx() - 1); mPath.setNextIdxDst(current.pos); setExpressionAnm(ANM_NONE, false); setMotion(MOT_DIVE_B_SWIM_A, -1.0f, false); mSwimAngleCalc = current.angle; mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; setLookMode(LOOK_NONE); mSwimMode = SWIM_RAIL; mActionSelect = 3; mMode = 2; // fallthrough case 2: if (diveCalc(mpHIO->m.mSwimAngleSpeed, 4, false)) { mActionSelect = 1; setAction(&daNpc_zrA_c::swimWaterfall); } break; case 3: break; } return true; } BOOL daNpc_zrA_c::talkSwim(void* param_0) { BOOL bvar2 = false; int flow_id; int choiceNo; switch (mMode) { case 0: if (mDamageTimer != 0) { break; } setExpression(EXPR_NONE, -1.0f); flow_id = mFlowID; mTurnMode = 0; mMode = 2; initTalk(flow_id, NULL); field_0x1558 = 0; // fallthrough case 2: switch (field_0x1558) { case 0: calcModulation(); if (field_0x9ea) { bvar2 = true; } else { setLookMode(LOOK_NONE); if (mCurAngle.y == fopAcM_searchPlayerAngleY(this)) { bvar2 = true; } else if (step(fopAcM_searchPlayerAngleY(this), -1, -1, 15)) { mTurnMode = 0; } } if (bvar2 && talkProc(NULL, 1, NULL)) { choiceNo = mFlow.getChoiceNo(); if (choiceNo == 0) { field_0x1558 = 1; mSwimAngleCalc = current.angle; mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; setLookMode(LOOK_NONE); } else { mMode = 3; dComIfGp_event_reset(); setAction(&daNpc_zrA_c::waitWaterfall); field_0x9ec = false; } } break; case 1: mMode = 3; dComIfGp_event_reset(); mActionSelect = 1; if (!dKy_daynight_check()) { mOrderEvtNo = EVT_CARRY_WATERFALL; } else { mOrderEvtNo = EVT_CARRY_WATERFALL_NIGHT; } changeEvent(l_resNames[l_evtGetParamList[mOrderEvtNo].arcIdx], l_evtNames[l_evtGetParamList[mOrderEvtNo].fileIdx], 1, 0xffff); } break; case 3: break; } return false; } BOOL daNpc_zrA_c::ECut_carryWaterfall(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: dComIfGp_getEvent()->setSkipProc(this, dEv_defaultSkipProc, 0); Z2GetAudioMgr()->subBgmStart(Z2BGM_ZORA_D01); break; case 10: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_FALLSWIM, -1.0f, false); current.angle.y = -0x8000; setAngle(current.angle.y); mPath.setNextIdxDst(current.pos); mAcch.SetGrndNone(); mAcch.SetWallNone(); field_0x153d = false; mSwimMode = SWIM_RAIL; mScaleFactor = mpHIO->m.mMaxScaleFactor; mCcStts.SetWeight(0); setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; field_0x153e = false; mSwimAngleCalc = current.angle; calcWaistAngleInit(); break; case 20: mPath.setIdx(5); current.pos = mPath.getPntPos(5); mPath.setNextIdxDst(current.pos); current.angle.y = -0x8000; current.angle.x = -0x4000; mCurAngle.x = -0x4000; shape_angle.x = -0x4000; setAngle(current.angle.y); break; case 30: mEventTimer = 60; break; case 40: break; } } switch (prm) { case 0: calcWaitSwim(false); ret = true; break; case 10: ret = true; // fallthrough case 20: resetModulation(); if (mMotion != MOT_FALLSWIM) { calcWaitSwim(false); if (mScaleFactor == 1.0f) { mSwimMode = SWIM_WAIT; } ret = true; } else { s16 angle_step = mpHIO->m.mSwimAngleSpeed * 2; cXyz pos, swim_speed; f32 speed_scale = mSwimSpeedScale; if (mPath.getDstPosDst2(current.pos, pos) && mPath.getIdx() == mPath.getNextIdx()) { mPath.reverse(); mSwimMode = SWIM_RAIL; mActionSelect = 3; setMotion(MOT_FLOAT_B, -1.0f, false); calcWaistAngleStop(); ret = true; } else { csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 4, angle_step); cLib_addCalc2(&mSwimSpeedF, speed_scale * mpHIO->m.mSwimSpeed, 0.1f, 1.0f); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); current.angle.z = angle.z; shape_angle.x = mCurAngle.x = current.angle.x; shape_angle.z = mCurAngle.z = current.angle.z; if (current.angle.x < -0x2000) { cLib_addCalcAngleS2(&mCurAngle.y, -0x8000, 4, angle_step); } else { cLib_addCalcAngleS2(&mCurAngle.y, current.angle.y, 4, angle_step); } shape_angle.y = mCurAngle.y; } } break; case 30: if (cLib_calcTimer(&mEventTimer) == 0) { ret = true; } calcWaitSwim(false); if (mScaleFactor == 1.0f) { mSwimMode = SWIM_WAIT; } cLib_chaseAngleS(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), mpHIO->m.mSwimAngleSpeed); setAngle(mCurAngle.y); break; case 40: ret = true; break; default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::ECut_carryWaterfallSkip(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: Z2GetAudioMgr()->subBgmStop(); break; case 10: mPath.onReverse(); mPath.setIdx(mPath.getEndIdx() - 1); current.pos = mPath.getPntPos(mPath.getEndIdx() - 1); old.pos = current.pos; current.angle.set(0, -0x8000, 0); shape_angle = mCurAngle = current.angle; setLookMode(LOOK_NONE); setMotion(MOT_FLOAT_B, -1.0f, false); mSwimMode = SWIM_RAIL; mActionSelect = 3; calcWaistAngleStop(); mAttnChangeTimer = 0; mTurnMode = 0; mSwimAngleCalc = current.angle; mEventTimer = 60; break; case 20: break; default: break; } } switch (prm) { case 0: ret = true; break; case 10: if (cLib_calcTimer(&mEventTimer) == 0) { ret = true; } calcWaitSwim(false); if (mScaleFactor == 1.0f) { mSwimMode = SWIM_WAIT; } cLib_chaseAngleS(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), mpHIO->m.mSwimAngleSpeed); setAngle(mCurAngle.y); break; case 20: ret = true; break; default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::diveCalc(s16 i_angleStep, s16 i_angleScale, BOOL param_2) { cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); cXyz pos; mPath.getDstPosDst2(current.pos, pos); csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, i_angleScale, i_angleStep); shape_angle = mCurAngle = current.angle; f32 frame = mAnm_p->getFrame(); cXyz dive_speed(0.0f, 0.0f, 0.0f); if (frame < 3.0f) { dive_speed.set(0.0f, -6.0f, 0.0f); } else if (frame < 6.0f) { dive_speed.set(0.0f, -9.0f, 0.0f); } else if (frame < 9.0f) { dive_speed.set(0.0f, -9.0f, 8.5f); } else if (frame < 13.0f) { dive_speed.set(0.0f, -9.0f, 5.7f); } else if (frame < 20.0f) { dive_speed.set(0.0f, 3.0f, 2.4f); } else if (frame < 36.0f) { dive_speed.set(2.0f, 3.0f, 6.5f); } mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&dive_speed, &dive_speed); current.pos += dive_speed; if (param_2 && mAcch.ChkWaterIn() && current.pos.y > mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth) { current.pos.y = mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth; } if (mBaseMotionAnm == ANM_SWIM_A || mBaseMotionAnm == ANM_SWIM_B) { return true; } else { return false; } } static void* s_subHoz(void* i_proc, void* i_this) { if (fopAc_IsActor(i_proc) && fopAcM_GetName(i_proc) == fpcNm_NPC_HOZ_e) { return i_proc; } return NULL; } static void* s_sub(void* i_proc, void* i_this) { if (fopAc_IsActor(i_proc) && fopAcM_GetName(i_proc) == fpcNm_CANOE_e) { return i_proc; } return NULL; } BOOL daNpc_zrA_c::waitRiverDescend(void* param_0) { switch (mMode) { case 0: setExpressionAnm(ANM_NONE, false); if (mMotion != MOT_FLOAT_B) { setMotion(MOT_WAIT_SWIM, -1.0f, false); } gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; calcWaistAngleStop(); field_0x1550 = true; mSwimSpeedF = 0.0f; field_0x1500 = daPy_getPlayerActorClass()->current.pos; mIsTurning = true; mMode = 2; // fallthrough case 2: { daPy_py_c* player = daPy_getPlayerActorClass(); calcWaitSwim(true); cXyz pos; moveRiverPosCalc(pos); if (mGameMode == GAME_MODE_3) { if (mActorMngr[2].getActorP() == NULL) { fopAc_ac_c* canoe = (fopAc_ac_c*)fpcM_Search(s_sub, this); if (canoe != NULL && !((player->current.pos - this->current.pos).absXZ() > 1000.0f)) { mActorMngr[2].entry(canoe); if (!player->checkCanoeSlider()) { player->setCanoeSlider(); mActionSelect = 4; setAction(&daNpc_zrA_c::swimGoalRiverDescend); break; } } } } else if (mGameMode == GAME_MODE_0) { if (mActorMngr[2].getActorP() == NULL) { daNpc_Hoz_c* iza = (daNpc_Hoz_c*)fpcM_Search(s_subHoz, this); if (iza != NULL) { mActorMngr[2].entry(iza); if (iza->getType() == daNpc_Hoz_c::TYPE_1 || iza->getType() == daNpc_Hoz_c::TYPE_5) { mGameMode = GAME_MODE_1; if (dComIfGs_isSwitch(mSwitch1, fopAcM_GetRoomNo(this))) { field_0x15c0 = 2; } } else { mGameMode = GAME_MODE_2; if (!daNpcF_chkEvtBit(0x60)) { daNpcF_onEvtBit(0x60); } } } } } if (player->checkCanoeRide()) { if (mGameMode == GAME_MODE_2) { daNpc_Hoz_c* iza = static_cast(mActorMngr[2].getActorP()); if (iza != NULL && iza->getGameStartFlag()) { mActionSelect = 3; mPath.setNextIdx(); setAction(&daNpc_zrA_c::diveRiverDescend); break; } } else if (mGameMode == GAME_MODE_1) { if (field_0x15c0 == 0) { if ((player->current.pos - current.pos).absXZ() < mpHIO->m.field_0xa8) { field_0x15c0 = 1; mOrderEvtNo = EVT_BEFORE_BLAST_ZRR; } } else if (field_0x15c0 == 1) { cXyz vec2(34301.445f, -6541.864f, -24243.617f); if (dComIfGs_isSwitch(mSwitch1, fopAcM_GetRoomNo(this))) { mOrderEvtNo = EVT_AFTER_BLAST_ZRR; mOrderNewEvt = true; } else { if ((current.pos - vec2).absXZ() >= 100.0f) { mActionSelect = 3; setAction(&daNpc_zrA_c::diveRiverDescend); } } } else { cXyz vec3 = player->current.pos; vec3 -= current.pos; if (vec3.absXZ() < 10000.0f) { mPath.setNextIdxDst(current.pos); mActionSelect = 3; setAction(&daNpc_zrA_c::diveRiverDescend); break; } } } cLib_addCalcAngleS2(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), 2, 0x800); setAngle(mCurAngle.y); } break; } case 3: speedF = 0.0f; break; } return true; } BOOL daNpc_zrA_c::swimRiverDescend(void* param_0) { cXyz pos_sp94; cXyz swim_speed_sp88; s16 angle_step_r28 = (s16)mpHIO->m.mSwimAngleSpeed; s16 angle_scale_r27 = 6; f32 sp28 = 0.25f; f32 sp24 = 4.0f; f32 water_height = mAcch.m_wtr.GetHeight(); switch (mMode) { case 0: gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; field_0x153d = false; setExpressionAnm(ANM_NONE, false); if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mSwimMode = SWIM_RAIL; mCcStts.SetWeight(0); setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mMode = 2; field_0x153e = false; mSwimAngleCalc = current.angle; calcWaistAngleInit(); field_0x1500 = daPy_getPlayerActorClass()->current.pos; // fallthrough case 2: { csXyz angle_sp44; daPy_py_c* player_r26 = daPy_getPlayerActorClass(); cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); int ivar8_sp20 = mRiverPathIdx; moveRiverPosCalc(pos_sp94); if (field_0x153c) { mMeterCount = dMeter2Info_getNowCount(); cXyz head_pos_sp7c; mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&head_pos_sp7c); if (field_0x153e) { if (mIsAboveWater && mAnm_p->getFrame() > 13.0f && mAnm_p->getFrame() < 17.0f) { f32 play_speed_sp1c = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed_sp1c, 0.3f, 0.7f, 0.5f); mAnm_p->setPlaySpeed(play_speed_sp1c); } angle_sp44.y = cLib_targetAngleY(¤t.pos, &pos_sp94); cLib_addCalcAngleS2(&mSwimAngleCalc.y, angle_sp44.y, (s16)angle_scale_r27, angle_step_r28); cLib_addCalcAngleS2(¤t.angle.y, mSwimAngleCalc.y, (s16)angle_scale_r27, angle_step_r28); mSwimSpeed.set(0.0f, mSwimSpeed.y, mSwimSpeed.absXZ()); mDoMtx_stack_c::YrotS(current.angle.y); mDoMtx_stack_c::multVec(&mSwimSpeed, &mSwimSpeed); calcBank((s16)angle_step_r28 / 2, angle_scale_r27 * 2, current.angle.y, current.angle.z); mSwimSpeed.y -= 1.8f; current.pos += mSwimSpeed; if (current.angle.x < 0x3000) { current.angle.x = -cM_atan2s(mSwimSpeed.y, mSwimSpeed.absXZ()); } shape_angle = mCurAngle = current.angle; if (mAcch.ChkWaterHit()) { if (mIsAboveWater && mSwimSpeed.y <= 0.0f && head_pos_sp7c.y + mSwimSpeed.y <= water_height) { cXyz wpillar_pos = head_pos_sp7c; wpillar_pos.y = water_height; fopKyM_createWpillar(&wpillar_pos, 2.5f, 0); mIsAboveWater = false; mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH, 0, -1); mAnm_p->setPlaySpeed(1.0f); } if (current.pos.y <= water_height - mpHIO->m.mMinDepth) { field_0x153e = false; field_0x153c = false; mSwimSpeedF = mSwimSpeed.abs(); } } return true; } angle_sp44.y = cLib_targetAngleY(¤t.pos, &pos_sp94); angle_sp44.z = current.angle.z; if (mSwimSpeedF > 40.0f) { angle_sp44.x = -0x3000; if (mAcch.ChkWaterHit()) { if (head_pos_sp7c.y < water_height) { angle_step_r28 = mpHIO->m.mSwimAngleSpeed * 2; angle_scale_r27 = 2; } else if (!mIsAboveWater) { cXyz wpillar_pos_sp64 = head_pos_sp7c; wpillar_pos_sp64.y = water_height; fopKyM_createWpillar(&wpillar_pos_sp64, 2.5f, 0); mIsAboveWater = true; mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH_OUT, 0, -1); } else { if (mAnm_p->getFrame() > 13.0f && mAnm_p->getFrame() < 17.0f) { f32 play_speed_sp18 = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed_sp18, 0.3f, 0.7f, 0.8f); mAnm_p->setPlaySpeed(play_speed_sp18); } if (current.pos.y > water_height && current.angle.x < -0x2000) { swim_speed_sp88.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed_sp88); mSwimSpeed = swim_speed_sp88; field_0x153e = true; if (mSwimSpeed.y > 20.0f) { mSwimSpeed.y = 20.0f; } calcBank(angle_step_r28, (s16)angle_scale_r27, angle_sp44.y, angle_sp44.z); current.angle.z = angle_sp44.z; return true; } } } } else { angle_sp44.x = cLib_targetAngleX(&pos_sp94, ¤t.pos); } } else { u8 meter_count_sp09 = dMeter2Info_getNowCount(); if (mGameMode != GAME_MODE_1 && meter_count_sp09 > mMeterCount) { field_0x153c = true; } mMeterCount = meter_count_sp09; if (mRiverPathIdx == mPath.getEndIdx()) { angle_sp44.x = 0x1000; angle_sp44.y = -0x4000; angle_sp44.z = current.angle.z; } else { angle_sp44.x = cLib_targetAngleX(&pos_sp94, ¤t.pos); angle_sp44.y = cLib_targetAngleY(¤t.pos, &pos_sp94); angle_sp44.z = current.angle.z; } if (mGameMode == GAME_MODE_1 && ivar8_sp20 != mRiverPathIdx) { createRuppi(); } } cXyz vec_sp58 = field_0x1500 - player_r26->current.pos; f32 target_speed_f31 = vec_sp58.abs(); if (target_speed_f31 < mpHIO->m.mSwimSpeed) { target_speed_f31 = mpHIO->m.mSwimSpeed; } else { target_speed_f31 *= 1.4f; } if ((player_r26->current.pos - current.pos).absXZ() < 500.0f) { ANGLE_ADD(angle_sp44.x, 0x1000); } if (field_0x153c) { if (target_speed_f31 < 3.0f * mpHIO->m.mSwimSpeed) { target_speed_f31 = 3.0f * mpHIO->m.mSwimSpeed; } target_speed_f31 *= 1.2f; } else if (mRiverPathIdx >= mPath.getIdx()) { f32 player_dst_f29 = mPath.chkPassDst(mRiverPathIdx, player_r26->current.pos); f32 dst_f28 = mPath.chkPassDst(mRiverPathIdx, current.pos); if (dst_f28 - player_dst_f29 > 5000.0f) { target_speed_f31 = 0.0f; } else if (dst_f28 - player_dst_f29 > 3500.0f) { target_speed_f31 *= 0.4f; } else if (dst_f28 - player_dst_f29 > 3000.0f) { target_speed_f31 *= 0.8f; } if (target_speed_f31 == 0.0f) { angle_sp44.x = cLib_targetAngleX(&player_r26->current.pos, ¤t.pos); angle_sp44.y = cLib_targetAngleY(¤t.pos, &player_r26->current.pos); } } field_0x1500 = player_r26->current.pos; cLib_addCalc2(&mSwimSpeedF, target_speed_f31, sp28, sp24); calcSwimAngle(angle_sp44, mSwimAngleCalc, angle_scale_r27, angle_step_r28); swim_speed_sp88.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed_sp88); f32 play_speed_sp14 = mAnm_p->getPlaySpeed(); if (target_speed_f31 != 0.0f) { cLib_addCalc2(&play_speed_sp14, cLib_minMaxLimit((mSwimSpeedF - vec_sp58.abs()) / 25.0f, 0.0f, 1.3f) + 0.7f, 0.2f, 0.05f); } else { cLib_addCalc2(&play_speed_sp14, 1.7f, 0.2f, 0.05f); } mAnm_p->setPlaySpeed(play_speed_sp14); if (!field_0x153c && mAcch.ChkWaterHit() && current.pos.y > water_height - mpHIO->m.mMinDepth) { current.pos.y = water_height - mpHIO->m.mMinDepth; } calcBank(angle_step_r28, angle_scale_r27, angle_sp44.y, angle_sp44.z); current.angle.z = angle_sp44.z; shape_angle = mCurAngle = current.angle; } case 3: break; } return true; } BOOL daNpc_zrA_c::swimRiverDescend2(void* param_0) { cXyz pos, swim_speed; s16 angle_step = mpHIO->m.mSwimAngleSpeed; f32 water_height = mAcch.m_wtr.GetHeight(); switch (mMode) { case 0: gravity = 0.0f; speed.setall(0.0f); speedF = 0.0f; field_0x153d = false; setExpressionAnm(ANM_NONE, false); if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mSwimMode = SWIM_RAIL; mCcStts.SetWeight(0); setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; field_0x153e = false; mSwimAngleCalc = current.angle; calcWaistAngleInit(); mMode = 2; // fallthrough case 2: { moveRiverPosCalc(pos); cXyz vec(34301.445f, -6541.864f, -24243.617f); if ((current.pos - vec).absXZ() < 100.0f) { if (mMotion != MOT_FLOAT_B) { setExpressionAnm(ANM_NONE, false); setMotion(MOT_FLOAT_B, -1.0f, false); mActionSelect = 0; setAction(&daNpc_zrA_c::waitRiverDescend); } } else if (dComIfGs_isSwitch(mSwitch1, fopAcM_GetRoomNo(this))) { mOrderEvtNo = EVT_AFTER_BLAST_ZRR; mOrderNewEvt = true; setExpressionAnm(ANM_NONE, false); setMotion(MOT_FLOAT_B, -1.0f, false); mActionSelect = 0; setAction(&daNpc_zrA_c::waitRiverDescend); } else { csXyz angle; cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); angle.x = cLib_targetAngleX(&vec, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &vec); angle.z = current.angle.z; cLib_addCalc2(&mSwimSpeedF, 2.0f * mpHIO->m.mSwimSpeed, 0.25f, 4.0f); calcSwimAngle(angle, mSwimAngleCalc, 6, angle_step); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 1.7f, 0.2f, 0.05f); mAnm_p->setPlaySpeed(play_speed); if (mAcch.ChkWaterHit() && current.pos.y > water_height - mpHIO->m.mMinDepth) { current.pos.y = water_height - mpHIO->m.mMinDepth; } calcBank(angle_step, 6, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; } break; } case 3: break; } return true; } BOOL daNpc_zrA_c::diveRiverDescend(void* param_0) { s16 angle_step = mpHIO->m.mSwimAngleSpeed * 2; switch (mMode) { case 0: setExpressionAnm(ANM_NONE, false); if (mActionType == ACT_TYPE_0) { setMotion(MOT_DIVE_B_SWIM_B, -1.0f, false); } else { setMotion(MOT_DIVE_B_SWIM_A, -1.0f, false); } mSwimMode = SWIM_3; mCcStts.SetWeight(0); setLookMode(LOOK_NONE); mSwimAngleCalc = current.angle; mMode = 2; // fallthrough case 2: { cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); cXyz pos; csXyz angle; mPath.getDstPos(current.pos, pos); angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 3, angle_step); shape_angle = mCurAngle = current.angle; f32 frame = mAnm_p->getFrame(); cXyz dive_speed(0.0f, 0.0f, 0.0f); if (mBaseMotionAnm == ANM_DIVE_B) { if (frame <= 3.0f) { dive_speed.set(0.0f, 0.0f, 0.0f); } else if (frame <= 6.0f) { dive_speed.set(0.0f, 14.0f, 0.0f); } else if (frame <= 9.0f) { dive_speed.set(0.0f, 3.0f, 8.5f); } else if (frame <= 13.0f) { dive_speed.set(0.0f, -9.25f, 4.5f); } else if (frame <= 20.0f) { dive_speed.set(0.0f, -14.0f, 2.5f); } else { dive_speed.set(0.0f, 0.0f, 6.25f); } } mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&dive_speed, &dive_speed); current.pos += dive_speed; if (mGameMode == GAME_MODE_1 && field_0x15c0 == 1 && dComIfGs_isSwitch(mSwitch1, fopAcM_GetRoomNo(this))) { setExpressionAnm(ANM_NONE, false); setMotion(MOT_FLOAT_B, -1.0f, false); mOrderEvtNo = EVT_AFTER_BLAST_ZRR; mOrderNewEvt = true; mActionSelect = 0; setAction(&daNpc_zrA_c::waitRiverDescend); } else if (mBaseMotionAnm == ANM_SWIM_A || mBaseMotionAnm == ANM_SWIM_B) { if (mGameMode == GAME_MODE_1 && field_0x15c0 == 1) { mActionSelect = 6; setAction(&daNpc_zrA_c::swimRiverDescend2); } else { mActionSelect = 1; setAction(&daNpc_zrA_c::swimRiverDescend); } } break; } case 3: break; } return true; } BOOL daNpc_zrA_c::swimGoalRiverDescend(void* param_0) { daPy_py_c* player; cXyz pos, swim_speed; s16 angle_step = mpHIO->m.mSwimAngleSpeed; switch (mMode) { case 0: setExpressionAnm(ANM_NONE, false); if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mSwimMode = SWIM_RAIL; mCcStts.SetWeight(0); setLookMode(LOOK_NONE); mSwimAngleCalc = current.angle; calcWaistAngleInit(); field_0x1500 = daPy_getPlayerActorClass()->current.pos; mSwimSpeedF = mpHIO->m.mSwimSpeed; mMode = 2; // fallthrough case 2: player = daPy_getPlayerActorClass(); cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); if (player->current.pos.y < -14100.0f) { if (!daNpcF_chkEvtBit(0x60)) { mOrderEvtNo = EVT_THANKS_BLAST; } else { int count = dMeter2Info_getNowCount(); if (count >= 30) { dComIfGs_onSwitch(mSwitch1, fopAcM_GetRoomNo(this)); dComIfGs_onSwitch(mSwitch2, fopAcM_GetRoomNo(this)); mOrderEvtNo = EVT_THANKS_BLAST; } else if (count >= 25) { dComIfGs_onSwitch(mSwitch1, fopAcM_GetRoomNo(this)); mOrderEvtNo = EVT_THANKS_BLAST; } else { mOrderEvtNo = EVT_RESULT_ANNOUNCE; } } } else { mPath.getDstPos(current.pos, pos); f32 target_speed; cXyz vec; if (mPath.getIdx() != mPath.getNextIdx()) { vec = field_0x1500 - player->current.pos; target_speed = vec.abs() * 1.2f; if (target_speed < mpHIO->m.mSwimSpeed) { target_speed = mpHIO->m.mSwimSpeed; } } else { target_speed = 0.0f; if (mSwimSpeedF < 10.0f) { pos = player->current.pos; } } field_0x1500 = player->current.pos; cLib_addCalc2(&mSwimSpeedF, target_speed, 0.3f, 5.0f); csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 3, angle_step); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); f32 play_speed = mAnm_p->getPlaySpeed(); //!@bug vec is used here despite not being initialized in all code paths f32 target_play_speed = cLib_minMaxLimit((mSwimSpeedF - vec.abs()) / 25.0f, 0.0f, 1.3f) + 0.7f; cLib_addCalc2(&play_speed, target_play_speed, 0.2f, 0.1f); mAnm_p->setPlaySpeed(play_speed); calcBank(angle_step, 3, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; } break; case 3: break; } return true; } BOOL daNpc_zrA_c::returnRiverDescend(void* param_0) { cXyz pos, swim_speed; s16 angle_step = mpHIO->m.mSwimAngleSpeed; f32 swim_speed_scale = mSwimSpeedScale; switch (mMode) { case 0: mMode = 2; // fallthrough case 2: if (mPath.getDstPos(current.pos, pos) && mPath.getIdx() == mPath.getNextIdx()) { mPath.reverse(); fopAcM_delete(mActorMngr[2].getActorP()); fopAcM_delete(this); return true; } else { csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; s16 angle_diff_x = angle.x - current.angle.x; s16 angle_diff_y = angle.y - current.angle.y; bool bvar4 = false; if (mActionType != ACT_TYPE_0 && (abs(angle_diff_x) > 0x3000 || abs(angle_diff_y) > 0x3000) && mSwimSpeedF > 14.0f) { f32 frame = mAnm_p->getFrame(); if ((angle.z <= 0x2000 || angle_diff_y >= 0) && (angle.z >= -0x2000 || angle_diff_y <= 0)) { if (angle_diff_x < -0x3000) { if (frame >= 2.0f && frame <= 4.0f) { bvar4 = true; } } else { if (frame >= 16.0f && frame <= 18.0f) { mAnm_p->setFrame(18.0f); mAnm_p->setMorf(2.0f); mAnm_p->setPlaySpeed(0.1f); bvar4 = true; } } } if (bvar4) { calcSwimAngle(angle, mSwimAngleCalc, 4, angle_step); } else { calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step / 2); } } else { calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step); } cLib_addCalc2(&mSwimSpeedF, swim_speed_scale * mpHIO->m.mSwimSpeed, 0.2f, 3.0f); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (mAcch.ChkWaterHit()) { current.pos.y = mAcch.m_wtr.GetHeight() - mpHIO->m.mMinDepth; } if (!bvar4) { f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, mSwimSpeedF / mpHIO->m.mSwimAnmRate, 0.2f, 0.1f); mAnm_p->setPlaySpeed(play_speed); } calcBank(angle_step, 8, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; calcCanoeMove(true); } break; case 3: break; } return true; } void daNpc_zrA_c::moveRiverPosCalc(cXyz& o_pos) { cXyz pos; mPath.getDstPos(daPy_getPlayerActorClass()->current.pos, pos); mRiverPathIdx = mPath.getDstPosChase(mRiverPathIdx, current.pos, o_pos); f32 water_y; if (fopAcM_getWaterY(&o_pos, &water_y)) { o_pos.y = water_y - 130.0f; } else { o_pos.y -= 130.0f; } } void daNpc_zrA_c::createRuppi() { int item; if (cLib_getRndValue(0, 5) < 4) { item = dItemNo_GREEN_RUPEE_e; } else { item = dItemNo_BLUE_RUPEE_e; } cXyz pos(0.0f, 0.0f, -100.0f); mDoMtx_stack_c::transS(current.pos); mDoMtx_stack_c::ZXYrotM(mCurAngle.x, mCurAngle.y, mCurAngle.z); mDoMtx_stack_c::multVec(&pos, &pos); f32 water_y; if (fopAcM_getWaterY(&pos, &water_y)) { pos.y = water_y + 50.0f; } csXyz angle(0, current.angle.y, 0); cXyz scl(1.0f, 1.0f, 1.0f); f32 speed_f = 0.0f; f32 speed_y = 50.0f; fopAcM_fastCreateItem(&pos, item, fopAcM_GetRoomNo(this), &angle, &scl, &speed_f, &speed_y, -1, 0, NULL); } BOOL daNpc_zrA_c::ECut_beforeBlastzrR(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; cXyz player_pos = daPy_getPlayerActorClass()->current.pos; cXyz canoe_pos(41744.918f, -6498.715f, -18601.64f); daCanoe_c* canoe; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: daNpcF_offTmpBit(0xb); break; case 10: initTalk(mFlowID, NULL); break; case 15: break; case 20: initTalk(mFlowID, NULL); break; } } switch (prm) { case 0: calcWaitSwim(true); cLib_addCalcAngleS2(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), 0x20, 0x200); setAngle(mCurAngle.y); ret = true; break; case 10: if (talkProc(NULL, 1, NULL)) { ret = true; } canoe = (daCanoe_c*)fpcM_Search(s_sub, this); if (canoe != NULL) { canoe->setPosAndAngle(&canoe_pos, -0x35e8); } calcWaitSwim(true); cLib_addCalcAngleS2(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), 0x20, 0x200); setAngle(mCurAngle.y); break; case 15: { canoe = (daCanoe_c*)fpcM_Search(s_sub, this); if (canoe != NULL) { canoe->setPosAndAngle(&canoe_pos, -0x35e8); } cXyz target_pos(30895.559f, -6592.8496f, -23170.195f); calcWaitSwim(true); s16 target_angle = cLib_targetAngleY(¤t.pos, &target_pos); if (mCurAngle.y != target_angle) { if (abs((s16)(mCurAngle.y - target_angle)) > 0x400) { mCurAngle.y -= 0x400; } else { mCurAngle.y = target_angle; } setAngle(mCurAngle.y); } else { ret = true; } break; } case 20: if (talkProc(NULL, 1, NULL)) { ret = true; } canoe = (daCanoe_c*)fpcM_Search(s_sub, this); if (canoe != NULL) { canoe->setPosAndAngle(&canoe_pos, -0x35e8); } calcWaitSwim(true); break; default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::ECut_afterBlastzrR(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; cXyz player_pos = daPy_getPlayerActorClass()->current.pos; cXyz canoe_pos(40944.918f, -6498.715f, -18601.64f); daCanoe_c* canoe; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: { cXyz target_pos(32651.498f, -5900.219f, -22464.525f); setLookMode(LOOK_NONE); mTurnMode = 0; calcWaistAngleStop(); field_0x1550 = true; mSwimSpeedF = 0.0f; mIsTurning = true; current.pos.set(34301.445f, -6541.864f, -24243.617f); old.pos = current.pos; setAngle(cLib_targetAngleY(¤t.pos, &target_pos)); field_0x15c0 = 2; break; } case 10: initTalk(mFlowID, NULL); break; } } switch (prm) { case 0: case 10: calcWaitSwim(true); canoe = (daCanoe_c*)fpcM_Search(s_sub, this); if (canoe != NULL) { canoe->setPosAndAngle(&canoe_pos, -0x35e8); } if (prm == 0) { ret = true; } else { if (talkProc(NULL, 1, NULL)) { ret = true; } } break; default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::ECut_thanksBlast(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; s16 angle_step = mpHIO->m.mSwimAngleSpeed; f32 water_height = mAcch.m_wtr.GetHeight(); daPy_py_c* player = daPy_getPlayerActorClass(); cXyz player_pos = player->current.pos; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: daNpcF_offTmpBit(0xb); daNpcF_offTmpBit(0xc); if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mTurnMode = 0; break; case 1: if (mActorMngr[2].getActorP() != NULL && fopAcM_GetName(mActorMngr[2].getActorP()) == fpcNm_CANOE_e) { static_cast(mActorMngr[2].getActorP())->setWaterFallDownSe(); } daPy_getPlayerActorClass()->offCanoeSlider(); if (daNpcF_chkEvtBit(0x60)) { dComIfG_TimerDeleteRequest(4); } else { dComIfG_TimerDeleteRequest(3); } dMeter2Info_resetMiniGameItem(false); break; case 10: initTalk(mFlowID, NULL); break; case 20: { mPath.onReverse(); mPath.setIdx(mPath.getEndIdx() - 1); cXyz pos1(-77941.7f, -18800.0f - mpHIO->m.mMinDepth - 30.0f, 39645.3f); cXyz pos2(-78941.7f, -18800.0f - mpHIO->m.mMinDepth - 30.0f, 39645.3f); current.pos = pos1; current.angle.y = cLib_targetAngleY(&pos1, &player_pos); setAngle(current.angle.y); cXyz water_pos = current.pos; f32 water_y; if (fopAcM_getWaterY(&water_pos, &water_y)) { water_pos.y = water_y; } cXyz offset(0.0f, 0.0f, mpHIO->m.field_0xa0); csXyz angle(0, cLib_targetAngleY(&pos1, &pos2), 0); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::transM(offset); mDoMtx_stack_c::multVecZero(&field_0x159c[0]); field_0x159c[0] += water_pos; offset.set(0.0f, 0.0f, mpHIO->m.field_0xa4); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::transM(offset); mDoMtx_stack_c::multVecZero(&field_0x159c[1]); field_0x159c[1] += field_0x159c[0]; field_0x159c[2] = field_0x159c[1]; cLib_targetAngleY(&pos2, &pos1); static_cast(mActorMngr[2].getActorP()) ->setPosAndAngle(&field_0x159c[1], angle.y + 0x8000); break; } case 30: initTalk(mFlowID, NULL); break; case 31: { int item_id = 0; if (mFlow.getEventId(&item_id) == 1) { mItemID = fopAcM_createItemForPresentDemo(¤t.pos, item_id, 0, -1, -1, NULL, NULL); } field_0x9eb = true; break; } case 40: field_0x9eb = false; initTalk(mFlowID, NULL); break; case 50: if (mActionType == ACT_TYPE_0) { setMotion(MOT_DIVE_B_SWIM_B, -1.0f, false); } else { setMotion(MOT_DIVE_B_SWIM_A, -1.0f, false); } break; case 60: calcWaistAngleInit(); mEventTimer = 120; mSwimAngleCalc = current.angle; break; } } switch (prm) { case 0: if (player_pos.y < -18640.0f) { ret = true; } // fallthrough case 1: if (mMotion == MOT_SWIM_A || mMotion == MOT_SWIM_B) { if (mBaseMotionAnm != ANM_SWIM_A && mBaseMotionAnm != ANM_SWIM_B) { break; } cXyz pos; f32 target_speed; if (mPath.getIdx() != mPath.getNextIdx()) { mPath.getDstPos(current.pos, pos); cXyz vec = field_0x1500 - player->current.pos; target_speed = vec.abs() * 1.2f; if (target_speed < mpHIO->m.mSwimSpeed) { target_speed = mpHIO->m.mSwimSpeed; } } else { if ((field_0x1500 - player->current.pos).absXZ() < 5.0f) { cXyz vec1(350.0f, 0.0f, 0.0f); cXyz vec2, vec3; mDoMtx_stack_c::YrotS(player->current.angle.y); mDoMtx_stack_c::multVec(&vec1, &vec2); vec3 = player->current.pos - vec2; vec2 += player->current.pos; if ((vec2 - current.pos).absXZ() < (vec3 - current.pos).absXZ()) { pos = vec2; } else { pos = vec3; } if ((player_pos - current.pos).absXZ() > 450.0f) { target_speed = mpHIO->m.mSwimSpeed * 1.5f * 1.5f; } else { target_speed = 15.0f; pos = player_pos; } } else { target_speed = 0.0f; if (mSwimSpeedF < 10.0f) { pos = player_pos; } else { mPath.getDstPos(current.pos, pos); } } } cLib_addCalc2(&mSwimSpeedF, target_speed, 0.2f, 3.0f); f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 1.0f, 0.2f, 0.03f); mAnm_p->setPlaySpeed(play_speed); csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; current.angle.z = 0; calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step); calcBank(angle_step, 8, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (mAcch.ChkWaterHit() && current.pos.y > water_height - mpHIO->m.mMinDepth) { current.pos.y = water_height - mpHIO->m.mMinDepth; } if ((field_0x1500 - player->current.pos).absXZ() < 10.0f && (player_pos - current.pos).absXZ() < 400.0f) { setMotion(MOT_FLOAT_B, -1.0f, false); calcWaistAngleStop(); } field_0x1500 = player->current.pos; } else { calcWaitSwim(true); if (mCurAngle.y == fopAcM_searchPlayerAngleY(this)) { if (mBaseMotionAnm == ANM_WAIT_SWIM) { if (prm == 1) { ret = true; } mTurnMode = 0; } } else { cLib_chaseAngleS(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), mpHIO->m.mSwimAngleSpeed); setAngle(mCurAngle.y); } } break; case 10: calcWaitSwim(true); if (talkProc(NULL, 1, NULL)) { ret = true; } break; case 20: calcWaitSwim(true); calcCanoeMove(false); current.angle.y = cLib_targetAngleY(¤t.pos, &player_pos); setAngle(current.angle.y); ret = true; break; case 30: case 40: calcWaitSwim(true); calcCanoeMove(false); if (talkProc(NULL, 1, NULL)) { ret = true; mSwimAngleCalc = current.angle; mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; setLookMode(LOOK_NONE); } break; case 31: field_0x9eb = true; ret = true; calcWaitSwim(true); calcCanoeMove(false); break; case 50: { s16 angle_step = mpHIO->m.mSwimAngleSpeed; cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); cXyz pos; csXyz angle; mPath.getDstPosDst2(current.pos, pos); angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 4, angle_step); shape_angle = mCurAngle = current.angle; f32 frame = mAnm_p->getFrame(); cXyz dive_speed(0.0f, 0.0f, 0.0f); if (mBaseMotionAnm == ANM_DIVE_B) { if (frame <= 3.0f) { dive_speed.set(0.0f, 0.0f, 0.0f); } else if (frame <= 6.0f) { dive_speed.set(0.0f, 22.0f, 0.0f); } else if (frame <= 9.0f) { dive_speed.set(0.0f, 6.0f, 8.5f); } else if (frame <= 13.0f) { dive_speed.set(0.0f, -9.25f, 4.5f); } else if (frame <= 20.0f) { dive_speed.set(0.0f, -14.0f, 2.5f); } else { dive_speed.set(0.0f, 0.0f, 6.25f); } } mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&dive_speed, &dive_speed); current.pos += dive_speed; if (mBaseMotionAnm == ANM_SWIM_A || mBaseMotionAnm == ANM_SWIM_B) { ret = true; if (!calcWaistAngleCheck()) { calcWaistAngleInit(); mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; } cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); } calcCanoeMove(true); break; } case 60: { cXyz pos; mPath.getDstPos(current.pos, pos); f32 water_y; if (fopAcM_getWaterY(¤t.pos, &water_y) && pos.y > water_y) { pos.y = water_y; } csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; current.angle.z = 0; calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step); calcBank(angle_step, 8, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (mAcch.ChkWaterHit() && current.pos.y > water_y - mpHIO->m.mMinDepth) { current.pos.y = water_y - mpHIO->m.mMinDepth; } calcCanoeMove(true); if (cLib_calcTimer(&mEventTimer) == 0) { ret = true; } break; } default: ret = true; break; } return ret; } BOOL daNpc_zrA_c::ECut_resultAnnounce(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; s16 angle_step = mpHIO->m.mSwimAngleSpeed; f32 water_height = mAcch.m_wtr.GetHeight(); daPy_py_c* player = daPy_getPlayerActorClass(); cXyz player_pos = player->current.pos; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: daNpcF_offTmpBit(0xb); daNpcF_offTmpBit(0xc); if (mActionType == ACT_TYPE_0) { setMotion(MOT_SWIM_B, -1.0f, false); } else { setMotion(MOT_SWIM_A, -1.0f, false); } mTurnMode = 0; break; case 1: if (mActorMngr[2].getActorP() != NULL && fopAcM_GetName(mActorMngr[2].getActorP()) == fpcNm_CANOE_e) { static_cast(mActorMngr[2].getActorP())->setWaterFallDownSe(); } daPy_getPlayerActorClass()->offCanoeSlider(); dComIfG_TimerDeleteRequest(4); dMeter2Info_resetMiniGameItem(false); break; case 10: initTalk(mFlowID, NULL); break; case 20: { mPath.onReverse(); mPath.setIdx(mPath.getEndIdx() - 1); cXyz pos1(-77941.7f, -18800.0f - mpHIO->m.mMinDepth - 30.0f, 39645.3f); cXyz pos2(-78941.7f, -18800.0f - mpHIO->m.mMinDepth - 30.0f, 39645.3f); current.pos = pos1; current.angle.y = cLib_targetAngleY(&pos1, &player_pos); setAngle(current.angle.y); cXyz water_pos = current.pos; f32 water_y; if (fopAcM_getWaterY(&water_pos, &water_y)) { water_pos.y = water_y; } cXyz offset(0.0f, 0.0f, mpHIO->m.field_0xa0); csXyz angle(0, cLib_targetAngleY(&pos1, &pos2), 0); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::transM(offset); mDoMtx_stack_c::multVecZero(&field_0x159c[0]); field_0x159c[0] += water_pos; offset.set(0.0f, 0.0f, mpHIO->m.field_0xa4); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::transM(offset); mDoMtx_stack_c::multVecZero(&field_0x159c[1]); field_0x159c[1] += field_0x159c[0]; field_0x159c[2] = field_0x159c[1]; cLib_targetAngleY(&pos2, &pos1); static_cast(mActorMngr[2].getActorP()) ->setPosAndAngle(&field_0x159c[1], angle.y + 0x8000); dComIfGp_event_offHindFlag(0x80); break; } case 30: initTalk(mFlowID, NULL); break; case 40: if (mActionType == ACT_TYPE_0) { setMotion(MOT_DIVE_B_SWIM_B, -1.0f, false); } else { setMotion(MOT_DIVE_B_SWIM_A, -1.0f, false); } break; case 50: calcWaistAngleInit(); mEventTimer = 120; mSwimAngleCalc = current.angle; break; } } switch (prm) { case 0: if (player_pos.y < -18640.0f) { ret = true; } // fallthrough case 1: if (mMotion == MOT_SWIM_A || mMotion == MOT_SWIM_B) { if (mBaseMotionAnm != ANM_SWIM_A && mBaseMotionAnm != ANM_SWIM_B) { break; } cXyz pos; f32 target_speed; if (mPath.getIdx() != mPath.getNextIdx()) { mPath.getDstPos(current.pos, pos); cXyz vec = field_0x1500 - player->current.pos; target_speed = vec.abs() * 1.2f; if (target_speed < mpHIO->m.mSwimSpeed) { target_speed = mpHIO->m.mSwimSpeed; } } else { if ((field_0x1500 - player->current.pos).absXZ() < 5.0f) { cXyz vec1(350.0f, 0.0f, 0.0f); cXyz vec2, vec3; mDoMtx_stack_c::YrotS(player->current.angle.y); mDoMtx_stack_c::multVec(&vec1, &vec2); vec3 = player->current.pos - vec2; vec2 += player->current.pos; if ((vec2 - current.pos).absXZ() < (vec3 - current.pos).absXZ()) { pos = vec2; } else { pos = vec3; } if ((player_pos - current.pos).absXZ() > 450.0f) { target_speed = mpHIO->m.mSwimSpeed * 1.5f * 1.5f; } else { target_speed = 15.0f; pos = player_pos; } } else { target_speed = 0.0f; if (mSwimSpeedF < 10.0f) { pos = player_pos; } else { mPath.getDstPos(current.pos, pos); } } } cLib_addCalc2(&mSwimSpeedF, target_speed, 0.2f, 3.0f); f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 1.0f, 0.2f, 0.03f); mAnm_p->setPlaySpeed(play_speed); csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; current.angle.z = 0; calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step); calcBank(angle_step, 8, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (mAcch.ChkWaterHit() && current.pos.y > water_height - mpHIO->m.mMinDepth) { current.pos.y = water_height - mpHIO->m.mMinDepth; } if ((field_0x1500 - player->current.pos).absXZ() < 10.0f && (player_pos - current.pos).absXZ() < 400.0f) { setMotion(MOT_FLOAT_B, -1.0f, false); calcWaistAngleStop(); } field_0x1500 = player->current.pos; } else { calcWaitSwim(true); if (mCurAngle.y == fopAcM_searchPlayerAngleY(this)) { if (mBaseMotionAnm == ANM_WAIT_SWIM) { if (prm == 1) { ret = true; } mTurnMode = 0; } } else { cLib_chaseAngleS(&mCurAngle.y, fopAcM_searchPlayerAngleY(this), mpHIO->m.mSwimAngleSpeed); setAngle(mCurAngle.y); } } break; case 10: calcWaitSwim(true); if (talkProc(NULL, 1, NULL)) { ret = true; } break; case 20: calcWaitSwim(true); calcCanoeMove(false); current.angle.y = cLib_targetAngleY(¤t.pos, &player_pos); setAngle(current.angle.y); ret = true; break; case 30: calcWaitSwim(true); calcCanoeMove(false); if (talkProc(NULL, 1, NULL)) { if (dComIfGs_isSaveDunSwitch(0x3e)) { dStage_changeScene(0xf, 0.0f, 0, fopAcM_GetRoomNo(this), 0, -1); } else { ret = true; mSwimAngleCalc = current.angle; mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; setLookMode(LOOK_NONE); } } break; case 40: { s16 angle_step = mpHIO->m.mSwimAngleSpeed; cLib_chaseF(&mScaleFactor, mpHIO->m.mMaxScaleFactor, (mpHIO->m.mMaxScaleFactor - 1.0f) / 30.0f); cXyz pos; csXyz angle; mPath.getDstPosDst2(current.pos, pos); angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 4, angle_step); shape_angle = mCurAngle = current.angle; f32 frame = mAnm_p->getFrame(); cXyz dive_speed(0.0f, 0.0f, 0.0f); if (mBaseMotionAnm == ANM_DIVE_B) { if (frame <= 3.0f) { dive_speed.set(0.0f, 0.0f, 0.0f); } else if (frame <= 6.0f) { dive_speed.set(0.0f, 22.0f, 0.0f); } else if (frame <= 9.0f) { dive_speed.set(0.0f, 6.0f, 8.5f); } else if (frame <= 13.0f) { dive_speed.set(0.0f, -9.25f, 4.5f); } else if (frame <= 20.0f) { dive_speed.set(0.0f, -14.0f, 2.5f); } else { dive_speed.set(0.0f, 0.0f, 6.25f); } } mDoMtx_stack_c::ZXYrotS(current.angle); mDoMtx_stack_c::multVec(&dive_speed, &dive_speed); current.pos += dive_speed; if (mBaseMotionAnm == ANM_SWIM_A || mBaseMotionAnm == ANM_SWIM_B) { ret = true; if (!calcWaistAngleCheck()) { calcWaistAngleInit(); mSwimSpeedScale = 1.0f; mSwimSpeedF = mSwimSpeedScale * mpHIO->m.mSwimSpeed; } cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); } calcCanoeMove(true); break; } case 50: { cXyz pos; mPath.getDstPos(current.pos, pos); f32 water_y; if (fopAcM_getWaterY(¤t.pos, &water_y) && pos.y > water_y) { pos.y = water_y; } csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; current.angle.z = 0; calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step); calcBank(angle_step, 8, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; cXyz swim_speed(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); if (mAcch.ChkWaterHit() && current.pos.y > water_y - mpHIO->m.mMinDepth) { current.pos.y = water_y - mpHIO->m.mMinDepth; } calcCanoeMove(true); if (cLib_calcTimer(&mEventTimer) == 0) { ret = true; } break; } default: ret = true; break; } return ret; } void daNpc_zrA_c::calcCanoeMove(BOOL param_0) { csXyz angle; cXyz vec; cXyz water_pos = current.pos; f32 water_y; if (fopAcM_getWaterY(&water_pos, &water_y)) { water_pos.y = water_y; } angle.x = cLib_targetAngleX(&field_0x159c[0], &water_pos); angle.y = cLib_targetAngleY(&water_pos, &field_0x159c[0]); angle.z = 0; vec.set(0.0f, 0.0f, mpHIO->m.field_0xa0); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::multVec(&vec, &field_0x159c[0]); field_0x159c[0] += water_pos; if (fopAcM_getWaterY(&field_0x159c[0], &water_y)) { field_0x159c[0].y = water_y; } angle.x = cLib_targetAngleX(&field_0x159c[1], &field_0x159c[0]); angle.y = cLib_targetAngleY(&field_0x159c[0], &field_0x159c[1]); vec.set(0.0f, 0.0f, mpHIO->m.field_0xa4); mDoMtx_stack_c::ZXYrotS(angle); mDoMtx_stack_c::multVec(&vec, &field_0x159c[1]); field_0x159c[1] += field_0x159c[0]; if (fopAcM_getWaterY(&field_0x159c[1], &water_y)) { field_0x159c[1].y = water_y; } if (param_0) { f32 fvar2 = (water_pos - field_0x159c[2]).abs(); (water_pos - field_0x159c[1]).abs(); if (fvar2 > mpHIO->m.field_0xa0 + mpHIO->m.field_0xa4) { cLib_addCalcPos2(&field_0x159c[2], field_0x159c[1], 0.2f, mSwimSpeedF * 1.2f); if (fopAcM_getWaterY(&field_0x159c[2], &water_y)) { field_0x159c[2].y = water_y; } } } else { field_0x159c[2] = field_0x159c[1]; } static_cast(mActorMngr[2].getActorP()) ->setPosAndAngle(&field_0x159c[2], angle.y + 0x8000); } static void* s_subMark(void* i_proc, void* i_this) { if (fopAc_IsActor(i_proc) && fopAcM_GetName(i_proc) == fpcNm_ZRA_MARK_e) { daObjZraMark_c* zra_mark = static_cast(i_proc); daNpc_zrA_c* _this = static_cast(i_this); if (zra_mark->getMarkNo() == _this->getNoFromParam()) { return i_proc; } } return NULL; } BOOL daNpc_zrA_c::tobiSearch(void* param_0) { daObjZraMark_c* zra_mark; switch (mMode) { case 0: mAcch.SetGrndNone(); mAcch.SetWallNone(); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_A, -1.0f, false); setLookMode(LOOK_NONE); mActionSelect = 0; mCcStts.SetWeight(0); mMode = 2; // fallthrough case 2: zra_mark = (daObjZraMark_c*)fpcM_Search(s_subMark, this); if (zra_mark != NULL) { zra_mark->entryPointer(this); setAction(&daNpc_zrA_c::tobiWait); } break; case 3: break; } return true; } BOOL daNpc_zrA_c::tobiWait(void* param_0) { switch (mMode) { case 0: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_A, -1.0f, false); setLookMode(LOOK_NONE); mAttnChangeTimer = 0; mTurnMode = 0; mActionSelect = 1; mMode = 2; // fallthrough case 2: if (mCcCyl.ChkTgHit() || mBlastFlag) { setAction(&daNpc_zrA_c::tobikomi1); } break; case 3: break; } return true; } BOOL daNpc_zrA_c::tobikomi1(void* param_0) { switch (mMode) { case 0: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_S, -1.0f, false); mActionSelect = 2; mMode = 2; // fallthrough case 2: if (mBaseMotionAnm == MOT_FLOAT_B) { if (mAnm_p->isStop()) { cXyz vec(-1.68f, -7.99f, 206.37f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&vec, &vec); current.pos += vec; old.pos = current.pos; setAction(&daNpc_zrA_c::tobikomi2); } else { s16 angle_y = home.angle.y; if (getAngleNoFromParam() == 1) { angle_y -= 0x2000; } else if (getAngleNoFromParam() == 2) { angle_y += 0x2000; } cLib_chaseAngleS(&mCurAngle.y, angle_y, 0x800); setAngle(mCurAngle.y); } } break; case 3: break; } return true; } BOOL daNpc_zrA_c::tobikomi2(void* param_0) { f32 water_y; switch (mMode) { case 0: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_T, -1.0f, false); mActionSelect = 3; mSwimSpeed.set(0.0f, -47.0f, 36.0f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&mSwimSpeed, &mSwimSpeed); mMode = 2; // fallthrough case 2: if (fopAcM_getWaterY(¤t.pos, &water_y)) { cXyz head_pos; mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&head_pos); if (head_pos.y <= water_y) { cXyz water_pos = head_pos; water_pos.y = water_y; fopKyM_createWpillar(&water_pos, 2.5f, 0); mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH, 0, -1); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_E, -1.0f, false); setAction(&daNpc_zrA_c::tobikomi3); break; } } mSwimSpeed.y -= 3.0f; current.pos += mSwimSpeed; break; case 3: break; } return true; } BOOL daNpc_zrA_c::tobikomi3(void* param_0) { switch (mMode) { case 0: mActionSelect = 4; mSwimAngleCalc = current.angle; mMode = 2; // fallthrough case 2: { cXyz vec(0.0f, 0.0f, mpHIO->m.mSwimSpeed * 1.5f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&vec, &vec); cLib_chasePos(&mSwimSpeed, vec, 25.0f); current.pos += mSwimSpeed; if (mBaseMotionAnm == ANM_SWIM_A) { if (mBlastFlag) { setAction(&daNpc_zrA_c::tobiJump); } else { setAction(&daNpc_zrA_c::tobiEnd); } } break; } case 3: break; } return true; } BOOL daNpc_zrA_c::tobiJump(void* param_0) { cXyz swim_speed; csXyz angle; f32 water_y; s16 angle_step = mpHIO->m.mSwimAngleSpeed * 2; s16 angle_scale = 4; switch (mMode) { case 0: mActionSelect = 5; mSwimAngleCalc = current.angle; mMode = 2; // fallthrough case 2: { cXyz head_pos; mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&head_pos); if (field_0x153e) { if (mAnm_p->getFrame() > 13.0f && mAnm_p->getFrame() < 17.0f) { f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, 0.3f, 0.5f, 0.8f); mAnm_p->setPlaySpeed(play_speed); } calcBank(angle_step, angle_scale, current.angle.y, current.angle.z); mSwimSpeed.y -= 2.0f; current.pos += mSwimSpeed; if (current.angle.x < 0x3a00) { current.angle.x = -cM_atan2s(mSwimSpeed.y, mSwimSpeed.absXZ()); } shape_angle = mCurAngle = current.angle; if (fopAcM_getWaterY(¤t.pos, &water_y)) { if (mIsAboveWater && head_pos.y + mSwimSpeed.y <= water_y) { cXyz water_pos = head_pos; water_pos.y = water_y; fopKyM_createWpillar(&water_pos, 2.5f, 0); mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH, 0, -1); mIsAboveWater = false; } if (current.pos.y <= water_y - mpHIO->m.mMinDepth) { setAction(&daNpc_zrA_c::tobiEnd); mSwimSpeedF = mSwimSpeed.absXZ(); } } return true; } else { angle.x = -0x3b00; angle.y = current.angle.y; angle.z = current.angle.z; if (fopAcM_getWaterY(¤t.pos, &water_y)) { angle_step = mpHIO->m.mSwimAngleSpeed * 2; angle_scale = 2; if (!(head_pos.y < water_y)) { if (!mIsAboveWater) { cXyz water_pos = head_pos; water_pos.y = water_y; fopKyM_createWpillar(&water_pos, 2.5f, 0); mIsAboveWater = true; mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH_OUT, 0, -1); } if (current.pos.y > water_y) { swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); mSwimSpeed = swim_speed; field_0x153e = true; return true; } } } calcSwimAngle(angle, mSwimAngleCalc, angle_scale, angle_step); cLib_addCalc2(&mSwimSpeedF, 2.0f * mpHIO->m.mSwimSpeed, 0.7f, 10.0f); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, mSwimSpeedF / mpHIO->m.mSwimAnmRate, 0.2f, 0.1f); mAnm_p->setPlaySpeed(play_speed); shape_angle = mCurAngle = current.angle; } break; } case 3: break; } return true; } BOOL daNpc_zrA_c::tobiEnd(void* param_0) { cXyz swim_speed; s16 angle_step = mpHIO->m.mSwimAngleSpeed; switch (mMode) { case 0: mActionSelect = 6; mMode = 2; // fallthrough case 2: { if (fopAcM_otherBgCheck(this, dComIfGp_getPlayer(0)) || fopAcM_CheckCondition(this, fopAcCnd_NODRAW_e)) { fopAcM_delete(this); return true; } csXyz angle; angle.x = 0x3000; angle.y = current.angle.y; angle.z = current.angle.z; calcSwimAngle(angle, mSwimAngleCalc, 8, angle_step); cLib_chaseF(&mSwimSpeedF, mpHIO->m.mSwimSpeed, mpHIO->m.mSwimSpeed / 3.0f); swim_speed.set(0.0f, 0.0f, mSwimSpeedF); calcSwimPos(swim_speed); f32 play_speed = mAnm_p->getPlaySpeed(); cLib_addCalc2(&play_speed, mSwimSpeedF / mpHIO->m.mSwimAnmRate, 0.2f, 0.1f); mAnm_p->setPlaySpeed(play_speed); calcBank(angle_step, 8, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; } case 3: break; } return true; } static void* s_subSP(void* i_proc, void* i_this) { if (fopAc_IsActor(i_proc) && fopAcM_GetName(i_proc) == fpcNm_NPC_ZRA_e) { daNpc_zrA_c* other = static_cast(i_proc); daNpc_zrA_c* _this = static_cast(i_this); if (other->getType() == _this->getType() && other->getNoFromParam() != _this->getNoFromParam()) { return other; } } return NULL; } BOOL daNpc_zrA_c::waitSearch(void* param_0) { switch (mMode) { case 0: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_WAIT_A, -1.0f, false); setLookMode(LOOK_NONE); mAcch.SetGrndNone(); mAcch.SetWallNone(); mMode = 2; // fallthrough case 2: if (mActorMngr[2].getActorP() == NULL) { fopAc_ac_c* other = (fopAc_ac_c*)fpcM_Search(s_subSP, this); if (other != NULL) { mActorMngr[2].entry(other); } } if (dComIfGs_isSwitch(mSwitch1, fopAcM_GetRoomNo(this))) { fopAcM_delete(this); } break; case 3: break; } return true; } BOOL daNpc_zrA_c::ECut_searchPrince1(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; fopAc_ac_c* talk_actors[2] = {this, mActorMngr[2].getActorP()}; f32 water_y; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: dComIfGs_onSwitch(mSwitch1, fopAcM_GetRoomNo(this)); setLookMode(LOOK_ACTOR); break; case 10: initTalk(mFlowID, talk_actors); break; case 20: setLookMode(LOOK_NONE); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_S, -1.0f, false); break; case 30: mSwimSpeed.set(0.0f, -31.2f, 14.7f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&mSwimSpeed, &mSwimSpeed); break; case 40: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_E, -1.0f, false); mSwimAngleCalc = current.angle; break; case 50: break; } } switch (prm) { case 0: ret = true; break; case 10: if (talkProc(NULL, 0, talk_actors)) { ret = true; } break; case 20: { if (mBaseMotionAnm == ANM_TOBIKOMI_S) { if (mAnm_p->isStop()) { cXyz dive_speed(-1.68f, -30.0f, 210.37f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&dive_speed, &dive_speed); current.pos += dive_speed; old.pos = current.pos; setExpression(EXPR_NONE, 0.0f); setMotion(MOT_TOBIKOMI_T, 0.0f, false); ret = true; } else { cLib_chaseAngleS(&mCurAngle.y, 0x2dca, 0x200); setAngle(mCurAngle.y); } } else if (mBaseMotionAnm == ANM_TOBIKOMI_T) { ret = true; } cXyz head_pos; mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&head_pos); break; } case 30: if (mBaseMotionAnm == ANM_TOBIKOMI_E) { ret = true; } else if (fopAcM_getWaterY(¤t.pos, &water_y)) { cXyz head_pos; mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&head_pos); if (head_pos.y <= water_y) { cXyz water_pos = head_pos; water_pos.y = water_y; fopKyM_createWpillar(&water_pos, 2.5f, 0); mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH, 0, -1); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_E, -1.0f, false); ret = true; break; } } mSwimSpeed.y -= 3.0f; current.pos += mSwimSpeed; break; case 40: { if (mBaseMotionAnm == ANM_SWIM_A) { ret = true; } cXyz swim_speed(0.0f, 0.0f, mpHIO->m.mSwimSpeed); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&swim_speed, &swim_speed); cLib_chasePos(&mSwimSpeed, swim_speed, 25.0f); current.pos += mSwimSpeed; break; } case 50: { cXyz pos(-4807.7f, -207.444f, 5109.854f); cXyz swim_speed(0.0f, 0.0f, mpHIO->m.mSwimSpeed); csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; mAnm_p->setPlaySpeed(mpHIO->m.mSwimSpeed / mpHIO->m.mSwimAnmRate); calcSwimAngle(angle, mSwimAngleCalc, 23, mpHIO->m.mSwimAngleSpeed / 2); calcSwimPos(swim_speed); calcBank(mpHIO->m.mSwimAngleSpeed / 2, 16, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; if ((pos - current.pos).absXZ() < 100.0f) { ret = true; } break; } default: ret = true; } return ret; } BOOL daNpc_zrA_c::ECut_searchPrince2(int i_staffID) { dEvent_manager_c& event_manager = dComIfGp_getEventManager(); BOOL ret = false; int prm = -1; f32 water_y; int* prm_p = dComIfGp_evmng_getMyIntegerP(i_staffID, "prm"); if (prm_p != NULL) { prm = *prm_p; } if (event_manager.getIsAddvance(i_staffID)) { switch (prm) { case 0: setLookMode(LOOK_ACTOR); break; case 10: break; case 20: setLookMode(LOOK_NONE); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_S, -1.0f, false); break; case 30: mSwimSpeed.set(0.0f, -31.2f, 14.7f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&mSwimSpeed, &mSwimSpeed); break; case 40: setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_E, -1.0f, false); mSwimAngleCalc = current.angle; break; case 50: break; } } switch (prm) { case 0: ret = true; break; case 10: ret = true; break; case 20: if (mBaseMotionAnm == ANM_TOBIKOMI_S) { if (mAnm_p->isStop()) { cXyz dive_speed(-1.68f, -30.0f, 210.37f); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&dive_speed, &dive_speed); current.pos += dive_speed; old.pos = current.pos; setExpression(EXPR_NONE, 0.0f); setMotion(MOT_TOBIKOMI_T, 0.0f, false); ret = true; } else { cLib_chaseAngleS(&mCurAngle.y, 0x2dca, 0x200); setAngle(mCurAngle.y); } } else if (mBaseMotionAnm == ANM_TOBIKOMI_T) { ret = true; } break; case 30: if (mBaseMotionAnm == ANM_TOBIKOMI_E) { ret = true; } else if (fopAcM_getWaterY(¤t.pos, &water_y)) { cXyz head_pos; mDoMtx_stack_c::copy(mAnm_p->getModel()->getAnmMtx(4)); mDoMtx_stack_c::scaleM(scale); mDoMtx_stack_c::multVecZero(&head_pos); if (head_pos.y <= water_y) { cXyz water_pos = head_pos; water_pos.y = water_y; fopKyM_createWpillar(&water_pos, 2.5f, 0); setExpression(EXPR_NONE, -1.0f); setMotion(MOT_TOBIKOMI_E, -1.0f, false); ret = true; mCreatureSound.startCreatureSound(Z2SE_ZRA_DIVE_SPLASH, 0, -1); break; } } mSwimSpeed.y -= 3.0f; current.pos += mSwimSpeed; break; case 40: { if (mBaseMotionAnm == ANM_SWIM_A) { ret = true; } cXyz swim_speed(0.0f, 0.0f, mpHIO->m.mSwimSpeed); mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&swim_speed, &swim_speed); cLib_chasePos(&mSwimSpeed, swim_speed, 25.0f); current.pos += mSwimSpeed; break; } case 50: { cXyz pos(-4807.7f, -207.444f, 5109.854f); cXyz swim_speed(0.0f, 0.0f, mpHIO->m.mSwimSpeed); csXyz angle; angle.x = cLib_targetAngleX(&pos, ¤t.pos); angle.y = cLib_targetAngleY(¤t.pos, &pos); angle.z = current.angle.z; mAnm_p->setPlaySpeed(mpHIO->m.mSwimSpeed / mpHIO->m.mSwimAnmRate); calcSwimAngle(angle, mSwimAngleCalc, 23, mpHIO->m.mSwimAngleSpeed / 2); calcSwimPos(swim_speed); calcBank(mpHIO->m.mSwimAngleSpeed / 2, 16, angle.y, angle.z); current.angle.z = angle.z; shape_angle = mCurAngle = current.angle; if ((pos - current.pos).absXZ() < 100.0f) { ret = true; } break; } default: ret = true; } return ret; }