Initial CPlayerGun implementations

This commit is contained in:
Jack Andersen 2017-08-24 20:18:09 -10:00
parent e8a55d84d4
commit ed991a6ac0
29 changed files with 685 additions and 43 deletions

View File

@ -340,6 +340,12 @@ void CSfxManager::SfxVolume(const CSfxHandle& handle, float vol)
handle->GetVoice()->setVolume(vol);
}
void CSfxManager::SfxSpan(const CSfxHandle& handle, float span)
{
if (handle->IsPlaying())
handle->GetVoice()->setSurroundPan(span);
}
u16 CSfxManager::TranslateSFXID(u16 id)
{
if (mpSfxTranslationTable == nullptr)

View File

@ -217,6 +217,7 @@ public:
static float GetReverbAmount();
static void PitchBend(const CSfxHandle& handle, float pitch);
static void SfxVolume(const CSfxHandle& handle, float vol);
static void SfxSpan(const CSfxHandle& handle, float span);
static u16 TranslateSFXID(u16);
static void SfxStop(const CSfxHandle& handle);
static CSfxHandle SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId);

View File

@ -293,7 +293,7 @@ void CPlayerState::ResetVisor()
x1c_visorTransitionFactor = 0.0f;
}
bool CPlayerState::ItemEnabled(CPlayerState::EItemType type)
bool CPlayerState::ItemEnabled(CPlayerState::EItemType type) const
{
if (HasPowerUp(type))
return (x4_enabledItems & (1 << u32(type)));
@ -312,7 +312,7 @@ void CPlayerState::DisableItem(CPlayerState::EItemType type)
x4_enabledItems &= ~(1 << u32(type));
}
bool CPlayerState::HasPowerUp(CPlayerState::EItemType type)
bool CPlayerState::HasPowerUp(CPlayerState::EItemType type) const
{
if (type < EItemType::Max)
return x24_powerups[u32(type)].x4_capacity != 0;

View File

@ -154,10 +154,10 @@ public:
void UpdateVisorTransition(float dt);
bool StartVisorTransition(EPlayerVisor visor);
void ResetVisor();
bool ItemEnabled(EItemType type);
bool ItemEnabled(EItemType type) const;
void DisableItem(EItemType type);
void EnableItem(EItemType type);
bool HasPowerUp(EItemType type);
bool HasPowerUp(EItemType type) const;
u32 GetItemCapacity(EItemType type) const;
u32 GetItemAmount(EItemType type) const;
void DecrPickup(EItemType type, s32 amount);

View File

@ -279,7 +279,7 @@ void CModelData::RenderParticles(const zeus::CFrustum& frustum) const
x10_animData->RenderAuxiliary(frustum);
}
void CModelData::Touch(EWhichModel which, int shaderIdx)
void CModelData::Touch(EWhichModel which, int shaderIdx) const
{
if (x10_animData)
x10_animData->Touch(PickAnimatedModel(which), shaderIdx);
@ -287,9 +287,9 @@ void CModelData::Touch(EWhichModel which, int shaderIdx)
PickStaticModel(which)->Touch(shaderIdx);
}
void CModelData::Touch(const CStateManager& stateMgr, int shaderIdx)
void CModelData::Touch(const CStateManager& stateMgr, int shaderIdx) const
{
Touch(GetRenderingModel(stateMgr), shaderIdx);
Touch(const_cast<CModelData&>(*this).GetRenderingModel(stateMgr), shaderIdx);
}
void CModelData::RenderThermal(const zeus::CTransform& xf,

View File

@ -132,8 +132,8 @@ public:
bool IsAnimating() const;
bool IsInFrustum(const zeus::CTransform& xf, const zeus::CFrustum& frustum) const;
void RenderParticles(const zeus::CFrustum& frustum) const;
void Touch(EWhichModel, int shaderIdx);
void Touch(const CStateManager& stateMgr, int shaderIdx);
void Touch(EWhichModel, int shaderIdx) const;
void Touch(const CStateManager& stateMgr, int shaderIdx) const;
void RenderThermal(const zeus::CTransform& xf, const zeus::CColor& a, const zeus::CColor& b);
void RenderUnsortedParts(EWhichModel, const zeus::CTransform& xf,
const CActorLights* lights, const CModelFlags& drawFlags);

View File

@ -78,8 +78,8 @@ struct TUniqueId
TUniqueId(u16 value, u16 version) : id(value | (version << 10)) {}
u16 id = u16(-1);
s16 Version() const { return s16((id >> 10) & 0x3f);}
s16 Value() const { return s16(id & 0x3ff);}
u16 Version() const { return u16((id >> 10) & 0x3f);}
u16 Value() const { return u16(id & 0x3ff);}
bool operator<(const TUniqueId& other) const { return (id < other.id); }
bool operator!=(const TUniqueId& other) const { return (id != other.id); }
bool operator==(const TUniqueId& other) const { return (id == other.id); }

View File

@ -8,4 +8,19 @@ CAuxWeapon::CAuxWeapon(TUniqueId id)
}
void CAuxWeapon::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&)
{
}
bool CAuxWeapon::IsComboFxActive(const CStateManager& mgr) const
{
return false;
}
void CAuxWeapon::Load(int curBeam, CStateManager& mgr)
{
}
}

