2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-14 11:11:21 +00:00
metaforce/Runtime/Weapon/CBurstFire.cpp
2018-12-07 15:49:15 -10:00

109 lines
2.8 KiB
C++

#include "CBurstFire.hpp"
#include "GameGlobalObjects.hpp"
namespace urde
{
CBurstFire::CBurstFire(const SBurst** burstDefs, s32 firstBurstCount)
: x10_firstBurstCounter(firstBurstCount)
{
while (*burstDefs)
{
x1c_burstDefs.push_back(*burstDefs);
++burstDefs;
}
}
void CBurstFire::Update(CStateManager& mgr, float dt)
{
x14_24_shouldFire = false;
if (x18_curBursts)
{
x8_timeToNextShot -= dt;
if (x8_timeToNextShot < 0.f)
{
x4_angleIdx += 1;
if (x18_curBursts->x4_shotAngles[x4_angleIdx] > 0)
{
x14_24_shouldFire = true;
x8_timeToNextShot = x18_curBursts->x24_timeToNextShot;
x8_timeToNextShot += (mgr.GetActiveRandom()->Float() - 0.5f) *
x18_curBursts->x28_timeToNextShotVariance;
}
else
{
x18_curBursts = nullptr;
}
}
}
}
zeus::CVector3f CBurstFire::GetDistanceCompensatedError(float dist, float maxErrDist) const
{
float xErr = GetMaxXError();
float zErr = GetMaxZError();
xErr = std::min(xErr, dist / maxErrDist * xErr);
zErr = std::min(zErr, dist / maxErrDist * zErr);
return GetError(xErr, zErr);
}
void CBurstFire::Start(CStateManager& mgr)
{
s32 burstIdx = -1;
const SBurst* bursts = x1c_burstDefs[x0_burstType];
if (x10_firstBurstCounter-- > 0)
{
burstIdx = xc_firstBurstIdx < 0 ? 0 : xc_firstBurstIdx;
}
else
{
int random = mgr.GetActiveRandom()->Range(0, 100);
int advanceAccum = 0;
do
{
burstIdx += 1;
s32 advanceWeight = bursts[burstIdx].x0_randomSelectionWeight;
if (advanceWeight == 0)
{
advanceAccum = 100;
burstIdx -= 1;
}
advanceAccum += advanceWeight;
} while (random > advanceAccum);
}
x18_curBursts = &bursts[burstIdx];
x4_angleIdx = -1;
x8_timeToNextShot = 0.f;
x14_24_shouldFire = false;
}
zeus::CVector3f CBurstFire::GetError(float xMag, float zMag) const
{
zeus::CVector3f ret;
if (x14_24_shouldFire && x18_curBursts)
{
s32 r0 = x18_curBursts->x4_shotAngles[x4_angleIdx];
if (x14_25_avoidAccuracy && (r0 == 4 || r0 == 12))
r0 = x4_angleIdx > 0 ? x18_curBursts->x4_shotAngles[x4_angleIdx - 1] :
x18_curBursts->x4_shotAngles[x4_angleIdx + 1];
if (r0 > 0)
{
float angle = r0 * zeus::degToRad(-22.5f);
ret.x() = std::cos(angle) * xMag;
ret.z() = std::sin(angle) * zMag;
}
}
return ret;
}
float CBurstFire::GetMaxXError() const
{
return g_tweakPlayer->GetPlayerXYHalfExtent() * 3.625f + 0.2f;
}
float CBurstFire::GetMaxZError() const
{
return g_tweakPlayer->GetEyeOffset();
}
}