mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-03 01:58:44 -04:00
2131 lines
62 KiB
C++
2131 lines
62 KiB
C++
/**
|
|
* @file d_a_e_hz.cpp
|
|
*
|
|
*/
|
|
|
|
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
|
|
|
#include "Z2AudioLib/Z2Instances.h"
|
|
#include "d/actor/d_a_e_hz.h"
|
|
#include "res/Object/E_hz.h"
|
|
#include "d/d_camera.h"
|
|
#include "f_op/f_op_actor_enemy.h"
|
|
#include "d/d_debug_viewer.h"
|
|
|
|
enum daE_HZ_Action {
|
|
/* 0 */ ACTION_WAIT,
|
|
/* 1 */ ACTION_HIDE,
|
|
/* 2 */ ACTION_ATTACK,
|
|
/* 3 */ ACTION_AWAY,
|
|
/* 4 */ ACTION_WIND,
|
|
/* 5 */ ACTION_DAMAGE,
|
|
/* 6 */ ACTION_DEATH,
|
|
/* 7 */ ACTION_CHANCE,
|
|
/* 8 */ ACTION_WIND_CHANCE,
|
|
/* 9 */ ACTION_WIND_WALK,
|
|
/* 10 */ ACTION_WATER_DEATH,
|
|
/* 11 */ ACTION_DEATH_WAIT
|
|
};
|
|
|
|
class daE_HZ_HIO_c : public JORReflexible {
|
|
public:
|
|
daE_HZ_HIO_c();
|
|
virtual ~daE_HZ_HIO_c() {}
|
|
|
|
void genMessage(JORMContext*);
|
|
|
|
/* 0x4 */ s8 enemy_sample;
|
|
/* 0x8 */ f32 basic_size;
|
|
/* 0xC */ u8 pl_detection_radius_display;
|
|
/* 0x10 */ f32 pl_detection_radius_in;
|
|
/* 0x14 */ f32 pl_detection_radius_outside;
|
|
/* 0x18 */ f32 escape_speed;
|
|
/* 0x1C */ f32 piyori_time;
|
|
/* 0x20 */ f32 extension_time;
|
|
/* 0x24 */ f32 stretch_anim_speed;
|
|
/* 0x28 */ f32 retention_time_before_stretch;
|
|
/* 0x2C */ f32 reeling_rotation_speed;
|
|
/* 0x30 */ f32 y_position_wrap;
|
|
/* 0x34 */ f32 camera_on_timer;
|
|
/* 0x38 */ f32 camera_off_timer;
|
|
};
|
|
|
|
daE_HZ_HIO_c::daE_HZ_HIO_c() {
|
|
enemy_sample = -1;
|
|
basic_size = 1.0f;
|
|
pl_detection_radius_display = 0;
|
|
pl_detection_radius_in = 700.0f;
|
|
pl_detection_radius_outside = 1200.0f;
|
|
escape_speed = 20.0f;
|
|
piyori_time = 160.0f;
|
|
reeling_rotation_speed = 5000.0f;
|
|
y_position_wrap = 400.0f;
|
|
extension_time = 15.0f;
|
|
stretch_anim_speed = 0.7f;
|
|
retention_time_before_stretch = 7.0f;
|
|
camera_on_timer = 1.0f;
|
|
camera_off_timer = 50.0f;
|
|
}
|
|
|
|
#if DEBUG
|
|
void daE_HZ_HIO_c::genMessage(JORMContext* ctx) {
|
|
ctx->genLabel(" 敵サンプル", 0x80000001);
|
|
ctx->genSlider("基本サイズ", &basic_size, 0.0f, 5.0f);
|
|
ctx->genCheckBox("PL発見半径表示", &pl_detection_radius_display, 0x1);
|
|
ctx->genSlider("PL発見半径(内)", &pl_detection_radius_in, 0.0f, 5000.0f);
|
|
ctx->genSlider("PL発見半径(外)", &pl_detection_radius_outside, 0.0f, 5000.0f);
|
|
ctx->genSlider("逃げ速度", &escape_speed, 0.0f, 200.0f);
|
|
ctx->genSlider("ぴより時間", &piyori_time, 0.0f, 500.0f);
|
|
ctx->genSlider("巻き込み回転速度", &reeling_rotation_speed, 0.0f, 10000.0f);
|
|
ctx->genSlider("巻き込みY位置", &y_position_wrap, 0.0f, 1000.0f);
|
|
ctx->genSlider("伸び溜め時間", &extension_time, 0.0f, 100.0f);
|
|
ctx->genSlider("伸びアニメ速度", &stretch_anim_speed, 0.0f, 1.0f);
|
|
ctx->genSlider("伸び前の溜め時間", &retention_time_before_stretch, 0.0f, 100.0f);
|
|
ctx->genLabel("カメラ用タイマー", 0x80000001);
|
|
ctx->genSlider("オンタイマー", &camera_on_timer, 0.0f, 100.0f);
|
|
ctx->genSlider("オフタイマー", &camera_off_timer, 0.0f, 100.0f);
|
|
}
|
|
#endif
|
|
|
|
void daE_HZ_c::setBck(int i_index, u8 i_attr, f32 i_morf, f32 i_rate) {
|
|
mpMorfSO->setAnm((J3DAnmTransform*)dComIfG_getObjectRes("E_HZ", i_index), i_attr, i_morf, i_rate, 0.0f, -1.0f);
|
|
}
|
|
|
|
bool daE_HZ_c::checkBck(int i_index) {
|
|
if (mpMorfSO->getAnm() == (J3DAnmTransform*)dComIfG_getObjectRes("E_HZ", i_index)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static u8 hio_set;
|
|
|
|
static daE_HZ_HIO_c l_HIO;
|
|
|
|
int daE_HZ_c::draw() {
|
|
g_env_light.settingTevStruct(0, ¤t.pos, &tevStr);
|
|
g_env_light.setLightTevColorType_MAJI(mpModel2, &tevStr);
|
|
mDoExt_modelUpdateDL(mpModel2);
|
|
|
|
if (field_0x6e8 != 0) {
|
|
return 1;
|
|
}
|
|
|
|
J3DMaterial* material;
|
|
J3DModel* morfModel = mpMorfSO->getModel();
|
|
g_env_light.setLightTevColorType_MAJI(morfModel, &tevStr);
|
|
|
|
if (mReadyChangeColor != 0) {
|
|
J3DModelData* morfModelData = morfModel->getModelData();
|
|
for (u16 i = 0; i < morfModelData->getMaterialNum(); i++) {
|
|
material = morfModelData->getMaterialNodePointer(i);
|
|
material->getTevColor(0)->r = mColor;
|
|
material->getTevColor(0)->g = mColor;
|
|
material->getTevColor(0)->b = mColor;
|
|
}
|
|
}
|
|
|
|
mpMorfSO->entryDL();
|
|
g_env_light.settingTevStruct(0x10, ¤t.pos, &mTevStr);
|
|
g_env_light.setLightTevColorType_MAJI(mpModel, &mTevStr);
|
|
mDoExt_modelUpdateDL(mpModel);
|
|
|
|
cXyz modified_pos;
|
|
modified_pos.set(current.pos.x, current.pos.y + 100.0f, current.pos.z);
|
|
|
|
if (!mDisableShadow) {
|
|
mShadowKey = dComIfGd_setShadow(mShadowKey, 1, morfModel, &modified_pos, nREG_F(19) + 800.0f, 0.0f,
|
|
current.pos.y, mObjAcch.GetGroundH(), mObjAcch.m_gnd,
|
|
&tevStr, 0, 1.0f, dDlst_shadowControl_c::getSimpleTex());
|
|
}
|
|
|
|
#if DEBUG
|
|
if (l_HIO.pl_detection_radius_display) {
|
|
cXyz pos(home.pos);
|
|
pos.y += 100.0f;
|
|
dDbVw_drawCircleOpa(pos, l_HIO.pl_detection_radius_in, (GXColor){0xC8, 0xC8, 0x00, 0xFF}, 1, 12);
|
|
dDbVw_drawCircleOpa(pos, l_HIO.pl_detection_radius_outside, (GXColor){0x00, 0xC8, 0x00, 0xFF}, 1, 12);
|
|
|
|
if (field_0x6e4) {
|
|
pos = current.pos;
|
|
pos.y += mAcchCir.GetWallH();
|
|
dDbVw_drawCircleOpa(pos, mAcchCir.GetWallR(), (GXColor){0x00, 0x00, 0xC8, 0xFF}, 1, 12);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int daE_HZ_Draw(daE_HZ_c* i_this) {
|
|
return i_this->draw();
|
|
}
|
|
|
|
static fopAc_ac_c* m_near_bomb;
|
|
|
|
static fopAc_ac_c* m_near_carry;
|
|
|
|
static fopAc_ac_c* m_near_weapon;
|
|
|
|
static void* s_obj_sub(void* i_actor, void* i_data) {
|
|
f32 actor_dist;
|
|
|
|
UNUSED(i_data);
|
|
|
|
if (fopAcM_IsActor(i_actor)) {
|
|
if (!fpcM_IsCreating(fopAcM_GetID(i_actor)) && !fopAcM_checkCarryNow((fopAc_ac_c*)i_actor))
|
|
{
|
|
actor_dist = fopAcM_searchActorDistance((fopAc_ac_c*)i_actor, (fopAc_ac_c*)i_data);
|
|
|
|
if (actor_dist < 100.0f && !fopAcM_GetSpeedF((fopAc_ac_c*)i_actor) &&
|
|
!fopAcM_GetSpeed((fopAc_ac_c*)i_actor).y)
|
|
{
|
|
if (fopAcM_GetName(i_actor) == fpcNm_Obj_Carry_e) {
|
|
m_near_carry = (fopAc_ac_c*)i_actor;
|
|
} else if (fopAcM_GetName(i_actor) == fpcNm_NBOMB_e) {
|
|
m_near_bomb = (fopAc_ac_c*)i_actor;
|
|
}
|
|
}
|
|
|
|
if (actor_dist < 500.0f && (fopAcM_GetName(i_actor) == fpcNm_BOOMERANG_e ||
|
|
fopAcM_GetName(i_actor) == fpcNm_NBOMB_e))
|
|
{
|
|
m_near_weapon = static_cast<fopAc_ac_c*>(i_actor);
|
|
}
|
|
if (actor_dist < 700.0f && fopAcM_GetName(i_actor) == fpcNm_ARROW_e &&
|
|
fopAcM_GetSpeedF((fopAc_ac_c*)i_actor))
|
|
{
|
|
m_near_weapon = static_cast<fopAc_ac_c*>(i_actor);
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void daE_HZ_c::setActionMode(int i_action) {
|
|
if (mAction != i_action || i_action == 5) {
|
|
if (mReadyNewAction) {
|
|
dComIfGp_event_reset();
|
|
mReadyNewAction = false;
|
|
OS_REPORT("setActionMode %d %d \n", mAction, i_action);
|
|
}
|
|
mDisableShadow = false;
|
|
mPrevAction = mAction;
|
|
mAction = i_action;
|
|
mMode = 0;
|
|
current.angle.y = shape_angle.y;
|
|
}
|
|
}
|
|
|
|
bool daE_HZ_c::checkHideStart() {
|
|
daPy_py_c* player = daPy_getPlayerActorClass();
|
|
|
|
if (mAttackCooldownTimer != 0) {
|
|
return 1;
|
|
}
|
|
|
|
if (mPlayerDist < l_HIO.pl_detection_radius_in ||
|
|
mPlayerDist > l_HIO.pl_detection_radius_outside)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (dComIfGp_checkPlayerStatus0(0, 0x4000) && player->getHookshotTopPos() != NULL) {
|
|
if (player->getHookshotTopPos()->abs(current.pos) < 500.0f) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
m_near_bomb = m_near_carry = m_near_weapon = NULL;
|
|
|
|
fpcM_Search(s_obj_sub, this);
|
|
|
|
if (m_near_bomb != NULL || m_near_carry != NULL || m_near_weapon != NULL) {
|
|
return 1;
|
|
}
|
|
|
|
if (player->getIronBallCenterPos() != NULL) {
|
|
if (player->getIronBallCenterPos()->absXZ(current.pos) < 400.0f) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool daE_HZ_c::checkAttackStart() {
|
|
field_0x6e9 = 0;
|
|
|
|
if (fopAcM_searchPlayerDistanceXZ(this) < 100.0f &&
|
|
std::abs(fopAcM_searchPlayerDistanceY(this)) < 110.0f)
|
|
{
|
|
if (!daPy_getPlayerActorClass()->checkBootsOrArmorHeavy()) {
|
|
field_0x6e9 |= (u8)1;
|
|
} else {
|
|
if (mAttackStartTimer == 0) {
|
|
mMode = 2;
|
|
current.pos.y += 2.0f;
|
|
mAttackStartTimer = cM_rndF(10.0f) + 20.0f;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_near_bomb = m_near_carry = m_near_weapon = NULL;
|
|
|
|
fpcM_Search(s_obj_sub, this);
|
|
cXyz unused;
|
|
|
|
if (m_near_bomb != NULL && !((daNbomb_c*)m_near_bomb)->checkStateExplode()) {
|
|
field_0x6e9 |= (u8)4;
|
|
mpBombActor = (daNbomb_c*)m_near_bomb;
|
|
}
|
|
|
|
if (m_near_carry != NULL) {
|
|
field_0x6e9 |= (u8)2;
|
|
mpCarryActor = (daObjCarry_c*)m_near_carry;
|
|
}
|
|
|
|
if (field_0x6e9) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool daE_HZ_c::checkArrowCharge() {
|
|
if (daPy_getPlayerActorClass()->checkArrowChargeEnd()) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void daE_HZ_c::setTgSetBit(int i_setBit) {
|
|
if (i_setBit) {
|
|
mSpheres[1].OnTgSetBit();
|
|
mSpheres[2].OnTgSetBit();
|
|
mSpheres[3].OnTgSetBit();
|
|
} else {
|
|
mSpheres[1].OffTgSetBit();
|
|
mSpheres[2].OffTgSetBit();
|
|
mSpheres[3].OffTgSetBit();
|
|
}
|
|
}
|
|
|
|
bool daE_HZ_c::isWait() {
|
|
if (mAction == ACTION_WAIT || mAction == ACTION_HIDE) {
|
|
return true;
|
|
}
|
|
|
|
if (mAction == ACTION_DEATH_WAIT && mMode == ACTION_WIND) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void daE_HZ_c::checkFall() {
|
|
if (mAction == ACTION_DEATH_WAIT || mAction == ACTION_WATER_DEATH) {
|
|
return;
|
|
}
|
|
|
|
if (mObjAcch.ChkGroundHit()) {
|
|
int acch_ground_code = dComIfG_Bgsp().GetGroundCode(mObjAcch.m_gnd);
|
|
// FAKEMATCH???
|
|
#if DEBUG
|
|
if (acch_ground_code != 4 && acch_ground_code != 10 && acch_ground_code != 5) {
|
|
return;
|
|
}
|
|
#else
|
|
if (acch_ground_code != 10 && (acch_ground_code - 4 > 1u)) {
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
dBgS_GndChk gnd_chk;
|
|
cXyz modified_pos(current.pos);
|
|
modified_pos.y += 300.0f;
|
|
gnd_chk.SetPos(&modified_pos);
|
|
|
|
f32 ground_cross = dComIfG_Bgsp().GroundCross(&gnd_chk);
|
|
if (speed.y < 0.0f && ground_cross != -G_CM3D_F_INF) {
|
|
s32 gnd_chk_ground_code = dComIfG_Bgsp().GetGroundCode(gnd_chk);
|
|
if ((gnd_chk_ground_code == 4 || gnd_chk_ground_code == 10 || gnd_chk_ground_code == 5) &&
|
|
ground_cross + 500.0f > current.pos.y)
|
|
{
|
|
cXyz pos;
|
|
mDoMtx_stack_c::copy(mpMorfSO->getModel()->getAnmMtx(0x12));
|
|
mDoMtx_stack_c::multVecZero(&pos);
|
|
fopAcM_createDisappear(this, &pos, 10, 0, 5);
|
|
setActionMode(0xB);
|
|
}
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::setCloseSmokeEffect() {
|
|
dBgS_GndChk gnd_chk;
|
|
|
|
cXyz modified_pos(current.pos);
|
|
modified_pos.y += 100.0f;
|
|
|
|
gnd_chk.SetPos(&modified_pos);
|
|
f32 groundCross = dComIfG_Bgsp().GroundCross(&gnd_chk);
|
|
if (groundCross != -G_CM3D_F_INF) {
|
|
dComIfGp_particle_setPolyColor(dPa_RM(ID_ZM_S_HAZIKIPLATESMOKE00), gnd_chk, &mSmokeEffectPosition, &tevStr,
|
|
&shape_angle, NULL, 0, NULL, -1, NULL);
|
|
}
|
|
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_CLOSE, 0, -1);
|
|
}
|
|
|
|
void daE_HZ_c::executeWait() {
|
|
f32 target;
|
|
|
|
field_0x566 = 0;
|
|
mSetModelAnmMtx = true;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
mSpheres[0].OnTgSetBit();
|
|
mSpheres[0].SetTgType(0x10040);
|
|
setBck(0x10, 2, 0.0f, 1.0f);
|
|
shape_angle.y = (s16)(mPlayerAngleY + 0x2000) & 0xC000;
|
|
mMode = 1;
|
|
field_0x6e4 = 0;
|
|
field_0x6b4 = 0;
|
|
/* fallthrough */
|
|
case 1:
|
|
if (!cLib_chaseF(¤t.pos.y, home.pos.y + 30.0f, 2.0f)) {
|
|
break;
|
|
} else {
|
|
mMode = 2;
|
|
field_0x6b2 = shape_angle.y = (s16)(shape_angle.y + 0x2000) & 0xC000;
|
|
field_0x6cc = 0;
|
|
field_0x6b6 = 0;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
shape_angle.y += field_0x6b6;
|
|
switch (field_0x6cc) {
|
|
case 0:
|
|
if ((s16)(field_0x6b2 - 0x1800) < shape_angle.y) {
|
|
cLib_chaseAngleS(&field_0x6b6, -0x200, 0x80);
|
|
} else if (cLib_chaseAngleS(&field_0x6b6, 0, 0x80)) {
|
|
field_0x6cc = 1;
|
|
mWaitTimer = 10;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if ((s16)(field_0x6b2 + 0x1800) > shape_angle.y) {
|
|
cLib_chaseAngleS(&field_0x6b6, 0x200, 0x80);
|
|
} else if (cLib_chaseAngleS(&field_0x6b6, 0, 0x80)) {
|
|
field_0x6cc = 3;
|
|
mWaitTimer = 10;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
case 1:
|
|
if (mWaitTimer == 0) {
|
|
field_0x6cc++;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
cLib_chaseAngleS(&field_0x6b6, -0x200, 0x80);
|
|
if (cLib_distanceAngleS(shape_angle.y, field_0x6b2) >= 0x500) {
|
|
break;
|
|
}
|
|
mWaitTimer = 10;
|
|
field_0x6cc = 5;
|
|
return;
|
|
|
|
case 5:
|
|
cLib_chaseAngleS(&field_0x6b6, 0, 0x80);
|
|
if (mWaitTimer == 0) {
|
|
if (checkArrowCharge()) {
|
|
mMode = 4;
|
|
} else {
|
|
mMode = 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (field_0x6cc >= 2 && field_0x6cc <= 4 &&
|
|
cLib_distanceAngleS(shape_angle.y, mPlayerAngleY) < 0x800)
|
|
{
|
|
mWaitTimer = 0;
|
|
field_0x6cc = 5;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
case 4:
|
|
target = home.pos.y + 30.0f;
|
|
if (cLib_chaseF(¤t.pos.y, target, 5.0f)) {
|
|
ANGLE_ADD(field_0x6b4, 0x800);
|
|
current.pos.y += cM_ssin(field_0x6b4) * 1.5f;
|
|
cLib_chaseAngleS(&shape_angle.y, mPlayerAngleY, 0x400);
|
|
}
|
|
}
|
|
|
|
if (checkBck(0x10) && (mpMorfSO->checkFrame(0.0f) || mpMorfSO->checkFrame(30.0f))) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_WAIT, -1);
|
|
}
|
|
if (checkHideStart()) {
|
|
setActionMode(ACTION_HIDE);
|
|
}
|
|
}
|
|
|
|
f32 daE_HZ_c::getHideSpeed() {
|
|
f32 ret;
|
|
if (field_0x6cc < 3) {
|
|
if (home.pos.y != current.pos.y) {
|
|
ret = 0.0f;
|
|
current.pos.y += 10.0f;
|
|
}
|
|
field_0x6cc++;
|
|
} else {
|
|
ret = 15.0f;
|
|
if (current.pos.y - home.pos.y > 50.0f) {
|
|
ret = 50.0f;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void daE_HZ_c::executeHide() {
|
|
f32 step;
|
|
|
|
field_0x566 = 0;
|
|
mSetModelAnmMtx = true;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
mSpheres[0].OnTgSetBit();
|
|
mSpheres[0].SetTgType(0x10000);
|
|
field_0x6e4 = 0;
|
|
setTgSetBit(0);
|
|
mSpheres[1].OffTgShield();
|
|
mSpheres[2].OffTgShield();
|
|
mSpheres[1].SetTgHitMark(CcG_Tg_UNK_MARK_0);
|
|
mSpheres[2].SetTgHitMark(CcG_Tg_UNK_MARK_0);
|
|
mWaitTimer = 0;
|
|
field_0x6cc = 0;
|
|
if (home.pos.y == current.pos.y) {
|
|
mMode = 3;
|
|
setBck(0xD, 0, 3.0f, 0.0f);
|
|
shape_angle.y = home.angle.y;
|
|
} else {
|
|
mMode = 1;
|
|
setBck(0x10, 2, 0.0f, 1.0f);
|
|
}
|
|
field_0x6b2 = (s16)(shape_angle.y + 0x2000) & 0xC000;
|
|
speed.y = speedF = 0.0f;
|
|
gravity = 0.0f;
|
|
break;
|
|
|
|
case 1:
|
|
s16 chaseAngle;
|
|
if (mPlayerDist > l_HIO.pl_detection_radius_outside) {
|
|
chaseAngle = 0x200;
|
|
} else {
|
|
chaseAngle = 0x800;
|
|
step = getHideSpeed();
|
|
if (cLib_chaseF(¤t.pos.y, home.pos.y, step)) {
|
|
shape_angle.y = field_0x6b2;
|
|
}
|
|
}
|
|
if (cLib_chaseAngleS(&shape_angle.y, field_0x6b2, chaseAngle)) {
|
|
mMode = 2;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (mPlayerDist > l_HIO.pl_detection_radius_outside) {
|
|
step = 5.0f;
|
|
} else {
|
|
step = getHideSpeed();
|
|
}
|
|
|
|
if (cLib_chaseF(¤t.pos.y, home.pos.y, step) && mWaitTimer == 0) {
|
|
mMode = 3;
|
|
setBck(0xD, 0, 3.0f, 0.0f);
|
|
setCloseSmokeEffect();
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if (checkAttackStart()) {
|
|
if (field_0x6e9 & 1) {
|
|
mMode = 4;
|
|
} else {
|
|
mMode = 5;
|
|
mRetentionBeforeStretchTimer = l_HIO.retention_time_before_stretch;
|
|
}
|
|
shape_angle.y = (s16)(mPlayerAngleY + 0x2000) & 0xC000;
|
|
break;
|
|
}
|
|
if (!checkHideStart() && !dComIfGp_checkPlayerStatus0(0, 0x4000)) {
|
|
setActionMode(ACTION_WAIT);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if (!eventInfo.checkCommandDemoAccrpt()) {
|
|
fopAcM_orderPotentialEvent(this, 2, 0, 0);
|
|
eventInfo.onCondition(dEvtCnd_CANDEMO_e);
|
|
} else {
|
|
mReadyNewAction = true;
|
|
mMode = 5;
|
|
mRetentionBeforeStretchTimer = l_HIO.retention_time_before_stretch;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
cLib_chaseF(¤t.pos.y, home.pos.y + 50.0f, 10.0f);
|
|
|
|
if (mRetentionBeforeStretchTimer == 2) {
|
|
if (mReadyNewAction) {
|
|
cXyz position(current.pos.x, daPy_getPlayerActorClass()->current.pos.y,
|
|
current.pos.z);
|
|
|
|
daPy_getPlayerActorClass()->setPlayerPosAndAngle(
|
|
&position, daPy_getPlayerActorClass()->shape_angle.y, 0);
|
|
dComIfGp_event_reset();
|
|
mReadyNewAction = false;
|
|
}
|
|
} else if (mRetentionBeforeStretchTimer == 1) {
|
|
mSetModelAnmMtx = false;
|
|
|
|
if (field_0x6e9 & 1) {
|
|
daPy_getPlayerActorClass()->setThrowDamage(shape_angle.y, 35.0f, 73.0f, 1, 0, 0);
|
|
mCameraOnTimer = l_HIO.camera_on_timer + 1.0f;
|
|
} else if (field_0x6e9 & 2) {
|
|
if (mpCarryActor != NULL) {
|
|
fopAcM_SetSpeedF(mpCarryActor, 35.0f);
|
|
speed = fopAcM_GetSpeed(mpCarryActor);
|
|
fopAcM_SetSpeed(mpCarryActor, speed.x, 73.0f, speed.y);
|
|
mpCarryActor->shape_angle.y = shape_angle.y;
|
|
mpCarryActor->current.angle.y = shape_angle.y;
|
|
mpCarryActor->mode_init_drop(0);
|
|
mpCarryActor = NULL;
|
|
}
|
|
} else if (field_0x6e9 & 4) {
|
|
if (mpBombActor != NULL && !mpBombActor->checkStateExplode()) {
|
|
fopAcM_SetSpeedF(mpBombActor, 35.0f);
|
|
speed = fopAcM_GetSpeed(mpBombActor);
|
|
fopAcM_SetSpeed(mpBombActor, speed.x, 73.0f, speed.y);
|
|
mpBombActor->shape_angle.y = shape_angle.y;
|
|
mpBombActor->current.angle.y = shape_angle.y;
|
|
mpBombActor = NULL;
|
|
}
|
|
}
|
|
field_0x6e9 = 0;
|
|
setActionMode(ACTION_ATTACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeAttack() {
|
|
static u16 d_HZ_JUMP_EFFECT_ID[2] = {
|
|
dPa_RM(ID_ZM_S_HAZIKIAPPEAR00),
|
|
dPa_RM(ID_ZM_S_HAZIKIAPPEAR01),
|
|
};
|
|
cXyz position;
|
|
switch (mMode) {
|
|
case 0:
|
|
current.pos = home.pos;
|
|
setTgSetBit(1);
|
|
mSpheres[1].OnTgShield();
|
|
mSpheres[2].OnTgShield();
|
|
mSpheres[1].SetTgHitMark(CcG_Tg_UNK_MARK_2);
|
|
mSpheres[2].SetTgHitMark(CcG_Tg_UNK_MARK_2);
|
|
mMode = 1;
|
|
setBck(0xD, 0, 3.0f, l_HIO.stretch_anim_speed);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_JUMP, -1);
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_JUMP, 0, -1);
|
|
break;
|
|
|
|
case 1:
|
|
MtxP anmMtx = mpMorfSO->getModel()->getAnmMtx(1);
|
|
position.set(anmMtx[0][3], anmMtx[1][3], anmMtx[2][3]);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
mJumpEffects[i] =
|
|
dComIfGp_particle_set(mJumpEffects[i], d_HZ_JUMP_EFFECT_ID[i], &position, &tevStr,
|
|
&shape_angle, NULL, 0xff, NULL, -1, NULL, NULL, NULL);
|
|
}
|
|
|
|
if (mpMorfSO->checkFrame(8.0f)) {
|
|
mpMorfSO->setPlaySpeed(1.0f);
|
|
} else if (mpMorfSO->checkFrame(38.0f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_LAUGH, -1);
|
|
}
|
|
|
|
if (!daPy_getPlayerActorClass()->checkThrowDamage()) {
|
|
if (mpMorfSO->getFrame() > 60.0f && mpMorfSO->getFrame() < 100.0f && checkHideStart()) {
|
|
mpMorfSO->setFrame(100.0f);
|
|
}
|
|
}
|
|
|
|
if (mpMorfSO->isStop()) {
|
|
setCloseSmokeEffect();
|
|
mAttackCooldownTimer = 20;
|
|
setActionMode(ACTION_HIDE);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (!daPy_getPlayerActorClass()->checkThrowDamage() &&
|
|
dCam_getBody()->GetForceLockOnActor() == this && mCameraOffTimer == 0)
|
|
{
|
|
mCameraOffTimer = l_HIO.camera_off_timer + 1.0f;
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::initBackWalk() {
|
|
cXyz position;
|
|
cXyz start;
|
|
cXyz end;
|
|
|
|
speedF = speed.y = 0.0f;
|
|
setTgSetBit(1);
|
|
mSpheres[0].OnTgSetBit();
|
|
mSpheres[0].SetTgType(0x10000);
|
|
|
|
if ((current.pos - home.pos).absXZ() < 300.0f) {
|
|
setBck(0x11, 2, 5.0f, 1.5f);
|
|
mMode = 3;
|
|
} else {
|
|
setBck(0x11, 2, 5.0f, 1.5f);
|
|
mMode = 2;
|
|
|
|
s16 targetAngleY = cLib_targetAngleY(&home.pos, ¤t.pos);
|
|
s16 modifiedTargetAngleY = (targetAngleY + 0x2000) & 0xC000;
|
|
position.set(0.0f, 0.0f, 300.0f);
|
|
cLib_offsetPos(&field_0x678, &home.pos, modifiedTargetAngleY, &position);
|
|
dBgS_LinChk linChk;
|
|
position.set(0.0f, 100.0f, 0.0f);
|
|
start = current.pos + position;
|
|
end = field_0x678 + position;
|
|
linChk.Set(&start, &end, NULL);
|
|
|
|
if (dComIfG_Bgsp().LineCross(&linChk)) {
|
|
if (modifiedTargetAngleY & 0x4000) {
|
|
targetAngleY = (s16)(targetAngleY + 0x4000 & 0x8000);
|
|
} else {
|
|
targetAngleY = (s16)((targetAngleY & 0x8000) + 0x4000);
|
|
}
|
|
cLib_offsetPos(&field_0x678, &home.pos, targetAngleY, &position);
|
|
}
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeAway() {
|
|
f32 diff;
|
|
switch (mMode) {
|
|
case 0:
|
|
gravity = 0.0f;
|
|
speed.y = 0.0f;
|
|
mSpheres[0].OffTgSetBit();
|
|
shape_angle.x = shape_angle.z = 0;
|
|
setBck(0xF, 0, 10.0f, 1.0f);
|
|
field_0x6e4 = 1;
|
|
mMode = 1;
|
|
field_0x6cc = 0;
|
|
field_0x6ea = 0;
|
|
break;
|
|
|
|
case 1:
|
|
if (mpMorfSO->checkFrame(4.0f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_STAND, -1);
|
|
} else if (mpMorfSO->checkFrame(20.0f)) {
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_SWING, 0, -1);
|
|
}
|
|
|
|
speedF = 0.0f;
|
|
if (field_0x6ea == 0) {
|
|
if (mpMorfSO->getFrame() >= 35.0f) {
|
|
gravity = -5.0f;
|
|
if (mObjAcch.ChkGroundHit()) {
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_M, 0, -1);
|
|
field_0x6ea++;
|
|
} else {
|
|
if (speed.y > -20.0f) {
|
|
speed.y = -20.0f;
|
|
}
|
|
mpMorfSO->setFrame(35.0f);
|
|
}
|
|
} else if (mpMorfSO->getFrame() >= 23.0f) {
|
|
speedF = 10.0f;
|
|
}
|
|
} else if (mObjAcch.ChkGroundHit()) {
|
|
if (mpMorfSO->isStop()) {
|
|
initBackWalk();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
diff = (current.pos - field_0x678).absXZ();
|
|
cLib_chaseAngleS(&shape_angle.y, cLib_targetAngleY(¤t.pos, &field_0x678),
|
|
diff < 500.0f ? (s16)0x800 : (s16)0x200);
|
|
cLib_chaseF(&speedF, l_HIO.escape_speed, 1.0f);
|
|
|
|
if (diff < 300.0f) {
|
|
speedF = 0.0f;
|
|
if (!cLib_addCalcPosXZ(¤t.pos, field_0x678, 1.0f, l_HIO.escape_speed, 5.0f)) {
|
|
mMode = 3;
|
|
}
|
|
if (mObjAcch.ChkWallHit()) {
|
|
field_0x6cc++;
|
|
if (field_0x6cc >= 30) {
|
|
mMode = 3;
|
|
}
|
|
} else {
|
|
field_0x6cc = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if (cLib_chaseAngleS(&shape_angle.y, cLib_targetAngleY(¤t.pos, &home.pos), 0x400)) {
|
|
setBck(5, 0, 5.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_WALK, -1);
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_WALK, 0, -1);
|
|
mMode = 4;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if (mpMorfSO->checkFrame(4.0f)) {
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_WALK, 0, -1);
|
|
} else if (mpMorfSO->checkFrame(10.0f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_BACK, -1);
|
|
} else if (mpMorfSO->checkFrame(14.0f)) {
|
|
speed.y = 0.0f;
|
|
speedF = 0.0f;
|
|
mMode = 5;
|
|
field_0x6e4 = 0;
|
|
setTgSetBit(0);
|
|
mSpheres[0].OffTgSetBit();
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_SWING, 0, -1);
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
mDisableShadow = true;
|
|
if (mpMorfSO->checkFrame(28.0f)) {
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_BACK, 0, -1);
|
|
}
|
|
if (current.pos.y <= home.pos.y) {
|
|
current.pos.y = home.pos.y;
|
|
speed.y = 0.0f;
|
|
}
|
|
cLib_addCalcPosXZ(¤t.pos, home.pos, 1.0f, 20.0f, 5.0f);
|
|
if (home.pos == current.pos) {
|
|
if (mpMorfSO->isStop()) {
|
|
setCloseSmokeEffect();
|
|
shape_angle.y = (s16)(shape_angle.y + 0x2000) & 0xC000;
|
|
gravity = 0.0f;
|
|
setActionMode(ACTION_HIDE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (checkBck(0x11)) {
|
|
if (mpMorfSO->checkFrame(0.0f)) {
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_WALK, 0, -1);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_WALK, -1);
|
|
} else if (mpMorfSO->checkFrame(15.0f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_WALK, -1);
|
|
}
|
|
}
|
|
current.angle.y = shape_angle.y;
|
|
}
|
|
|
|
void daE_HZ_c::setWindEnd() {
|
|
speed.y = 20.0f;
|
|
field_0x6b2 = 0x1000;
|
|
|
|
if (std::abs(fopAcM_searchPlayerDistanceY(this)) >= 300.0f) {
|
|
mWaitTimer = 5;
|
|
} else {
|
|
mWaitTimer = 10;
|
|
}
|
|
mMode = 4;
|
|
field_0x6e4 = 1;
|
|
gravity = -5.0f;
|
|
}
|
|
|
|
void daE_HZ_c::executeWind() {
|
|
cXyz position;
|
|
cXyz position2;
|
|
dBgS_GndChk gndChk;
|
|
dBgS_LinChk linChk;
|
|
BOOL bVar = false;
|
|
f32 deltaY;
|
|
f32 frame = mpMorfSO->getFrame();
|
|
f32 playerDist;
|
|
f32 groundCross;
|
|
mpBoomerangActor = daPy_py_c::getThrowBoomerangActor();
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
speed.y = speedF = gravity = 0.0f;
|
|
mSpheres[0].OffTgSetBit();
|
|
setBck(0x13, 0, 0.0f, 1.0f);
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_WIND, 0, -1);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_WIND_NAKU, -1);
|
|
speedF = speed.y = 0.0f;
|
|
mMode = 1;
|
|
field_0x6e4 = 0;
|
|
|
|
playerDist = fopAcM_searchPlayerDistance(this);
|
|
if (playerDist >= 1000.0f) {
|
|
playerDist = 1000.0f;
|
|
}
|
|
if (playerDist < 100.0f) {
|
|
playerDist = 100.0f;
|
|
}
|
|
|
|
field_0x6cc = (s16)((playerDist * 15.0f) / 1000.0f);
|
|
/* fallthrough */
|
|
case 1:
|
|
deltaY = 6.0f - frame / 3.0f;
|
|
if (deltaY < 0.0f) {
|
|
deltaY = 0.0f;
|
|
}
|
|
|
|
current.pos.y += deltaY;
|
|
ANGLE_SUB(shape_angle.y, 0x7D0);
|
|
|
|
if (mpMorfSO->checkFrame(field_0x6cc) || mpBoomerangActor == NULL ||
|
|
mpBoomerangActor->getReturnFlg())
|
|
{
|
|
bVar = true;
|
|
}
|
|
|
|
if (bVar) {
|
|
mpMorfSO->setFrame(15.0f);
|
|
mMode = 2;
|
|
field_0x6a8 = 60.0f;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
current.pos.y += field_0x6a8;
|
|
if (current.pos.y - home.pos.y >= 300.0f) {
|
|
if (frame < 23.0f) {
|
|
mpMorfSO->setFrame(23.0f);
|
|
}
|
|
|
|
if (mpBoomerangActor == NULL) {
|
|
setWindEnd();
|
|
} else {
|
|
position = mpBoomerangActor->current.pos;
|
|
|
|
if (current.pos.y - home.pos.y >= 400.0f) {
|
|
if (cLib_chaseF(&field_0x6a8, 0.0f, 10.0f)) {
|
|
bVar = true;
|
|
}
|
|
|
|
if (mpBoomerangActor->getReturnFlg() &&
|
|
fopAcM_searchPlayerDistance(mpBoomerangActor) < 500.0f)
|
|
{
|
|
bVar = true;
|
|
}
|
|
}
|
|
|
|
if (bVar) {
|
|
mMode = 3;
|
|
field_0x6e4 = 1;
|
|
speed.y = 0.0f;
|
|
position2 = position - current.pos;
|
|
field_0x6b2 = cLib_targetAngleY(¤t.pos, &position);
|
|
field_0x678.x = position2.absXZ();
|
|
field_0x678.y = position2.y;
|
|
field_0x678.z = 8192.0f;
|
|
field_0x6b4 = 0x800;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if (mpBoomerangActor == NULL) {
|
|
setWindEnd();
|
|
return;
|
|
}
|
|
|
|
position = mpBoomerangActor->current.pos;
|
|
if (mPlayerDist < 500.0f && mpBoomerangActor->getReturnFlg()) {
|
|
setWindEnd();
|
|
return;
|
|
}
|
|
|
|
ANGLE_ADD(field_0x6b2, 0x800);
|
|
linChk.Set(¤t.pos, &position, NULL);
|
|
if (!dComIfG_Bgsp().LineCross(&linChk)) {
|
|
cLib_chaseF(¤t.pos.x, position.x + field_0x678.x * cM_ssin(field_0x6b2), 50.0f);
|
|
cLib_chaseF(¤t.pos.z, position.z + field_0x678.x * cM_scos(field_0x6b2), 50.0f);
|
|
} else {
|
|
position.y += 10.0f;
|
|
}
|
|
|
|
cLib_chaseF(&field_0x678.x, 0.0f, 20.0f);
|
|
gndChk.SetPos(&position);
|
|
|
|
groundCross = dComIfG_Bgsp().GroundCross(&gndChk);
|
|
if (frame < 38.0f) {
|
|
if (position.y - groundCross < 500.0f) {
|
|
position.y = groundCross + 500.0f;
|
|
}
|
|
} else if (position.y - groundCross < l_HIO.y_position_wrap) {
|
|
position.y = groundCross + l_HIO.y_position_wrap;
|
|
}
|
|
|
|
cLib_chaseF(¤t.pos.y, position.y + field_0x678.y, 20.0f);
|
|
cLib_chaseF(&field_0x678.y, 0.0f, 5.0f);
|
|
cLib_chaseAngleS(&shape_angle.z, field_0x678.z * cM_scos(field_0x6b4), 0x100);
|
|
|
|
if (mpMorfSO->isStop()) {
|
|
cLib_chaseAngleS(&shape_angle.x, -0x8000, 0x400);
|
|
}
|
|
|
|
ANGLE_SUB(shape_angle.y, l_HIO.reeling_rotation_speed);
|
|
break;
|
|
|
|
case 4:
|
|
cLib_chaseAngleS(&shape_angle.x, -0x8000, 0x800);
|
|
cLib_chaseAngleS(&shape_angle.z, field_0x678.z * cM_scos(field_0x6b4), 0x100);
|
|
cLib_chaseF(&field_0x678.z, 0.0f, 512.0f);
|
|
|
|
if (mWaitTimer != 0) {
|
|
speed.y = 20.0f;
|
|
} else if (mObjAcch.ChkGroundHit()) {
|
|
setTgSetBit(1);
|
|
mPiyoriTimer = l_HIO.piyori_time;
|
|
setBck(0xE, 0, 0.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_LANDING, -1);
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_LANDING, 0, -1);
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_M, 0, -1);
|
|
shape_angle.x = 0;
|
|
speed.y = 15.0f;
|
|
mMode = 5;
|
|
}
|
|
|
|
shape_angle.y -= field_0x6b2;
|
|
break;
|
|
|
|
case 5:
|
|
if (field_0x6b2 > 0x400) {
|
|
mSound.startCreatureSoundLevel(Z2SE_EN_HZ_SLIDE, 0, -1);
|
|
}
|
|
cLib_chaseAngleS(&shape_angle.z, field_0x678.z * cM_scos(field_0x6b4), 0x100);
|
|
cLib_chaseF(&field_0x678.z, 0.0f, 512.0f);
|
|
if (mpMorfSO->checkFrame(13.0f)) {
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1);
|
|
}
|
|
if (mObjAcch.ChkGroundHit()) {
|
|
cLib_chaseAngleS(&field_0x6b2, 0, 0x100);
|
|
if (field_0x6b2 == 0) {
|
|
if (mpMorfSO->isStop()) {
|
|
setActionMode(ACTION_CHANCE);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
shape_angle.y -= field_0x6b2;
|
|
break;
|
|
}
|
|
|
|
if (checkBck(dRes_ID_E_HZ_BCK_HZ_WIND_e) && mpMorfSO->checkFrame(25.0f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_WIND, -1);
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeChance() {
|
|
switch (mMode) {
|
|
case 0:
|
|
gravity = -5.0f;
|
|
field_0x6e4 = 1;
|
|
setBck(dRes_ID_E_HZ_BCK_HZ_FAINT_e, J3DFrameCtrl::EMode_LOOP, 3.0f, 1.0f);
|
|
setTgSetBit(1);
|
|
mSpheres[0].OnTgSetBit();
|
|
mSpheres[0].SetTgType(0x10000);
|
|
mMode = 1;
|
|
shape_angle.x = shape_angle.z = 0;
|
|
speedF = 0.0f;
|
|
/* fallthrough */
|
|
|
|
case 1:
|
|
if (mpMorfSO->checkFrame(0.0f)) {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_FAINT, -1);
|
|
}
|
|
if (mPiyoriTimer == 0) {
|
|
setTgSetBit(0);
|
|
setActionMode(ACTION_AWAY);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::initRollDamage() {
|
|
current.angle.y = mAtInfo.mHitDirection.y + 0x8000;
|
|
shape_angle.x = shape_angle.z = 0;
|
|
|
|
if (mAction == ACTION_DEATH) {
|
|
if (field_0x6cc == 0) {
|
|
speedF = 20.0f;
|
|
field_0x6b6 = 0x1000;
|
|
return;
|
|
}
|
|
|
|
if (field_0x6cc == 1) {
|
|
speedF = 35.0f;
|
|
field_0x6b6 = 0x1400;
|
|
return;
|
|
}
|
|
|
|
if (field_0x6cc == 2) {
|
|
speedF = 20.0f;
|
|
field_0x6b6 = 0;
|
|
return;
|
|
}
|
|
|
|
speedF = 30.0f;
|
|
field_0x6b6 = 0x800;
|
|
} else {
|
|
if (field_0x6cc == 0) {
|
|
speedF = 10.0f;
|
|
field_0x6b6 = 0;
|
|
return;
|
|
}
|
|
|
|
if (field_0x6cc == 1) {
|
|
speedF = 30.0f;
|
|
field_0x6b6 = 0x1000;
|
|
return;
|
|
}
|
|
|
|
speedF = 20.0f;
|
|
field_0x6b6 = 0;
|
|
}
|
|
}
|
|
|
|
bool daE_HZ_c::doRollDamage() {
|
|
shape_angle.y += field_0x6b6;
|
|
|
|
if (mObjAcch.ChkGroundHit()) {
|
|
if (speedF >= 3.0f) {
|
|
fopAcM_effSmokeSet2(&mSmokeKey, &mSmokeKey2, ¤t.pos, NULL, 1.5f, &tevStr);
|
|
}
|
|
|
|
cLib_chaseF(&speedF, 0.0f, 1.0f);
|
|
cLib_chaseAngleS(&field_0x6b6, 0, 0x80);
|
|
if (!speedF && field_0x6b6 == 0 && mpMorfSO->isStop()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void daE_HZ_c::executeDamage() {
|
|
switch (mMode) {
|
|
case 0:
|
|
gravity = -5.0f;
|
|
mSpheres[0].OffTgSetBit();
|
|
field_0x6e4 = 1;
|
|
initRollDamage();
|
|
if (mPrevAction == 3) {
|
|
mMode = 2;
|
|
setBck(dRes_ID_E_HZ_BCK_HZ_WALK_D_R_e, J3DFrameCtrl::EMode_NONE, 5.0f, 1.0f);
|
|
} else {
|
|
mMode = 1;
|
|
setBck(dRes_ID_E_HZ_BCK_HZ_DAMAGE_e, J3DFrameCtrl::EMode_NONE, 5.0f, 1.0f);
|
|
}
|
|
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DAMAGE, -1);
|
|
mpMorfSO->setFrame(0.0f);
|
|
break;
|
|
|
|
case 1:
|
|
if (speedF > 2.0f) {
|
|
mSound.startCreatureSoundLevel(Z2SE_EN_HZ_SLIDE, 0, -1);
|
|
}
|
|
|
|
if (mpMorfSO->checkFrame(28.0f)) {
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_S, 0, -1);
|
|
}
|
|
|
|
if (doRollDamage()) {
|
|
setActionMode(ACTION_CHANCE);
|
|
break;
|
|
}
|
|
|
|
if (mPiyoriTimer == 0 && !speedF) {
|
|
speedF = 0.0f;
|
|
setTgSetBit(0);
|
|
setActionMode(ACTION_AWAY);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (doRollDamage()) {
|
|
setActionMode(ACTION_AWAY);
|
|
mMode = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeDeath() {
|
|
mDamageDeathTimer = 10;
|
|
field_0x566 = 0;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
if (mpBgW != NULL) {
|
|
dComIfG_Bgsp().Release(mpBgW);
|
|
mpBgW = NULL;
|
|
}
|
|
gravity = -5.0f;
|
|
mSpheres[0].OffTgSetBit();
|
|
setTgSetBit(0);
|
|
field_0x6e4 = 1;
|
|
mMode = 1;
|
|
|
|
if (field_0x6cc >= 2) {
|
|
setBck(8, 0, 5.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DEATH_STAND, -1);
|
|
} else {
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DEATH, -1);
|
|
if (mPrevAction == 7) {
|
|
setBck(7, 0, 5.0f, 1.0f);
|
|
} else if (mPrevAction == 3) {
|
|
setBck(7, 0, 10.0f, 1.0f);
|
|
} else {
|
|
setBck(7, 0, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
initRollDamage();
|
|
/* fallthrough */
|
|
|
|
case 1:
|
|
if (checkBck(7)) {
|
|
if (mpMorfSO->checkFrame(41.5f)) {
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_M, 0, -1);
|
|
}
|
|
if (speedF > 2.0f) {
|
|
mSound.startCreatureSoundLevel(Z2SE_EN_HZ_SLIDE, 0, -1);
|
|
}
|
|
if (mpMorfSO->checkFrame(35.0f)) {
|
|
mReadyChangeColor = 1;
|
|
}
|
|
} else {
|
|
if (mpMorfSO->isStop()) {
|
|
mReadyChangeColor = 1;
|
|
}
|
|
}
|
|
if (doRollDamage()) {
|
|
mMode = 2;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (mpMorfSO->isStop()) {
|
|
fopAcM_createDisappear(this, ¤t.pos, 10, 0, 5);
|
|
setActionMode(0xB);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (mReadyChangeColor != 0) {
|
|
cLib_addCalc2(&mColor, -20.0f, 1.0f, 0.4f);
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::setWindChanceEnd() {
|
|
mWaitTimer = 30;
|
|
mMode = 2;
|
|
field_0x6b6 = 0x1800;
|
|
}
|
|
|
|
void daE_HZ_c::executeWindChance() {
|
|
cXyz end;
|
|
cXyz start;
|
|
dBgS_LinChk linChk;
|
|
|
|
mpBoomerangActor = daPy_py_c::getThrowBoomerangActor();
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
setTgSetBit(0);
|
|
mSpheres[0].OffTgSetBit();
|
|
setBck(0xB, 2, 3.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_FAINT, -1);
|
|
mMode = 1;
|
|
field_0x6b6 = 0;
|
|
field_0x6b2 = l_HIO.reeling_rotation_speed;
|
|
field_0x6b4 = 0;
|
|
/* fallthrough */
|
|
case 1:
|
|
if (mpBoomerangActor == NULL) {
|
|
setWindChanceEnd();
|
|
return;
|
|
}
|
|
|
|
end = mpBoomerangActor->current.pos;
|
|
ANGLE_ADD(field_0x6b6, 0x800);
|
|
start = current.pos;
|
|
start.y += 50.0f;
|
|
linChk.Set(&start, &end, NULL);
|
|
|
|
if (dComIfG_Bgsp().LineCross(&linChk)) {
|
|
setWindChanceEnd();
|
|
return;
|
|
}
|
|
|
|
cLib_chaseF(¤t.pos.x, end.x + field_0x678.x * cM_ssin(field_0x6b6), 30.0f);
|
|
cLib_chaseF(¤t.pos.z, end.z + field_0x678.x * cM_scos(field_0x6b6), 30.0f);
|
|
cLib_chaseF(&field_0x678.x, 0.0f, 20.0f);
|
|
|
|
if (mObjAcch.ChkGroundHit()) {
|
|
speed.y = 20.0f;
|
|
}
|
|
|
|
shape_angle.y -= field_0x6b2;
|
|
ANGLE_ADD(field_0x6b4, 0x1000);
|
|
shape_angle.x = (s16)(cM_scos(field_0x6b4) * 6144.0f);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
case 2:
|
|
cLib_chaseAngleS(&field_0x6b2, 0, 0x100);
|
|
cLib_chaseAngleS(&field_0x6b6, 0, 0x200);
|
|
shape_angle.y -= field_0x6b2;
|
|
ANGLE_ADD(field_0x6b4, 0x1000);
|
|
shape_angle.x = (s16)(field_0x6b6 * cM_scos(field_0x6b4));
|
|
|
|
if (mWaitTimer == 0) {
|
|
if (mPiyoriTimer != 0) {
|
|
S16_ADD(mPiyoriTimer, 20);
|
|
}
|
|
|
|
setActionMode(ACTION_CHANCE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeWindWalk() {
|
|
switch (mMode) {
|
|
case 0:
|
|
setTgSetBit(0);
|
|
mSpheres[0].OffTgSetBit();
|
|
setBck(0xC, 0, 3.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_GALE, -1);
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_WALK, 0, -1);
|
|
mMode = 1;
|
|
speedF = 0.0f;
|
|
/* fallthrough */
|
|
|
|
case 1:
|
|
if (mpMorfSO->checkFrame(14.0f) || mpMorfSO->checkFrame(24.0f)) {
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_WALK, 0, -1);
|
|
}
|
|
if (mpMorfSO->isStop()) {
|
|
setActionMode(ACTION_AWAY);
|
|
initBackWalk();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::setWaterEffect() {
|
|
cXyz position(current.pos.x, mGroundCross, current.pos.z);
|
|
static cXyz sc(2.0f, 2.0f, 2.0f);
|
|
static u16 w_eff_id[4] = {
|
|
ID_ZI_J_DOWNWTRA_A,
|
|
ID_ZI_J_DOWNWTRA_B,
|
|
ID_ZI_J_DOWNWTRA_C,
|
|
ID_ZI_J_DOWNWTRA_D,
|
|
};
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
mWaterEffects[i] = dComIfGp_particle_set(mWaterEffects[i], w_eff_id[i], &position, &tevStr,
|
|
0, &sc, 0xFF, NULL, -1, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeWaterDeath() {
|
|
field_0x566 = 0;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
speedF = gravity = 0.0f;
|
|
mMode = 1;
|
|
setWaterEffect();
|
|
mSound.startCreatureSound(Z2SE_CM_BODYFALL_WATER_L, 0, -1);
|
|
if (checkBck(0x13)) {
|
|
setBck(0xA, 0, 0.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DROWNED_B, -1);
|
|
} else if (checkBck(5) || checkBck(0xC) || checkBck(0xF) || checkBck(0x11) ||
|
|
checkBck(0x12))
|
|
{
|
|
setBck(9, 0, 3.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DROWNED_A, -1);
|
|
} else {
|
|
setBck(0xA, 0, 3.0f, 1.0f);
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DROWNED_B, -1);
|
|
}
|
|
/* fallthrough */
|
|
case 1:
|
|
cLib_chaseF(&speed.y, 5.0f, 10.0f);
|
|
cLib_chaseAngleS(&shape_angle.x, 0, 0x800);
|
|
cLib_chaseAngleS(&shape_angle.z, 0, 0x800);
|
|
if (mpMorfSO->checkFrame(10.0f) || mpMorfSO->checkFrame(20.0f) ||
|
|
mpMorfSO->checkFrame(36.0f) || mpMorfSO->checkFrame(57.0f))
|
|
{
|
|
setWaterEffect();
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_DROWNSPLASH, 0, -1);
|
|
}
|
|
if (speed.y > 0.0f) {
|
|
if (current.pos.y + 100.0f > mGroundCross) {
|
|
current.pos.y = mGroundCross - 100.0f;
|
|
mMode = 2;
|
|
speed.y = 0.0f;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (mpMorfSO->checkFrame(10.0f) || mpMorfSO->checkFrame(20.0f) ||
|
|
mpMorfSO->checkFrame(36.0f) || mpMorfSO->checkFrame(57.0f))
|
|
{
|
|
setWaterEffect();
|
|
mSound.startCreatureSound(Z2SE_EN_HZ_DROWNSPLASH, 0, -1);
|
|
}
|
|
if (mpMorfSO->isStop()) {
|
|
cXyz position;
|
|
|
|
mDoMtx_stack_c::copy(mpMorfSO->getModel()->getAnmMtx(0x12));
|
|
mDoMtx_stack_c::multVecZero(&position);
|
|
fopAcM_createDisappear(this, &position, 10, 0, 5);
|
|
setActionMode(0xB);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (current.pos.y + 150.0f < mGroundCross && mGroundCross < current.pos.y + 50.0f) {
|
|
cXyz position(current.pos.x, mGroundCross, current.pos.z);
|
|
|
|
fopAcM_effHamonSet(&mEffect, &position, 1.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::executeDeathWait() {
|
|
field_0x566 = 0;
|
|
|
|
switch (mMode) {
|
|
case 0:
|
|
dComIfGs_onSwitch(mParam, fopAcM_GetRoomNo(this));
|
|
mSound.deleteObject();
|
|
field_0x6e8 = 1;
|
|
attention_info.flags = 0;
|
|
attention_info.position = eyePos = current.pos = home.pos;
|
|
fopAcM_SetGroup(this, 0);
|
|
mMode = 3;
|
|
break;
|
|
|
|
case 1:
|
|
mSound.deleteObject();
|
|
field_0x6e8 = 1;
|
|
attention_info.flags = 0;
|
|
attention_info.position = eyePos = current.pos = home.pos;
|
|
fopAcM_SetGroup(this, 0);
|
|
mMode = 4;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::damage_check() {
|
|
s16 targetAngleY;
|
|
|
|
if (mAction != 1 || mMode < 4) {
|
|
if (mSpheres[0].ChkTgHit() && mSpheres[0].GetTgHitObj()->ChkAtType(AT_TYPE_BOOMERANG)) {
|
|
mSpheres[0].ClrTgHit();
|
|
if (mAction == ACTION_CHANCE) {
|
|
setActionMode(ACTION_WIND_CHANCE);
|
|
} else if (mAction == ACTION_AWAY) {
|
|
setActionMode(ACTION_WIND_WALK);
|
|
} else {
|
|
setActionMode(ACTION_WIND);
|
|
}
|
|
setTgSetBit(0);
|
|
mDamageDeathTimer = 10;
|
|
} else if (mDamageDeathTimer == 0) {
|
|
mStts.Move();
|
|
cXyz player_pos(daPy_getPlayerActorClass()->current.pos);
|
|
|
|
s32 bVar = 0;
|
|
|
|
for (int i = 1; i <= 2; i++) {
|
|
if (mSpheres[i].ChkTgHit()) {
|
|
mAtInfo.mpCollider = mSpheres[i].GetTgHitObj();
|
|
|
|
if (mAction == ACTION_ATTACK) {
|
|
mAtInfo.field_0x18 = 0x2a;
|
|
mAtInfo.mpCollider->SetAtAtp(0);
|
|
} else {
|
|
mAtInfo.field_0x18 = 0;
|
|
}
|
|
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_SLINGSHOT)) {
|
|
mSound.startCreatureSound(Z2SE_HIT_PACHINKO, 0x2D, -1);
|
|
return;
|
|
}
|
|
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_IRON_BALL)) {
|
|
bVar = true;
|
|
health = 0;
|
|
}
|
|
|
|
cc_at_check(this, &mAtInfo);
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_UNK)) {
|
|
mDamageDeathTimer = 0x14;
|
|
} else if (cc_pl_cut_bit_get() == 0x80) {
|
|
mDamageDeathTimer = 0x14;
|
|
} else {
|
|
mDamageDeathTimer = 10;
|
|
}
|
|
|
|
if (mAtInfo.mAttackPower <= 1) {
|
|
mDamageDeathTimer = KREG_S(8) + 10;
|
|
}
|
|
|
|
mSpheres[1].ClrTgHit();
|
|
mSpheres[2].ClrTgHit();
|
|
mSpheres[3].ClrTgHit();
|
|
|
|
if (mAction == ACTION_ATTACK) {
|
|
setActionMode(ACTION_HIDE);
|
|
return;
|
|
}
|
|
|
|
if (daPy_getPlayerActorClass()->getCutCount() >= 4 ||
|
|
((dCcD_GObjInf*)mAtInfo.mpCollider)->GetAtSpl() == 1)
|
|
{
|
|
bVar = true;
|
|
}
|
|
|
|
if (health < 1) {
|
|
field_0x6cc = 0;
|
|
if (bVar) {
|
|
field_0x6cc = 1;
|
|
}
|
|
|
|
if (mAction == ACTION_AWAY) {
|
|
field_0x6cc += 2;
|
|
}
|
|
|
|
setActionMode(ACTION_DEATH);
|
|
} else {
|
|
if (mAction == ACTION_AWAY) {
|
|
if (bVar) {
|
|
field_0x6cc = 1;
|
|
setActionMode(ACTION_DAMAGE);
|
|
return;
|
|
}
|
|
|
|
targetAngleY = cLib_targetAngleY(&mSpheres[1].GetCoCP(), &player_pos);
|
|
targetAngleY = (s16)(targetAngleY - shape_angle.y);
|
|
if (i == 1) {
|
|
if (abs(targetAngleY) >= 0x4000) {
|
|
if (bVar) {
|
|
mBackbone1YZRot.z = 0x5000;
|
|
mBackbone2YZRot.z = -0x4000;
|
|
mBackbone3YZRot.z = 0;
|
|
} else {
|
|
mBackbone1YZRot.z = 0x3000;
|
|
}
|
|
|
|
} else if (bVar) {
|
|
mBackbone1YZRot.z = -0x3000;
|
|
mBackbone2YZRot.z = -0x2000;
|
|
mBackbone3YZRot.z = -0x1000;
|
|
} else {
|
|
mBackbone1YZRot.z = -0x2000;
|
|
mBackbone2YZRot.z = -0x1000;
|
|
mBackbone3YZRot.z = -0x800;
|
|
}
|
|
speedF = 0.0f;
|
|
} else if (bVar) {
|
|
mBackbone1YZRot.z = 0x5000;
|
|
mBackbone2YZRot.z = -0x4000;
|
|
mBackbone3YZRot.z = 0;
|
|
} else {
|
|
mBackbone1YZRot.z = 0x3000;
|
|
}
|
|
|
|
if (targetAngleY < -0x2800) {
|
|
targetAngleY = -0x2800;
|
|
}
|
|
|
|
if (targetAngleY > 0x2800) {
|
|
targetAngleY = 0x2800;
|
|
}
|
|
|
|
mBackbone1YZRot.y = targetAngleY;
|
|
mSound.startCreatureVoice(Z2SE_EN_HZ_V_DAMAGE, -1);
|
|
return;
|
|
}
|
|
|
|
if (bVar) {
|
|
field_0x6cc = 1;
|
|
} else {
|
|
field_0x6cc = 0;
|
|
if (mAtInfo.mpCollider->ChkAtType(AT_TYPE_SHIELD_ATTACK)) {
|
|
field_0x6cc = 2;
|
|
}
|
|
}
|
|
|
|
setActionMode(ACTION_DAMAGE);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool daE_HZ_c::checkWaterSurface() {
|
|
dBgS_ObjGndChk_Spl spline;
|
|
|
|
Vec modified_pos;
|
|
modified_pos = current.pos;
|
|
modified_pos.y += 500.0f;
|
|
spline.SetPos(&modified_pos);
|
|
mGroundCross = dComIfG_Bgsp().GroundCross(&spline);
|
|
|
|
if (speed.y < 0.0f && mGroundCross > current.pos.y + 100.0f) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void daE_HZ_c::action() {
|
|
cXyz unused;
|
|
cXyz unused2;
|
|
|
|
mPlayerDist = fopAcM_searchPlayerDistance(this);
|
|
mPlayerAngleY = fopAcM_searchPlayerAngleY(this);
|
|
damage_check();
|
|
|
|
if (mAction != 10 && checkWaterSurface()) {
|
|
setActionMode(ACTION_WATER_DEATH);
|
|
}
|
|
|
|
attention_info.flags = fopAc_AttnFlag_BATTLE_e;
|
|
field_0x566 = 1;
|
|
|
|
switch (mAction) {
|
|
case ACTION_WAIT:
|
|
executeWait();
|
|
break;
|
|
|
|
case ACTION_HIDE:
|
|
attention_info.flags = 0;
|
|
executeHide();
|
|
break;
|
|
|
|
case ACTION_ATTACK:
|
|
executeAttack();
|
|
break;
|
|
|
|
case ACTION_AWAY:
|
|
executeAway();
|
|
break;
|
|
|
|
case ACTION_WIND:
|
|
executeWind();
|
|
break;
|
|
|
|
case ACTION_DAMAGE:
|
|
executeDamage();
|
|
break;
|
|
|
|
case ACTION_DEATH:
|
|
attention_info.flags = 0;
|
|
executeDeath();
|
|
break;
|
|
|
|
case ACTION_CHANCE:
|
|
executeChance();
|
|
break;
|
|
|
|
case ACTION_WIND_CHANCE:
|
|
executeWindChance();
|
|
break;
|
|
|
|
case ACTION_WIND_WALK:
|
|
executeWindWalk();
|
|
break;
|
|
|
|
case ACTION_WATER_DEATH:
|
|
attention_info.flags = 0;
|
|
executeWaterDeath();
|
|
break;
|
|
|
|
case ACTION_DEATH_WAIT:
|
|
attention_info.flags = 0;
|
|
executeDeathWait();
|
|
break;
|
|
}
|
|
|
|
if (mAction == ACTION_WAIT || mAction == ACTION_HIDE) {
|
|
mDisableShadow = true;
|
|
}
|
|
|
|
if (field_0x566 != 0) {
|
|
cXyz effPos;
|
|
|
|
mDoMtx_stack_c::copy(mpMorfSO->getModel()->getAnmMtx(0x12));
|
|
mDoMtx_stack_c::multVecZero(&effPos);
|
|
|
|
cXyz effSize(2.0f, 2.0f, 2.0f);
|
|
|
|
setMidnaBindEffect(this, &mSound, &effPos, &effSize);
|
|
}
|
|
|
|
checkFall();
|
|
mSound.setLinkSearch(false);
|
|
fopAcM_posMoveF(this, NULL);
|
|
|
|
if (field_0x6e4 != 0) {
|
|
mObjAcch.CrrPos(dComIfG_Bgsp());
|
|
} else {
|
|
mObjAcch.ClrGroundHit();
|
|
}
|
|
|
|
mpMorfSO->play(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this)));
|
|
}
|
|
|
|
void daE_HZ_c::mtx_set() {
|
|
mDoMtx_stack_c::transS(home.pos.x, home.pos.y - 13.0f, home.pos.z);
|
|
mpModel2->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
|
|
if (field_0x6e8 != 0) {
|
|
return;
|
|
}
|
|
|
|
mDoMtx_stack_c::transS(current.pos.x, current.pos.y, current.pos.z);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle);
|
|
mDoMtx_stack_c::scaleM(l_HIO.basic_size, l_HIO.basic_size, l_HIO.basic_size);
|
|
J3DModel* morfModel = mpMorfSO->getModel();
|
|
morfModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
mpMorfSO->modelCalc();
|
|
MtxP anmMtx = morfModel->getAnmMtx(7);
|
|
mpModel->setBaseTRMtx(anmMtx);
|
|
mSmokeEffectPosition.set(anmMtx[0][3], anmMtx[1][3], anmMtx[2][3]);
|
|
if (mSetModelAnmMtx) {
|
|
mSetModelAnmMtx = false;
|
|
mDoMtx_stack_c::copy(anmMtx);
|
|
mDoMtx_stack_c::ZrotM(-0x4000);
|
|
mDoMtx_stack_c::transM(0.0f, 14.0f, 0.0f);
|
|
cMtx_copy(mDoMtx_stack_c::get(), mMtx);
|
|
} else {
|
|
mDoMtx_stack_c::transS(home.pos);
|
|
cMtx_copy(mDoMtx_stack_c::get(), mMtx);
|
|
}
|
|
|
|
if (mpBgW != NULL) {
|
|
mpBgW->Move();
|
|
}
|
|
}
|
|
|
|
void daE_HZ_c::cc_set() {
|
|
if (field_0x6e8 != 0) {
|
|
return;
|
|
}
|
|
|
|
cXyz pos;
|
|
J3DModel* morfModel = mpMorfSO->getModel();
|
|
|
|
attention_info.position = eyePos = mSmokeEffectPosition;
|
|
attention_info.position.y += 30.0f;
|
|
|
|
MTXCopy(morfModel->getAnmMtx(7), mDoMtx_stack_c::get());
|
|
mDoMtx_stack_c::multVecZero(&pos);
|
|
mSpheres[0].SetC(pos);
|
|
mSpheres[0].SetR(80.0f);
|
|
dComIfG_Ccsp()->Set(&mSpheres[0]);
|
|
|
|
MTXCopy(morfModel->getAnmMtx(1), mDoMtx_stack_c::get());
|
|
mDoMtx_stack_c::multVecZero(&pos);
|
|
mSpheres[1].SetC(pos);
|
|
mSpheres[1].SetR(80.0f);
|
|
dComIfG_Ccsp()->Set(&mSpheres[1]);
|
|
|
|
MTXCopy(morfModel->getAnmMtx(0x12), mDoMtx_stack_c::get());
|
|
mDoMtx_stack_c::multVecZero(&pos);
|
|
mSpheres[2].SetC(pos);
|
|
mSpheres[2].SetR(80.0f);
|
|
dComIfG_Ccsp()->Set(&mSpheres[2]);
|
|
}
|
|
|
|
int daE_HZ_c::execute() {
|
|
if (field_0x6e8 != 0) {
|
|
mtx_set();
|
|
attention_info.position = eyePos = current.pos;
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (mWaitTimer != 0) {
|
|
mWaitTimer--;
|
|
}
|
|
if (mDamageDeathTimer != 0) {
|
|
mDamageDeathTimer--;
|
|
}
|
|
if (mPiyoriTimer != 0) {
|
|
mPiyoriTimer--;
|
|
}
|
|
if (mAttackStartTimer != 0) {
|
|
mAttackStartTimer--;
|
|
}
|
|
if (mRetentionBeforeStretchTimer != 0) {
|
|
mRetentionBeforeStretchTimer--;
|
|
}
|
|
if (mAttackCooldownTimer != 0) {
|
|
mAttackCooldownTimer--;
|
|
}
|
|
|
|
if (mCameraOffTimer != 0) {
|
|
mCameraOffTimer--;
|
|
if (mCameraOffTimer == 0) {
|
|
if (dCam_getBody()->GetForceLockOnActor() == this) {
|
|
dCam_getBody()->ForceLockOff(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dCam_getBody()->GetForceLockOnActor() == this &&
|
|
daPy_getPlayerActorClass()->current.pos.y < current.pos.y - 100.0f)
|
|
{
|
|
dCam_getBody()->ForceLockOff(this);
|
|
}
|
|
|
|
if (mCameraOnTimer != 0) {
|
|
mCameraOnTimer--;
|
|
if (mCameraOnTimer == 0) {
|
|
if (dCam_getBody()->GetForceLockOnActor() != this) {
|
|
dCam_getBody()->ForceLockOn(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
cLib_chaseAngleS(&mBackbone1YZRot.z, 0, 0x200);
|
|
cLib_chaseAngleS(&mBackbone1YZRot.y, 0, 0x200);
|
|
cLib_chaseAngleS(&mBackbone2YZRot.z, 0, 0x200);
|
|
cLib_chaseAngleS(&mBackbone2YZRot.y, 0, 0x200);
|
|
cLib_chaseAngleS(&mBackbone3YZRot.z, 0, 0x200);
|
|
cLib_chaseAngleS(&mBackbone3YZRot.y, 0, 0x200);
|
|
action();
|
|
mtx_set();
|
|
cc_set();
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int daE_HZ_Execute(daE_HZ_c* i_this) {
|
|
return i_this->execute();
|
|
}
|
|
|
|
static int daE_HZ_IsDelete(daE_HZ_c* i_this) {
|
|
return 1;
|
|
}
|
|
|
|
int daE_HZ_c::_delete() {
|
|
dComIfG_resDelete(&mPhaseReq, "E_HZ");
|
|
dComIfG_resDelete(&mPhaseReq2, mpName);
|
|
|
|
if (mHIOInit) {
|
|
hio_set = false;
|
|
mDoHIO_DELETE_CHILD(l_HIO.enemy_sample);
|
|
}
|
|
|
|
if (heap != NULL) {
|
|
mSound.deleteObject();
|
|
}
|
|
|
|
if (mpBgW != NULL) {
|
|
dComIfG_Bgsp().Release(mpBgW);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int daE_HZ_Delete(daE_HZ_c* i_this) {
|
|
fopAcM_RegisterDeleteID(i_this, "E_HZ");
|
|
return i_this->_delete();
|
|
}
|
|
|
|
int daE_HZ_c::ctrlJoint(J3DJoint* i_joint, J3DModel* i_model) {
|
|
J3DJoint* joint = i_joint;
|
|
int joint_no = joint->getJntNo();
|
|
|
|
mDoMtx_stack_c::copy(i_model->getAnmMtx(joint_no));
|
|
|
|
switch (joint_no) {
|
|
case HZ_JNT_BACK_BONE1_e:
|
|
mDoMtx_stack_c::ZrotM(mBackbone1YZRot.z);
|
|
mDoMtx_stack_c::YrotM(mBackbone1YZRot.y);
|
|
break;
|
|
|
|
case HZ_JNT_BACK_BONE2_e:
|
|
mDoMtx_stack_c::ZrotM(mBackbone2YZRot.z);
|
|
mDoMtx_stack_c::YrotM(mBackbone2YZRot.y);
|
|
break;
|
|
|
|
case HZ_JNT_BACK_BONE3_e:
|
|
mDoMtx_stack_c::ZrotM(mBackbone3YZRot.z);
|
|
mDoMtx_stack_c::YrotM(mBackbone3YZRot.y);
|
|
break;
|
|
}
|
|
|
|
i_model->setAnmMtx(joint_no, mDoMtx_stack_c::get());
|
|
cMtx_copy(mDoMtx_stack_c::get(), J3DSys::mCurrentMtx);
|
|
return 1;
|
|
}
|
|
|
|
int daE_HZ_c::JointCallBack(J3DJoint* i_joint, int param_1) {
|
|
if (param_1 == 0) {
|
|
J3DModel* model = j3dSys.getModel();
|
|
daE_HZ_c* a_this = (daE_HZ_c*)model->getUserArea();
|
|
if (a_this != NULL) {
|
|
a_this->ctrlJoint(i_joint, model);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int daE_HZ_c::CreateHeap() {
|
|
J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes("E_HZ", dRes_INDEX_E_HZ_BMD_HZ_e);
|
|
JUT_ASSERT(2479, modelData != NULL);
|
|
|
|
mpMorfSO = new mDoExt_McaMorfSO(modelData, NULL, NULL,
|
|
(J3DAnmTransform*)dComIfG_getObjectRes("E_HZ", dRes_INDEX_E_HZ_BCK_HZ_WAIT_e), 0, 1.0f,
|
|
0, -1, &mSound, J3DMdlFlag_DifferedDLBuffer, 0x11000084);
|
|
|
|
if (mpMorfSO == NULL || mpMorfSO->getModel() == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
// This happens to work with MWCC since the member will only ever be initialized a pointer to a
|
|
// string in this TU's .data section, but comparing against a string literal is still UB.
|
|
#if AVOID_UB
|
|
if (strcmp(mpName, "E_hzp") == 0) {
|
|
#else
|
|
if (mpName == "E_hzp") {
|
|
#endif
|
|
modelData = (J3DModelData*)dComIfG_getObjectRes(mpName, 3);
|
|
} else {
|
|
modelData = (J3DModelData*)dComIfG_getObjectRes(mpName, 3);
|
|
}
|
|
|
|
JUT_ASSERT(2505, modelData != NULL);
|
|
|
|
mpModel = mDoExt_J3DModel__create(modelData, J3DMdlFlag_DifferedDLBuffer, 0x11000084);
|
|
if (mpModel == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
mpBgW = new dBgW();
|
|
if (mpBgW == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (mpBgW->Set((cBgD_t*)dComIfG_getObjectRes("E_HZ", dRes_INDEX_E_HZ_DZB_K_HZP00_e), 1, &mMtx) == 1) {
|
|
return 0;
|
|
}
|
|
|
|
mpBgW->SetCrrFunc(dBgS_MoveBGProc_Typical);
|
|
|
|
modelData = (J3DModelData*)dComIfG_getObjectRes("E_HZ", dRes_INDEX_E_HZ_BMD_HZ_HOLE_e);
|
|
JUT_ASSERT(2532, modelData != NULL);
|
|
|
|
mpModel2 = mDoExt_J3DModel__create(modelData, J3DMdlFlag_DifferedDLBuffer, 0x11000084);
|
|
if (mpModel2 == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
J3DModel* morfModel = mpMorfSO->getModel();
|
|
morfModel->setUserArea((u32)this);
|
|
for (u16 i = 0; i < morfModel->getModelData()->getJointNum(); i++) {
|
|
if (i != 0) {
|
|
morfModel->getModelData()->getJointNodePointer(i)->setCallBack(JointCallBack);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int useHeapInit(fopAc_ac_c* i_this) {
|
|
daE_HZ_c* actor = (daE_HZ_c*)i_this;
|
|
return actor->CreateHeap();
|
|
}
|
|
|
|
void daE_HZ_c::setInitPos() {
|
|
dBgS_GndChk gnd_chk;
|
|
cXyz modified_home_pos(home.pos);
|
|
|
|
modified_home_pos.y += 100.0f;
|
|
gnd_chk.SetPos(&modified_home_pos);
|
|
|
|
f32 ground_cross = dComIfG_Bgsp().GroundCross(&gnd_chk);
|
|
if (ground_cross != -G_CM3D_F_INF) {
|
|
home.pos.y = ground_cross;
|
|
old.pos.y = ground_cross;
|
|
current.pos.y = ground_cross;
|
|
}
|
|
|
|
s16 angle = home.angle.y = (s16)(home.angle.y + 0x2000) & 0xC000;
|
|
shape_angle.y = angle;
|
|
current.angle.y = angle;
|
|
setActionMode(ACTION_HIDE);
|
|
}
|
|
|
|
int daE_HZ_c::create() {
|
|
static dCcD_SrcSph cc_sph_src = {
|
|
{
|
|
{0x0, {{0x0, 0x0, 0x0}, {0x10040, 0x3}, 0x0}}, // mObj
|
|
{dCcD_SE_METAL, 0x0, 0x0, 0x0, 0x0}, // mGObjAt
|
|
{dCcD_SE_NONE, 0x0, 0x0, 0x0, 0x0}, // mGObjTg
|
|
{0x0}, // mGObjCo
|
|
}, // mObjInf
|
|
{
|
|
{{0.0f, 0.0f, 0.0f}, 40.0f} // mSph
|
|
} // mSphAttr
|
|
};
|
|
|
|
static dCcD_SrcSph cc_sph_src2 = {
|
|
{
|
|
{0x0, {{AT_TYPE_CSTATUE_SWING, 0x1, 0x0}, {0xd8fafdff, 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
|
|
};
|
|
|
|
fopAcM_ct(this, daE_HZ_c);
|
|
|
|
dKy_tevstr_init(&mTevStr, home.roomNo, 0xFF);
|
|
|
|
int phase = dComIfG_resLoad(&mPhaseReq, "E_HZ");
|
|
if (phase != cPhs_COMPLEATE_e) {
|
|
return phase;
|
|
}
|
|
|
|
u8 param = (fopAcM_GetParam(this) >> 8) & 0xFF;
|
|
if (param == 1) {
|
|
int dummy; // force debug to use r31 as stack pointer
|
|
|
|
mpName = "E_hzp2";
|
|
} else {
|
|
mpName = "E_hzp";
|
|
}
|
|
|
|
phase = dComIfG_resLoad(&mPhaseReq2, mpName);
|
|
if (phase == cPhs_COMPLEATE_e) {
|
|
OS_REPORT("E_HZ PARAM %x\n", fopAcM_GetParam(this));
|
|
|
|
if (!fopAcM_entrySolidHeap(this, useHeapInit, 0x2C20)) {
|
|
return cPhs_ERROR_e;
|
|
}
|
|
if (mpBgW != NULL && dComIfG_Bgsp().Regist(mpBgW, this)) {
|
|
return cPhs_ERROR_e;
|
|
}
|
|
|
|
if (!hio_set) {
|
|
mHIOInit = true;
|
|
hio_set = true;
|
|
l_HIO.enemy_sample = mDoHIO_CREATE_CHILD("ハジキさん", &l_HIO);
|
|
}
|
|
|
|
fopAcM_SetMtx(this, mpMorfSO->getModel()->getBaseTRMtx());
|
|
fopAcM_SetMin(this, -200.0f, -200.0f, -200.0f);
|
|
fopAcM_SetMax(this, 200.0f, 200.0f, 200.0f);
|
|
mObjAcch.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mAcchCir,
|
|
fopAcM_GetSpeed_p(this), NULL, NULL);
|
|
mAcchCir.SetWall(50.0f, 150.0f);
|
|
field_0x560 = health = 0x32;
|
|
mStts.Init(0xFF, 0, this);
|
|
mSpheres[0].Set(cc_sph_src);
|
|
mSpheres[1].Set(cc_sph_src2);
|
|
mSpheres[2].Set(cc_sph_src2);
|
|
mSpheres[3].Set(cc_sph_src2);
|
|
mSpheres[0].SetStts(&mStts);
|
|
mSpheres[1].SetStts(&mStts);
|
|
mSpheres[2].SetStts(&mStts);
|
|
mSpheres[3].SetStts(&mStts);
|
|
attention_info.distances[fopAc_attn_BATTLE_e] = 4;
|
|
mSound.init(¤t.pos, &eyePos, 3, 1);
|
|
mSound.setEnemyName("E_hz");
|
|
mAtInfo.mpSound = &mSound;
|
|
maxFallSpeed = -60.0f;
|
|
setInitPos();
|
|
mParam = fopAcM_GetParam(this);
|
|
|
|
if (mParam != 0xFF && dComIfGs_isSwitch(mParam, fopAcM_GetRoomNo(this))) {
|
|
setActionMode(0xB);
|
|
mMode = 1;
|
|
}
|
|
daE_HZ_Execute(this);
|
|
}
|
|
return phase;
|
|
}
|
|
|
|
static int daE_HZ_Create(daE_HZ_c* i_this) {
|
|
return i_this->create();
|
|
}
|
|
|
|
static actor_method_class l_daE_HZ_Method = {
|
|
(process_method_func)daE_HZ_Create, (process_method_func)daE_HZ_Delete,
|
|
(process_method_func)daE_HZ_Execute, (process_method_func)daE_HZ_IsDelete,
|
|
(process_method_func)daE_HZ_Draw,
|
|
};
|
|
|
|
actor_process_profile_definition g_profile_E_HZ = {
|
|
/* Layer ID */ fpcLy_CURRENT_e,
|
|
/* List ID */ 7,
|
|
/* List Prio */ fpcPi_CURRENT_e,
|
|
/* Proc Name */ fpcNm_E_HZ_e,
|
|
/* Proc SubMtd */ &g_fpcLf_Method.base,
|
|
/* Size */ sizeof(daE_HZ_c),
|
|
/* Size Other */ 0,
|
|
/* Parameters */ 0,
|
|
/* Leaf SubMtd */ &g_fopAc_Method.base,
|
|
/* Draw Prio */ fpcDwPi_E_HZ_e,
|
|
/* Actor SubMtd */ &l_daE_HZ_Method,
|
|
/* Status */ fopAcStts_UNK_0x40000_e,
|
|
/* Group */ fopAc_ENEMY_e,
|
|
/* Cull Type */ fopAc_CULLBOX_CUSTOM_e,
|
|
};
|
|
|
|
AUDIO_INSTANCES;
|