View File

@ -2,6 +2,7 @@
#define __URDE_CAUXWEAPON_HPP__
#include "RetroTypes.hpp"
#include "CStateManager.hpp"
namespace urde
{
@ -10,6 +11,9 @@ class CAuxWeapon
{
public:
explicit CAuxWeapon(TUniqueId id);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
bool IsComboFxActive(const CStateManager& mgr) const;
void Load(int curBeam, CStateManager& mgr);
};
}

View File

@ -36,4 +36,24 @@ void CGrappleArm::RenderGrappleBeam(const CStateManager& mgr, const zeus::CVecto
}
void CGrappleArm::TouchModel(const CStateManager& mgr) const
{
}
void CGrappleArm::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&)
{
}
void CGrappleArm::EnterStruck(CStateManager& mgr, float angle, bool attack, bool b2)
{
}
void CGrappleArm::EnterIdle(CStateManager& mgr)
{
}
}

View File

@ -4,6 +4,7 @@
#include "RetroTypes.hpp"
#include "zeus/CVector3f.hpp"
#include "Character/CModelData.hpp"
#include "CStateManager.hpp"
namespace urde
{
@ -54,6 +55,10 @@ public:
void GrappleBeamDisconnected();
void GrappleBeamConnected();
void RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos);
void TouchModel(const CStateManager& mgr) const;
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void EnterStruck(CStateManager& mgr, float angle, bool attack, bool b2);
void EnterIdle(CStateManager& mgr);
};
}

View File

@ -8,4 +8,9 @@ CGunMotion::CGunMotion(CAssetId, const zeus::CVector3f& vec)
}
void CGunMotion::PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool attack)
{
}
}

View File

@ -8,12 +8,24 @@
namespace urde
{
namespace SamusGun
{
enum class EAnimationState
{
Zero,
One,
Two
};
}
class CGunMotion
{
CModelData x0_modelData;
public:
CGunMotion(CAssetId, const zeus::CVector3f& vec);
const CModelData& GetModelData() const { return x0_modelData; }
void PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool attack);
};
}

View File

@ -1,7 +1,6 @@
#include "CGunWeapon.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "Particle/CGenDescription.hpp"
namespace urde
{
@ -56,4 +55,18 @@ void CGunWeapon::AsyncLoadSuitArm(CStateManager& mgr)
{
}
void CGunWeapon::ActivateCharge(bool b1, bool b2)
{
}
void CGunWeapon::Touch(const CStateManager& mgr)
{
}
void CGunWeapon::TouchHolo(const CStateManager& mgr)
{
}
}

View File

@ -9,6 +9,7 @@
#include "Character/CAnimCharacterSet.hpp"
#include "Particle/CElementGen.hpp"
#include "CToken.hpp"
#include "CStateManager.hpp"
namespace urde
{
@ -16,13 +17,22 @@ namespace NWeaponTypes
{
enum class EGunAnimType
{
Zero,
One,
Two,
Three,
Four,
FromMissile,
ToMissile,
Seven,
MissileReload,
FromBeam
};
}
class CActorLights;
class CGunController;
struct CModelFlags;
class CStateManager;
class CWeaponDescription;
class CVelocityInfo
@ -38,8 +48,12 @@ public:
class CGunWeapon
{
public:
enum class ESecondaryFxType : u32
enum class ESecondaryFxType
{
Zero,
One,
Two,
Three
};
protected:
static const char* skBeamXferNames[5];
@ -53,6 +67,9 @@ protected:
TToken<CGenDescription> x160_xferEffect;
rstl::reserved_vector<TCachedToken<CGenDescription>, 2> x16c_muzzleEffects;
rstl::reserved_vector<TCachedToken<CGenDescription>, 2> x188_secondaryEffects;
rstl::reserved_vector<std::unique_ptr<CElementGen>, 2> x1a4_muzzleGenerators;
u32 x1b8_ = 0;
CRainSplashGenerator* x1bc_rainSplashGenerator = nullptr;
EWeaponType x1c0_weaponType;
TUniqueId x1c4_playerId;
EMaterialTypes x1c8_playerMaterial;
@ -71,14 +88,19 @@ public:
virtual void Fire(bool, float, CPlayerState::EChargeState, const zeus::CTransform&, CStateManager&, TUniqueId) {}
virtual void EnableFx(bool) {}
virtual void EnableSecondaryFx(ESecondaryFxType) {}
void ActivateCharge(bool b1, bool b2);
void Touch(const CStateManager& mgr);
void TouchHolo(const CStateManager& mgr);
virtual void Draw(bool, const CStateManager&, const zeus::CTransform&, const CModelFlags&,
const CActorLights*) const {}
virtual void DrawMuzzleFx(const CStateManager&) const {}
virtual void Update(float, CStateManager&) {}
virtual void Load(bool) {}
virtual void Load(CStateManager& mgr, bool) {}
virtual void Unload(CStateManager&) {}
virtual bool IsLoaded() const {return false;}
const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; }
void SetRainSplashGenerator(CRainSplashGenerator* g) { x1bc_rainSplashGenerator = g; }
CElementGen* GetChargeMuzzleFx() const { return x1a4_muzzleGenerators[1].get(); }
};
}

