mirror of
https://github.com/zeldaret/tww.git
synced 2026-05-23 06:54:16 -04:00
a5641b0ba9
remove a bunch of externs
1309 lines
42 KiB
C++
1309 lines
42 KiB
C++
//
|
|
// Generated by dtk
|
|
// Translation Unit: d_a_arrow.cpp
|
|
//
|
|
|
|
#include "d/actor/d_a_arrow.h"
|
|
#include "JSystem/JKernel/JKRHeap.h"
|
|
#include "m_Do/m_Do_mtx.h"
|
|
#include "d/d_com_inf_game.h"
|
|
#include "d/d_procname.h"
|
|
#include "d/d_npc.h"
|
|
#include "d/d_item_data.h"
|
|
#include "d/actor/d_a_player.h"
|
|
#include "d/actor/d_a_player_link.h"
|
|
#include "d/d_jnt_hit.h"
|
|
#include "d/d_s_play.h"
|
|
#include "dolphin/types.h"
|
|
|
|
// Needed for the .data section to match.
|
|
static f32 dummy1[3] = {1.0f, 1.0f, 1.0f};
|
|
static f32 dummy2[3] = {1.0f, 1.0f, 1.0f};
|
|
|
|
s16 daArrow_c::m_count;
|
|
|
|
const char daArrow_c::m_arc_name[] = "Link";
|
|
|
|
const dCcD_SrcCps daArrow_c::m_at_cps_src = {
|
|
// dCcD_SrcGObjInf
|
|
{
|
|
/* Flags */ 0,
|
|
/* SrcObjAt Type */ AT_TYPE_NORMAL_ARROW,
|
|
/* SrcObjAt Atp */ 2,
|
|
/* SrcObjAt SPrm */ 0xB,
|
|
/* SrcObjTg Type */ 0,
|
|
/* SrcObjTg SPrm */ 0,
|
|
/* SrcObjCo SPrm */ 0,
|
|
/* SrcGObjAt Se */ 7,
|
|
/* SrcGObjAt HitMark */ 0xD,
|
|
/* SrcGObjAt Spl */ 0,
|
|
/* SrcGObjAt Mtrl */ 0,
|
|
/* SrcGObjAt GFlag */ 0,
|
|
/* SrcGObjTg Se */ 0,
|
|
/* SrcGObjTg HitMark */ 0,
|
|
/* SrcGObjTg Spl */ 0,
|
|
/* SrcGObjTg Mtrl */ 0,
|
|
/* SrcGObjTg GFlag */ 0,
|
|
/* SrcGObjCo GFlag */ 0,
|
|
},
|
|
// cM3dGCpsS
|
|
{
|
|
/* Start */ 0.0f, 0.0f, 0.0f,
|
|
/* End */ 0.0f, 0.0f, 0.0f,
|
|
/* Radius */ 5.0f,
|
|
},
|
|
};
|
|
|
|
const dCcD_SrcSph daArrow_c::m_co_sph_src = {
|
|
// dCcD_SrcGObjInf
|
|
{
|
|
/* Flags */ 0,
|
|
/* SrcObjAt Type */ 0,
|
|
/* SrcObjAt Atp */ 0,
|
|
/* SrcObjAt SPrm */ 0,
|
|
/* SrcObjTg Type */ 0,
|
|
/* SrcObjTg SPrm */ 0,
|
|
/* SrcObjCo SPrm */ 0x119,
|
|
/* SrcGObjAt Se */ 7,
|
|
/* SrcGObjAt HitMark */ 0,
|
|
/* SrcGObjAt Spl */ 0,
|
|
/* SrcGObjAt Mtrl */ 0,
|
|
/* SrcGObjAt GFlag */ 0,
|
|
/* SrcGObjTg Se */ 0,
|
|
/* SrcGObjTg HitMark */ 0,
|
|
/* SrcGObjTg Spl */ 0,
|
|
/* SrcGObjTg Mtrl */ 0,
|
|
/* SrcGObjTg GFlag */ 0x04,
|
|
/* SrcGObjCo GFlag */ 0,
|
|
},
|
|
// cM3dGSphS
|
|
{
|
|
/* Center */ 0.0f, 0.0f, 0.0f,
|
|
/* Radius */ 25.0f,
|
|
},
|
|
};
|
|
|
|
/* 800D455C-800D457C .text createHeap_CB__FP10fopAc_ac_c */
|
|
static BOOL createHeap_CB(fopAc_ac_c* i_this) {
|
|
return ((daArrow_c*)i_this)->_createHeap();
|
|
}
|
|
|
|
/* 800D457C-800D4648 .text _createHeap__9daArrow_cFv */
|
|
BOOL daArrow_c::_createHeap() {
|
|
// arrowglitter.bdl for Light Arrows, arrow.bdl otherwise.
|
|
s32 modelFileIndex = (mArrowType == TYPE_LIGHT ? 0x38 : 0x37) & 0xFFFF;
|
|
J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes(m_arc_name, modelFileIndex);
|
|
JUT_ASSERT(190, modelData != 0);
|
|
|
|
mpModel = mDoExt_J3DModel__create(modelData, 0x00080000, 0x11000022);
|
|
if (!mpModel) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D4648-800D4668 .text atHit_CB__FP10fopAc_ac_cP12dCcD_GObjInfP10fopAc_ac_cP12dCcD_GObjInf */
|
|
void atHit_CB(fopAc_ac_c* i_this, dCcD_GObjInf* thisObjInf, fopAc_ac_c* hitActor, dCcD_GObjInf* hitObjInf) {
|
|
((daArrow_c*)i_this)->_atHit(thisObjInf, hitActor, hitObjInf);
|
|
}
|
|
|
|
/* 800D4668-800D47C0 .text _atHit__9daArrow_cFP12dCcD_GObjInfP10fopAc_ac_cP12dCcD_GObjInf */
|
|
void daArrow_c::_atHit(dCcD_GObjInf* thisObjInf, fopAc_ac_c* hitActor, dCcD_GObjInf* hitObjInf) {
|
|
// Keep track of which actor this arrow hit as well as the position the hit occurred at.
|
|
if (!hitActor) {
|
|
return;
|
|
}
|
|
if (!fopAc_IsActor(hitActor)) {
|
|
return;
|
|
}
|
|
if (!fopAcM_GetJntHit(hitActor)) {
|
|
return;
|
|
}
|
|
|
|
cXyz hitPos(*thisObjInf->GetAtHitPosP());
|
|
f32 hitDist = (hitPos - current.pos).abs();
|
|
if (hitDist < mNearestHitDist) {
|
|
mNearestHitDist = hitDist;
|
|
mHitActorProcID = fpcM_GetID(hitActor);
|
|
if (hitObjInf->ChkTgShield()) {
|
|
mbHitActor = false;
|
|
field_0x6ec = NULL;
|
|
} else {
|
|
mbHitActor = true;
|
|
field_0x6ec = hitActor;
|
|
}
|
|
mNearestHitPos = *thisObjInf->GetAtHitPosP();
|
|
}
|
|
}
|
|
|
|
/* 800D47C0-800D4814 .text checkCreater__9daArrow_cFv */
|
|
void daArrow_c::checkCreater() {
|
|
// Check if this arrow was fired by Princess Zelda (during the Ganondorf fight).
|
|
fopAc_ac_c* archer;
|
|
if (fopAcM_SearchByID(mParentPcId, &archer)) {
|
|
if (fpcM_GetName(archer) == PROC_PZ) {
|
|
mbShotByZelda = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 800D4814-800D48E8 .text setLightEffect__9daArrow_cFv */
|
|
void daArrow_c::setLightEffect() {
|
|
if (field_0x682 == mArrowType) {
|
|
if (mArrowType == TYPE_NORMAL) {
|
|
return;
|
|
}
|
|
if (!field_0x688) {
|
|
field_0x684 = fopAcM_createChild(
|
|
PROC_ARROW_LIGHTEFF, fpcM_GetID(this),
|
|
mArrowType, &field_0x6a8,
|
|
current.roomNo, &shape_angle, NULL, -1, NULL
|
|
);
|
|
if (field_0x684 != -1) {
|
|
field_0x688 = true;
|
|
}
|
|
}
|
|
} else {
|
|
fopAcM_delete(fopAcM_SearchByID(field_0x684));
|
|
field_0x688 = false;
|
|
}
|
|
field_0x682 = mArrowType;
|
|
}
|
|
|
|
/* 800D48E8-800D4994 .text setBlur__9daArrow_cFv */
|
|
void daArrow_c::setBlur() {
|
|
JPABaseEmitter* emitter = mPtclFollowCb.getEmitter();
|
|
if (!emitter) {
|
|
return;
|
|
}
|
|
s32 alpha = emitter->getGlobalAlpha();
|
|
if (alpha - 50 <= 0) {
|
|
mPtclFollowCb.end();
|
|
} else {
|
|
emitter->setGlobalAlpha(alpha - 50);
|
|
}
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(field_0x67c);
|
|
emitter->setGlobalRTMatrix(mDoMtx_stack_c::get());
|
|
}
|
|
|
|
/* 800D4994-800D4A04 .text createBlur__9daArrow_cFv */
|
|
void daArrow_c::createBlur() {
|
|
if (!mPtclFollowCb.getEmitter()) {
|
|
dComIfGp_particle_setP1(0x48, ¤t.pos, NULL, NULL, 0xFF, &mPtclFollowCb);
|
|
}
|
|
}
|
|
|
|
/* 800D4A04-800D4ADC .text setArrowShootSe__9daArrow_cFv */
|
|
void daArrow_c::setArrowShootSe() {
|
|
static const s32 se[8] = {
|
|
0,
|
|
0,
|
|
JA_SE_LK_FIT_FIRE_ARROW,
|
|
JA_SE_LK_SHOOT_FIRE_ARROW,
|
|
JA_SE_LK_FIT_ICE_ARROW,
|
|
JA_SE_LK_SHOOT_ICE_ARROW,
|
|
JA_SE_LK_FIT_LIGHT_ARROW,
|
|
JA_SE_LK_SHOOT_LIGHT_ARROW,
|
|
};
|
|
|
|
if (mArrowType == TYPE_NORMAL) {
|
|
return;
|
|
}
|
|
|
|
fopAcM_seStartCurrent(this, se[mArrowType*2+0], 0);
|
|
|
|
fopAcM_seStartCurrent(this, se[mArrowType*2+1], 0);
|
|
}
|
|
|
|
/* 800D4ADC-800D4B70 .text setDrawShapeMaterial__9daArrow_cFv */
|
|
void daArrow_c::setDrawShapeMaterial() {
|
|
struct ArrowAttackInfo {
|
|
u32 mAtType;
|
|
u8 mAtp;
|
|
u16 mTipJointIdx;
|
|
};
|
|
static const ArrowAttackInfo arrow_mat[] = {
|
|
{
|
|
/* mAtType */ AT_TYPE_NORMAL_ARROW,
|
|
/* mAtp */ 2,
|
|
/* mTipJointIdx */ 4,
|
|
},
|
|
{
|
|
/* mAtType */ AT_TYPE_FIRE_ARROW,
|
|
/* mAtp */ 4,
|
|
/* mTipJointIdx */ 2,
|
|
},
|
|
{
|
|
/* mAtType */ AT_TYPE_ICE_ARROW,
|
|
/* mAtp */ 4,
|
|
/* mTipJointIdx */ 3,
|
|
},
|
|
{
|
|
/* mAtType */ AT_TYPE_LIGHT_ARROW,
|
|
/* mAtp */ 0xFF,
|
|
/* mTipJointIdx */ 0,
|
|
},
|
|
};
|
|
|
|
mCps.SetAtType(arrow_mat[mArrowType].mAtType);
|
|
mCps.SetAtAtp(arrow_mat[mArrowType].mAtp);
|
|
|
|
if (mbShotByZelda) {
|
|
mCps.SetAtAtp(4);
|
|
mCps.SetAtType(arrow_mat[0].mAtType);
|
|
mCps.OnAtSPrmBit(0xE);
|
|
}
|
|
|
|
if (arrow_mat[mArrowType].mTipJointIdx != 0) {
|
|
J3DModelData* modelData = mpModel->getModelData();
|
|
J3DJoint* tipJoint = modelData->getJointNodePointer(arrow_mat[mArrowType].mTipJointIdx);
|
|
mpTipMat = tipJoint->getMesh();
|
|
}
|
|
}
|
|
|
|
/* 800D4B70-800D4D98 .text arrowShooting__9daArrow_cFv */
|
|
void daArrow_c::arrowShooting() {
|
|
field_0x6a8 = current.pos;
|
|
f32 xCos = cM_scos(current.angle.x);
|
|
speed.x = 200.0f * cM_ssin(current.angle.y) * xCos;
|
|
speed.y = 200.0f * cM_ssin(current.angle.x);
|
|
speed.z = 200.0f * cM_scos(current.angle.y) * xCos;
|
|
|
|
setArrowShootSe();
|
|
|
|
if (mArrowType == TYPE_LIGHT && !mbShotByZelda) {
|
|
if (strcmp(dComIfGp_getStartStageName(), "GanonK") != 0) {
|
|
// Not in Puppet Ganon's boss room.
|
|
mCps.SetAtSpl((dCcG_At_Spl)0xB);
|
|
}
|
|
}
|
|
|
|
field_0x67c = shape_angle;
|
|
|
|
createBlur();
|
|
|
|
field_0x602 = m_count;
|
|
m_count += 1;
|
|
if (m_count == 5) {
|
|
m_count = 0;
|
|
}
|
|
|
|
cXyz end = current.pos + speed*1.25f;
|
|
mCps.SetStartEnd(current.pos, end);
|
|
mCps.SetR(5.0f);
|
|
mCps.CalcAtVec();
|
|
|
|
dComIfG_Ccsp()->Set(&mCps);
|
|
// Using the dComIfG_Ccsp inline here breaks the match.
|
|
// dComIfG_Ccsp()->SetMass(&mCps, 1);
|
|
g_dComIfG_gameInfo.play.mCcS.SetMass(&mCps, 1);
|
|
|
|
mbHitActor = false;
|
|
mNearestHitPos = end;
|
|
mNearestHitDist = MAXFLOAT;
|
|
}
|
|
|
|
/* 800D4D98-800D4DC0 .text arrowUseMp__9daArrow_cFv */
|
|
void daArrow_c::arrowUseMp() {
|
|
static const s16 use_mp[4] = {
|
|
-0, // Normal Arrows
|
|
-1, // Fire Arrows
|
|
-1, // Ice Arrows
|
|
-2, // Light Arrows
|
|
};
|
|
|
|
dComIfGp_setItemMagicCount(use_mp[mArrowType]);
|
|
}
|
|
|
|
// This is a fake inline (not present in debug maps) which is required for ShieldReflect to match.
|
|
// It's possible that an inline similar to this was added to the final game even though it didn't exist in the demo,
|
|
// as this section of code was missing from the demo's version of ShieldReflect.
|
|
inline void setSphereCoordsFromXYAngles(cXyz& xyz, f32 mag, s16 targetAngleX, s16 targetAngleY) {
|
|
f32 normZ;
|
|
f32 normY;
|
|
f32 normX;
|
|
normX = cM_ssin(targetAngleY) * cM_scos(targetAngleX);
|
|
normY = -cM_ssin(targetAngleX);
|
|
normZ = cM_scos(targetAngleY) * cM_scos(targetAngleX);
|
|
xyz.x = normX * mag;
|
|
xyz.y = normY * mag;
|
|
xyz.z = normZ * mag;
|
|
}
|
|
|
|
/* 800D4DC0-800D50A0 .text ShieldReflect__9daArrow_cFv */
|
|
void daArrow_c::ShieldReflect() {
|
|
f32 vel = speed.abs();
|
|
|
|
daPy_lk_c* link = daPy_getPlayerLinkActorClass();
|
|
s16 targetAngleY = link->shape_angle.y + link->getBodyAngleY();
|
|
s16 targetAngleX = link->getBodyAngleX();
|
|
|
|
fopAc_ac_c* ganondorf;
|
|
if (fopAcM_SearchByName(PROC_GND, &ganondorf) && dComIfGp_getAttention().LockonTruth() && dComIfGp_getAttention().LockonTarget(0) == ganondorf) {
|
|
cXyz ganondorfChestPos = ganondorf->current.pos;
|
|
ganondorfChestPos.y = g_regHIO.mChild[8].mFloatRegs[0] + 130.0f;
|
|
targetAngleX = -cLib_targetAngleX(&link->current.pos, &ganondorfChestPos);
|
|
fpcM_SetParam(ganondorf, 0x23);
|
|
field_0x608 = g_regHIO.mChild[0].mShortRegs[3] + 15;
|
|
mpSparkleEmitter = dComIfGp_particle_set(0x3EE, &link->current.pos);
|
|
}
|
|
|
|
// // Regswaps without creating a fake inline.
|
|
// // f1 -> f3: normY
|
|
// // f3 -> f1: normZ
|
|
// f32 normZ;
|
|
// f32 normY;
|
|
// f32 normX;
|
|
// normX = cM_ssin(targetAngleY) * cM_scos(targetAngleX);
|
|
// normY = -cM_ssin(targetAngleX);
|
|
// normZ = cM_scos(targetAngleY) * cM_scos(targetAngleX);
|
|
// speed.x = normX * vel;
|
|
// speed.y = normY * vel;
|
|
// speed.z = normZ * vel;
|
|
setSphereCoordsFromXYAngles(speed, vel, targetAngleX, targetAngleY);
|
|
|
|
shape_angle.x = cM_atan2s(-speed.y, -speed.absXZ());
|
|
shape_angle.y = cM_atan2s(-speed.x, -speed.z);
|
|
shape_angle.z = 0;
|
|
}
|
|
|
|
/* 800D50A0-800D5388 .text check_water_in__9daArrow_cFv */
|
|
bool daArrow_c::check_water_in() {
|
|
u8 prev_field_0x699 = field_0x699;
|
|
field_0x699 = daPy_lk_c::setItemWaterEffect(this, field_0x699, 1);
|
|
if (prev_field_0x699 == 0 && field_0x699 == 1) {
|
|
f32 waterY;
|
|
fopAcM_getWaterY(¤t.pos, &waterY);
|
|
|
|
f32 deltaY = fabs(next.pos.y - current.pos.y);
|
|
f32 waterDist = fabs(waterY - current.pos.y);
|
|
cXyz waterHitPos;
|
|
if (deltaY < 1.0f) {
|
|
waterHitPos = current.pos;
|
|
} else {
|
|
f32 weight = waterDist / deltaY;
|
|
if (weight > 1.0f) {
|
|
weight = 1.0f;
|
|
}
|
|
waterHitPos = (next.pos * weight) + (current.pos * (1.0f - weight));
|
|
}
|
|
|
|
mCurrProcFunc = &procWater;
|
|
fopAcM_SetParam(this, 4);
|
|
|
|
if (mArrowType == TYPE_FIRE) {
|
|
mInWaterTimer = 1;
|
|
dComIfGp_particle_setP1(0x35A, &waterHitPos);
|
|
if (field_0x6e4 == 0) {
|
|
dKy_arrowcol_chg_on(¤t.pos, 0);
|
|
}
|
|
} else if (mArrowType == TYPE_ICE) {
|
|
mInWaterTimer = 300;
|
|
fopAcM_createChild(
|
|
PROC_ARROW_ICEEFF, fpcM_GetID(this), mArrowType,
|
|
&waterHitPos, current.roomNo, ¤t.angle, NULL, -1, NULL
|
|
);
|
|
if (field_0x6e4 == 0) {
|
|
dKy_arrowcol_chg_on(¤t.pos, 1);
|
|
}
|
|
} else if (mArrowType == TYPE_LIGHT) {
|
|
dComIfGp_particle_setP1(0x2A1, &waterHitPos);
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_LIGHT_ARW_EFF, 0);
|
|
if (field_0x6e4 == 0) {
|
|
dKy_arrowcol_chg_on(¤t.pos, 2);
|
|
}
|
|
mInWaterTimer = 1;
|
|
} else {
|
|
mInWaterTimer = 1;
|
|
}
|
|
|
|
field_0x698 = 0;
|
|
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* 800D5388-800D53AC .text changeArrowMp__9daArrow_cFv */
|
|
BOOL daArrow_c::changeArrowMp() {
|
|
u8 magic = dComIfGs_getMagic();
|
|
return magic >= 1;
|
|
}
|
|
|
|
/* 800D53AC-800D553C .text changeArrowType__9daArrow_cFv */
|
|
daArrow_c* daArrow_c::changeArrowType() {
|
|
u8 origArrowType = mArrowType;
|
|
mBtkFrame = 0.0f;
|
|
|
|
daArrow_c* ret = this;
|
|
|
|
if (mArrowType == TYPE_NORMAL) {
|
|
if (dComIfGs_getMagic() < 1 || !(dComIfGs_getItem(0xC) == MAGIC_ARROW || dComIfGs_getItem(0xC) == LIGHT_ARROW)) {
|
|
mArrowType = TYPE_NORMAL;
|
|
} else {
|
|
mArrowType = TYPE_FIRE;
|
|
}
|
|
} else if (mArrowType == TYPE_FIRE) {
|
|
if (dComIfGs_getMagic() < 1 || !(dComIfGs_getItem(0xC) == MAGIC_ARROW || dComIfGs_getItem(0xC) == LIGHT_ARROW)) {
|
|
mArrowType = TYPE_NORMAL;
|
|
} else {
|
|
mArrowType = TYPE_ICE;
|
|
}
|
|
} else if (mArrowType == TYPE_ICE) {
|
|
if (dComIfGs_getMagic() < 2 || dComIfGs_getItem(0xC) != LIGHT_ARROW) {
|
|
mArrowType = TYPE_NORMAL;
|
|
} else {
|
|
mArrowType = TYPE_LIGHT;
|
|
}
|
|
} else if (mArrowType == TYPE_LIGHT) {
|
|
mArrowType = TYPE_NORMAL;
|
|
}
|
|
|
|
if (mArrowType != origArrowType) {
|
|
m_keep_type = mArrowType;
|
|
daArrow_c* newNockedArrow = (daArrow_c*)fopAcM_fastCreate(PROC_ARROW, 0, ¤t.pos, current.roomNo, NULL, NULL, -1, NULL, NULL);
|
|
if (!newNockedArrow) {
|
|
mArrowType = origArrowType;
|
|
m_keep_type = origArrowType;
|
|
setDrawShapeMaterial();
|
|
ret = this;
|
|
} else {
|
|
mArrowType = origArrowType;
|
|
fopAcM_delete(this);
|
|
ret = newNockedArrow;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* 800D553C-800D560C .text changeArrowTypeNotReady__9daArrow_cFv */
|
|
void daArrow_c::changeArrowTypeNotReady() {
|
|
if (m_keep_type == TYPE_NORMAL) {
|
|
if (dComIfGs_getMagic() < 1) {
|
|
return;
|
|
}
|
|
if (dComIfGs_getItem(0xC) == MAGIC_ARROW || dComIfGs_getItem(0xC) == LIGHT_ARROW) {
|
|
m_keep_type = TYPE_FIRE;
|
|
}
|
|
} else if (m_keep_type == TYPE_FIRE) {
|
|
if (dComIfGs_getMagic() < 1) {
|
|
return;
|
|
}
|
|
if (dComIfGs_getItem(0xC) == MAGIC_ARROW || dComIfGs_getItem(0xC) == LIGHT_ARROW) {
|
|
m_keep_type = TYPE_ICE;
|
|
}
|
|
} else if (m_keep_type == TYPE_ICE) {
|
|
if (dComIfGs_getMagic() >= 2 && dComIfGs_getItem(0xC) == LIGHT_ARROW) {
|
|
m_keep_type = TYPE_LIGHT;
|
|
} else {
|
|
m_keep_type = TYPE_NORMAL;
|
|
}
|
|
} else if (m_keep_type == TYPE_LIGHT) {
|
|
m_keep_type = TYPE_NORMAL;
|
|
}
|
|
}
|
|
|
|
/* 800D560C-800D56B0 .text setRoomInfo__9daArrow_cFv */
|
|
void daArrow_c::setRoomInfo() {
|
|
u32 roomNo;
|
|
|
|
mGndChk.SetPos(¤t.pos);
|
|
f32 groundY = dComIfG_Bgsp()->GroundCross(&mGndChk);
|
|
if (groundY != -1000000000.0f) {
|
|
roomNo = dComIfG_Bgsp()->GetRoomId(mGndChk);
|
|
mTevStr.mEnvrIdxOverride = dComIfG_Bgsp()->GetPolyColor(mGndChk);
|
|
} else {
|
|
roomNo = dComIfGp_roomControl_getStayNo();
|
|
}
|
|
|
|
mTevStr.mRoomNo = roomNo;
|
|
mStts.SetRoomId(roomNo);
|
|
current.roomNo = roomNo;
|
|
}
|
|
|
|
/* 800D56B0-800D5854 .text setKeepMatrix__9daArrow_cFv */
|
|
void daArrow_c::setKeepMatrix() {
|
|
// Transform the arrow onto its archer's hand.
|
|
if (mbShotByZelda) {
|
|
fopNpc_npc_c* zelda;
|
|
fopAcM_SearchByID(mParentPcId, (fopAc_ac_c**)&zelda);
|
|
|
|
mDoMtx_stack_c::transS(0.7f, -0.07f, -0.2f);
|
|
mDoMtx_stack_c::XYZrotM(0x238E, 0x2CDF, 0x29BE);
|
|
|
|
// Copy the matrix of Zelda's hand_R1 joint to the arrow model.
|
|
// TODO: After daPz_c is implemented, this should use her daPz_c::getRightHandMatrix() inline method.
|
|
MtxP handMtx = zelda->mpMcaMorf->getModel()->mpNodeMtx[0x13];
|
|
cMtx_concat(handMtx, mDoMtx_stack_c::get(), mDoMtx_stack_c::get());
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
|
|
MtxP mtx = mDoMtx_stack_c::get();
|
|
current.pos.set(mtx[0][3], mtx[1][3], mtx[2][3]);
|
|
|
|
mDoMtx_MtxToRot(mDoMtx_stack_c::get(), &shape_angle);
|
|
current.angle.y = shape_angle.y;
|
|
current.angle.x = -shape_angle.x;
|
|
} else {
|
|
daPy_py_c* player = daPy_getPlayerActorClass();
|
|
|
|
mDoMtx_stack_c::transS(7.6f, -0.8f, -0.5f);
|
|
// This function takes three signed shorts, but one of the literals passed here is unsigned.
|
|
// X rotation must be a float literal to force the compiler to pass an unsigned short.
|
|
// Z rotation must be an int literal to pass a signed short as normal.
|
|
mDoMtx_stack_c::XYZrotM((248.5f*65536)/360, 0x238E, -0x6333);
|
|
|
|
MtxP handMtx = player->getLeftHandMatrix();
|
|
cMtx_concat(handMtx, mDoMtx_stack_c::get(), mDoMtx_stack_c::get());
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
|
|
MtxP mtx = mDoMtx_stack_c::get();
|
|
current.pos.set(mtx[0][3], mtx[1][3], mtx[2][3]);
|
|
|
|
mDoMtx_MtxToRot(mDoMtx_stack_c::get(), &shape_angle);
|
|
current.angle.y = shape_angle.y;
|
|
current.angle.x = -shape_angle.x;
|
|
}
|
|
}
|
|
|
|
/* 800D5854-800D5A70 .text setStopActorMatrix__9daArrow_cFv */
|
|
void daArrow_c::setStopActorMatrix() {
|
|
s16 xRot = 0;
|
|
if (cLib_calcTimer(&field_0x604) != 0) {
|
|
f32 temp = (field_0x604 / 40.0f);
|
|
xRot = 1024.0f * temp*temp * cM_ssin(field_0x604 * 0x52FB);
|
|
}
|
|
fopAc_ac_c* hitActor = fopAcM_SearchByID(mHitActorProcID);
|
|
if (!hitActor) {
|
|
return;
|
|
}
|
|
JntHit_c* jntHit = fopAcM_GetJntHit(hitActor);
|
|
if (!jntHit) {
|
|
return;
|
|
}
|
|
J3DModel* hitModel = jntHit->getModel();
|
|
|
|
static cXyz offset_arrow_pos(0.0f, 0.0f, -50.0f);
|
|
|
|
mDoMtx_stack_c::copy(hitModel->mpNodeMtx[mHitJointIndex]);
|
|
csXyz hitJointRot;
|
|
mDoMtx_MtxToRot(mDoMtx_stack_c::get(), &hitJointRot);
|
|
|
|
mDoMtx_stack_c::transM(field_0x618);
|
|
mDoMtx_stack_c::ZXYrotM(field_0x6e6);
|
|
|
|
cXyz pos(0.0f, 0.0f, 0.0f);
|
|
mDoMtx_stack_c::multVecZero(&pos);
|
|
current.pos = pos;
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(hitJointRot);
|
|
mDoMtx_stack_c::ZXYrotM(field_0x6e6);
|
|
mDoMtx_stack_c::XrotM(xRot);
|
|
mDoMtx_stack_c::transM(offset_arrow_pos);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
}
|
|
|
|
/* 800D5A70-800D5B20 .text procWait__9daArrow_cFv */
|
|
BOOL daArrow_c::procWait() {
|
|
speedF = 0.0f;
|
|
setKeepMatrix();
|
|
cMtx_copy(mpModel->getBaseTRMtx(), field_0x6b4);
|
|
field_0x6e6 = shape_angle;
|
|
|
|
if (fopAcM_GetParam(this) == 1) {
|
|
if (!mbShotByZelda) {
|
|
arrowUseMp();
|
|
checkRestMp();
|
|
}
|
|
|
|
mCurrProcFunc = &procMove;
|
|
arrowShooting();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D5B20-800D6BF4 .text procMove__9daArrow_cFv */
|
|
BOOL daArrow_c::procMove() {
|
|
speedF = 100.0f;
|
|
current.pos += speed;
|
|
cXyz quarterStepPos = current.pos + speed*0.25f;
|
|
mLinChk.Set(&next.pos, &quarterStepPos, this);
|
|
field_0x6e6 = shape_angle;
|
|
|
|
cMtx_copy(mpModel->getBaseTRMtx(), field_0x6b4);
|
|
field_0x67c.z += 0x889;
|
|
|
|
s32 hitType = 0; // No hit
|
|
if (mCps.ChkAtHit()) {
|
|
cXyz temp12;
|
|
cXyz hitPos;
|
|
csXyz temp11;
|
|
if (mArrowType == TYPE_LIGHT && field_0x664 == 0 && mCps.ChkAtShieldHit() && fpcM_GetName(mCps.GetAtHitAc()) == PROC_PLAYER) {
|
|
mCps.GetAtHitAc();
|
|
hitPos = *mCps.GetAtHitPosP();
|
|
hitType = -1; // Reflected hit
|
|
field_0x664 = 1;
|
|
ShieldReflect();
|
|
} else {
|
|
fopAc_ac_c* hitActor;
|
|
BOOL hitWasBlocked;
|
|
s32 bHitActor = mbHitActor;
|
|
if (bHitActor) {
|
|
hitActor = field_0x6ec;
|
|
hitPos = mNearestHitPos;
|
|
hitWasBlocked = FALSE;
|
|
} else {
|
|
hitActor = mCps.GetAtHitAc();
|
|
hitPos = *mCps.GetAtHitPosP();
|
|
hitWasBlocked = mCps.ChkAtShieldHit();
|
|
}
|
|
|
|
if (hitActor) {
|
|
JntHit_c* jntHit = fopAcM_GetJntHit(hitActor);
|
|
if (mArrowType == TYPE_LIGHT) {
|
|
if (fpcM_GetName(mCps.GetAtHitAc()) == PROC_BGN
|
|
|| fpcM_GetName(mCps.GetAtHitAc()) == PROC_BGN2
|
|
|| fpcM_GetName(mCps.GetAtHitAc()) == PROC_BGN3) {
|
|
// Hit Puppet Ganon.
|
|
if (hitWasBlocked) {
|
|
field_0x6a8 = hitPos;
|
|
current.pos = hitPos - (speed * 0.25f);
|
|
|
|
if (field_0x6e4 == 0) {
|
|
dKy_arrowcol_chg_on(¤t.pos, 2);
|
|
}
|
|
|
|
mCurrProcFunc = &procStop_BG;
|
|
fopAcM_OnStatus(this, fopAcStts_UNK4000_e);
|
|
fopAcM_SetParam(this, 2);
|
|
field_0x604 = 0x28;
|
|
|
|
dComIfG_Bgsp()->i_GetTriPla(mLinChk);
|
|
|
|
csXyz temp10;
|
|
temp10.x = cM_atan2s(speed.y, speed.absXZ());
|
|
temp10.y = cM_atan2s(speed.x, speed.z);
|
|
temp10.z = 0;
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(temp10.x, temp10.y, 0);
|
|
cMtx_copy(mDoMtx_stack_c::get(), field_0x6b4);
|
|
|
|
dComIfGp_particle_setP1(0x2A1, &field_0x6a8, &temp10);
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_LIGHT_ARW_EFF, 0);
|
|
fopAcM_delete(this);
|
|
} else {
|
|
hitType = 0; // No hit (pass through)
|
|
}
|
|
} else {
|
|
hitType = 0; // No hit (pass through)
|
|
}
|
|
} else if (hitWasBlocked) {
|
|
hitType = 1; // Blocked hit
|
|
} else if (jntHit) {
|
|
mHitJointIndex = jntHit->searchJntHitPosAngleOffset(&hitPos, &shape_angle, &temp12, &temp11);
|
|
if (mHitJointIndex >= 0) {
|
|
field_0x6e6 = temp11;
|
|
field_0x618 = temp12;
|
|
hitType = 2; // Hit a joint
|
|
} else if (mHitJointIndex == -3) {
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hitType > 0) {
|
|
field_0x604 = 0x28;
|
|
fopAcM_OnStatus(this, fopAcStts_UNK4000_e);
|
|
|
|
if (mPtclFollowCb.mpEmitter) {
|
|
mPtclFollowCb.end();
|
|
}
|
|
|
|
if (hitType == 1) { // Blocked hit
|
|
fopAcM_SetParam(this, 3);
|
|
mCurrProcFunc = &procReturn;
|
|
speed *= -0.1f;
|
|
speed.y += speed.absXZ();
|
|
current.pos = next.pos;
|
|
field_0x69c = 0x2C00;
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, 0);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
fopAcM_seStartCurrent(this, JA_SE_LK_ARROW_REBOUND, 0x20);
|
|
} else if (hitType == 2) { // Hit a joint
|
|
fpcM_SetParam(this, 2);
|
|
mCurrProcFunc = &procStop_Actor;
|
|
|
|
if (mArrowType == TYPE_FIRE) {
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_FIRE_ARW_EFF, 0);
|
|
field_0x698 = 0;
|
|
} else if (mArrowType == TYPE_ICE) {
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_ICE_ARW_EFF, 0);
|
|
} else if (mArrowType == TYPE_LIGHT) {
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_LIGHT_ARW_EFF, 0);
|
|
field_0x698 = 0;
|
|
}
|
|
|
|
setStopActorMatrix();
|
|
}
|
|
} else if (dComIfG_Bgsp()->LineCross(&mLinChk)) {
|
|
cXyz* linEnd = &mLinChk.GetLinP()->GetEndP();
|
|
field_0x6a8 = *linEnd;
|
|
current.pos = *linEnd - (speed * 0.25f);
|
|
|
|
if (!check_water_in()) {
|
|
s32 temp8;
|
|
switch (mArrowType) {
|
|
case TYPE_FIRE:
|
|
temp8 = 0;
|
|
break;
|
|
case TYPE_ICE:
|
|
temp8 = 1;
|
|
break;
|
|
case TYPE_LIGHT:
|
|
temp8 = 2;
|
|
break;
|
|
default:
|
|
temp8 = -1;
|
|
}
|
|
|
|
if (temp8 >= 0 && field_0x6e4 == 0) {
|
|
dKy_arrowcol_chg_on(¤t.pos, temp8);
|
|
}
|
|
|
|
mCurrProcFunc = &procStop_BG;
|
|
fopAcM_OnStatus(this, fopAcStts_UNK4000_e);
|
|
fopAcM_SetParam(this, 2);
|
|
field_0x604 = 0x28;
|
|
cM3dGPla* triPla = dComIfG_Bgsp()->i_GetTriPla(mLinChk);
|
|
|
|
csXyz temp10;
|
|
temp10.x = cM_atan2s(-triPla->mNormal.y, -triPla->mNormal.absXZ());
|
|
temp10.y = cM_atan2s(-triPla->mNormal.x, -triPla->mNormal.z);
|
|
temp10.z = 0;
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(temp10.x, temp10.y, 0);
|
|
cMtx_copy(mDoMtx_stack_c::get(), field_0x6b4);
|
|
|
|
if (mArrowType == TYPE_FIRE) {
|
|
dComIfGp_particle_setP1(0x29A, &field_0x6a8, &temp10);
|
|
dComIfGp_particle_setP1(0x29B, &field_0x6a8, &temp10);
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_FIRE_ARW_EFF, 0);
|
|
field_0x698 = 0;
|
|
} else if (mArrowType == TYPE_ICE) {
|
|
if (dComIfG_Bgsp()->ChkGrpInf(mLinChk, 0x200)) {
|
|
fopAcM_create(PROC_Obj_Magmarock, NULL, &field_0x6a8, current.roomNo, NULL, NULL, -1, NULL);
|
|
} else {
|
|
dComIfGp_particle_setP1(0x29E, &field_0x6a8, &temp10);
|
|
|
|
fopAcM_createChild(
|
|
PROC_ARROW_ICEEFF, fpcM_GetID(this),
|
|
mArrowType, &field_0x6a8,
|
|
current.roomNo, &field_0x6e6, NULL, -1, NULL
|
|
);
|
|
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_ICE_ARW_EFF, 0);
|
|
}
|
|
} else if (mArrowType == TYPE_LIGHT) {
|
|
dComIfGp_particle_setP1(0x2A1, &field_0x6a8, &temp10);
|
|
fopAcM_seStartCurrent(this, JA_SE_OBJ_LIGHT_ARW_EFF, 0);
|
|
field_0x698 = 0;
|
|
}
|
|
|
|
s32 attribCode = dComIfG_Bgsp()->GetAttributeCode(mLinChk);
|
|
s32 mtrlSndId = dComIfG_Bgsp()->GetMtrlSndId(mLinChk);
|
|
|
|
if (mArrowType == TYPE_NORMAL && (attribCode == 0x3 || attribCode == 0x14 || attribCode == 0xF || attribCode == 0x9 || attribCode == 0x15)) {
|
|
mCurrProcFunc = &procReturn;
|
|
fopAcM_SetParam(this, 3);
|
|
speed *= -0.1f;
|
|
speed.y += speed.absXZ();
|
|
current.pos = next.pos;
|
|
field_0x69c = 0x2C00;
|
|
csXyz temp9;
|
|
cM3d_CalcVecZAngle(triPla->mNormal, &temp9);
|
|
|
|
dComIfGp_particle_setP1(0xC, &field_0x6a8, &temp9);
|
|
fopAcM_seStartCurrent(this, JA_SE_LK_ARROW_REBOUND, mtrlSndId);
|
|
} else {
|
|
fopAcM_seStartCurrent(this, JA_SE_LK_ARROW_HIT, mtrlSndId);
|
|
}
|
|
}
|
|
} else if (check_water_in()) {
|
|
// Do nothing.
|
|
// There was probably some code here that got commented out.
|
|
}
|
|
|
|
if (mCurrProcFunc == &procWater) {
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, 0);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
} else {
|
|
if ((current.pos - field_0x6a8).abs() > 25000.0f) {
|
|
speed.y -= 2.0f;
|
|
if (speed.y < -100.0f) {
|
|
speed.y = -100.0f;
|
|
}
|
|
if (field_0x6a8.y > current.pos.y) {
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
} else if ((current.pos - field_0x6a8).abs() > 20000.0f) {
|
|
field_0x6e4 = 1;
|
|
}
|
|
|
|
createBlur();
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, 0);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
|
|
cXyz end = current.pos + speed*1.25f;
|
|
mCps.SetStartEnd(current.pos, end);
|
|
mCps.SetR(5.0f);
|
|
mCps.CalcAtVec();
|
|
|
|
dComIfG_Ccsp()->Set(&mCps);
|
|
// Using the dComIfG_Ccsp inline here breaks the match.
|
|
// dComIfG_Ccsp()->SetMass(&mCps, 1);
|
|
g_dComIfG_gameInfo.play.mCcS.SetMass(&mCps, 1);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D6BF4-800D6E70 .text procReturn__9daArrow_cFv */
|
|
BOOL daArrow_c::procReturn() {
|
|
speedF = 0.0f;
|
|
speed.y -= 2.0f;
|
|
current.pos += speed;
|
|
shape_angle.x += field_0x69c;
|
|
cXyz quarterStepPos = current.pos + speed*0.25f;
|
|
field_0x699 = daPy_lk_c::setItemWaterEffect(this, field_0x699, 1);
|
|
mLinChk.Set(&next.pos, &quarterStepPos, this);
|
|
setBlur();
|
|
|
|
if (dComIfG_Bgsp()->LineCross(&mLinChk)) {
|
|
cM3dGPla* triPla = dComIfG_Bgsp()->i_GetTriPla(mLinChk);
|
|
f32 temp2 = speed.abs();
|
|
cXyz temp1;
|
|
C_VECReflect(&speed, &triPla->mNormal, &temp1);
|
|
speed.x = temp1.x*temp2*0.5f;
|
|
speed.y = temp1.y*temp2*0.5f;
|
|
speed.z = temp1.z*temp2*0.5f;
|
|
|
|
s32 temp3 = -field_0x69c;
|
|
field_0x69c = (temp3 / 2);
|
|
triPla = dComIfG_Bgsp()->i_GetTriPla(mLinChk);
|
|
if (triPla->mNormal.y >= 0.5f) {
|
|
field_0x69a = 1;
|
|
}
|
|
} else if (field_0x69a && speed.y < 0.0f) {
|
|
fopAcM_delete(this);
|
|
}
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, 0);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D6E70-800D71F8 .text procStop_BG__9daArrow_cFv */
|
|
BOOL daArrow_c::procStop_BG() {
|
|
speedF = 0.0f;
|
|
|
|
if (!dComIfG_Bgsp()->ChkPolySafe(mLinChk)) {
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL temp2 = FALSE;
|
|
|
|
if (field_0x604 > 0) {
|
|
field_0x604--;
|
|
f32 temp4 = (field_0x604*(1/40.0f)) * 1024.0f * (field_0x604*(1/40.0f)) * cM_ssin(field_0x604*0x52FB);
|
|
shape_angle.x = field_0x6e6.x + temp4;
|
|
shape_angle.y = field_0x6e6.y;
|
|
temp2 = TRUE;
|
|
} else if (field_0x600) {
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
|
|
setBlur();
|
|
|
|
if (dComIfG_Bgsp()->ChkMoveBG(mLinChk)) {
|
|
dComIfG_Bgsp()->MoveBgTransPos(mLinChk, true, &field_0x6a8, ¤t.angle, &shape_angle);
|
|
temp2 = TRUE;
|
|
}
|
|
|
|
if (temp2) {
|
|
f32 xCos = cM_scos(shape_angle.x);
|
|
current.pos.x = field_0x6a8.x - cM_ssin(shape_angle.y) * 50.0f * xCos;
|
|
current.pos.y = field_0x6a8.y + cM_ssin(shape_angle.x) * 50.0f;
|
|
current.pos.z = field_0x6a8.z - cM_scos(shape_angle.y) * 50.0f * xCos;
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, 0);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
}
|
|
|
|
if (mArrowType == TYPE_NORMAL) {
|
|
mSph.SetC(current.pos);
|
|
dComIfG_Ccsp()->Set(&mSph);
|
|
|
|
if (field_0x6a0 == 0) {
|
|
field_0x600 = true;
|
|
field_0x698 = 0;
|
|
} else {
|
|
field_0x6a0--;
|
|
|
|
if (field_0x6a0 < 60) {
|
|
// This matches but probably isn't what they actually wrote.
|
|
u32 signBit = ((u32)field_0x6a0)>>31;
|
|
if ((((field_0x6a0&1) ^ signBit) - signBit) == 0) {
|
|
field_0x698 = 0;
|
|
} else {
|
|
field_0x698 = 1;
|
|
}
|
|
} else {
|
|
field_0x698 = 1;
|
|
}
|
|
}
|
|
|
|
if (mSph.ChkCoHit()) {
|
|
dComIfGp_getItemArrowNumCount(1);
|
|
fopAcM_createItemForSimpleDemo(¤t.pos, ARROW_10, -1, NULL, NULL, 0.0f, 0.0f);
|
|
mDoAud_seStart(JA_SE_CONSUMP_ITEM_GET, NULL, 0, 0);
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (mbShotByZelda) {
|
|
field_0x600 = true;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D71F8-800D727C .text procStop_Actor__9daArrow_cFv */
|
|
BOOL daArrow_c::procStop_Actor() {
|
|
speedF = 0.0f;
|
|
if (field_0x600) {
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
|
|
setBlur();
|
|
|
|
if (fopAcM_SearchByID(mHitActorProcID)) {
|
|
setStopActorMatrix();
|
|
} else {
|
|
field_0x600 = true;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D727C-800D72BC .text procWater__9daArrow_cFv */
|
|
BOOL daArrow_c::procWater() {
|
|
if (mInWaterTimer <= 0) {
|
|
fopAcM_delete(this);
|
|
return TRUE;
|
|
}
|
|
|
|
mInWaterTimer--;
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D72BC-800D72EC .text checkRestMp__9daArrow_cFv */
|
|
void daArrow_c::checkRestMp() {
|
|
static const s16 use_mp[4] = {
|
|
0, // Normal Arrows
|
|
1, // Fire Arrows
|
|
1, // Ice Arrows
|
|
2, // Light Arrows
|
|
};
|
|
|
|
u8 currMagic = dComIfGs_getMagic();
|
|
if (currMagic < use_mp[m_keep_type]) {
|
|
m_keep_type = 0;
|
|
}
|
|
}
|
|
|
|
/* 800D72EC-800D7320 .text setTypeByPlayer__9daArrow_cFv */
|
|
void daArrow_c::setTypeByPlayer() {
|
|
checkRestMp();
|
|
mArrowType = m_keep_type;
|
|
}
|
|
|
|
/* 800D7320-800D74FC .text createInit__9daArrow_cFv */
|
|
BOOL daArrow_c::createInit() {
|
|
if (mArrowType == TYPE_LIGHT) {
|
|
mpBtk = daPy_getPlayerLinkActorClass()->getLightArrowBtk();
|
|
} else {
|
|
mpBtk = daPy_getPlayerLinkActorClass()->getIceArrowBtk();
|
|
}
|
|
|
|
mCurrProcFunc = &procWait;
|
|
|
|
setKeepMatrix();
|
|
mCullMtx = mpModel->getBaseTRMtx();
|
|
mCull.mBox.mMin.x = -6.0f;
|
|
mCull.mBox.mMin.y = -6.0f;
|
|
mCull.mBox.mMin.z = 0.0f;
|
|
mCull.mBox.mMax.x = 6.0f;
|
|
mCull.mBox.mMax.y = 6.0f;
|
|
mCull.mBox.mMax.z = 65.0f;
|
|
|
|
mStts.Init(10, 0xFF, this);
|
|
mCps.Set(m_at_cps_src);
|
|
mCps.SetStts(&mStts);
|
|
mCps.SetAtHitCallback(&atHit_CB);
|
|
mSph.Set(m_co_sph_src);
|
|
mSph.SetStts(&mStts);
|
|
|
|
field_0x602 = -1;
|
|
|
|
if (mArrowType != TYPE_LIGHT) {
|
|
J3DModelData* modelData = mpModel->getModelData();
|
|
modelData->getJointNodePointer(4)->getMesh()->getShape()->hide();
|
|
modelData->getJointNodePointer(2)->getMesh()->getShape()->hide();
|
|
modelData->getJointNodePointer(3)->getMesh()->getShape()->hide();
|
|
modelData->getJointNodePointer(3)->getMesh()->getNext()->getShape()->hide();
|
|
}
|
|
setDrawShapeMaterial();
|
|
|
|
field_0x698 = 1;
|
|
field_0x699 = 0;
|
|
field_0x69a = 0;
|
|
field_0x69c = 0;
|
|
field_0x6a0 = 300;
|
|
mInWaterTimer = 0;
|
|
field_0x6e4 = 0;
|
|
field_0x688 = 0;
|
|
field_0x664 = 0;
|
|
field_0x604 = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D74FC-800D7820 .text _execute__9daArrow_cFv */
|
|
BOOL daArrow_c::_execute() {
|
|
if (mbShotByZelda) {
|
|
if (field_0x664 == 0) {
|
|
if (daPy_getPlayerLinkActorClass()->checkPlayerGuard()) {
|
|
mCps.SetAtSpl((dCcG_At_Spl)0);
|
|
mCps.SetAtType(AT_TYPE_NORMAL_ARROW);
|
|
} else {
|
|
mCps.SetAtSpl((dCcG_At_Spl)0xB);
|
|
mCps.SetAtType(AT_TYPE_LIGHT_ARROW);
|
|
}
|
|
} else {
|
|
mCps.SetAtSpl((dCcG_At_Spl)0);
|
|
mCps.SetAtType(AT_TYPE_NORMAL_ARROW);
|
|
}
|
|
}
|
|
|
|
if (field_0x608 != 0) {
|
|
field_0x608--;
|
|
s8 temp4 = 0;
|
|
daPy_py_c* player = daPy_getPlayerActorClass();
|
|
|
|
cXyz offset;
|
|
offset.x = 0.0f;
|
|
offset.y = g_regHIO.mChild->mFloatRegs[8] + 45.0f;
|
|
offset.z = g_regHIO.mChild->mFloatRegs[9] + 30.0f;
|
|
mDoMtx_YrotS(*calc_mtx, player->shape_angle.y);
|
|
cXyz offsetOut;
|
|
MtxPosition(&offset, &offsetOut);
|
|
current.pos = player->current.pos + offsetOut;
|
|
|
|
mDoMtx_stack_c::transS(current.pos);
|
|
mDoMtx_stack_c::ZXYrotM(shape_angle.x, shape_angle.y, 0);
|
|
mpModel->setBaseTRMtx(mDoMtx_stack_c::get());
|
|
|
|
if (mpSparkleEmitter) {
|
|
if (field_0x608) {
|
|
f32 scale = field_0x608*2.0f;
|
|
if (scale > 7.0f) {
|
|
scale = 7.0f;
|
|
}
|
|
mpSparkleEmitter->setGlobalTranslation(current.pos.x, current.pos.y, current.pos.z);
|
|
JGeometry::TVec3<f32> scaleVec;
|
|
scaleVec.x = scale;
|
|
scaleVec.y = scale;
|
|
scaleVec.z = scale;
|
|
mpSparkleEmitter->setGlobalScale(scaleVec);
|
|
} else {
|
|
mpSparkleEmitter->becomeInvalidEmitter();
|
|
mpSparkleEmitter = NULL;
|
|
temp4 = 1;
|
|
}
|
|
}
|
|
if (temp4 == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (field_0x602 == m_count) {
|
|
field_0x600 = true;
|
|
}
|
|
|
|
if (mBtkFrame > 0.0f) {
|
|
mBtkFrame += 1.0f;
|
|
if (mBtkFrame >= mpBtk->getFrameMax()) {
|
|
mBtkFrame = 0.0f;
|
|
}
|
|
} else {
|
|
if (cM_rnd() < 0.02f) {
|
|
mBtkFrame += 1.0f;
|
|
}
|
|
}
|
|
|
|
setLightEffect();
|
|
|
|
if (mCurrProcFunc) {
|
|
(this->*mCurrProcFunc)();
|
|
}
|
|
|
|
mAttentionInfo.mPosition = current.pos;
|
|
mEyePos = current.pos;
|
|
setRoomInfo();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D7820-800D7960 .text _draw__9daArrow_cFv */
|
|
BOOL daArrow_c::_draw() {
|
|
if (!field_0x698) {
|
|
return TRUE;
|
|
}
|
|
|
|
g_env_light.settingTevStruct(TEV_TYPE_ACTOR, ¤t.pos, &mTevStr);
|
|
g_env_light.setLightTevColorType(mpModel, &mTevStr);
|
|
|
|
if (mArrowType != TYPE_LIGHT) {
|
|
mpTipMat->getShape()->show();
|
|
J3DMaterial* nextMat = mpTipMat->getNext();
|
|
if (nextMat) {
|
|
nextMat->getShape()->show();
|
|
}
|
|
}
|
|
|
|
mpBtk->setFrame(mBtkFrame);
|
|
dComIfGd_setListP1();
|
|
mDoExt_modelUpdateDL(mpModel);
|
|
dComIfGd_setList();
|
|
|
|
if (mArrowType != TYPE_LIGHT) {
|
|
mpTipMat->getShape()->hide();
|
|
J3DMaterial* nextMat = mpTipMat->getNext();
|
|
if (nextMat) {
|
|
nextMat->getShape()->hide();
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D7960-800D7A38 .text _create__9daArrow_cFv */
|
|
s32 daArrow_c::_create() {
|
|
fopAcM_SetupActor(this, daArrow_c);
|
|
|
|
checkCreater();
|
|
|
|
if (mbShotByZelda) {
|
|
mArrowType = TYPE_LIGHT;
|
|
} else {
|
|
setTypeByPlayer();
|
|
}
|
|
|
|
if (dComIfGp_getMiniGameType() == 8) {
|
|
mArrowType = TYPE_NORMAL;
|
|
}
|
|
|
|
const static u32 heap_size[] = {
|
|
0x1300,
|
|
0x1300,
|
|
0x1300,
|
|
0x820,
|
|
};
|
|
if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)&createHeap_CB, heap_size[mArrowType])) {
|
|
return cPhs_ERROR_e;
|
|
}
|
|
|
|
// Using the enum here breaks the match.
|
|
// return createInit() ? cPhs_COMPLEATE_e : cPhs_ERROR_e;
|
|
return createInit() ? 4 : 5;
|
|
}
|
|
|
|
/* 800D7A38-800D7DB4 .text __ct__9daArrow_cFv */
|
|
daArrow_c::daArrow_c() : mPtclFollowCb(0, 0) {}
|
|
|
|
/* 800D81D0-800D8200 .text _delete__9daArrow_cFv */
|
|
BOOL daArrow_c::_delete() {
|
|
mPtclFollowCb.end();
|
|
return TRUE;
|
|
}
|
|
|
|
/* 800D8200-800D8220 .text daArrowCreate__FPv */
|
|
s32 daArrowCreate(void* i_this) {
|
|
return ((daArrow_c*)i_this)->_create();
|
|
}
|
|
|
|
/* 800D8220-800D8240 .text daArrowDelete__FPv */
|
|
BOOL daArrowDelete(void* i_this) {
|
|
return ((daArrow_c*)i_this)->_delete();
|
|
}
|
|
|
|
/* 800D8240-800D8260 .text daArrowExecute__FPv */
|
|
BOOL daArrowExecute(void* i_this) {
|
|
return ((daArrow_c*)i_this)->_execute();
|
|
}
|
|
|
|
/* 800D8260-800D8280 .text daArrowDraw__FPv */
|
|
BOOL daArrowDraw(void* i_this) {
|
|
return ((daArrow_c*)i_this)->_draw();
|
|
}
|
|
|
|
/* 800D8280-800D8288 .text daArrowIsDelete__FPv */
|
|
BOOL daArrowIsDelete(void* i_this) {
|
|
return TRUE;
|
|
}
|
|
|
|
actor_method_class daArrowMethodTable = {
|
|
(process_method_func)daArrowCreate,
|
|
(process_method_func)daArrowDelete,
|
|
(process_method_func)daArrowExecute,
|
|
(process_method_func)daArrowIsDelete,
|
|
(process_method_func)daArrowDraw,
|
|
};
|
|
|
|
actor_process_profile_definition g_profile_ARROW = {
|
|
/* LayerID */ fpcLy_CURRENT_e,
|
|
/* ListID */ 9,
|
|
/* ListPrio */ fpcLy_CURRENT_e,
|
|
/* ProcName */ PROC_ARROW,
|
|
/* Proc SubMtd */ &g_fpcLf_Method.mBase,
|
|
/* Size */ sizeof(daArrow_c),
|
|
/* SizeOther */ 0,
|
|
/* Parameters */ 0,
|
|
/* Leaf SubMtd */ &g_fopAc_Method.base,
|
|
/* Priority */ 0x01BF,
|
|
/* Actor SubMtd */ &daArrowMethodTable,
|
|
/* Status */ fopAcStts_UNK4000_e | fopAcStts_UNK40000_e,
|
|
/* Group */ fopAc_ACTOR_e,
|
|
/* CullType */ fopAc_CULLBOX_CUSTOM_e,
|
|
};
|