mirror of
https://github.com/zeldaret/tp
synced 2026-05-23 15:01:53 -04:00
67b576ad9a
* f_op debug 1 * f_op debug 2 * f_op debug 3 * f_op debug 4 * f_op debug 5 * f_op_debug fix build * f_op linking * remove goto in fopac_create * fix regressions * fix regressions * pr comments
1040 lines
30 KiB
C++
1040 lines
30 KiB
C++
/**
|
|
* d_a_obj_stone.cpp
|
|
* Actor - Object Stone
|
|
*
|
|
* Small and large rocks
|
|
*
|
|
*/
|
|
|
|
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
|
|
|
#include "d/actor/d_a_obj_stone.h"
|
|
#include "d/actor/d_a_player.h"
|
|
#include "d/d_lib.h"
|
|
#include "f_op/f_op_kankyo_mng.h"
|
|
#include "global.h"
|
|
#include "SSystem/SComponent/c_math.h"
|
|
#include <math.h>
|
|
|
|
const static int l_bmdIdx[2] = {3, 3};
|
|
|
|
const static dCcD_SrcSph l_sph_src = {
|
|
{
|
|
{0, {{AT_TYPE_THROW_OBJ, 0x03, 0x13}, {0xD8FAFDFF, 0x11}, 0x79}},
|
|
{dCcD_SE_THROW_OBJ, 0, 0, 0, {0x08}},
|
|
{dCcD_SE_NONE, 0x02, 0, 0, {0x03}},
|
|
{0},
|
|
},
|
|
{
|
|
{
|
|
{0.0f, 0.0f, 0.0f},
|
|
50.0f,
|
|
},
|
|
}};
|
|
|
|
// radius
|
|
const static f32 l_r[2] = {
|
|
30.0f,
|
|
50.0f,
|
|
};
|
|
|
|
const static f32 l_rolling_speedF[2] = {9.0f, 9.0f};
|
|
|
|
const static u32 l_rolling_time[2] = {
|
|
30,
|
|
23,
|
|
};
|
|
|
|
const static f32 l_initial_offsetY[2] = {10.0f, 20.0f};
|
|
|
|
const static f32 l_put_offsetY[2] = {20.0f, 30.0f};
|
|
|
|
const static u8 l_weight[2] = {120, 200};
|
|
|
|
const static f32 l_speedH[2] = {
|
|
36.0f,
|
|
43.0f,
|
|
};
|
|
|
|
const static f32 l_speedV[2] = {
|
|
27.0f,
|
|
22.0f,
|
|
};
|
|
|
|
const static f32 l_water_speedH[2] = {
|
|
5.0f,
|
|
5.0f,
|
|
};
|
|
|
|
const static f32 l_water_speedV[2] = {
|
|
5.0f,
|
|
5.0f,
|
|
};
|
|
|
|
const static f32 l_water_resist[2] = {
|
|
0.02f,
|
|
0.02f,
|
|
};
|
|
|
|
const static f32 l_water_walk_resist[2] = {
|
|
0.15f,
|
|
0.15f,
|
|
};
|
|
|
|
const static f32 l_buoyancy[2] = {
|
|
5.9f,
|
|
5.9f,
|
|
};
|
|
|
|
const static f32 l_shadow_size[2] = {40.0f, 65.0f};
|
|
|
|
const static f32 l_wpillar_scl[2] = {
|
|
0.65f,
|
|
1.1f,
|
|
};
|
|
|
|
const static f32 l_hamon_scl[2] = {
|
|
0.7f,
|
|
1.2f,
|
|
};
|
|
|
|
const static f32 l_yogan_eff_scl[2] = {
|
|
0.6f,
|
|
1.1f,
|
|
};
|
|
|
|
const static f32 l_wall_h[2] = {
|
|
30.0f,
|
|
50.0f,
|
|
};
|
|
|
|
const static f32 l_wall_r[2] = {30.0f, 50.0f};
|
|
|
|
const static s16 l_rot_angle[2] = {35, 18};
|
|
|
|
const static s16 l_walk_rot_angle[2] = {40, 40};
|
|
|
|
static char* l_arcName[2] = {
|
|
"D_Srock", // small rock
|
|
"D_Brock", // big rock
|
|
};
|
|
|
|
static f32 bound(cXyz* param_0, cBgS_PolyInfo const& param_1, f32 param_2) {
|
|
cM3dGPla plane;
|
|
f32 ret;
|
|
if (dComIfG_Bgsp().GetTriPla(param_1, &plane)) {
|
|
cXyz pos;
|
|
f32 abs = param_0->abs();
|
|
|
|
C_VECReflect(param_0, (Vec*)&plane, &pos);
|
|
*param_0 = pos * abs * param_2;
|
|
|
|
return param_0->absXZ();
|
|
} else {
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
static bool CheckCreateHeap(fopAc_ac_c* i_this) {
|
|
return static_cast<daObjStone_c*>(i_this)->CreateHeap();
|
|
}
|
|
|
|
void daObjStone_c::initBaseMtx() {
|
|
field_0x0910 = cXyz::Zero;
|
|
field_0x091c = 0;
|
|
field_0x0930 = ZeroQuat;
|
|
field_0x0920 = field_0x0930;
|
|
mpModel->setBaseScale(scale);
|
|
setBaseMtx();
|
|
}
|
|
|
|
void daObjStone_c::setBaseMtx() {
|
|
mDoMtx_quatMultiply(&field_0x0920, &field_0x0930, &field_0x0920);
|
|
mDoMtx_stack_c::transS(current.pos.x, current.pos.y + mInitialOffsetY, current.pos.z);
|
|
mDoMtx_stack_c::quatM(&field_0x0920);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, shape_angle.z);
|
|
mDoMtx_stack_c::ZXYrotM(mShapeAngle);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
field_0x0930 = field_0x0920;
|
|
field_0x0920 = ZeroQuat;
|
|
}
|
|
|
|
int daObjStone_c::Create() {
|
|
mShapeAngle = shape_angle;
|
|
shape_angle.setall(0);
|
|
|
|
fopAcM_SetMtx(this, mpModel->getBaseTRMtx());
|
|
|
|
// set chkCirlce wall bounds
|
|
mChkCircle.SetWall(l_wall_h[mStoneType], l_wall_r[mStoneType]);
|
|
|
|
// setup chkobj
|
|
mChkObj.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mChkCircle,
|
|
fopAcM_GetSpeed_p(this), 0, 0);
|
|
mChkObj.SetWtrChkMode(2);
|
|
mChkObj.ClrObj();
|
|
mChkObj.SetBomb();
|
|
|
|
mStatus.Init(l_weight[mStoneType], 0xFF, this);
|
|
|
|
// setup collider
|
|
mCollider.Set(l_sph_src);
|
|
mCollider.SetR(l_r[mStoneType]);
|
|
mCollider.SetStts(&mStatus);
|
|
|
|
if (mStoneType == OBJ_STONE_TYPE_SMALL) {
|
|
mCollider.SetAtAtp(2);
|
|
}
|
|
|
|
fopAcM_setCullSizeSphere(this, 0.0f, 0.0f, 0.0f, l_r[mStoneType] * 1.2f);
|
|
cLib_onBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e);
|
|
attention_info.distances[fopAc_attn_CARRY_e] = 0x2A;
|
|
fopAcM_OnCarryType(this, fopAcM_CARRY_LIGHT);
|
|
|
|
cXyz other_pos = current.pos;
|
|
|
|
mChkObj.CrrPos(dComIfG_Bgsp());
|
|
current.pos = other_pos;
|
|
mInitialOffsetY = 0.0f;
|
|
field_0x094d = 0x1E;
|
|
|
|
// Set heavy carry type if big stone
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
fopAcM_OnCarryType(this, fopAcM_CARRY_HEAVY);
|
|
}
|
|
|
|
init_modePutWait();
|
|
initBaseMtx();
|
|
|
|
u8 stoneType = mStoneType;
|
|
|
|
cXyz pos = current.pos;
|
|
pos.y += 1.0f;
|
|
|
|
// Create the mark actor that goes under the stone
|
|
fopAcM_createChild(PROC_Obj_StoneMark, fopAcM_GetID(this), stoneType, &pos,
|
|
fopAcM_GetRoomNo(this), &shape_angle, &scale, -1, 0);
|
|
|
|
mSound.init(¤t.pos, 1);
|
|
mLastPosY = current.pos.y;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
bool daObjStone_c::CreateHeap() {
|
|
mpModel = mDoExt_J3DModel__create(
|
|
(J3DModelData*)dComIfG_getObjectRes(l_arcName[mStoneType], l_bmdIdx[mStoneType]), 0x80000,
|
|
0x11000084);
|
|
return mpModel != NULL;
|
|
}
|
|
|
|
int daObjStone_c::create() {
|
|
fopAcM_ct(this, daObjStone_c);
|
|
|
|
mStoneType = getType();
|
|
|
|
int phase = dComIfG_resLoad(&mPhase, l_arcName[mStoneType]);
|
|
|
|
if (phase == cPhs_COMPLEATE_e) {
|
|
// Allocate solid heap on GAME and load rock's model into it
|
|
if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)CheckCreateHeap, 0x860)) {
|
|
return cPhs_ERROR_e;
|
|
}
|
|
|
|
// Load everything else?
|
|
if (!Create()) {
|
|
return cPhs_ERROR_e;
|
|
}
|
|
}
|
|
|
|
return phase;
|
|
}
|
|
|
|
int daObjStone_c::execute() {
|
|
cXyz pos;
|
|
|
|
mStatus.SetWeight(l_weight[this->mStoneType]);
|
|
fopAcM_SetGravity(this, -6.0f);
|
|
mode_proc_call();
|
|
|
|
if (mCollider.ChkTgHit() && mCollider.GetTgHitObj()) {
|
|
mSound.startCollisionSE(mCollider.GetTgHitObjHitSeID(1), 2, 0);
|
|
}
|
|
|
|
mSound.framework(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this)));
|
|
attention_info.position = current.pos;
|
|
eyePos = attention_info.position;
|
|
|
|
setBaseMtx();
|
|
pos = current.pos;
|
|
pos.y += mInitialOffsetY;
|
|
|
|
mCollider.SetC(pos);
|
|
dComIfG_Ccsp()->Set(&mCollider);
|
|
mChkObj.OffLineCheck();
|
|
field_0x094f = mIsInWater;
|
|
effect_delete(false);
|
|
return 1;
|
|
}
|
|
|
|
void daObjStone_c::mode_proc_call() {
|
|
static daObjStone_c::modeFunc l_func[7] = {
|
|
&daObjStone_c::modeWait,
|
|
&daObjStone_c::modeDrop,
|
|
&daObjStone_c::modeCarry,
|
|
&daObjStone_c::modePutWait,
|
|
&daObjStone_c::modeWalk,
|
|
&daObjStone_c::modeBreak,
|
|
&daObjStone_c::modeYogan,
|
|
};
|
|
if (fopAcM_checkCarryNow(this) && field_0x0907 != 2) {
|
|
if (daPy_py_c::checkNowWolf()) {
|
|
init_modePushWolfNonBreak();
|
|
} else {
|
|
init_modeCarry();
|
|
}
|
|
}
|
|
if (mCollider.ChkTgHit()) {
|
|
cCcD_Obj* tgHitObj = mCollider.GetTgHitObj();
|
|
if (tgHitObj != NULL) {
|
|
fopAc_ac_c* tgHitActor = mCollider.GetTgHitAc();
|
|
if (fopAcM_GetName(tgHitActor) == PROC_OBJ_GRA) {
|
|
init_modeBreak();
|
|
} else {
|
|
if (tgHitObj->ChkAtType(AT_TYPE_BOMB)) {
|
|
init_modeBreak();
|
|
}
|
|
if (tgHitObj->ChkAtType(AT_TYPE_IRON_BALL) && tgHitObj->GetAtAtp() != 1) {
|
|
init_modeBreak();
|
|
} else if (tgHitObj->ChkAtType(AT_TYPE_CSTATUE_SWING) &&
|
|
(fopAcM_GetName(tgHitActor) == PROC_Obj_VolcanicBomb))
|
|
{
|
|
init_modeBreak();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (mCollider.ChkAtHit()) {
|
|
init_modeBreak();
|
|
}
|
|
bool isGroundLanding = mChkObj.ChkGroundLanding();
|
|
u32 isWallhit = mChkObj.ChkWallHit();
|
|
bool isGroundHit = mChkObj.ChkGroundHit();
|
|
bool isWaterHit = mChkObj.ChkWaterHit();
|
|
bool isWaterIn = mChkObj.ChkWaterIn();
|
|
if (field_0x0907 == 1) {
|
|
if (isGroundLanding && !isWaterIn) {
|
|
speed.x = speedF * cM_ssin(current.angle.y);
|
|
speed.z = speedF * cM_scos(current.angle.y);
|
|
speed.y = mLastSpeedY;
|
|
if (speed.abs() > 2.0f) {
|
|
bound(&speed, mChkObj.m_gnd, 0.4f);
|
|
} else {
|
|
speed.setall(0.0f);
|
|
}
|
|
speedF = speed.absXZ();
|
|
current.angle.y = cM_atan2s(speed.x, speed.z);
|
|
} else {
|
|
if (isWallhit && !field_0x0951 && isWaterIn) {
|
|
speed.x = speedF * cM_ssin(current.angle.y);
|
|
speed.z = speedF * cM_scos(current.angle.y);
|
|
speed.y = mLastSpeedY;
|
|
if (speed.abs() > 2.0f) {
|
|
bound(&speed, mChkCircle, 0.5f);
|
|
} else {
|
|
speed.setall(0.0f);
|
|
}
|
|
speed.y = mLastSpeedY;
|
|
speedF = speed.absXZ();
|
|
current.angle.y = cM_atan2s(speed.x, speed.z);
|
|
}
|
|
}
|
|
}
|
|
if (field_0x0907 == 4 && isWallhit) {
|
|
speed.x = speedF * cM_ssin(current.angle.y);
|
|
speed.z = speedF * cM_scos(current.angle.y);
|
|
if (speed.abs() > 2.0f) {
|
|
bound(&speed, mChkCircle, 0.5f);
|
|
} else {
|
|
speed.setall(0.0f);
|
|
}
|
|
speedF = speed.absXZ();
|
|
current.angle.y = cM_atan2s(speed.x, speed.z);
|
|
}
|
|
mIsInWater = false;
|
|
if (isWaterHit || isWaterIn) {
|
|
f32 waterHeight = mChkObj.m_wtr.GetHeight();
|
|
int iVar10 = dComIfG_Bgsp().GetPolyAtt0(mChkObj.m_wtr);
|
|
if (waterHeight > current.pos.y) {
|
|
switch (iVar10) {
|
|
case 7:
|
|
case 11:
|
|
default:
|
|
mIsInWater = 1;
|
|
if (field_0x094f == 0) {
|
|
fopKyM_createWpillar(¤t.pos, l_wpillar_scl[mStoneType], 0);
|
|
cXyz cStack_d4(current.pos.x, waterHeight - 0.1f, current.pos.z);
|
|
dBgS_ObjGndChk adStack_c8;
|
|
adStack_c8.SetPos(&cStack_d4);
|
|
f32 dVar17 = dComIfG_Bgsp().GroundCross(&adStack_c8);
|
|
if (dVar17 == -G_CM3D_F_INF) {
|
|
dVar17 = -100000.0f;
|
|
}
|
|
dVar17 = fabs(waterHeight - dVar17);
|
|
if ((mStoneType == OBJ_STONE_TYPE_SMALL && dVar17 < 60.0f) ||
|
|
(mStoneType == OBJ_STONE_TYPE_BIG && dVar17 < 100.0f))
|
|
{
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_ASASE, 0);
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_WTR, 0);
|
|
}
|
|
}
|
|
if (isGroundHit) {
|
|
f32 waterHeightDiff = waterHeight - current.pos.y;
|
|
if ((mStoneType == OBJ_STONE_TYPE_SMALL && waterHeightDiff < 60.0f) ||
|
|
(mStoneType == OBJ_STONE_TYPE_BIG && waterHeightDiff < 90.0f))
|
|
{
|
|
cXyz cStack_e0(current.pos);
|
|
cStack_e0.y = waterHeight;
|
|
fopAcM_effHamonSet(&field_0x0954, &cStack_e0, l_hamon_scl[mStoneType], 0.1f);
|
|
}
|
|
}
|
|
if (speed.y < -10.0f) {
|
|
speed.y = -10.0f;
|
|
}
|
|
if (speed.y > 10.0f) {
|
|
speed.y = 10.0f;
|
|
}
|
|
if (speedF > 10.0f) {
|
|
speedF = 10.0f;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (field_0x0907 != 6) {
|
|
init_modeYogan();
|
|
cXyz cStack_ec(current.pos.x, waterHeight, current.pos.z);
|
|
cXyz cStack_f8(l_yogan_eff_scl[mStoneType], l_yogan_eff_scl[mStoneType],
|
|
l_yogan_eff_scl[mStoneType]);
|
|
dComIfGp_particle_set(0x8757, &cStack_ec, &tevStr, 0, &cStack_f8);
|
|
dComIfGp_particle_set(0x8758, &cStack_ec, &tevStr, 0, &cStack_f8);
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
if (field_0x0907 == 1) {
|
|
if (mIsInWater) {
|
|
if (isGroundLanding) {
|
|
init_modeWalk();
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_PUT_WTR, 0);
|
|
}
|
|
} else {
|
|
if (isGroundLanding) {
|
|
if (!isWaterIn) {
|
|
int iVar8 = dComIfG_Bgsp().GetPolyAtt0(mChkObj.m_gnd);
|
|
if (iVar8 == 1 || iVar8 == 3 || iVar8 == 4) {
|
|
mInitialOffsetY = l_put_offsetY[mStoneType];
|
|
if (mStoneType == 1) {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_L_ROCK_BOUND, 0);
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_BOUND, 0);
|
|
}
|
|
init_modeWalk();
|
|
} else {
|
|
init_modeBreak();
|
|
}
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_PUT_WTR, 0);
|
|
}
|
|
}
|
|
if (isWallhit) {
|
|
init_modeBreak();
|
|
}
|
|
}
|
|
} else if (field_0x0907 == 0 && isGroundLanding) {
|
|
if (!isWaterIn) {
|
|
if (speedF == 0.0f) {
|
|
if (mStoneType == 1) {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_L_ROCK_PUT, 0);
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_PUT, 0);
|
|
}
|
|
} else if (mStoneType == 1) {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_L_ROCK_BOUND, 0);
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_BOUND, 0);
|
|
}
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_PUT_WTR, 0);
|
|
}
|
|
}
|
|
if (field_0x094d != 0) {
|
|
field_0x094d--;
|
|
} else {
|
|
if (field_0x0907 != 2) {
|
|
f32 dVar16 = fabs(current.pos.y - mLastPosY);
|
|
if (isGroundLanding && !isWaterHit && dVar16 > 50.0f) {
|
|
fopAcM_effSmokeSet1(&field_0x095c, &field_0x0960,
|
|
¤t.pos, 0, l_r[mStoneType] / l_r[1], &tevStr, 1);
|
|
dComIfGp_particle_levelEmitterOnEventMove(field_0x095c);
|
|
dComIfGp_particle_levelEmitterOnEventMove(field_0x0960);
|
|
field_0x094d = 30;
|
|
}
|
|
}
|
|
}
|
|
if (isGroundHit) {
|
|
mLastPosY = current.pos.y;
|
|
}
|
|
(this->*(l_func[field_0x0907]))();
|
|
CrrPos();
|
|
field_0x0951 = isWallhit;
|
|
}
|
|
|
|
void daObjStone_c::init_modePutWait() {
|
|
mCollider.OffAtSPrmBit(1);
|
|
mCollider.OnCoSPrmBit(1);
|
|
cLib_onBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e);
|
|
mInitialOffsetY = l_initial_offsetY[mStoneType];
|
|
mMode = 0;
|
|
field_0x0907 = 3;
|
|
}
|
|
|
|
void daObjStone_c::modePutWait() {
|
|
mMode++;
|
|
}
|
|
|
|
void daObjStone_c::init_modeWait() {
|
|
mCollider.OffAtSPrmBit(1);
|
|
mCollider.OnCoSPrmBit(1);
|
|
cLib_onBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e);
|
|
mMode = 0;
|
|
field_0x0907 = 0;
|
|
}
|
|
|
|
void daObjStone_c::modeWait() {
|
|
mMode++;
|
|
speedF *= 0.95f;
|
|
|
|
fopAcM_posMoveF(this, mStatus.GetCCMoveP());
|
|
cLib_chaseF(&mInitialOffsetY, l_put_offsetY[mStoneType], 8.0f);
|
|
|
|
if (mMode > 5 && checkRollAngle()) {
|
|
init_modeWalk();
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::init_modeDrop() {
|
|
mCollider.OnAtSPrmBit(1);
|
|
mCollider.OnCoSPrmBit(1);
|
|
cLib_offBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e);
|
|
mMode = 0;
|
|
mLastPosY = current.pos.y;
|
|
field_0x0907 = 1;
|
|
}
|
|
|
|
void daObjStone_c::modeDrop() {
|
|
cXyz pos2, pos;
|
|
mMode++;
|
|
mChkObj.OnLineCheck();
|
|
|
|
if (mIsInWater != 0) {
|
|
mCollider.OffAtSPrmBit(1);
|
|
mChkObj.ChkGroundHit() ? cLib_onBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e) :
|
|
cLib_offBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e);
|
|
|
|
pos2.x = speedF * cM_ssin(current.angle.y);
|
|
pos2.y = speed.y;
|
|
pos2.z = speedF * cM_scos(current.angle.y);
|
|
|
|
pos = pos2;
|
|
pos.x = -pos.x * l_water_resist[mStoneType];
|
|
pos.y = -pos.y * l_water_resist[mStoneType];
|
|
pos.z = -pos.z * l_water_resist[mStoneType];
|
|
|
|
pos2 += pos;
|
|
speedF = sqrtf(pos2.x * pos2.x + pos2.z * pos2.z);
|
|
speed.y = pos2.y;
|
|
|
|
fopAcM_SetGravity(this, -6.0f + l_buoyancy[mStoneType]);
|
|
}
|
|
|
|
fopAcM_posMoveF(this, mStatus.GetCCMoveP());
|
|
mLastSpeedY = speed.y;
|
|
calcRotBaseMtx(0);
|
|
}
|
|
|
|
|
|
void daObjStone_c::init_modeCarry() {
|
|
mCollider.OffCoSPrmBit(1);
|
|
mCollider.OffAtSPrmBit(1);
|
|
fopAcM_SetModel(this, mpModel);
|
|
mMode = 0;
|
|
field_0x0950 = field_0x0907;
|
|
if (mIsInWater == 0) {
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_L_ROCK_LIFT, 0); // literals inline
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_LIFT, 0); // literals inline
|
|
}
|
|
}
|
|
|
|
field_0x0907 = 2;
|
|
}
|
|
|
|
void daObjStone_c::modeCarry() {
|
|
mMode++;
|
|
|
|
if (mMode == 8 && mStoneType == OBJ_STONE_TYPE_SMALL) {
|
|
mInitialOffsetY = l_r[mStoneType];
|
|
set_carry_eff();
|
|
}
|
|
|
|
if (mMode == 17 && mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
mInitialOffsetY = l_r[mStoneType];
|
|
set_carry_eff();
|
|
}
|
|
|
|
if (field_0x0908 == 0) {
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
if (mMode == 21) {
|
|
createItem();
|
|
field_0x0908 = 1;
|
|
}
|
|
} else if (mMode == 14) {
|
|
createItem();
|
|
field_0x0908 = 1;
|
|
}
|
|
}
|
|
|
|
if ((mStoneType == OBJ_STONE_TYPE_SMALL && mMode > 8) ||
|
|
(mStoneType == OBJ_STONE_TYPE_BIG && mMode > 17))
|
|
{
|
|
f32 frame_rate = daPy_getLinkPlayerActorClass()->getBaseAnimeFrameRate() * 0.25f;
|
|
mDoMtx_quatSlerp(&field_0x0930, &ZeroQuat, &field_0x0930, frame_rate);
|
|
}
|
|
|
|
if (!fopAcM_checkCarryNow(this)) {
|
|
if (speedF != 0.0f) {
|
|
mChkObj.CrrPos(dComIfG_Bgsp());
|
|
mIsInWater = mChkObj.ChkWaterIn();
|
|
|
|
if (!mIsInWater) {
|
|
speedF = l_speedH[mStoneType];
|
|
speed.y = l_speedV[mStoneType];
|
|
} else {
|
|
speedF = l_water_speedH[mStoneType];
|
|
speed.y = l_water_speedV[mStoneType];
|
|
|
|
if (speed.y < -10.0f)
|
|
speed.y = -10.0f;
|
|
|
|
if (speed.y > 10.0f)
|
|
speed.y = 10.0f;
|
|
|
|
if (speedF > 10.0f)
|
|
speedF = 10.0f;
|
|
}
|
|
mInitialOffsetY = l_r[mStoneType];
|
|
init_modeDrop();
|
|
} else {
|
|
mLastPosY = current.pos.y;
|
|
init_modeWait();
|
|
}
|
|
|
|
model = 0;
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::init_modeWalk() {
|
|
mCollider.OffAtSPrmBit(1);
|
|
mCollider.OnCoSPrmBit(1);
|
|
cLib_onBit<u32>(attention_info.flags, fopAc_AttnFlag_CARRY_e);
|
|
mMode = 0;
|
|
field_0x0907 = 4;
|
|
}
|
|
|
|
void daObjStone_c::modeWalk() {
|
|
mMode++;
|
|
if (field_0x0908 == 0) {
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
if (mMode == 4) {
|
|
createItem();
|
|
field_0x0908 = 1;
|
|
}
|
|
} else if (mMode == 7) {
|
|
createItem();
|
|
field_0x0908 = 1;
|
|
}
|
|
}
|
|
if (mIsInWater) {
|
|
cXyz local_b0;
|
|
cXyz local_bc;
|
|
local_b0.x = speedF * cM_ssin(current.angle.y);
|
|
local_b0.y = speed.y;
|
|
local_b0.z = speedF * cM_scos(current.angle.y);
|
|
local_bc = local_b0;
|
|
local_bc.x = -local_bc.x * l_water_walk_resist[mStoneType];
|
|
local_bc.y = -local_bc.y * l_water_walk_resist[mStoneType];
|
|
local_bc.z = -local_bc.z * l_water_walk_resist[mStoneType];
|
|
local_b0 += local_bc;
|
|
speedF = std::sqrt(local_b0.x * local_b0.x + local_b0.z * local_b0.z);
|
|
speed.y = local_b0.y;
|
|
fopAcM_SetGravity(this, -6.0f + l_buoyancy[mStoneType]);
|
|
}
|
|
fopAcM_posMoveF(this, mStatus.GetCCMoveP());
|
|
f32 dVar15 = 89.0f;
|
|
cXyz cStack_c8(current.pos);
|
|
cStack_c8.y += 50.0f;
|
|
f32 dVar14 = 1.0f - 0.2f;
|
|
cM3dGPla acStack_a4;
|
|
bool iVar7 = fopAcM_gc_c::gndCheck(&cStack_c8);
|
|
bool isTriPla = fopAcM_gc_c::getTriPla(&acStack_a4);
|
|
f32 dVar12 = fopAcM_gc_c::getGroundY();
|
|
if (iVar7 && dVar12 != -G_CM3D_F_INF && isTriPla) {
|
|
f32 dVar12 = cM_scos(cM_deg2s(dVar15 - 0.5f));
|
|
cXyz cStack_d4(acStack_a4.mNormal);
|
|
if (cStack_d4.y < dVar12) {
|
|
cXyz local_e0(cStack_d4);
|
|
s16 sVar9 = cM_atan2s(local_e0.x, local_e0.z);
|
|
f32 dVar12 = 10.0f;
|
|
dVar12 *= (1.0f - cStack_d4.y);
|
|
if (dVar12 < 0.1f) {
|
|
dVar12 = 0.1f;
|
|
} else {
|
|
if (dVar12 > 1.0f) {
|
|
dVar12 = 1.0f;
|
|
}
|
|
}
|
|
cXyz local_ec((speedF * cM_ssin(current.angle.y)), 0.0f,
|
|
speedF * cM_scos(current.angle.y));
|
|
cXyz cStack_f8((dVar12 * cM_ssin(sVar9)), 0.0f, dVar12 * cM_scos(sVar9));
|
|
local_ec += cStack_f8;
|
|
speedF =
|
|
std::sqrt(local_ec.x * local_ec.x + local_ec.z * local_ec.z);
|
|
current.angle.y = cM_atan2s(local_ec.x, local_ec.z);
|
|
}
|
|
}
|
|
speedF *= dVar14;
|
|
if (mStatus.GetCCMoveP()->abs2XZ() > 0.01000000070780516f) {
|
|
speedF *= 0.9f;
|
|
}
|
|
if (speedF < 0.5f) {
|
|
speedF = 0;
|
|
}
|
|
f32 step = 8.0f;
|
|
if (speed.y < 0.0f && std::fabs(speed.y) > step) {
|
|
step = std::fabs(speed.y);
|
|
}
|
|
cLib_chaseF(&mInitialOffsetY, l_put_offsetY[mStoneType], step);
|
|
calcRotBaseMtx(NULL);
|
|
if (speedF == 0.0f && mChkObj.ChkGroundHit()) {
|
|
init_modeWait();
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::init_modePushWolfNonBreak() {
|
|
mCollider.OffAtSPrmBit(1);
|
|
mCollider.OnCoSPrmBit(1);
|
|
fopAcM_cancelCarryNow(this);
|
|
current.angle.y = daPy_getPlayerActorClass()->current.angle.y;
|
|
speedF = l_rolling_speedF[mStoneType];
|
|
field_0x0950 = field_0x0907;
|
|
mMode = 0;
|
|
|
|
if (mIsInWater == 0) {
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_L_ROCK_ROLL, 0); // literals inline
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_ROLL, 0); // literals inline
|
|
}
|
|
}
|
|
|
|
field_0x0907 = 4;
|
|
}
|
|
|
|
void daObjStone_c::init_modeYogan() {
|
|
mCollider.OffAtSPrmBit(1);
|
|
mCollider.OnCoSPrmBit(1);
|
|
mInitialOffsetY = l_initial_offsetY[mStoneType];
|
|
mMode = 0;
|
|
fopAcM_SetGravity(this, -0.4f);
|
|
fopAcM_SetMaxFallSpeed(this, -2.0f);
|
|
current.pos.y = mChkObj.m_wtr.GetHeight();
|
|
field_0x0907 = 6;
|
|
}
|
|
|
|
void daObjStone_c::modeYogan() {
|
|
f32 height = mChkObj.m_wtr.GetHeight();
|
|
f32 pos_y = 200.0f + current.pos.y;
|
|
|
|
bool pos_check = height > pos_y;
|
|
bool gnd_landing = mChkObj.ChkGroundLanding();
|
|
|
|
speedF *= 0.65f;
|
|
fopAcM_posMoveF(this, 0);
|
|
|
|
if (pos_check || gnd_landing) {
|
|
fopAcM_delete(this);
|
|
}
|
|
|
|
mMode++;
|
|
}
|
|
|
|
const static u16 l_eff_id[3] = {
|
|
0x859B, 0x859C, 0x859D,
|
|
};
|
|
|
|
void daObjStone_c::init_modeBreak() {
|
|
if (field_0x0907 != 5) {
|
|
fopAcM_cancelCarryNow(this);
|
|
if (!mIsInWater) {
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_L_ROCK_BREAK, 0);
|
|
} else {
|
|
fopAcM_seStart(this, Z2SE_OBJ_CMN_ROCK_BREAK, 0);
|
|
}
|
|
}
|
|
cXyz acStack_40;
|
|
if (mStoneType == OBJ_STONE_TYPE_BIG) {
|
|
acStack_40.setall(1.0f);
|
|
} else {
|
|
acStack_40.setall(0.5f);
|
|
}
|
|
J3DModelData* stone_bmd = (J3DModelData*)dComIfG_getObjectRes("Always", 27);
|
|
JUT_ASSERT(1687, stone_bmd != NULL);
|
|
JPABaseEmitter* emitter = dComIfGp_particle_set(
|
|
0x15c, ¤t.pos, 0, &acStack_40, 0xff, &dPa_modelEcallBack::getEcallback(), fopAcM_GetRoomNo(this), 0, 0, 0);
|
|
dPa_modelEcallBack::setModel(emitter, stone_bmd, tevStr,
|
|
3, 0, NULL, 0);
|
|
for (int i = 0; i < 3; i = i + 1) {
|
|
dComIfGp_particle_set(
|
|
l_eff_id[i],
|
|
¤t.pos, NULL, &acStack_40, 0xff, 0, fopAcM_GetRoomNo(this), 0, 0, 0);
|
|
}
|
|
if (field_0x0908 == 0) {
|
|
createItem();
|
|
field_0x0908 = 1;
|
|
}
|
|
mMode = 0;
|
|
field_0x0907 = 5;
|
|
fopAcM_delete(this);
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::modeBreak() {
|
|
mMode++;
|
|
fopAcM_delete(this);
|
|
}
|
|
|
|
void daObjStone_c::CrrPos() {
|
|
bool check1 = false;
|
|
bool check2 = false;
|
|
|
|
cXyz pos = current.pos;
|
|
u8 mode = field_0x0907;
|
|
|
|
if (mode == 2) {
|
|
check1 = true;
|
|
pos = current.pos;
|
|
}
|
|
|
|
if (field_0x0907 == 3) {
|
|
check2 = true;
|
|
}
|
|
|
|
if (!check2) {
|
|
mChkObj.CrrPos(dComIfG_Bgsp());
|
|
}
|
|
|
|
if (check1) {
|
|
current.pos = pos;
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::createItem() {
|
|
int item_no = getItemNo();
|
|
int item_bit = getItemBit();
|
|
|
|
csXyz angle(0, home.angle.y, 0);
|
|
u8 item_type = getItemType();
|
|
|
|
if (item_type == 0) {
|
|
cXyz pos(home.pos);
|
|
fopAcM_createItem(&pos, item_no, item_bit, fopAcM_GetHomeRoomNo(this), &angle, 0, 8);
|
|
} else {
|
|
fopAcM_createItemFromTable(&home.pos, item_no, item_bit, fopAcM_GetHomeRoomNo(this), &angle,
|
|
8, 0, 0, 0, false);
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::calcRotBaseMtx(s16* param_1) {
|
|
cXyz local_5c = current.pos - old.pos;
|
|
cXyz cStack_68(local_5c.x, 0.0f, local_5c.z);
|
|
bool iVar5 = local_5c.normalizeRS();
|
|
bool iVar6 = cStack_68.normalizeRS();
|
|
bool bVar4 = true;
|
|
if (!iVar5 && !iVar6) {
|
|
bVar4 = false;
|
|
}
|
|
if (iVar6) {
|
|
field_0x0910 = cStack_68;
|
|
mDoMtx_stack_c::YrotS(0x4000);
|
|
mDoMtx_stack_c::multVec(&field_0x0910, &field_0x0910);
|
|
} else if (iVar5) {
|
|
field_0x0910 = cXyz::BaseX;
|
|
}
|
|
if (bVar4) {
|
|
f32 dVar9 = std::fabs(speedF);
|
|
f32 dVar10 = std::fabs(speed.y);
|
|
if (current.pos.y == old.pos.y) {
|
|
dVar10 = 0.0f;
|
|
}
|
|
s16 sVar7 = l_rot_angle[mStoneType];
|
|
if (field_0x0907 != 1) {
|
|
sVar7 = l_walk_rot_angle[mStoneType];
|
|
}
|
|
if (param_1 != NULL) {
|
|
sVar7 = *param_1;
|
|
}
|
|
if (mChkObj.ChkWaterIn()) {
|
|
sVar7 *= 0.5f;
|
|
}
|
|
field_0x091c = sVar7 * (dVar9 + dVar10);
|
|
field_0x0920.x = field_0x0910.x * cM_ssin(field_0x091c);
|
|
field_0x0920.y = field_0x0910.y * cM_ssin(field_0x091c);
|
|
field_0x0920.z = field_0x0910.z * cM_ssin(field_0x091c);
|
|
field_0x0920.w = cM_scos(field_0x091c);
|
|
} else {
|
|
field_0x0920 = ZeroQuat;
|
|
}
|
|
}
|
|
|
|
int daObjStone_c::checkRollAngle() {
|
|
f32 dVar11 = 89.0f;
|
|
cXyz pos = current.pos;
|
|
pos.y += 50.0f;
|
|
|
|
cM3dGPla plane;
|
|
bool gnd_chk = fopAcM_gc_c::gndCheck(&pos);
|
|
bool triPla = dComIfG_Bgsp().GetTriPla(fopAcM_gc_c::mGndCheck, &plane);
|
|
f32 ground_y = fopAcM_gc_c::getGroundY();
|
|
|
|
if (gnd_chk && -G_CM3D_F_INF != ground_y && triPla) {
|
|
f32 tmp2 = cM_scos(cM_deg2s(dVar11 - 0.5f));
|
|
cXyz pos2 = plane.mNormal;
|
|
|
|
if (pos2.y < tmp2) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const static u16 l_carry_eff_id[3] = {0x859E, 0x859F, 0x85A0};
|
|
|
|
void daObjStone_c::set_carry_eff() {
|
|
cXyz pos;
|
|
|
|
if (mStoneType == 1) {
|
|
pos.setall(1.0f);
|
|
} else {
|
|
pos.setall(0.5f);
|
|
}
|
|
|
|
if (field_0x0950 == 3) {
|
|
for (int i = 0; i < 3; i++) {
|
|
field_0x0964[i] =
|
|
dComIfGp_particle_set(l_carry_eff_id[i], ¤t.pos, 0, &pos, 0xFF, 0, 0xFFFFFFFF,
|
|
0, 0, 0); // float literal inline
|
|
if (field_0x0964[i] != 0) {
|
|
field_0x0964[i]->becomeImmortalEmitter();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void daObjStone_c::effect_delete(bool param_1) {
|
|
for (int i = 0; i < 3; i = i + 1) {
|
|
if (field_0x0964[i] != NULL) {
|
|
if ((field_0x0964[i]->getAge() > 5 &&
|
|
field_0x0964[i]->getParticleNumber() == 0) ||
|
|
param_1)
|
|
{
|
|
field_0x0964[i]->becomeInvalidEmitter();
|
|
field_0x0964[i]->quitImmortalEmitter();
|
|
field_0x0964[i] = NULL;
|
|
} else {
|
|
field_0x0964[i]->setGlobalTranslation(current.pos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int daObjStone_c::draw() {
|
|
g_env_light.settingTevStruct(8, ¤t.pos, &tevStr);
|
|
g_env_light.setLightTevColorType_MAJI(mpModel, &tevStr);
|
|
mDoExt_modelUpdateDL(mpModel);
|
|
|
|
if (!model) {
|
|
f32 shadow_size = l_shadow_size[mStoneType];
|
|
GXTexObj* pTex = dDlst_shadowControl_c::getSimpleTex();
|
|
cXyz pos = current.pos;
|
|
|
|
dComIfGd_setSimpleShadow(&pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
|
|
1.0f, pTex);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int daObjStone_c::_delete() {
|
|
mSound.deleteObject();
|
|
fopAcM_offActor(this, fopAcM_GetSetId(this));
|
|
effect_delete(true);
|
|
dComIfG_resDelete(&mPhase, l_arcName[mStoneType]);
|
|
return 1;
|
|
}
|
|
|
|
static int daObjStone_Draw(daObjStone_c* i_this) {
|
|
return i_this->draw();
|
|
}
|
|
|
|
static int daObjStone_Execute(daObjStone_c* i_this) {
|
|
return i_this->execute();
|
|
}
|
|
|
|
static int daObjStone_Delete(daObjStone_c* i_this) {
|
|
return i_this->_delete();
|
|
}
|
|
|
|
static int daObjStone_Create(fopAc_ac_c* param_0) {
|
|
return static_cast<daObjStone_c*>(param_0)->create();
|
|
}
|
|
|
|
static actor_method_class l_daObjStone_Method = {
|
|
(process_method_func)daObjStone_Create,
|
|
(process_method_func)daObjStone_Delete,
|
|
(process_method_func)daObjStone_Execute,
|
|
(process_method_func)NULL,
|
|
(process_method_func)daObjStone_Draw,
|
|
};
|
|
|
|
actor_process_profile_definition g_profile_Obj_Stone = {
|
|
fpcLy_CURRENT_e, // mLayerID
|
|
8, // mListID
|
|
fpcPi_CURRENT_e, // mListPrio
|
|
PROC_Obj_Stone, // mProcName
|
|
&g_fpcLf_Method.base, // sub_method
|
|
sizeof(daObjStone_c), // mSize
|
|
0, // mSizeOther
|
|
0, // mParameters
|
|
&g_fopAc_Method.base, // sub_method
|
|
511, // mPriority
|
|
&l_daObjStone_Method, // sub_method
|
|
0x40100, // mStatus
|
|
fopAc_ACTOR_e, // mActorType
|
|
fopAc_CULLSPHERE_CUSTOM_e, // cullType
|
|
};
|