mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-23 14:41:33 -04:00
84fcdf22a0
* e_ws work * more doc * add debug message * move declaration * more match * test * Revert "more match" This reverts commit 3d910e6e913d84685aa40fe993a50402b3ee27a1. * fix * cleanup * fix * rename mIsHome
1023 lines
29 KiB
C++
1023 lines
29 KiB
C++
/**
|
|
* @file d_a_e_ws.cpp
|
|
*
|
|
*/
|
|
|
|
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
|
|
|
#include "d/actor/d_a_e_ws.h"
|
|
#include "d/actor/d_a_obj_carry.h"
|
|
#include <cmath>
|
|
#include "f_op/f_op_actor_enemy.h"
|
|
|
|
#define PLAYER_NOT_FOUND 0
|
|
#define PLAYER_TARGET 1
|
|
#define PLAYER_NEAR 2
|
|
|
|
class daE_WS_HIO_c : public JORReflexible {
|
|
public:
|
|
daE_WS_HIO_c();
|
|
virtual ~daE_WS_HIO_c() {}
|
|
|
|
void genMessage(JORMContext*);
|
|
|
|
/* 0x04 */ s8 id;
|
|
/* 0x08 */ f32 base_size;
|
|
/* 0x0C */ f32 move_range;
|
|
/* 0x10 */ f32 search_range;
|
|
/* 0x14 */ f32 search_y_range;
|
|
/* 0x18 */ f32 dist_to_ground;
|
|
/* 0x1C */ f32 search_angle;
|
|
/* 0x20 */ f32 attack_speed;
|
|
/* 0x24 */ u8 debug_ON;
|
|
};
|
|
|
|
|
|
namespace {
|
|
static dCcD_SrcSph cc_ws_src = {
|
|
{
|
|
{0x0, {{AT_TYPE_CSTATUE_SWING, 0x1, 0xD}, {0xD8F9FDF5, 0x3}, 0x75}}, // mObj
|
|
{dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt
|
|
{dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x2}, // mGObjTg
|
|
{0x0}, // mGObjCo
|
|
}, // mObjInf
|
|
{
|
|
{{0.0f, 0.0f, 0.0f}, 40.0f} // mSph
|
|
} // mSphAttr
|
|
};
|
|
|
|
static dCcD_SrcSph cc_bokkuri_src = {
|
|
{
|
|
{0x0, {{AT_TYPE_CSTATUE_SWING, 0x1, 0x0}, {0x20008, 0x3}, 0x0}}, // mObj
|
|
{dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt
|
|
{dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x2}, // mGObjTg
|
|
{0x0}, // mGObjCo
|
|
}, // mObjInf
|
|
{
|
|
{{0.0f, 0.0f, 0.0f}, 40.0f} // mSph
|
|
} // mSphAttr
|
|
};
|
|
}
|
|
|
|
daE_WS_HIO_c::daE_WS_HIO_c() {
|
|
id = -1;
|
|
base_size = 0.8f;
|
|
move_range = 50.0f;
|
|
search_range = 300.0f;
|
|
search_y_range = 200.0f;
|
|
dist_to_ground = 270.0f;
|
|
debug_ON = false;
|
|
search_angle = 18200;
|
|
attack_speed = 10.0f;
|
|
}
|
|
|
|
#if DEBUG
|
|
void daE_WS_HIO_c::genMessage(JORMContext* ctx) {
|
|
ctx->genLabel("スタルウォーーーーーーーール", 0x80000001);
|
|
ctx->genSlider("基本サイズ", &base_size, 0.0f, 5.0f);
|
|
ctx->genSlider("サーチ角度", &search_angle, 0.0f, 30000.0f);
|
|
ctx->genSlider("攻撃速度", &attack_speed, 0.0f, 100.0f);
|
|
ctx->genSlider("移動範囲", &move_range, 0.0f, 1000.0f);
|
|
ctx->genSlider("サーチ範囲", &search_range, 0.0f, 1000.0f);
|
|
ctx->genSlider("サーチY上下範囲", &search_y_range, 0.0f, 1000.0f);
|
|
ctx->genSlider("地面までの距離", &dist_to_ground, 0.0f, 1000.0f);
|
|
ctx->genCheckBox("デバック表示", &debug_ON, 0x1);
|
|
}
|
|
#endif
|
|
|
|
int daE_WS_c::draw() {
|
|
J3DModel* model = mAnm_p->getModel();
|
|
g_env_light.settingTevStruct(0, ¤t.pos, &tevStr);
|
|
g_env_light.setLightTevColorType_MAJI(model, &tevStr);
|
|
|
|
if (mDownColor) {
|
|
J3DModelData* modelData_p = model->getModelData();
|
|
for (u16 i = 0; i < modelData_p->getMaterialNum(); i++) {
|
|
J3DMaterial* material_p = modelData_p->getMaterialNodePointer(i);
|
|
material_p->getTevColor(0)->r = mDownColor;
|
|
material_p->getTevColor(0)->g = mDownColor;
|
|
material_p->getTevColor(0)->b = mDownColor;
|
|
}
|
|
}
|
|
|
|
mAnm_p->entryDL();
|
|
|
|
cXyz sp8;
|
|
sp8.set(current.pos.x, 100.0f + current.pos.y, current.pos.z);
|
|
mShadowId = dComIfGd_setShadow(mShadowId, 1, model, &sp8, 400.0f, 0.0f, current.pos.y, mAcch.GetGroundH(), mAcch.m_gnd, &tevStr, 0, 1.0f, dDlst_shadowControl_c::getSimpleTex());
|
|
return 1;
|
|
}
|
|
|
|
static int daE_WS_Draw(daE_WS_c* i_this) {
|
|
return i_this->draw();
|
|
}
|
|
|
|
void daE_WS_c::setBck(int i_anm, u8 i_mode, f32 i_morf, f32 i_speed) {
|
|
mAnm_p->setAnm((J3DAnmTransform*)dComIfG_getObjectRes("E_WS", i_anm), i_mode, i_morf, i_speed, 0.0f, -1.0f);
|
|
}
|
|
|
|
void daE_WS_c::setFootSound() {
|
|
if (mAnm_p->getAnm() == dComIfG_getObjectRes("E_WS", 7)) {
|
|
if (mAnm_p->checkFrame(0.0f) ||
|
|
mAnm_p->checkFrame(4.5f) ||
|
|
mAnm_p->checkFrame(7.5f) ||
|
|
mAnm_p->checkFrame(9.0f) ||
|
|
mAnm_p->checkFrame(13.5f) ||
|
|
mAnm_p->checkFrame(16.0f) ||
|
|
mAnm_p->checkFrame(19.0f) ||
|
|
mAnm_p->checkFrame(23.5f) ||
|
|
mAnm_p->checkFrame(25.0f) ||
|
|
mAnm_p->checkFrame(28.0f) ||
|
|
mAnm_p->checkFrame(32.5f) ||
|
|
mAnm_p->checkFrame(36.0f) ||
|
|
mAnm_p->checkFrame(39.5f))
|
|
{
|
|
mSound.startCreatureSound(Z2SE_EN_WS_FOOTNOTE, 0, -1);
|
|
}
|
|
} else if (mAnm_p->getAnm() == dComIfG_getObjectRes("E_WS", 8)) {
|
|
if (mAnm_p->checkFrame(0.5f) ||
|
|
mAnm_p->checkFrame(6.0f) ||
|
|
mAnm_p->checkFrame(11.0f) ||
|
|
mAnm_p->checkFrame(16.0f) ||
|
|
mAnm_p->checkFrame(21.0f) ||
|
|
mAnm_p->checkFrame(26.5f) ||
|
|
mAnm_p->checkFrame(31.0f))
|
|
{
|
|
mSound.startCreatureSound(Z2SE_EN_WS_FOOTNOTE, 0, -1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void daE_WS_c::setActionMode(int i_action) {
|
|
if (mAction != i_action) {
|
|
mAction = i_action;
|
|
mMode = 0;
|
|
}
|
|
}
|
|
|
|
f32 daE_WS_c::calcTargetDist(cXyz i_basePos, cXyz i_targetPos) {
|
|
return i_basePos.abs(i_targetPos);
|
|
}
|
|
|
|
s16 daE_WS_c::calcTargetAngle(cXyz i_basePos, cXyz i_targetPos) {
|
|
cXyz mae;
|
|
cXyz ato = i_targetPos - i_basePos;
|
|
|
|
mDoMtx_stack_c::XrotS(-mTargetWallAngle.x);
|
|
mDoMtx_stack_c::YrotM(-mTargetWallAngle.y);
|
|
mDoMtx_stack_c::multVec(&ato, &mae);
|
|
return cM_atan2s(mae.x, mae.z);
|
|
}
|
|
|
|
static u8 hio_set;
|
|
|
|
static daE_WS_HIO_c l_HIO;
|
|
|
|
bool daE_WS_c::checkInSearchRange(cXyz i_basePos, cXyz i_targetPos) {
|
|
if (calcTargetDist(i_basePos, i_targetPos) < l_HIO.search_range && std::abs(i_basePos.y - i_targetPos.y) < l_HIO.search_y_range) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int daE_WS_c::checkPlayerPos() {
|
|
cXyz player_pos;
|
|
mDoMtx_stack_c::copy(daPy_getLinkPlayerActorClass()->getModelJointMtx(0));
|
|
mDoMtx_stack_c::multVecZero(&player_pos);
|
|
|
|
if ((daPy_getPlayerActorClass()->checkClimbMove() ||
|
|
dComIfGp_checkPlayerStatus1(0, 0x2000000) ||
|
|
dComIfGp_checkPlayerStatus1(0, 0x10000) ||
|
|
calcTargetDist(current.pos, player_pos) < 150.0f) &&
|
|
checkInSearchRange(player_pos, mHomePos) && checkInSearchRange(current.pos, mHomePos))
|
|
{
|
|
dBgS_GndChk gndchk;
|
|
cXyz gndpos;
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(mWallAngle);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle);
|
|
mDoMtx_stack_c::transM(0.0f, 100.0f, 0.0f);
|
|
mDoMtx_stack_c::multVecZero(&gndpos);
|
|
|
|
gndchk.SetPos(&gndpos);
|
|
gndpos.y = dComIfG_Bgsp().GroundCross(&gndchk);
|
|
if (current.pos.y - gndpos.y > l_HIO.dist_to_ground) {
|
|
// Return 1 if walltula is looking towards player
|
|
if (cLib_distanceAngleS(shape_angle.y, calcTargetAngle(current.pos, player_pos)) < l_HIO.search_angle) {
|
|
return PLAYER_TARGET;
|
|
}
|
|
|
|
// otherwise return 2 if player is near the walltula
|
|
if (calcTargetDist(current.pos, player_pos) < 150.0f) {
|
|
return PLAYER_NEAR;
|
|
}
|
|
}
|
|
}
|
|
|
|
return PLAYER_NOT_FOUND;
|
|
}
|
|
|
|
bool daE_WS_c::checkAttackEnd() {
|
|
cXyz player_pos;
|
|
mDoMtx_stack_c::copy(daPy_getLinkPlayerActorClass()->getModelJointMtx(0));
|
|
mDoMtx_stack_c::multVecZero(&player_pos);
|
|
|
|
BOOL checkPlayerNear = FALSE;
|
|
if (
|
|
daPy_getPlayerActorClass()->checkClimbMove() ||
|
|
dComIfGp_checkPlayerStatus1(0, 0x02000000) ||
|
|
dComIfGp_checkPlayerStatus1(0, 0x10000) ||
|
|
calcTargetDist(current.pos, player_pos) < 200.0f
|
|
) {
|
|
checkPlayerNear = TRUE;
|
|
}
|
|
if (!checkPlayerNear ||
|
|
!checkInSearchRange(current.pos, mHomePos) ||
|
|
checkBeforeBg(shape_angle.y)
|
|
)
|
|
{
|
|
setActionMode(ACTION_WAIT_e);
|
|
speedF = 0.0f;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void daE_WS_c::executeWait() {
|
|
int playerCheck = checkPlayerPos();
|
|
if (playerCheck == PLAYER_TARGET) {
|
|
setActionMode(ACTION_ATTACK_e);
|
|
return;
|
|
}
|
|
|
|
if (playerCheck == PLAYER_NEAR && mMode != 3 && mMode != 4) {
|
|
mMode = 2;
|
|
}
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
mWaitTimer = 50.0f + cM_rndF(50.0f);
|
|
setBck(9, 2, 3.0f, 1.0f);
|
|
mMode = 1;
|
|
/* fallthrough */
|
|
case 1:
|
|
if (mWaitTimer == 0) {
|
|
mMode = 2;
|
|
}
|
|
break;
|
|
case 2:
|
|
speedF = 0.0f;
|
|
mIsReturnHome = 0;
|
|
mTargetAngle = shape_angle.y + cM_rndFX(32768.0f); // random turn up to ±180°
|
|
|
|
if (playerCheck == PLAYER_NEAR) {
|
|
mStepAngle = 0x200;
|
|
setBck(8, 2, 3.0f, 2.4f);
|
|
} else {
|
|
if (calcTargetDist(current.pos, mHomePos) >= l_HIO.move_range) {
|
|
mTargetAngle = calcTargetAngle(current.pos, mHomePos);
|
|
mIsReturnHome = 1;
|
|
}
|
|
mStepAngle = 0x100;
|
|
setBck(8, 2, 3.0f, 1.2f);
|
|
}
|
|
|
|
mMode = 3;
|
|
/* fallthrough */
|
|
case 3:
|
|
setFootSound();
|
|
|
|
if (cLib_chaseAngleS(&shape_angle.y, mTargetAngle, mStepAngle)) {
|
|
mMode = 4;
|
|
mWaitTimer = 10;
|
|
setBck(9, 2, 3.0f, 1.0f);
|
|
}
|
|
break;
|
|
case 4:
|
|
if (mWaitTimer == 0) {
|
|
mMode = 5;
|
|
}
|
|
break;
|
|
case 5:
|
|
mMode = 6;
|
|
speedF = 3.0f;
|
|
mWaitTimer = 20.0f + cM_rndF(10.0f);
|
|
setBck(7, 2, 3.0f, 1.0f);
|
|
/* fallthrough */
|
|
case 6:
|
|
setFootSound();
|
|
|
|
if (mIsReturnHome == 0) {
|
|
if (calcTargetDist(current.pos, mHomePos) >= l_HIO.move_range) {
|
|
mWaitTimer = 0;
|
|
}
|
|
}
|
|
|
|
if (checkBeforeBg(shape_angle.y)) {
|
|
mWaitTimer = 0;
|
|
}
|
|
|
|
if (mWaitTimer == 0) {
|
|
speedF = 0.0f;
|
|
mMode = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
current.angle.y = shape_angle.y;
|
|
}
|
|
|
|
void daE_WS_c::executeAttack() {
|
|
cXyz player_pos;
|
|
mDoMtx_stack_c::copy(daPy_getLinkPlayerActorClass()->getModelJointMtx(0));
|
|
mDoMtx_stack_c::multVecZero(&player_pos);
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
setBck(8, 2, 3.0f, 3.5f);
|
|
mMode = 1;
|
|
speedF = 0.0f;
|
|
/* fallthrough */
|
|
case 1:
|
|
setFootSound();
|
|
|
|
if (checkAttackEnd()) {
|
|
return;
|
|
}
|
|
|
|
if (cLib_chaseAngleS(&shape_angle.y, calcTargetAngle(current.pos, player_pos), 0x300)) {
|
|
mMode = 2;
|
|
setBck(10, 2, 3.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_WS_V_YOKOKU, -1);
|
|
mWaitTimer = 10;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (mWaitTimer == 0) {
|
|
speedF = l_HIO.attack_speed * mBodyScale;
|
|
setBck(7, 2, 3.0f, 3.0f);
|
|
mMode = 3;
|
|
}
|
|
|
|
if (checkAttackEnd()) {
|
|
return;
|
|
}
|
|
|
|
break;
|
|
case 3: {
|
|
setFootSound();
|
|
cLib_chaseAngleS(&shape_angle.y, calcTargetAngle(current.pos, player_pos), 0x400);
|
|
|
|
BOOL checkAttackStart = FALSE;
|
|
if (checkBeforeBg(shape_angle.y)) {
|
|
checkAttackStart = TRUE;
|
|
}
|
|
if (mCcSph.ChkAtHit()) {
|
|
cCcD_Obj* hitObj = mCcSph.GetAtHitObj();
|
|
if (fopAcM_GetName(dCc_GetAc(hitObj->GetAc())) == fpcNm_ALINK_e) {
|
|
checkAttackStart = TRUE;
|
|
}
|
|
}
|
|
if (!checkInSearchRange(current.pos, mHomePos)) {
|
|
checkAttackStart = TRUE;
|
|
}
|
|
if (checkAttackStart) {
|
|
mMode = 4;
|
|
speedF = 0.0f;
|
|
setBck(4, 0, 3.0f, 1.0f);
|
|
break;
|
|
}
|
|
|
|
if (checkAttackEnd()) {
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 4:
|
|
if (mAnm_p->checkFrame(7.5f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_WS_V_ATTACK, -1);
|
|
}
|
|
|
|
if (mAnm_p->isStop()) {
|
|
setActionMode(ACTION_WAIT_e);
|
|
}
|
|
/* fallthrough */
|
|
}
|
|
|
|
current.angle.y = shape_angle.y;
|
|
}
|
|
|
|
void daE_WS_c::executeDown() {
|
|
mInvulnerabilityTimer = 10;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
mCcSph.OffAtSetBit();
|
|
mCcSph.OffTgSetBit();
|
|
mCcBokkuriSph.OffTgSetBit();
|
|
|
|
mMode = 1;
|
|
speed.y = 0.0f;
|
|
speedF = 0.0f;
|
|
setBck(5, 0, 0.0f, 1.0f);
|
|
|
|
mSound.startCreatureVoice(Z2SE_EN_WS_V_DAMAGE, -1);
|
|
/* fallthrough */
|
|
case 1:
|
|
if (mAnm_p->isStop()) {
|
|
mBgc.SetWall(0.0f, 4.0f);
|
|
current.angle.y = mTargetWallAngle.y;
|
|
setBck(6, 0, 3.0f, 0.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_WS_V_DEATH, -1);
|
|
speedF = 5.0f;
|
|
gravity = -3.0f;
|
|
mAcch.SetGroundUpY(25.0f * mBodyScale);
|
|
mMode = 2;
|
|
attention_info.flags = 0;
|
|
}
|
|
return;
|
|
case 2:
|
|
if (abs(shape_angle.y) < 0x4000) {
|
|
cLib_chaseAngleS(&shape_angle.y, 0, 0x200);
|
|
cLib_chaseAngleS(&shape_angle.x, 0x4000, 0x400);
|
|
} else {
|
|
cLib_chaseAngleS(&shape_angle.y, -0x8000, 0x200);
|
|
cLib_chaseAngleS(&shape_angle.x, -0x4000, 0x400);
|
|
}
|
|
|
|
if (mAcch.ChkGroundHit()) {
|
|
speedF = 3.0f + cM_rndF(2.0f);
|
|
speed.y = 12.0f;
|
|
mMode = 3;
|
|
mWaitTimer = 30;
|
|
setBck(6, 0, 5.0f, 1.0f);
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1);
|
|
}
|
|
break;
|
|
case 3:
|
|
if (abs(shape_angle.y) < 0x4000) {
|
|
cLib_chaseAngleS(&shape_angle.y, 0, 0x200);
|
|
cLib_chaseAngleS(&shape_angle.x, 0x4000, 0x400);
|
|
} else {
|
|
cLib_chaseAngleS(&shape_angle.y, -0x8000, 0x200);
|
|
cLib_chaseAngleS(&shape_angle.x, -0x4000, 0x400);
|
|
}
|
|
|
|
if (mAcch.ChkGroundHit()) {
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1);
|
|
|
|
if (abs(shape_angle.y) < 0x4000) {
|
|
shape_angle.y = 0;
|
|
shape_angle.x = 0x4000;
|
|
} else {
|
|
shape_angle.y = -0x8000;
|
|
shape_angle.x = -0x4000;
|
|
}
|
|
|
|
speedF = 0.0f;
|
|
speed.y = 0.0f;
|
|
mMode = 4;
|
|
return;
|
|
}
|
|
break;
|
|
case 4:
|
|
cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f);
|
|
|
|
if (mAnm_p->isStop()) {
|
|
mWaitTimer = 15;
|
|
mMode = 5;
|
|
return;
|
|
}
|
|
break;
|
|
case 5:
|
|
cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f);
|
|
|
|
if (mWaitTimer == 0) {
|
|
fopAcM_delete(this);
|
|
fopAcM_createDisappear(this, ¤t.pos, 7, 0, 7);
|
|
|
|
if (bitSw != 0xFF && !dComIfGs_isSwitch(bitSw, fopAcM_GetRoomNo(this))) {
|
|
dComIfGs_onSwitch(bitSw, fopAcM_GetRoomNo(this));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void daE_WS_c::executeWindDown() {
|
|
mInvulnerabilityTimer = 10;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
mCcSph.OffAtSetBit();
|
|
mCcSph.OffTgSetBit();
|
|
mCcBokkuriSph.OffTgSetBit();
|
|
|
|
mBgc.SetWall(0.0f, 4.0f);
|
|
mMode = 1;
|
|
setBck(7, 2, 3.0f, 1.0f);
|
|
|
|
mSound.startCreatureVoice(Z2SE_EN_WS_V_DAMAGE, -1);
|
|
mWaitTimer = 5;
|
|
mAcch.SetGroundUpY(20.0f);
|
|
attention_info.flags = 0;
|
|
speed.y = 0.0f;
|
|
speedF = 5.0f;
|
|
current.angle.y = mTargetWallAngle.y;
|
|
mStepAngle = -0x800;
|
|
break;
|
|
case 1:
|
|
shape_angle.y += mStepAngle;
|
|
cLib_chaseAngleS(&mWallAngle.y, 0, 0x400);
|
|
cLib_chaseAngleS(&mWallAngle.x, 0, 0x400);
|
|
shape_angle.x += 0x800;
|
|
shape_angle.z += 0x800;
|
|
speed.y = 30.0f;
|
|
|
|
if (mWaitTimer == 0) {
|
|
mMode = 2;
|
|
gravity = -3.0f;
|
|
}
|
|
break;
|
|
case 2:
|
|
shape_angle.y += mStepAngle;
|
|
cLib_chaseAngleS(&mWallAngle.y, 0, 0x400);
|
|
cLib_chaseAngleS(&mWallAngle.x, 0, 0x400);
|
|
cLib_chaseAngleS(&shape_angle.x, -0x8000, 0x400);
|
|
cLib_chaseAngleS(&shape_angle.z, 0, 0x400);
|
|
|
|
if (mAcch.ChkGroundHit()) {
|
|
speedF = 3.0f + cM_rndF(2.0f);
|
|
speed.y = 12.0f;
|
|
mMode = 3;
|
|
mWaitTimer = 30;
|
|
setBck(6, 0, 5.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_WS_V_DEATH, -1);
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1);
|
|
}
|
|
break;
|
|
case 3:
|
|
shape_angle.y += mStepAngle;
|
|
cLib_chaseAngleS(&mStepAngle, 0, 0x80);
|
|
cLib_chaseAngleS(&shape_angle.x, -0x8000, 0x400);
|
|
cLib_chaseAngleS(&shape_angle.z, 0, 0x400);
|
|
|
|
if (mAcch.ChkGroundHit()) {
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1);
|
|
shape_angle.x = -0x8000;
|
|
speedF = 0.0f;
|
|
speed.y = 0.0f;
|
|
mMode = 4;
|
|
}
|
|
break;
|
|
case 4:
|
|
cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f);
|
|
shape_angle.y += mStepAngle;
|
|
cLib_chaseAngleS(&mStepAngle, 0, 0x80);
|
|
shape_angle.y += mStepAngle;
|
|
|
|
if (mAnm_p->isStop()) {
|
|
mWaitTimer = 15;
|
|
mMode = 5;
|
|
}
|
|
break;
|
|
case 5:
|
|
cLib_addCalc2(&mDownColor, -20.0f, 1.0f, 0.4f);
|
|
if (mWaitTimer == 0) {
|
|
fopAcM_delete(this);
|
|
fopAcM_createDisappear(this, ¤t.pos, 7, 0, 7);
|
|
|
|
if (bitSw != 0xFF && !dComIfGs_isSwitch(bitSw, fopAcM_GetRoomNo(this))) {
|
|
dComIfGs_onSwitch(bitSw, fopAcM_GetRoomNo(this));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void daE_WS_c::damage_check() {
|
|
if (mInvulnerabilityTimer == 0) {
|
|
if (mAction == ACTION_DOWN_e || mAction == ACTION_WIND_DOWN_e) {
|
|
return;
|
|
}
|
|
|
|
mCcStts.Move();
|
|
|
|
if (mCcBokkuriSph.ChkTgHit()) {
|
|
mAtInfo.mpCollider = mCcBokkuriSph.GetTgHitObj();
|
|
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_20000)) {
|
|
dComIfGp_setHitMark(1, this, &eyePos, NULL, NULL, 0);
|
|
dScnPly_c::setPauseTimer(4);
|
|
mSound.startCreatureSound(Z2SE_EN_ST_SHELL_BREAK, 0, -1);
|
|
} else if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_THROW_OBJ)) {
|
|
fopAc_ac_c* throwobj_p = dCc_GetAc(mAtInfo.mpCollider->GetAc());
|
|
if (fopAcM_GetName(throwobj_p) == fpcNm_Obj_Carry_e && ((daObjCarry_c*)throwobj_p)->getType() == daObjCarry_c::TYPE_BOKKURI) {
|
|
mSound.startCreatureSound(Z2SE_EN_ST_SHELL_BREAK, 0, -1);
|
|
}
|
|
}
|
|
|
|
cc_at_check(this, &mAtInfo);
|
|
setActionMode(ACTION_DOWN_e);
|
|
return;
|
|
}
|
|
|
|
if (mCcSph.ChkTgHit()) {
|
|
mAtInfo.mpCollider = mCcSph.GetTgHitObj();
|
|
cc_at_check(this, &mAtInfo);
|
|
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_WOLF_ATTACK | AT_TYPE_WOLF_CUT_TURN | AT_TYPE_10000000 | AT_TYPE_MIDNA_LOCK)) {
|
|
mInvulnerabilityTimer = 20;
|
|
} else {
|
|
mInvulnerabilityTimer = 10;
|
|
}
|
|
|
|
if (mAtInfo.mAttackPower <= 1) {
|
|
mInvulnerabilityTimer = KREG_S(8) + 10;
|
|
}
|
|
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_BOOMERANG)) {
|
|
setActionMode(ACTION_WIND_DOWN_e);
|
|
} else {
|
|
setActionMode(ACTION_DOWN_e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void daE_WS_c::action() {
|
|
attention_info.distances[fopAc_attn_BATTLE_e] = 46;
|
|
damage_check();
|
|
field_0x566 = 0;
|
|
|
|
switch (mAction) {
|
|
case ACTION_WAIT_e:
|
|
executeWait();
|
|
break;
|
|
case ACTION_ATTACK_e:
|
|
field_0x566 = 1;
|
|
executeAttack();
|
|
break;
|
|
case ACTION_DOWN_e:
|
|
executeDown();
|
|
break;
|
|
case ACTION_WIND_DOWN_e:
|
|
executeWindDown();
|
|
break;
|
|
}
|
|
|
|
mSound.setLinkSearch(field_0x566);
|
|
|
|
if (mAction != ACTION_DOWN_e && mAction != ACTION_WIND_DOWN_e) {
|
|
cXyz ato;
|
|
mDoMtx_stack_c::YrotS(mTargetWallAngle.y);
|
|
mDoMtx_stack_c::XrotM(mTargetWallAngle.x);
|
|
mDoMtx_stack_c::YrotM(current.angle.y);
|
|
|
|
cXyz mae(0.0f, 0.0f, speedF);
|
|
mDoMtx_stack_c::multVec(&mae, &ato);
|
|
speed = ato;
|
|
current.pos += speed;
|
|
} else {
|
|
fopAcM_posMoveF(this, NULL);
|
|
}
|
|
|
|
mAcch.CrrPos(dComIfG_Bgsp());
|
|
mAnm_p->play(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this)));
|
|
}
|
|
|
|
void daE_WS_c::mtx_set() {
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(mWallAngle);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle);
|
|
mDoMtx_stack_c::scaleM(mBodyScale, mBodyScale, mBodyScale);
|
|
|
|
J3DModel* model_p = mAnm_p->getModel();
|
|
model_p->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
mAnm_p->modelCalc();
|
|
}
|
|
|
|
void daE_WS_c::cc_set() {
|
|
cXyz mae;
|
|
cXyz ato;
|
|
J3DModel* model = mAnm_p->getModel();
|
|
|
|
mDoMtx_stack_c::YrotS(mTargetWallAngle.y);
|
|
mDoMtx_stack_c::XrotM(mTargetWallAngle.x);
|
|
mae.set(0.0f, 15.0f + nREG_F(10), 0.0f);
|
|
mDoMtx_stack_c::multVec(&mae, &ato);
|
|
attention_info.position = current.pos + ato;
|
|
attention_info.position.y += 90.0f * mBodyScale;
|
|
|
|
MTXCopy(model->getAnmMtx(1), mDoMtx_stack_c::get());
|
|
mae.set(-15.0f + nREG_F(5), -10.0f + nREG_F(6), nREG_F(7));
|
|
mDoMtx_stack_c::multVec(&mae, &eyePos);
|
|
|
|
mCcSph.SetC(eyePos);
|
|
mCcSph.SetR(35.0f);
|
|
dComIfG_Ccsp()->Set(&mCcSph);
|
|
|
|
mCcBokkuriSph.SetC(eyePos);
|
|
mCcBokkuriSph.SetR(60.0f);
|
|
dComIfG_Ccsp()->Set(&mCcBokkuriSph);
|
|
}
|
|
|
|
int daE_WS_c::execute() {
|
|
if (mWaitTimer != 0) {
|
|
mWaitTimer--;
|
|
}
|
|
|
|
if (mInvulnerabilityTimer != 0) {
|
|
mInvulnerabilityTimer--;
|
|
}
|
|
|
|
action();
|
|
mtx_set();
|
|
cc_set();
|
|
|
|
cXyz effpos(current.pos);
|
|
cXyz effsize(0.5f, 0.5f, 0.5f);
|
|
setMidnaBindEffect(this, &mSound, &effpos, &effsize);
|
|
return 1;
|
|
}
|
|
|
|
static int daE_WS_Execute(daE_WS_c* i_this) {
|
|
return i_this->execute();
|
|
}
|
|
|
|
void daE_WS_c::checkInitialWall() {
|
|
cXyz endpos;
|
|
cXyz offset(0.0f, 0.0f, 200.0f);
|
|
dBgS_LinChk linchk;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
cLib_offsetPos(&endpos, ¤t.pos, (shape_angle.y + (i << 14)), &offset);
|
|
linchk.Set(¤t.pos, &endpos, NULL);
|
|
|
|
if (dComIfG_Bgsp().LineCross(&linchk)) {
|
|
if (arg0 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) {
|
|
return;
|
|
}
|
|
|
|
current.pos = linchk.GetCross();
|
|
|
|
cM3dGPla tri;
|
|
dComIfG_Bgsp().GetTriPla(linchk, &tri);
|
|
|
|
cXyz* tri_np = tri.GetNP();
|
|
mTargetWallAngle.y = cM_atan2s(tri_np->x, tri_np->z);
|
|
mTargetWallAngle.x = cM_atan2s(tri_np->absXZ(), tri_np->y);
|
|
mWallAngle = mTargetWallAngle;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool daE_WS_c::checkBeforeBg(s16 i_angle) {
|
|
dBgS_LinChk linchk;
|
|
cXyz mae;
|
|
cXyz ato;
|
|
cXyz endpos;
|
|
cXyz startpos;
|
|
|
|
if (!speedF) {
|
|
return false;
|
|
}
|
|
|
|
mDoMtx_stack_c::YrotS(mTargetWallAngle.y);
|
|
mDoMtx_stack_c::XrotM(mTargetWallAngle.x);
|
|
mDoMtx_stack_c::YrotM(i_angle);
|
|
mae.set(0.0f, 50.0f * mBodyScale, 0.0f);
|
|
mDoMtx_stack_c::multVec(&mae, &startpos);
|
|
startpos += current.pos;
|
|
|
|
mDoMtx_stack_c::YrotS(mTargetWallAngle.y);
|
|
mDoMtx_stack_c::XrotM(mTargetWallAngle.x);
|
|
mDoMtx_stack_c::YrotM(i_angle);
|
|
mae.set(0.0f, 0.0f, 50.0f * mBodyScale);
|
|
mDoMtx_stack_c::multVec(&mae, &ato);
|
|
|
|
mae.set(ato.x, 0.0f, ato.z);
|
|
endpos = startpos + mae;
|
|
|
|
linchk.Set(&startpos, &endpos, NULL);
|
|
if (dComIfG_Bgsp().LineCross(&linchk)) {
|
|
return 1;
|
|
}
|
|
|
|
if (ato.y > 0.0f) {
|
|
mae.set(0.0f, 50.0f * mBodyScale, 0.0f);
|
|
} else {
|
|
mae.set(0.0f, -l_HIO.dist_to_ground, 0.0f);
|
|
}
|
|
|
|
endpos = startpos + mae;
|
|
linchk.Set(&startpos, &endpos, NULL);
|
|
if (dComIfG_Bgsp().LineCross(&linchk)) {
|
|
return true;
|
|
}
|
|
|
|
mDoMtx_stack_c::YrotS(mTargetWallAngle.y);
|
|
mDoMtx_stack_c::XrotM(mTargetWallAngle.x);
|
|
mDoMtx_stack_c::YrotM(i_angle);
|
|
mae.set(0.0f, 50.0f * mBodyScale, 100.0f * mBodyScale);
|
|
mDoMtx_stack_c::multVec(&mae, &ato);
|
|
startpos = current.pos + ato;
|
|
|
|
cXyz sp38(0.0f, -40.0f * mBodyScale, 100.0f * mBodyScale);
|
|
mDoMtx_stack_c::multVec(&sp38, &ato);
|
|
endpos = current.pos + ato;
|
|
|
|
linchk.Set(&startpos, &endpos, NULL);
|
|
if (!dComIfG_Bgsp().LineCross(&linchk)) {
|
|
return true;
|
|
}
|
|
|
|
if (arg0 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) {
|
|
return true;
|
|
}
|
|
|
|
cM3dGPla tri;
|
|
dComIfG_Bgsp().GetTriPla(linchk, &tri);
|
|
|
|
cXyz* tri_np = tri.GetNP();
|
|
cLib_chaseAngleS(&mWallAngle.y, cM_atan2s(tri_np->x, tri_np->z), 0x100);
|
|
checkWall();
|
|
return false;
|
|
}
|
|
|
|
bool daE_WS_c::checkWall() {
|
|
cXyz startpos;
|
|
cXyz endpos;
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(mWallAngle);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle);
|
|
|
|
mDoMtx_stack_c::transM(0.0f, 100.0f, 0.0f);
|
|
mDoMtx_stack_c::multVecZero(&startpos);
|
|
|
|
mDoMtx_stack_c::transM(0.0f, -150.0f, 0.0f);
|
|
mDoMtx_stack_c::multVecZero(&endpos);
|
|
|
|
dBgS_LinChk linchk;
|
|
linchk.Set(&startpos, &endpos, NULL);
|
|
if (dComIfG_Bgsp().LineCross(&linchk)) {
|
|
if (arg0 == 0 && dComIfG_Bgsp().GetWallCode(linchk) != 1 && dComIfG_Bgsp().GetWallCode(linchk) != 4) {
|
|
return false;
|
|
}
|
|
|
|
current.pos = linchk.GetCross();
|
|
|
|
cM3dGPla tri;
|
|
dComIfG_Bgsp().GetTriPla(linchk, &tri);
|
|
|
|
cXyz* tri_np = tri.GetNP();
|
|
mTargetWallAngle.y = cM_atan2s(tri_np->x, tri_np->z);
|
|
mTargetWallAngle.x = cM_atan2s(tri_np->absXZ(), tri_np->y);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static int daE_WS_IsDelete(daE_WS_c* a_this) {
|
|
return 1;
|
|
}
|
|
|
|
int daE_WS_c::_delete() {
|
|
dComIfG_resDelete(&mPhase, "E_WS");
|
|
|
|
if (mHioSet) {
|
|
hio_set = FALSE;
|
|
mDoHIO_DELETE_CHILD(l_HIO.id);
|
|
}
|
|
|
|
if (heap != NULL) {
|
|
mSound.deleteObject();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int daE_WS_Delete(daE_WS_c* i_this) {
|
|
fopAcM_RegisterDeleteID(i_this, "E_WS");
|
|
return i_this->_delete();
|
|
}
|
|
|
|
int daE_WS_c::CreateHeap() {
|
|
J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes("E_WS", 0xD);
|
|
JUT_ASSERT(1401, modelData != NULL);
|
|
|
|
mAnm_p = new mDoExt_McaMorfSO(modelData, NULL, NULL, (J3DAnmTransform*)dComIfG_getObjectRes("E_WS", 7), 0, 1.0f, 0, -1, &mSound, 0x80000, 0x11000084);
|
|
if (mAnm_p == NULL || mAnm_p->getModel() == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int useHeapInit(fopAc_ac_c* actor) {
|
|
return ((daE_WS_c*)actor)->CreateHeap();
|
|
}
|
|
|
|
int daE_WS_c::create() {
|
|
fopAcM_ct(this, daE_WS_c);
|
|
|
|
int phase_state = dComIfG_resLoad(&mPhase, "E_WS");
|
|
if (phase_state == cPhs_COMPLEATE_e) {
|
|
OS_REPORT("E_WS PARAM %x\n", fopAcM_GetParam(this));
|
|
|
|
bitSw = (fopAcM_GetParam(this) & 0xFF00) >> 8;
|
|
if (bitSw != 0xFF && dComIfGs_isSwitch(bitSw, fopAcM_GetRoomNo(this))) {
|
|
OS_REPORT("E_WS やられ後なので再セットしません\n");
|
|
return cPhs_ERROR_e;
|
|
}
|
|
|
|
if (!fopAcM_entrySolidHeap(this, useHeapInit, 0x1B60)) {
|
|
return cPhs_ERROR_e;
|
|
}
|
|
|
|
if (!hio_set) {
|
|
hio_set = true;
|
|
mHioSet = true;
|
|
l_HIO.id = mDoHIO_CREATE_CHILD("スタルウォール", &l_HIO);
|
|
}
|
|
|
|
arg0 = fopAcM_GetParam(this);
|
|
if (arg0 == 0xFF) {
|
|
arg0 = 0;
|
|
}
|
|
|
|
if (((fopAcM_GetParam(this) & 0xFF0000) >> 0x10) == 1) {
|
|
mBodyScale = 0.5f;
|
|
} else {
|
|
mBodyScale = 0.8f;
|
|
}
|
|
|
|
attention_info.flags = fopAc_AttnFlag_BATTLE_e;
|
|
fopAcM_SetMtx(this, mAnm_p->getModel()->getBaseTRMtx());
|
|
fopAcM_SetMin(this, -200.0f, -200.0f, -200.0f);
|
|
fopAcM_SetMax(this, 200.0f, 200.0f, 200.0f);
|
|
|
|
mAcch.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mBgc, fopAcM_GetSpeed_p(this), NULL, NULL);
|
|
mBgc.SetWall(0.0f, 0.0f);
|
|
|
|
health = 10;
|
|
field_0x560 = 10;
|
|
|
|
mCcStts.Init(100, 0, this);
|
|
mCcSph.Set(cc_ws_src);
|
|
mCcSph.SetStts(&mCcStts);
|
|
mCcBokkuriSph.Set(cc_bokkuri_src);
|
|
mCcBokkuriSph.SetStts(&mCcStts);
|
|
|
|
mSound.init(¤t.pos, &eyePos, 3, 1);
|
|
mSound.setEnemyName("E_ws");
|
|
|
|
mAtInfo.mpSound = &mSound;
|
|
mAtInfo.mPowerType = 1;
|
|
|
|
setActionMode(ACTION_WAIT_e);
|
|
checkInitialWall();
|
|
|
|
mHomePos = current.pos;
|
|
speed.y = 0.0f;
|
|
gravity = 0.0f;
|
|
mtx_set();
|
|
}
|
|
|
|
return phase_state;
|
|
}
|
|
|
|
static int daE_WS_Create(daE_WS_c* i_this) {
|
|
return i_this->create();
|
|
}
|
|
|
|
static actor_method_class l_daE_WS_Method = {
|
|
(process_method_func)daE_WS_Create,
|
|
(process_method_func)daE_WS_Delete,
|
|
(process_method_func)daE_WS_Execute,
|
|
(process_method_func)daE_WS_IsDelete,
|
|
(process_method_func)daE_WS_Draw,
|
|
};
|
|
|
|
actor_process_profile_definition g_profile_E_WS = {
|
|
/* Layer ID */ fpcLy_CURRENT_e,
|
|
/* List ID */ 7,
|
|
/* List Prio */ fpcPi_CURRENT_e,
|
|
/* Proc Name */ fpcNm_E_WS_e,
|
|
/* Proc SubMtd */ &g_fpcLf_Method.base,
|
|
/* Size */ sizeof(daE_WS_c),
|
|
/* Size Other */ 0,
|
|
/* Parameters */ 0,
|
|
/* Leaf SubMtd */ &g_fopAc_Method.base,
|
|
/* Draw Prio */ fpcDwPi_E_WS_e,
|
|
/* Actor SubMtd */ &l_daE_WS_Method,
|
|
/* Status */ fopAcStts_UNK_0x40000_e | fopAcStts_UNK_0x10000_e | fopAcStts_CULL_e,
|
|
/* Group */ fopAc_ENEMY_e,
|
|
/* Cull Type */ fopAc_CULLBOX_CUSTOM_e,
|
|
};
|