View File

@ -21,4 +21,9 @@ CPhazonBeam::CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playe
x274_27 = false;
}
void CPhazonBeam::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&)
{
}
}

View File

@ -24,6 +24,10 @@ class CPhazonBeam : public CGunWeapon
public:
CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId,
EMaterialTypes playerMaterial, const zeus::CVector3f& scale);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
bool IsFiring() const { return x278_ < 1.f / 6.f; }
void SetX274_25(bool b) { x274_25 = b; }
void SetX274_26(bool b) { x274_26 = b; }
};
}

View File

@ -14,4 +14,9 @@ CPlasmaBeam::CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playe
x22c_25 = false;
}
void CPlasmaBeam::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&)
{
}
}

View File

@ -19,6 +19,7 @@ class CPlasmaBeam : public CGunWeapon
public:
CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId,
EMaterialTypes playerMaterial, const zeus::CVector3f& scale);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
};
}

View File

@ -1,7 +1,14 @@
#include "TCastTo.hpp"
#include "CPlayerGun.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "Character/CPrimitive.hpp"
#include "World/CPlayer.hpp"
#include "CEnergyProjectile.hpp"
#include "MP1/World/CMetroid.hpp"
#include "World/CScriptWater.hpp"
#include "World/CGameLight.hpp"
#include "Input/ControlMapper.hpp"
namespace urde
{
@ -15,7 +22,7 @@ static float kVerticalVarianceTable[] = { 30.f, 30.f, 30.f };
float CPlayerGun::CMotionState::gGunExtendDistance = 0.125f;
CPlayerGun::CPlayerGun(TUniqueId playerId)
: x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, 0, 0, 0, 0.1f), x538_thisId(playerId),
: x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, 0, 0, 0, 0.1f), x538_playerId(playerId),
x550_camBob(CPlayerCameraBob::ECameraBobType::One,
zeus::CVector2f(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY),
CPlayerCameraBob::kCameraBobPeriod),
@ -124,9 +131,205 @@ void CPlayerGun::LoadHandAnimTokens()
CAnimData::PrimitiveSetToTokenVector(prims, x540_handAnimTokens, true);
}
void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&)
void CPlayerGun::TakeDamage(bool attack, bool notFromMetroid, CStateManager& mgr)
{
bool hasAngle = false;
float angle = 0.f;
if (x398_damageAmt >= 10.f && !attack && (x2f8_ & 0x10) != 0x10 && !x832_26_ && x384_ <= 0.f)
{
x384_ = 20.f;
x364_ = 0.75f;
if (x678_morph.GetGunState() == CGunMorph::EGunState::One)
{
zeus::CVector3f localDamageLoc = mgr.GetPlayer().GetTransform().transposeRotate(x3dc_damageLocation);
angle = zeus::CRelAngle(std::atan2(localDamageLoc.y, localDamageLoc.x)).asDegrees();
hasAngle = true;
}
}
if (hasAngle || attack)
{
if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan)
{
x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Two, mgr, angle, attack);
if ((attack && notFromMetroid) || x833_31_)
x740_grappleArm->EnterStruck(mgr, angle, attack, !x833_31_);
}
}
x398_damageAmt = 0.f;
x3dc_damageLocation = zeus::CVector3f::skZero;
}
void CPlayerGun::CreateGunLight(CStateManager& mgr)
{
if (x53c_lightId != kInvalidUniqueId)
return;
x53c_lightId = mgr.AllocateUniqueId();
CGameLight* light = new CGameLight(x53c_lightId, kInvalidAreaId, false, "GunLite", x3e8_xf, x538_playerId,
CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skBlack),
x53c_lightId.Value(), 0, 0.f);
mgr.AddObject(light);
}
void CPlayerGun::DeleteGunLight(CStateManager& mgr)
{
if (x53c_lightId == kInvalidUniqueId)
return;
mgr.FreeScriptObject(x53c_lightId);
x53c_lightId = kInvalidUniqueId;
}
void CPlayerGun::SetGunLightActive(bool active, CStateManager& mgr)
{
if (x53c_lightId == kInvalidUniqueId)
return;
if (TCastToPtr<CGameLight> light = mgr.ObjectById(x53c_lightId))
{
light->SetActive(active);
if (active)
{
if (CElementGen* gen = x72c_currentBeam->GetChargeMuzzleFx())
{
if (gen->SystemHasLight())
{
CLight genLight = gen->GetLight();
genLight.SetColor(zeus::CColor::skBlack);
light->SetLight(genLight);
}
}
}
}
}
static const u32 skBeamIdMap[] = { 0, 1, 2, 3, 0 };
static const u32 skBeamAnimIds[] = { 0, 1, 2, 1 };
void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr)
{
const CPlayer& player = mgr.GetPlayer();
bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed;
switch (msg)
{
case EScriptObjectMessage::Registered:
{
CreateGunLight(mgr);
x320_ = x314_pendingSelectedBeam = x310_selectedBeam =
skBeamIdMap[int(mgr.GetPlayerState()->GetCurrentBeam())];
x72c_currentBeam = x738_nextBeam = x760_selectableBeams[x310_selectedBeam];
x72c_currentBeam->Load(mgr, true);
x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get());
x744_auxWeapon->Load(x310_selectedBeam, mgr);
CAnimPlaybackParms parms(skBeamAnimIds[int(mgr.GetPlayerState()->GetCurrentBeam())], -1, 1.f, true);
x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false);
break;
}
case EScriptObjectMessage::Deleted:
DeleteGunLight(mgr);
break;
case EScriptObjectMessage::UpdateSplashInhabitant:
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed)
{
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(sender))
{
if (water->GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::PhazonFluid)
{
x835_24_canFirePhazon = true;
x835_25_inPhazonBeam = true;
}
}
}
if (player.GetDistanceUnderWater() > player.GetEyeHeight())
{
x834_27_underwater = true;
if (x744_auxWeapon->IsComboFxActive(mgr) && x310_selectedBeam != 2)
StopContinuousBeam(mgr, false);
}
else
{
x834_27_underwater = false;
}
break;
case EScriptObjectMessage::RemoveSplashInhabitant:
x834_27_underwater = false;
x835_24_canFirePhazon = false;
break;
case EScriptObjectMessage::AddPhazonPoolInhabitant:
x835_30_inPhazonPool = true;
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed)
x835_24_canFirePhazon = true;
break;
case EScriptObjectMessage::UpdatePhazonPoolInhabitant:
x835_30_inPhazonPool = true;
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed)
{
x835_24_canFirePhazon = true;
x835_25_inPhazonBeam = true;
if (x833_28_phazonBeamActive && static_cast<CPhazonBeam*>(x72c_currentBeam)->IsFiring())
if (TCastToPtr<CEntity> ent = mgr.ObjectById(sender))
mgr.SendScriptMsg(ent.GetPtr(), x538_playerId, EScriptObjectMessage::Decrement);
}
break;
case EScriptObjectMessage::RemovePhazonPoolInhabitant:
x835_30_inPhazonPool = false;
x835_24_canFirePhazon = false;
break;
case EScriptObjectMessage::Damage:
{
bool attackDamage = false;
bool metroidAttached = false;
if (TCastToConstPtr<CEnergyProjectile> proj = mgr.GetObjectById(sender))
{
if ((proj->GetAttribField() & CGameProjectile::EProjectileAttrib::Twelve) !=
CGameProjectile::EProjectileAttrib::None)
{
x394_damageTimer = proj->GetDamageDuration();
attackDamage = true;
}
}
else if (TCastToConstPtr<CPatterned> ai = mgr.GetObjectById(sender))
{
if (ai->GetX402_28())
{
x394_damageTimer = ai->GetDamageDuration();
attackDamage = true;
if (player.GetAttachedActor() != kInvalidUniqueId)
metroidAttached = CPatterned::CastTo<MP1::CMetroid>(
mgr.GetObjectById(player.GetAttachedActor())) != nullptr;
}
}
if (!x834_30_damaged)
{
if (attackDamage)
{
x834_31_ = false;
CancelFiring(mgr);
}
TakeDamage(attackDamage, !metroidAttached, mgr);
x834_30_damaged = attackDamage;
}
break;
}
case EScriptObjectMessage::OnFloor:
if (player.GetControlsFrozen() && !x834_30_damaged)
{
x2f4_ = 0;
x2ec_firing = 0;
CancelFiring(mgr);
TakeDamage(true, false, mgr);
x394_damageTimer = 0.75f;
x834_30_damaged = true;
}
break;
default:
break;
}
x740_grappleArm->AcceptScriptMsg(msg, sender, mgr);
x758_plasmaBeam->AcceptScriptMsg(msg, sender, mgr);
x75c_phazonBeam->AcceptScriptMsg(msg, sender, mgr);
x744_auxWeapon->AcceptScriptMsg(msg, sender, mgr);
}
void CPlayerGun::AsyncLoadSuit(CStateManager& mgr)
@ -135,9 +338,38 @@ void CPlayerGun::AsyncLoadSuit(CStateManager& mgr)
x740_grappleArm->AsyncLoadSuit(mgr);
}
void CPlayerGun::TouchModel(const CStateManager& stateMgr)
void CPlayerGun::TouchModel(const CStateManager& mgr)
{
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
{
x73c_gunMotion->GetModelData().Touch(mgr, 0);
switch (x33c_gunOverrideMode)
{
case EGunOverrideMode::One:
if (x75c_phazonBeam)
x75c_phazonBeam->Touch(mgr);
break;
case EGunOverrideMode::Two:
if (x738_nextBeam)
x738_nextBeam->Touch(mgr);
break;
default:
if (!x833_28_phazonBeamActive)
x72c_currentBeam->Touch(mgr);
else
x75c_phazonBeam->Touch(mgr);
break;
}
x72c_currentBeam->TouchHolo(mgr);
x740_grappleArm->TouchModel(mgr);
x6e0_rightHandModel.Touch(mgr, 0);
}
if (x734_)
{
x734_->Touch(mgr);
x734_->TouchHolo(mgr);
}
}
void CPlayerGun::DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr)
@ -146,11 +378,212 @@ void CPlayerGun::DamageRumble(const zeus::CVector3f& location, float damage, con
x3dc_damageLocation = location;
}
void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr)
void CPlayerGun::ResetCharge(CStateManager& mgr, bool b1)
{
}
void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr)
{
}
void CPlayerGun::SetPhazonBeamMorph(bool intoPhazonBeam)
{
x39c_ = intoPhazonBeam ? 0.f : 1.f;
x835_27_intoPhazonBeam = intoPhazonBeam;
x835_26_phazonBeamMorphing = true;
}
void CPlayerGun::Reset(CStateManager& mgr, bool b1)
{
x72c_currentBeam->Reset(mgr);
x832_25_ = false;
x832_24_ = false;
x833_26_ = false;
x348_ = 0.f;
SetGunLightActive(false, mgr);
if ((x2f8_ & 0x10) != 0x10)
{
if (!b1 && (x2f8_ & 0x2) != 0x2)
{
if ((x2f8_ & 0x8) != 0x8)
{
x2f8_ |= 0x1;
x2f8_ &= 0xFFE9;
}
x318_ = 0;
x31c_missileMode = EMissleMode::Inactive;
}
}
else
{
x2f8_ &= ~0x7;
}
}
void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx)
{
StopContinuousBeam(mgr, true);
if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam))
ResetCharge(mgr, false);
CAnimPlaybackParms parms(skBeamAnimIds[x314_pendingSelectedBeam], -1, 1.f, true);
x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false);
Reset(mgr, false);
if (playSelectionSfx)
CSfxManager::SfxStart(1774, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId);
x2ec_firing &= ~0x1;
x320_ = x310_selectedBeam;
x833_30_ = true;
}
void CPlayerGun::PlaySfx(u16 sfx, bool underwater, bool looped, float pan)
{
CSfxHandle hnd = CSfxManager::SfxStart(sfx, 1.f, pan, true, 0x7f, looped, kInvalidAreaId);
CSfxManager::SfxSpan(hnd, 0.f);
if (underwater)
CSfxManager::PitchBend(hnd, -1.f);
}
static const u16 skFromMissileSound[] = { 1824, 1849, 1851, 1853 };
static const u16 skFromBeamSound[] = { 0, 1822, 1828, 1826 };
static const u16 skToMissileSound[] = { 1823, 1829, 1850, 1852 };
void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool b1)
{
if (x338_ != 5)
x72c_currentBeam->PlayAnim(type, b1);
u16 sfx = 0xffff;
switch (type)
{
case NWeaponTypes::EGunAnimType::FromMissile:
x2f8_ &= ~0x4;
sfx = skFromMissileSound[x310_selectedBeam];
break;
case NWeaponTypes::EGunAnimType::MissileReload:
sfx = 1769;
break;
case NWeaponTypes::EGunAnimType::FromBeam:
sfx = skFromBeamSound[x310_selectedBeam];
break;
case NWeaponTypes::EGunAnimType::ToMissile:
x2f8_ &= ~0x1;
sfx = skToMissileSound[x310_selectedBeam];
break;
default:
break;
}
if (sfx != 0xffff)
PlaySfx(sfx, x834_27_underwater, false, 0.165f);
}
void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect)
{
if (withEffect)
{
x32c_ = 9;
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Three);
}
else
{
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Zero);
}
x834_24_charging = false;
x348_ = 0.f;
x72c_currentBeam->ActivateCharge(false, false);
SetGunLightActive(false, mgr);
}
void CPlayerGun::HandlePhazonBeamChange(CStateManager& mgr)
{
bool inMorph = false;
switch (x33c_gunOverrideMode)
{
case EGunOverrideMode::Normal:
SetPhazonBeamMorph(true);
x338_ = 8;
inMorph = true;
break;
case EGunOverrideMode::Three:
if (!x835_25_inPhazonBeam)
{
SetPhazonBeamMorph(true);
x338_ = 9;
inMorph = true;
if (x75c_phazonBeam)
{
x75c_phazonBeam->SetX274_25(false);
x75c_phazonBeam->SetX274_26(true);
}
}
break;
default:
break;
}
if (inMorph)
{
ResetBeamParams(mgr, *mgr.GetPlayerState(), true);
x2f8_ = 0x8;
PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false);
if (x833_31_)
{
x832_30_ = true;
x740_grappleArm->EnterIdle(mgr);
}
CancelCharge(mgr, false);
}
}
void CPlayerGun::HandleWeaponChange(const CFinalInput& input, CStateManager& mgr)
{
x833_25_ = false;
if (ControlMapper::GetPressInput(ControlMapper::ECommands::Morph, input))
StopContinuousBeam(mgr, true);
if ((x2f8_ & 0x8) != 0x8)
{
if (!x835_25_inPhazonBeam)
HandleBeamChange(input, mgr);
else
HandlePhazonBeamChange(mgr);
}
}
void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr)
{
CPlayerState& state = *mgr.GetPlayerState();
bool damageNotMorphed = (x834_30_damaged &&
mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed);
if (x832_24_ || damageNotMorphed || (x2f8_ & 0x8) == 0x8)
return;
if (state.HasPowerUp(CPlayerState::EItemType::ChargeBeam))
{
if (!state.ItemEnabled(CPlayerState::EItemType::ChargeBeam))
state.EnableItem(CPlayerState::EItemType::ChargeBeam);
}
else if (state.ItemEnabled(CPlayerState::EItemType::ChargeBeam))
{
state.DisableItem(CPlayerState::EItemType::ChargeBeam);
ResetCharge(mgr, false);
}
switch (mgr.GetPlayer().GetMorphballTransitionState())
{
default:
x2f4_ = 0;
break;
case CPlayer::EPlayerMorphBallState::Unmorphed:
if ((x2f8_ & 0x10) != 0x10)
HandleWeaponChange(input, mgr);
case CPlayer::EPlayerMorphBallState::Morphed:
x2f4_ = ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) ? 1 : 0;
x2f4_ |= ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) ? 2 : 0;
break;
}
}
void CPlayerGun::ResetIdle(CStateManager& mgr)
{
@ -168,6 +601,11 @@ float CPlayerGun::GetBeamVelocity() const
return 10.f;
}
void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1)
{
}
void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr)
{

View File

@ -37,9 +37,23 @@ public:
{
};
enum class EGunOverrideMode
{
Normal,
One,
Two,
Three
};
private:
class CGunMorph
{
public:
enum class EGunState
{
Zero,
One
};
private:
float x0_ = 0.f;
float x4_gunTransformTime;
float x8_ = 0.f;
@ -48,7 +62,7 @@ private:
float x14_ = 2.f;
float x18_transitionFactor = 1.f;
u32 x1c_ = 2;
u32 x20_ = 1;
EGunState x20_gunState = EGunState::One;
union
{
@ -64,6 +78,7 @@ private:
CGunMorph(float gunTransformTime, float holoHoldTime)
: x4_gunTransformTime(gunTransformTime), x10_holoHoldTime(std::fabs(holoHoldTime)) {}
float GetTransitionFactor() const { return x18_transitionFactor; }
EGunState GetGunState() const { return x20_gunState; }
};
class CMotionState
@ -97,7 +112,7 @@ private:
u32 x330_chargeWeaponIdx = 0;
u32 x334_ = 0;
u32 x338_ = 0;
u32 x33c_ = 0;
EGunOverrideMode x33c_gunOverrideMode = EGunOverrideMode::Normal;
float x340_chargeBeamFactor = 0.f;
float x344_ = 0.f;
float x348_ = 0.f;
@ -119,7 +134,7 @@ private:
float x388_ = 0.f;
float x38c_ = 0.f;
float x390_ = 0.f;
float x394_ = 0.f;
float x394_damageTimer = 0.f;
float x398_damageAmt = 0.f;
float x39c_ = 0.f;
float x3a0_ = 0.f;
@ -132,9 +147,9 @@ private:
zeus::CTransform x4a8_;
zeus::CTransform x4d8_;
zeus::CTransform x508_;
TUniqueId x538_thisId;
TUniqueId x538_playerId;
TUniqueId x53a_ = kInvalidUniqueId;
TUniqueId x53c_ = kInvalidUniqueId;
TUniqueId x53c_lightId = kInvalidUniqueId;
std::vector<CToken> x540_handAnimTokens;
CPlayerCameraBob x550_camBob;
u32 x658_ = 1;
@ -160,7 +175,7 @@ private:
CModelData x6e0_rightHandModel;
CGunWeapon* x72c_currentBeam = nullptr;
u32 x730_ = 0;
u32 x734_ = 0;
CGunWeapon* x734_ = nullptr;
CGunWeapon* x738_nextBeam = nullptr;
std::unique_ptr<CGunMotion> x73c_gunMotion;
std::unique_ptr<CGrappleArm> x740_grappleArm;
@ -197,7 +212,7 @@ private:
bool x833_25_ : 1;
bool x833_26_ : 1;
bool x833_27_ : 1;
bool x833_28_ : 1;
bool x833_28_phazonBeamActive : 1;
bool x833_29_ : 1;
bool x833_30_ : 1;
bool x833_31_ : 1;
@ -205,19 +220,19 @@ private:
bool x834_24_charging : 1;
bool x834_25_ : 1;
bool x834_26_ : 1;
bool x834_27_ : 1;
bool x834_27_underwater : 1;
bool x834_28_ : 1;
bool x834_29_ : 1;
bool x834_30_ : 1;
bool x834_30_damaged : 1;
bool x834_31_ : 1;
bool x835_24_ : 1;
bool x835_25_ : 1;
bool x835_26_ : 1;
bool x835_27_ : 1;
bool x835_24_canFirePhazon : 1;
bool x835_25_inPhazonBeam : 1;
bool x835_26_phazonBeamMorphing : 1;
bool x835_27_intoPhazonBeam : 1;
bool x835_28_bombReady : 1;
bool x835_29_powerBombReady : 1;
bool x835_30_ : 1;
bool x835_30_inPhazonPool : 1;
bool x835_31_actorAttached : 1;
};
u32 _dummy = 0;
@ -228,10 +243,19 @@ private:
void InitMuzzleData();
void InitCTData();
void LoadHandAnimTokens();
void CreateGunLight(CStateManager& mgr);
void DeleteGunLight(CStateManager& mgr);
void SetGunLightActive(bool active, CStateManager& mgr);
void SetPhazonBeamMorph(bool intoPhazonBeam);
void Reset(CStateManager& mgr, bool b1);
void ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx);
void PlaySfx(u16 sfx, bool underwater, bool looped, float pan);
void PlayAnim(NWeaponTypes::EGunAnimType type, bool b1);
void CancelCharge(CStateManager& mgr, bool withEffect);
public:
explicit CPlayerGun(TUniqueId playerId);
void TakeDamage(bool attack, bool notFromMetroid, CStateManager& mgr);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void AsyncLoadSuit(CStateManager& mgr);
void TouchModel(const CStateManager& stateMgr);
@ -250,10 +274,15 @@ public:
void SetAssistAimTransform(const zeus::CTransform& xf) { x478_assistAimXf = xf; }
CGrappleArm& GetGrappleArm() { return *x740_grappleArm; }
void DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr);
void ResetCharge(CStateManager& mgr, bool b1);
void HandleBeamChange(const CFinalInput& input, CStateManager& mgr);
void HandlePhazonBeamChange(CStateManager& mgr);
void HandleWeaponChange(const CFinalInput& input, CStateManager& mgr);
void ProcessInput(const CFinalInput& input, CStateManager& mgr);
void ResetIdle(CStateManager& mgr);
void CancelFiring(CStateManager& mgr);
float GetBeamVelocity() const;
void StopContinuousBeam(CStateManager& mgr, bool b1);
void Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr);
void PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos);
void Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const;

