#include "d/col/bg/d_bg_s_acch.h" #include "d/a/d_a_player.h" #include "d/col/bg/d_bg_s.h" #include "d/col/c/c_bg_s_lin_chk.h" #include "d/col/c/c_bg_w.h" dBgS_AcchCir::dBgS_AcchCir() { mWallRR = 0.0f; field_0x44 = 0.0f; mWallH = 0.0f; mWallR = 0.0f; mWallHDirect = 0.0f; mWallAngleY = 0.0f; mFlags = 0; } dBgS_AcchCir::~dBgS_AcchCir() {} bool dBgS_AcchCir::ChkWallHit() const { bool ret = false; if (mFlags & WALL_HIT) { if (dBgS::GetInstance()->ChkPolySafe(*this)) { ret = true; } } return ret; } void dBgS_AcchCir::SetWallR(f32 wallR) { mWallR = wallR; } void dBgS_AcchCir::SetWall(f32 wallH, f32 wallR) { mWallH = wallH; SetWallR(wallR); } dBgS_Acch::dBgS_Acch() : mFlags(0), mpPos(nullptr), mpOldPos(nullptr), mSpeed(0.0f, 0.0f, 0.0f), mpSpeed(nullptr), mpAngle(nullptr), mpShapeAngle(nullptr), mBgIndex(0), field_0x094(0), field_0x098(0), mpMyObj(nullptr), mTblSize(0), mpAcchCir(nullptr), field_0x0A8(0.0f), field_0x0AC(0.0f), mGroundHeight(-1e9f), field_0x0B4(120.0f), field_0x0C8(0.0f), field_0x0CC(0.0f), mRoofHeight(1e9f), field_0x0D4(1.0f), field_0x0D8(0.0f), mpOutPolyInfo(nullptr), mRoofH_0x0E0(0.0f), mGroundH_0x0E4(0.0f), field_0x0E8(1e9f), field_0x1D0(-1.0f), field_0x2F4(1000.0f), field_0x390(0), field_0x394(0) { SetPolyPassChk(GetPolyPassChkInfo()); SetGrpPassChk(GetGrpPassChkInfo()); SetRoofNone(); mRoof.field_0x7C = 1; field_0x398.set(0.0f, 0.0f, 0.0f); field_0x3A4.set(0.0f, 0.0f, 0.0f); } dBgS_Acch::~dBgS_Acch() {} void dBgS_Acch::Set( mVec3_c *pPos, mVec3_c *pOldPos, dAcObjBase_c *pObj, int tblSize, dBgS_AcchCir *pAccCir, mVec3_c *pSpeed, mAng3_c *pAngle, mAng3_c *pShapeAngle ) { mpPos = pPos; mpOldPos = pOldPos; mpMyObj = pObj; mActorId = pObj->mID; mpSpeed = pSpeed; if (pSpeed) { mSpeed = *pSpeed; } else { mSpeed.set(0.0f, 0.0f, 0.0f); } mTblSize = tblSize; mpAcchCir = pAccCir; mpAngle = pAngle; mpShapeAngle = pShapeAngle; mGroundHeight = mpPos->y; field_0x1A8.Init(); } void dBgS_Acch::Set(dAcObjBase_c *pObj, int tblSize, dBgS_AcchCir *pAcchCir) { mTblSize = tblSize; mpAcchCir = pAcchCir; mpMyObj = pObj; mActorId = pObj->getID(); mpPos = &pObj->getPosition(); mpOldPos = &pObj->getOldPosition(); mpSpeed = &pObj->getVelocity(); if (mpSpeed) { mSpeed = pObj->getVelocity(); } else { mSpeed.set(0.0f, 0.0f, 0.0f); } mpAngle = &pObj->getAngle(); mpShapeAngle = &pObj->getRotation(); } bool dBgS_Acch::fn_8033f5b0(mVec3_c *pPos, mVec3_c *pOldPos, f32 height) { *pOldPos = *pPos; cBgS_LinChk line; mVec3_c v1, v2; v1 = *GetOldPos(); v1.y += height; v2 = *pPos; v2.y += height; line.Set2(v1, v2, mActorId); bool ret = false; line.SetExtChk(*this); if (dBgS::GetInstance()->LineCross(&line)) { ret = true; *pPos = line.mLin.mEnd; cM3dGPla pla; dBgS::GetInstance()->GetTriPla(line, &pla); if (!cBgW_CheckBGround(pla.mNormal.y)) { VEC3Add(pPos, pla.mNormal, pPos); pPos->y -= height; } } mpPos = pPos; mpOldPos = pOldPos; return ret; } void dBgS_Acch::GroundCheck(dBgS &bgs, bool param2) { if (!(mFlags & GRND_NONE)) { mVec3_c gnd_pos = *GetPos(); // This Ordering is weird f32 temp = (field_0x0B4 - field_0x0A8) + field_0x0AC; if (mFlags & ACCH_FLAG_0x20000) { if (temp <= 1.1f) { temp = 1.1f; } } gnd_pos.y += temp; if (!(mFlags & GND_THIN_CELLING_OFF)) { mVec3_c old_pos(*GetOldPos()); old_pos.y += 0.25f; mVec3_c pos(*GetPos()); bgs.MoveBgCrrPos(mGnd, Chk_0x10000000(), &old_pos, nullptr, nullptr, false, false); bgs.MoveBgCrrPos(mGnd, Chk_0x10000000(), &pos, nullptr, nullptr, false, false); cBgS_LinChk line; line.Set2(pos, old_pos, mActorId); line.SetExtChk(*this); line.mBackFlag = true; if (!bgs.LineCross(&line)) { dBgS_RoofChk roof; roof.mActorId = mGnd.mActorId; roof.SetPos(&pos); f32 roof_height = bgs.RoofChk(&roof); cM3dGPla plane; if (roof_height != 1e9f) { bgs.GetTriPla(roof, &plane); if (gnd_pos.y > roof_height) { gnd_pos.y = roof_height; } } } } field_0x0AC = 0.0f; if (gnd_pos.y > mRoofHeight) { gnd_pos.y = mRoofHeight + 0.25f; } if (gnd_pos.y < mpPos->y + field_0x0E8 && mpPos->y + field_0x0E8 < (field_0x0B4 - field_0x0A8) + field_0x0AC + mpPos->y) { gnd_pos.y = mpPos->y + field_0x0E8; } mGnd.SetExtChk(*this); mGnd.SetPos(&gnd_pos); mGroundHeight = bgs.GroundCross(&mGnd); Clr_0x10000000(); if (mGroundHeight != -1e9f) { dBgS::GetInstance()->SetLightingCode(GetMyObj(), mGnd); field_0x0CC = mGroundHeight + field_0x0A8; if (field_0x0CC > field_0x0C8) { mpPos->y = field_0x0CC; if (ChkClrSpeedY() && mpSpeed) { mpSpeed->y = 0.0f; } bgs.GetTriPla(mGnd, &mPlane_0x0B8); SetGroundFind(); if (param2) { SetGroundHit(); } Set_0x10000000(); if (!Chk_0x8000000() && !Chk_0x80000000()) { Set_0x8000000(); bgs.RideCallBack(mGnd, GetMyObj()); } if (!(Chk_0x4000000())) { SetGroundLanding(); } } } if (Chk_0x4000000() && !i_ChkGroundHit()) { SetGroundAway(); } } else { mGroundHeight = -1e9f; } } void dBgS_Acch::RoofCheck(dBgS &bgs) { if (mGroundHeight == -1e9f) { return; } if (mFlags & LINE_DOWN && field_0x0CC > field_0x0D8 && (mGroundHeight <= mRoofHeight || cM3d_IsZero(mGroundHeight - mRoofHeight))) { mpPos->y = (mGroundHeight + mRoofHeight) * 0.5f; } else if (mpPos->y > field_0x0D8 && field_0x0D8 > mGroundHeight) { mpPos->y = field_0x0D8; } if (mFlags & ROOF_NONE) { return; } if (mGroundHeight >= mRoofHeight) { mRoof.SetExtChk(*this); ClrRoofHit(); mVec3_c roof_pos = *GetPos(); roof_pos.y -= 0.25f; mRoof.SetPos(&roof_pos); mRoofHeight = bgs.RoofChk(&mRoof); } } void dBgS_Acch::GroundRoofProc(dBgS &bgs, bool param2) { field_0x0D8 = 1e9f; if (!(mFlags & ROOF_NONE)) { mRoof.SetExtChk(*this); ClrRoofHit(); mVec3_c roof_pos(*GetPos()); roof_pos.y -= 0.25f; mRoof.SetPos(&roof_pos); mRoofHeight = bgs.RoofChk(&mRoof); if (mRoofHeight != 1e9f) { if (mpPos->y + field_0x0D4 > mRoofHeight) { field_0x0D8 = mRoofHeight - field_0x0D4; SetRoofHit(); } else if (field_0x0C8 + field_0x0D4 > mRoofHeight) { field_0x0D8 = mRoofHeight - field_0x0D4; SetRoofHit(); } } } if (!(mFlags & GRND_NONE)) { mFlags &= ~GROUND_FIND; GroundCheck(bgs, param2); RoofCheck(bgs); } else { if (field_0x0D8 < mpPos->y) { mpPos->y = field_0x0D8; } mFlags &= ~ACCH_FLAG_0x10000000; mGroundHeight = -1e9f; } } void dBgS_Acch::LineCheck(dBgS &bgs) { if (!(mFlags & ACCH_FLAG_0x20000000)) { mFlags |= ACCH_FLAG_0x20000000; dBgS_RoofChk roof; roof.mActorId = mGnd.mActorId; mVec3_c roof_pos = *GetOldPos(); roof_pos.y -= 0.25f; roof.SetPos(&roof_pos); mRoofH_0x0E0 = dBgS::GetInstance()->RoofChk(&roof); dBgS_GndChk gnd; gnd.mActorId = mGnd.mActorId; mVec3_c gnd_pos = *GetOldPos(); gnd_pos.y += 0.25f; gnd.SetPos(&gnd_pos); mGroundH_0x0E4 = dBgS::GetInstance()->GroundCross(&gnd); } cBgS_LinChk line; field_0x0E8 = 1e9f; int i = 0; do { mVec3_c old_pos = *GetOldPos(); mVec3_c pos = *GetPos(); f32 cirWallH = GetWallH(i); if (mRoofH_0x0E0 - 0.25f < old_pos.y + cirWallH && mGroundH_0x0E4 + 0.25f > old_pos.y + cirWallH) { cirWallH = (mRoofH_0x0E0 + mGroundH_0x0E4) * 0.5f - old_pos.y; } else if (mRoofH_0x0E0 - 0.25f < old_pos.y + cirWallH) { cirWallH = (mRoofH_0x0E0 - old_pos.y) - 0.25f; } else if (mGroundH_0x0E4 + 0.25f > old_pos.y + cirWallH) { cirWallH = (mGroundH_0x0E4 - old_pos.y) + 0.25f; } if (field_0x0E8 > cirWallH) { field_0x0E8 = cirWallH; } old_pos.y += cirWallH; pos.y += cirWallH; if (GetSpeedY() < 0.0f) { if (GetMyObj() != nullptr && GetMyObj()->isActorPlayer() && !static_cast(GetMyObj())->CheckPlayerFly() && ChkLink()) { pos.y -= GetSpeedY(); } } if (old_pos.x != pos.x || old_pos.y != pos.y || old_pos.z != pos.z) { line.Set2(old_pos, pos, mActorId); if (ChkCirUnk0x8(i)) { line.mPreGroundChk = true; } else { line.mPreGroundChk = false; } if (ChkCirUnk0x10(i)) { line.mPreRoofChk = true; } else { line.mPreRoofChk = false; } line.SetExtChk(*this); if (bgs.LineCross(&line)) { *GetPos() = line.GetLinEnd(); OnLineCheckHit(); if (mpOutPolyInfo) { *mpOutPolyInfo = line; } cM3dGPla plane; bgs.GetTriPla(line, &plane); if (!cBgW_CheckBGround(plane.mNormal.y)) { mVec3_c *pPos = GetPos(); VEC3Add(*pPos, plane.mNormal, *pPos); if (!cM3d_IsZero( nw4r::math::FSqrt(plane.mNormal.x * plane.mNormal.x + plane.mNormal.z * plane.mNormal.z) )) { SetWallHDirect(i, GetPos()->y); } GetPos()->y -= GetWallH(i); } else { GetPos()->y -= 1.0f; mFlags |= ACCH_FLAG_0x20000; } } } i++; } while (i < GetTblSize()); } extern "C" void fn_80359C80(dBgS_SphChk *, cBgD_Vtx_t *, int, int, int, cM3dGPla *, void *); void dBgS_Acch::SphCheck() { f32 height = field_0x1D0; mSph.SetExtChk(*this); mSph.mCallback = fn_80359C80; if (height < 0.0f) { height = 1e9f; if (height > field_0x0A8 && field_0x0A8 > 0.0f) { height = field_0x0A8; } if (height > field_0x0D4 && field_0x0D4 > 1.0f) { height = field_0x0D4; } height *= 0.8f; } mSph.Set(mpPos, height); field_0x1A8.Init(); dBgS::GetInstance()->SphChk(&mSph, &field_0x1A8); field_0x1A8.CalcPos(mpPos); } void dBgS_Acch::CrrPos(dBgS &bgs) { if (!(mFlags & ACCH_FLAG_0x1)) { bgs.MoveBgCrrPos(mGnd, ChkGroundHit(), mpPos, mpAngle, mpShapeAngle, false, false); GroundCheckInit(bgs); u32 prev = field_0x394; Init(); // Not in the mood to mess with these inlines lol } } f32 dBgS_Acch::GetWallAllR() { f32 ret = 0.0f; int i = 0; do { if (ret < mpAcchCir[i].GetWallR()) { ret = mpAcchCir[i].GetWallR(); } ++i; } while (i < mTblSize); return ret; } void dBgS_Acch::CalcWallBmdCyl() { if (mTblSize <= 0) { mWallCyl.Set(*mpPos, 0.0f, 0.0f); } else { f32 speed = GetSpeedY(); // TOD Stuff f32 dvar8 = GetWallAllR(); f32 dvar9 = mpAcchCir->GetWallH(); f32 dvar10 = mpAcchCir->GetWallH(); // if (mTblSize >= 1) { // for (int i = 0; i < mTblSize; i++) { // f32 tmp = mpAcchCir[i].GetWallH(); // if (dvar9 > tmp) { // dvar9 = mpAcchCir[i].GetWallH(); // } // f32 tmp2 = mpAcchCir[i].GetWallH(); // if (dvar10 < tmp2) { // dvar10 = mpAcchCir[i].GetWallH(); // } // } // } mVec3_c xyz(*GetPos()); // TODO: Stuff mWallCyl.Set(xyz, dvar8, dvar10 - dvar9); } } void dBgS_Acch::SetGroundUpY(f32 param_0) { field_0x0AC = param_0 - field_0x0A8; field_0x0A8 = param_0; } bool dBgS_Acch::fn_80340ca0(cBgS_PolyInfo &info) const { int idx = 0; if (ChkGndHit()) { info.SetPolyInfo(mGnd); return false; } if (ChkWallHit(&idx)) { info.SetPolyInfo(mpAcchCir[idx]); return false; } if (ChkRoofHit()) { info.SetPolyInfo(mRoof); return false; } return true; } void dBgS_Acch::Draw(dBgS &) { // Name inferred from being called from (NPC?) draw functions. // Maybe a debug visual? } void dBgS_Acch::SetMoveBGOnly() { mFlags |= MOVE_BG_ONLY; mWtr.OnMoveBGOnly(); } void dBgS_Acch::ClrMoveBGOnly() { mFlags &= ~MOVE_BG_ONLY; mWtr.OffMoveBGOnly(); } bool dBgS_Acch::ChkGndHit() const { bool ret = false; if (mFlags & GROUND_HIT) { if (dBgS::GetInstance()->ChkPolySafe(mGnd)) { ret = true; } } return ret; } bool dBgS_Acch::ChkRoofHit() const { bool ret = false; if (mFlags & ROOF_HIT) { if (dBgS::GetInstance()->ChkPolySafe(mRoof)) { ret = true; } } return ret; } bool dBgS_Acch::ChkWallHit(int *pOutIndex) const { if (mFlags & WALL_HIT) { int i = 0; do { if (mpAcchCir[i].ChkWallHit()) { if (pOutIndex) { *pOutIndex = i; } return true; } i++; } while (i < mTblSize); } return false; } void dBgS_Acch::SetGndThinCellingOff() { mFlags |= GND_THIN_CELLING_OFF; } void dBgS_Acch::ClrGndThinCellingOff() { mFlags &= ~GND_THIN_CELLING_OFF; } void dBgS_Acch::Set_0x2000000() { mFlags |= ACCH_FLAG_0x2000000; } void dBgS_Acch::Clr_0x2000000() { mFlags &= ~ACCH_FLAG_0x2000000; } void dBgS_Acch::OnWallSort() { mFlags |= WALL_SORT; } dBgS_AcchCir &dBgS_Acch::GetCir(int idx) { return mpAcchCir[idx]; } void dBgS_Acch::fn_80340f70(const mVec3_c *pVec) { bool adjusted = false; if (field_0x398.x > pVec->x) { field_0x398.x = pVec->x; adjusted = true; } else if (field_0x3A4.x < pVec->x) { field_0x3A4.x = pVec->x; adjusted = true; } if (field_0x398.z > pVec->z) { field_0x398.z = pVec->z; adjusted = true; } else if (field_0x3A4.z < pVec->z) { field_0x3A4.z = pVec->z; adjusted = true; } if (!adjusted && field_0x394 > 0) { field_0x394--; } } void dBgS_Acch::fn_80341000() { mpPos->x += field_0x398.x + field_0x3A4.x; mpPos->z += field_0x398.z + field_0x3A4.z; } dBgS_ObjAcch::dBgS_ObjAcch() { SetObj(); } dBgS_ObjAcch::~dBgS_ObjAcch() {} dBgS_LinkAcch::dBgS_LinkAcch() { SetLink(); } dBgS_LinkAcch::~dBgS_LinkAcch() {} dBgS_BombAcch::dBgS_BombAcch() { SetBomb(); } dBgS_BombAcch::~dBgS_BombAcch() {}