View File

@ -21,6 +21,7 @@ public:
Unknown1 = (1 << 7),
Bombs = (1 << 8),
PowerBombs = (1 << 9),
Twelve = (1 << 12),
StaticInterference = (1 << 14),
};
@ -35,7 +36,7 @@ private:
CDamageInfo x12c_;
float x148_;
float x14c_;
float x150_;
float x150_damageDuration;
float x154_interferenceDuration;
public:
CWeapon(TUniqueId, TAreaId, bool, TUniqueId, EWeaponType, const std::string&, const zeus::CTransform&,
@ -52,6 +53,7 @@ public:
const CDamageInfo& GetDamageInfo() const;
CDamageInfo& DamageInfo();
void SetDamageInfo(const CDamageInfo&);
float GetDamageDuration() const { return x150_damageDuration; }
float GetInterferenceDuration() const { return x154_interferenceDuration; }
void Think(float, CStateManager &) {}

View File

@ -59,6 +59,7 @@ public:
void SetVisorParameters(const CVisorParameters& vParams) { x54_visorParms = vParams; }
const CVisorParameters& GetVisorParameters() const { return x54_visorParms; }
const CLightParameters& GetLightParameters() const { return x0_lightParms; }
bool HasThermalHeat() const { return x58_25_thermalHeat; }
};
}

View File

@ -1,6 +1,7 @@
#include "CPatterned.hpp"
#include "CPatternedInfo.hpp"
#include "TCastTo.hpp"
#include "CActorParameters.hpp"
namespace urde
{
@ -24,6 +25,12 @@ CPatterned::CPatterned(ECharacter character, TUniqueId uid, const std::string& n
pInfo.xfc_stateMachineId, actorParms, pInfo.xd8_stepUpHeight, 0.8f),
x34c_character(character)
{
x400_25_ = true;
x400_31_ = moveType == CPatterned::EMovementType::Flyer;
x402_29_ = true;
x402_30_ = x402_31_ = actorParms.HasThermalHeat();
x403_25_ = true;
x403_26_ = true;
}
}

View File

@ -85,6 +85,42 @@ protected:
ECharacter x34c_character;
float x338_;
union
{
struct
{
bool x400_24_ : 1;
bool x400_25_ : 1; // t
bool x400_26_ : 1;
bool x400_27_ : 1;
bool x400_28_ : 1;
bool x400_29_ : 1;
bool x400_30_ : 1;
bool x400_31_ : 1; // r25 == 1
bool x401_24_ : 1;
bool x401_25_ : 1;
bool x401_26_ : 1;
bool x401_27_ : 1;
bool x401_28_ : 1;
bool x401_29_ : 1;
bool x401_30_ : 1;
bool x401_31_ : 1;
bool x402_24_ : 1;
bool x402_25_ : 1;
bool x402_26_ : 1;
bool x402_27_ : 1;
bool x402_28_ : 1;
bool x402_29_ : 1; // t
bool x402_30_ : 1;
bool x402_31_ : 1;
bool x403_24_ : 1;
bool x403_25_ : 1; // t
bool x403_26_ : 1; // t
};
u32 _dummy2 = 0;
};
std::unique_ptr<CBodyController> x450_bodyController;
union
@ -95,8 +131,11 @@ protected:
bool x4e1_25_ : 1;
bool x4e1_26_ : 1;
};
u32 _dummy2 = 0;
u32 _dummy3 = 0;
};
float x500_ = 0.f;
float x504_damageDur = 0.f;
public:
CPatterned(ECharacter character, TUniqueId uid, const std::string& name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pinfo,
@ -126,9 +165,11 @@ public:
}
bool GetX328_26() const { return x328_26_; }
bool GetX402_28() const { return x402_28_; }
virtual bool IsOnGround() const { return x328_27_onGround; }
virtual float GetGravityConstant() const { return 24.525002f; }
float GetDamageDuration() const { return x504_damageDur; }
};
}

View File

@ -2996,7 +2996,7 @@ void CPlayer::UpdateFootstepSounds(const CFinalInput& input, CStateManager& mgr,
if (x790_footstepSfxSel != EFootstepSfx::None && x78c_footstepSfxTimer > sfxDelay)
{
static float EarHeight = GetEyeHeight() - 0.1f;
if (xe6_24_fluidCounter != 0 && x828_waterLevelOnPlayer > 0.f && x828_waterLevelOnPlayer < EarHeight)
if (xe6_24_fluidCounter != 0 && x828_distanceUnderWater > 0.f && x828_distanceUnderWater < EarHeight)
{
if (x82c_inLava)
{
@ -5628,7 +5628,7 @@ float CPlayer::JumpInput(const CFinalInput& input, CStateManager& mgr)
hDoubleJumpAccel = g_tweakPlayer->GetSidewaysHorizontalDoubleJumpAccel();
}
if (x828_waterLevelOnPlayer >= 0.8f * GetEyeHeight())
if (x828_distanceUnderWater >= 0.8f * GetEyeHeight())
doubleJumpImpulse *= jumpFactor;
if (x258_movementState == EPlayerMovementState::StartingJump)
@ -6522,19 +6522,19 @@ bool CPlayer::CheckSubmerged() const
if (xe6_24_fluidCounter == 0)
return false;
return x828_waterLevelOnPlayer >= (x2f8_morphBallState == EPlayerMorphBallState::Morphed ?
return x828_distanceUnderWater >= (x2f8_morphBallState == EPlayerMorphBallState::Morphed ?
2.f * g_tweakPlayer->GetPlayerBallHalfExtent() : 0.5f * GetEyeHeight());
}
void CPlayer::UpdateSubmerged(CStateManager& mgr)
{
x82c_inLava = false;
x828_waterLevelOnPlayer = 0.f;
x828_distanceUnderWater = 0.f;
if (xe6_24_fluidCounter != 0)
{
if (TCastToPtr<CScriptWater> water = mgr.ObjectById(xc4_fluidId))
{
x828_waterLevelOnPlayer =
x828_distanceUnderWater =
-(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z);
CFluidPlane::EFluidType fluidType = water->GetFluidPlane().GetFluidType();
x82c_inLava = (fluidType == CFluidPlane::EFluidType::Lava || fluidType == CFluidPlane::EFluidType::ThickLava);

View File

@ -347,7 +347,7 @@ private:
std::unique_ptr<CModelData> x7f0_ballTransitionBeamModel;
zeus::CTransform x7f4_gunWorldXf;
float x824_transitionFilterTimer = 0.f;
float x828_waterLevelOnPlayer = 0.f;
float x828_distanceUnderWater = 0.f;
bool x82c_inLava = false;
TUniqueId x82e_ridingPlatform = kInvalidUniqueId;
TUniqueId x830_playerHint = kInvalidUniqueId;
@ -429,6 +429,7 @@ public:
float, float, const CMaterialList&);
bool IsTransparent() const;
bool GetControlsFrozen() const { return x760_controlsFrozen; }
float GetTransitionAlpha(const zeus::CVector3f& camPos, float zNear) const;
s32 ChooseTransitionToAnimation(float dt, CStateManager& mgr) const;
void TransitionToMorphBallState(float dt, CStateManager& mgr);
@ -663,7 +664,9 @@ public:
void ApplySubmergedPitchBend(CSfxHandle& sfx);
void DetachActorFromPlayer();
bool AttachActorToPlayer(TUniqueId id, bool disableGun);
TUniqueId GetAttachedActor() const { return x26c_attachedActor; }
float GetAttachedActorStruggle() const { return xa28_attachedActorStruggle; }
float GetDistanceUnderWater() const { return x828_distanceUnderWater; }
};
}

View File

@ -222,6 +222,9 @@ enum class EScriptObjectMessage
InvulnDamage = 42,
ProjectileCollide = 43,
InSnakeWeed = 44,
AddPhazonPoolInhabitant = 45,
UpdatePhazonPoolInhabitant = 46,
RemovePhazonPoolInhabitant = 47,
InternalMessage26 = 48
};

2
hecl

@ -1 +1 @@
Subproject commit 77e859a8176e58efadd8d49e2ee58f0a2b831dd0
Subproject commit 2466f4f0e37974b37709f1f4447d1adf185343b3