diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp index f8a5ac10a..78136b594 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp @@ -55,10 +55,10 @@ struct ITweakPlayerRes : ITweak return xc8_ballTransitions[0]; case EBeamId::Ice: return xc8_ballTransitions[1]; - case EBeamId::Plasma: - return xc8_ballTransitions[3]; case EBeamId::Wave: return xc8_ballTransitions[2]; + case EBeamId::Plasma: + return xc8_ballTransitions[3]; case EBeamId::Phazon: return xc8_ballTransitions[4]; } @@ -76,10 +76,10 @@ struct ITweakPlayerRes : ITweak return xc8_cineGun[0]; case EBeamId::Ice: return xc8_cineGun[1]; - case EBeamId::Plasma: - return xc8_cineGun[3]; case EBeamId::Wave: return xc8_cineGun[2]; + case EBeamId::Plasma: + return xc8_cineGun[3]; case EBeamId::Phazon: return xc8_cineGun[4]; } diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index 9351ca994..036a99f2d 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -86,12 +86,13 @@ public: FusionPhazon }; - enum class EBeamId : u32 + enum class EBeamId : s32 { + Invalid = -1, Power, Ice, - Plasma, Wave, + Plasma, Phazon = 27 }; @@ -137,6 +138,7 @@ public: EPlayerSuit GetCurrentSuit() const; EPlayerSuit GetCurrentSuitRaw() const { return x20_currentSuit; } EBeamId GetCurrentBeam() const { return x8_currentBeam; } + void SetCurrentBeam(EBeamId beam) { x8_currentBeam = beam; } bool CanVisorSeeFog(const CStateManager& stateMgr) const; EPlayerVisor GetCurrentVisor() const { return x14_currentVisor; } EPlayerVisor GetTransitioningVisor() const { return x18_transitioningVisor; } diff --git a/Runtime/Character/CActorLights.cpp b/Runtime/Character/CActorLights.cpp index 61eae2fea..84e85da5e 100644 --- a/Runtime/Character/CActorLights.cpp +++ b/Runtime/Character/CActorLights.cpp @@ -38,7 +38,7 @@ void CActorLights::BuildConstantAmbientLighting() { x299_26_ = true; x298_24_dirty = true; - x29c_shadowLightValIdx = -1; + x29c_shadowLightArrIdx = -1; x2a0_shadowLightIdx = -1; } @@ -49,7 +49,7 @@ void CActorLights::BuildConstantAmbientLighting(const zeus::CColor& color) x294_aid = kInvalidAreaId; x298_24_dirty = true; x298_26_hasAreaLights = true; - x29c_shadowLightValIdx = -1; + x29c_shadowLightArrIdx = -1; x2a0_shadowLightIdx = -1; } @@ -201,7 +201,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& /* World lights disabled */ if (x298_31_disableWorldLights) x2d4_worldLightingLevel = worldLightingLevel; - x29c_shadowLightValIdx = -1; + x29c_shadowLightArrIdx = -1; return true; } @@ -230,7 +230,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& x2d4_worldLightingLevel = worldLightingLevel; x298_24_dirty = false; x294_aid = area.GetAreaId(); - x29c_shadowLightValIdx = -1; + x29c_shadowLightArrIdx = -1; x288_ambientColor = zeus::CColor::skClear; /* Find candidate lights via PVS */ @@ -369,7 +369,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& zeus::CVector3f delta = light.GetPosition() - vec; float deltaMag = delta.magnitude(); bool useShadow = false; - if (x298_27_findShadowLight && x29c_shadowLightValIdx == -1 && light.GetType() != ELightType::LocalAmbient && + if (x298_27_findShadowLight && x29c_shadowLightArrIdx == -1 && light.GetType() != ELightType::LocalAmbient && deltaMag > 2.f && !aabb.pointInside(light.GetPosition())) { /* Perform shadow dynamic range check */ @@ -383,7 +383,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& if (useShadow) { /* Note shadow light */ - x29c_shadowLightValIdx = x0_areaLights.size(); + x29c_shadowLightArrIdx = x0_areaLights.size(); x2a0_shadowLightIdx = value.x0_areaLightIdx; } else if (!outOfBounds) diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp index 729d0b07c..c9499e6cb 100644 --- a/Runtime/Character/CActorLights.hpp +++ b/Runtime/Character/CActorLights.hpp @@ -40,8 +40,8 @@ class CActorLights u16 _dummy = 0; }; bool x29a_findNearestDynamicLights = false; - u32 x29c_shadowLightValIdx = -1; - u32 x2a0_shadowLightIdx = -1; + s32 x29c_shadowLightArrIdx = -1; + s32 x2a0_shadowLightIdx = -1; u32 x2a4_lastUpdateFrame = 0; u32 x2a8_areaUpdateFramePeriod; zeus::CVector3f x2ac_actorPosBias; @@ -51,7 +51,7 @@ class CActorLights float x2cc_actorPositionDeltaUpdateThreshold; float x2d0_shadowDynamicRangeThreshold = 0.f; float x2d4_worldLightingLevel = 1.f; - u32 x2d8_brightLightIdx = -1; + s32 x2d8_brightLightIdx = -1; u32 x2dc_brightLightLag = 0; static void MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag); @@ -75,11 +75,11 @@ public: void ActivateLights(CBooModel& model) const; void SetCastShadows(bool v) { x298_25_castShadows = v; } void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } + void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; } void SetAmbientChannelOverflow(bool v) { x298_29_ambientChannelOverflow = v; } void DisableAreaLights(); void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; } void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; } - void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; } const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; } const CLight& GetLight(u32 idx) const; @@ -88,6 +88,9 @@ public: const std::vector& GetAreaLights() const { return x0_areaLights; } const std::vector& GetDynamicLights() const { return x144_dynamicLights; } bool GetIsDirty() const { return x298_24_dirty; } + bool HasShadowLight() const { return x29c_shadowLightArrIdx != -1; } + s32 GetShadowLightArrIndex() const { return x29c_shadowLightArrIdx; } + s32 GetShadowLightIndex() const { return x2a0_shadowLightIdx; } }; } diff --git a/Runtime/GuiSys/CHudVisorBeamMenu.hpp b/Runtime/GuiSys/CHudVisorBeamMenu.hpp index 6df116c8a..77d01a940 100644 --- a/Runtime/GuiSys/CHudVisorBeamMenu.hpp +++ b/Runtime/GuiSys/CHudVisorBeamMenu.hpp @@ -37,8 +37,8 @@ private: CGuiFrame& x0_baseHud; EHudVisorBeamMenu x4_type; - u32 x8_selectedItem = 0; - u32 xc_pendingSelection = 0; + int x8_selectedItem = 0; + int xc_pendingSelection = 0; float x10_interp = 1.f; bool x14_24_visibleDebug : 1; bool x14_25_visibleGame : 1; diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index 54ae2c317..ca2f7842c 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -625,7 +625,7 @@ void CSamusHud::UpdateVisorAndBeamMenus(float dt, const CStateManager& mgr) if (x2a8_beamMenu) { - x2a8_beamMenu->SetSelection(gun.GetSelectedBeam(), gun.GetPendingSelectedBeam(), beamInterp); + x2a8_beamMenu->SetSelection(int(gun.GetCurrentBeam()), int(gun.GetNextBeam()), beamInterp); x2a8_beamMenu->SetPlayerHas(BuildPlayerHasBeams(mgr)); } diff --git a/Runtime/MP1/World/CMetroidBeta.cpp b/Runtime/MP1/World/CMetroidBeta.cpp index eec431cfe..dc0403278 100644 --- a/Runtime/MP1/World/CMetroidBeta.cpp +++ b/Runtime/MP1/World/CMetroidBeta.cpp @@ -14,5 +14,10 @@ CMetroidBeta::CMetroidBeta(TUniqueId uid, const std::string& name, const CEntity { } +void CMetroidBeta::RenderHitGunEffect() const +{ + +} + } } diff --git a/Runtime/MP1/World/CMetroidBeta.hpp b/Runtime/MP1/World/CMetroidBeta.hpp index f7a44204c..e1f2a6b20 100644 --- a/Runtime/MP1/World/CMetroidBeta.hpp +++ b/Runtime/MP1/World/CMetroidBeta.hpp @@ -16,6 +16,7 @@ public: CMetroidBeta(TUniqueId uid, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const CMetroidData& metroidData); + void RenderHitGunEffect() const; }; } diff --git a/Runtime/Weapon/CAuxWeapon.cpp b/Runtime/Weapon/CAuxWeapon.cpp index 6fe5591db..b0d95fde3 100644 --- a/Runtime/Weapon/CAuxWeapon.cpp +++ b/Runtime/Weapon/CAuxWeapon.cpp @@ -18,7 +18,7 @@ bool CAuxWeapon::IsComboFxActive(const CStateManager& mgr) const return false; } -void CAuxWeapon::Load(int curBeam, CStateManager& mgr) +void CAuxWeapon::Load(CPlayerState::EBeamId curBeam, CStateManager& mgr) { } @@ -33,4 +33,9 @@ void CAuxWeapon::LoadIdle() } +void CAuxWeapon::RenderMuzzleFx() const +{ + +} + } diff --git a/Runtime/Weapon/CAuxWeapon.hpp b/Runtime/Weapon/CAuxWeapon.hpp index 092db769e..7d5bdd709 100644 --- a/Runtime/Weapon/CAuxWeapon.hpp +++ b/Runtime/Weapon/CAuxWeapon.hpp @@ -1,6 +1,7 @@ #ifndef __URDE_CAUXWEAPON_HPP__ #define __URDE_CAUXWEAPON_HPP__ +#include "CPlayerState.hpp" #include "RetroTypes.hpp" #include "CStateManager.hpp" @@ -14,10 +15,11 @@ public: explicit CAuxWeapon(TUniqueId id); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); bool IsComboFxActive(const CStateManager& mgr) const; - void Load(int curBeam, CStateManager& mgr); + void Load(CPlayerState::EBeamId curBeam, CStateManager& mgr); void StopComboFx(CStateManager& mgr, bool b1); void LoadIdle(); bool IsLoaded() const { return x80_24_isLoaded; } + void RenderMuzzleFx() const; }; } diff --git a/Runtime/Weapon/CGrappleArm.cpp b/Runtime/Weapon/CGrappleArm.cpp index 43fa34170..536ce90a5 100644 --- a/Runtime/Weapon/CGrappleArm.cpp +++ b/Runtime/Weapon/CGrappleArm.cpp @@ -46,6 +46,17 @@ void CGrappleArm::Update(float grappleSwingT, float dt, CStateManager& mgr) } +void CGrappleArm::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) +{ + +} + +void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, + const CModelFlags& flags, const CActorLights* lights) const +{ + +} + void CGrappleArm::AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) { diff --git a/Runtime/Weapon/CGrappleArm.hpp b/Runtime/Weapon/CGrappleArm.hpp index 6896893ef..52459dc60 100644 --- a/Runtime/Weapon/CGrappleArm.hpp +++ b/Runtime/Weapon/CGrappleArm.hpp @@ -10,6 +10,9 @@ namespace urde { +class CStateManager; +class CModelFlags; +class CActorLights; class CGrappleArm { @@ -31,6 +34,7 @@ public: private: CModelData x0_modelData; zeus::CTransform x220_xf; + zeus::CTransform x2e0_auxXf; std::unique_ptr x328_gunController; EArmState x334_animState; union @@ -51,6 +55,7 @@ public: void AsyncLoadSuit(CStateManager& mgr); void SetTransform(const zeus::CTransform& xf) { x220_xf = xf; } const zeus::CTransform& GetTransform() const { return x220_xf; } + zeus::CTransform& AuxTransform() { return x2e0_auxXf; } void SetAnimState(EArmState state); EArmState GetAnimState() const { return x334_animState; } bool GetActive() const { return x3b2_24_active; } @@ -64,6 +69,9 @@ public: void RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos); void TouchModel(const CStateManager& mgr) const; void Update(float grappleSwingT, 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 CActorLights* lights) const; void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void EnterStruck(CStateManager& mgr, float angle, bool attack, bool b2); void EnterIdle(CStateManager& mgr); diff --git a/Runtime/Weapon/CGunWeapon.cpp b/Runtime/Weapon/CGunWeapon.cpp index feeee24b9..cf06a707c 100644 --- a/Runtime/Weapon/CGunWeapon.cpp +++ b/Runtime/Weapon/CGunWeapon.cpp @@ -95,6 +95,11 @@ void CGunWeapon::TouchHolo(const CStateManager& mgr) } +void CGunWeapon::DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const +{ + +} + void CGunWeapon::UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting) { @@ -112,4 +117,11 @@ zeus::CAABox CGunWeapon::GetBounds() const return zeus::CAABox::skNullBox; } +zeus::CAABox CGunWeapon::GetBounds(const zeus::CTransform& xf) const +{ + if (x10_solidModelData) + return x10_solidModelData->GetBounds(xf); + return zeus::CAABox::skNullBox; +} + } diff --git a/Runtime/Weapon/CGunWeapon.hpp b/Runtime/Weapon/CGunWeapon.hpp index 6ad0730bb..c146d0342 100644 --- a/Runtime/Weapon/CGunWeapon.hpp +++ b/Runtime/Weapon/CGunWeapon.hpp @@ -118,6 +118,7 @@ public: virtual void Load(CStateManager& mgr, bool) {} virtual void Unload(CStateManager&) {} virtual bool IsLoaded() const {return false;} + void DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const; void UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting); const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; } void SetRainSplashGenerator(CRainSplashGenerator* g) { x1bc_rainSplashGenerator = g; } @@ -129,10 +130,12 @@ public: { x100_gunController->LoadFidgetAnimAsync(mgr, s32(type), s32(x200_beamId), parm2); } void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) { x100_gunController->EnterFidget(mgr, s32(type), s32(x200_beamId), parm2); } + bool HasSolidModelData() const { return x10_solidModelData.operator bool(); } CModelData& GetSolidModelData() { return *x10_solidModelData; } const SWeaponInfo& GetWeaponInfo() const; zeus::CAABox GetBounds() const; - void SetLeavingBeam() { x218_29_leavingBeam = true; } + zeus::CAABox GetBounds(const zeus::CTransform& xf) const; + void SetLeavingBeam(bool leaving) { x218_29_leavingBeam = leaving; } }; } diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index 0d932efc0..4959f93cf 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -1,3 +1,5 @@ +#include +#include #include "TCastTo.hpp" #include "CPlayerGun.hpp" #include "GameGlobalObjects.hpp" @@ -12,6 +14,10 @@ #include "Input/ControlMapper.hpp" #include "CBomb.hpp" #include "CPowerBomb.hpp" +#include "Graphics/CBooRenderer.hpp" +#include "World/CWorld.hpp" +#include "Camera/CGameCamera.hpp" +#include "GuiSys/CStringTable.hpp" namespace urde { @@ -30,7 +36,7 @@ CPlayerGun::CPlayerGun(TUniqueId playerId) zeus::CVector2f(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY), CPlayerCameraBob::kCameraBobPeriod), x678_morph(g_tweakPlayerGun->GetGunTransformTime(), g_tweakPlayerGun->GetHoloHoldTime()), - x6c8_(zeus::CVector3f(-0.29329199f, 0.f, -0.2481945f), + x6c8_hologramClipCube(zeus::CVector3f(-0.29329199f, 0.f, -0.2481945f), zeus::CVector3f(0.29329199f, 1.292392f, 0.2481945f)), x6e0_rightHandModel(CAnimRes(g_tweakGunRes->xc_rightHand, 0, zeus::CVector3f(3.f), 0, true)) { @@ -86,9 +92,9 @@ CPlayerGun::CPlayerGun(TUniqueId playerId) void CPlayerGun::InitBeamData() { x760_selectableBeams[0] = x74c_powerBeam.get(); - x760_selectableBeams[0] = x750_iceBeam.get(); - x760_selectableBeams[0] = x754_waveBeam.get(); - x760_selectableBeams[0] = x758_plasmaBeam.get(); + x760_selectableBeams[1] = x750_iceBeam.get(); + x760_selectableBeams[2] = x754_waveBeam.get(); + x760_selectableBeams[3] = x758_plasmaBeam.get(); x72c_currentBeam = x760_selectableBeams[0]; x738_nextBeam = x72c_currentBeam; x774_holoTransitionGen->SetParticleEmission(true); @@ -142,7 +148,7 @@ void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& { x384_ = 20.f; x364_ = 0.75f; - if (x678_morph.GetGunState() == CGunMorph::EGunState::One) + if (x678_morph.GetGunState() == CGunMorph::EGunState::OutWipeDone) { zeus::CVector3f localDamageLoc = mgr.GetPlayer().GetTransform().transposeRotate(x3dc_damageLocation); angle = zeus::CRelAngle(std::atan2(localDamageLoc.y, localDamageLoc.x)).asDegrees(); @@ -211,7 +217,6 @@ void CPlayerGun::SetGunLightActive(bool active, CStateManager& mgr) } } -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) @@ -223,12 +228,11 @@ void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt case EScriptObjectMessage::Registered: { CreateGunLight(mgr); - x320_ = x314_pendingSelectedBeam = x310_selectedBeam = - skBeamIdMap[int(mgr.GetPlayerState()->GetCurrentBeam())]; - x72c_currentBeam = x738_nextBeam = x760_selectableBeams[x310_selectedBeam]; + x320_currentAuxBeam = x314_nextBeam = x310_currentBeam = mgr.GetPlayerState()->GetCurrentBeam(); + x72c_currentBeam = x738_nextBeam = x760_selectableBeams[int(x310_currentBeam)]; x72c_currentBeam->Load(mgr, true); x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); - x744_auxWeapon->Load(x310_selectedBeam, mgr); + x744_auxWeapon->Load(x310_currentBeam, mgr); CAnimPlaybackParms parms(skBeamAnimIds[int(mgr.GetPlayerState()->GetCurrentBeam())], -1, 1.f, true); x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false); break; @@ -251,7 +255,7 @@ void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt if (player.GetDistanceUnderWater() > player.GetEyeHeight()) { x834_27_underwater = true; - if (x744_auxWeapon->IsComboFxActive(mgr) && x310_selectedBeam != 2) + if (x744_auxWeapon->IsComboFxActive(mgr) && x310_currentBeam != CPlayerState::EBeamId::Wave) StopContinuousBeam(mgr, false); } else @@ -373,10 +377,10 @@ void CPlayerGun::TouchModel(const CStateManager& mgr) x6e0_rightHandModel.Touch(mgr, 0); } - if (x734_) + if (x734_loadingBeam) { - x734_->Touch(mgr); - x734_->TouchHolo(mgr); + x734_loadingBeam->Touch(mgr); + x734_loadingBeam->TouchHolo(mgr); } } @@ -426,7 +430,7 @@ void CPlayerGun::ResetCharge(CStateManager& mgr, bool b1) x32c_ = 0; x330_chargeState = EChargeState::Normal; - x320_ = x310_selectedBeam; + x320_currentAuxBeam = x310_currentBeam; x833_30_ = true; x832_27_ = false; x832_26_ = false; @@ -472,7 +476,7 @@ void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) { CPlayerState& playerState = *mgr.GetPlayerState(); float maxBeamInput = 0.f; - int selectBeam = -1; + CPlayerState::EBeamId selectBeam = CPlayerState::EBeamId::Invalid; for (int i=0 ; i<4 ; ++i) { if (playerState.HasPowerUp(skBeamArr[i])) @@ -481,18 +485,18 @@ void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) if (inputVal > 0.65f && inputVal > maxBeamInput) { maxBeamInput = inputVal; - selectBeam = i; + selectBeam = CPlayerState::EBeamId(i); } } } - if (selectBeam < 0) + if (selectBeam == CPlayerState::EBeamId::Invalid) return; x833_25_ = true; - if (x310_selectedBeam != selectBeam && playerState.HasPowerUp(skBeamArr[selectBeam])) + if (x310_currentBeam != selectBeam && playerState.HasPowerUp(skBeamArr[int(selectBeam)])) { - x314_pendingSelectedBeam = u32(selectBeam); + x314_nextBeam = selectBeam; u32 flags = 0; if ((x2f8_ & 0x10) == 0x10) flags = 0x10; @@ -508,7 +512,7 @@ void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) x338_ = 5; x2e4_invalidSfx.reset(); } - else if (playerState.HasPowerUp(skBeamArr[selectBeam])) + else if (playerState.HasPowerUp(skBeamArr[int(selectBeam)])) { if (ExitMissile()) { @@ -524,7 +528,7 @@ void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) void CPlayerGun::SetPhazonBeamMorph(bool intoPhazonBeam) { - x39c_ = intoPhazonBeam ? 0.f : 1.f; + x39c_phazonMorphT = intoPhazonBeam ? 0.f : 1.f; x835_27_intoPhazonBeam = intoPhazonBeam; x835_26_phazonBeamMorphing = true; } @@ -561,13 +565,13 @@ void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerS StopContinuousBeam(mgr, true); if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) ResetCharge(mgr, false); - CAnimPlaybackParms parms(skBeamAnimIds[x314_pendingSelectedBeam], -1, 1.f, true); + CAnimPlaybackParms parms(skBeamAnimIds[int(x314_nextBeam)], -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_lastFireButtonStates &= ~0x1; - x320_ = x310_selectedBeam; + x320_currentAuxBeam = x310_currentBeam; x833_30_ = true; } @@ -594,17 +598,17 @@ void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) { case NWeaponTypes::EGunAnimType::FromMissile: x2f8_ &= ~0x4; - sfx = skFromMissileSound[x310_selectedBeam]; + sfx = skFromMissileSound[int(x310_currentBeam)]; break; case NWeaponTypes::EGunAnimType::MissileReload: sfx = 1769; break; case NWeaponTypes::EGunAnimType::FromBeam: - sfx = skFromBeamSound[x310_selectedBeam]; + sfx = skFromBeamSound[int(x310_currentBeam)]; break; case NWeaponTypes::EGunAnimType::ToMissile: x2f8_ &= ~0x1; - sfx = skToMissileSound[x310_selectedBeam]; + sfx = skToMissileSound[int(x310_currentBeam)]; break; default: break; @@ -713,8 +717,10 @@ void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr) if ((x2f8_ & 0x10) != 0x10) HandleWeaponChange(input, mgr); case CPlayer::EPlayerMorphBallState::Morphed: - x2f4_fireButtonStates = ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) ? 1 : 0; - x2f4_fireButtonStates |= ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) ? 2 : 0; + x2f4_fireButtonStates = + ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) ? 1 : 0; + x2f4_fireButtonStates |= + ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) ? 2 : 0; break; } } @@ -808,13 +814,13 @@ void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1) { ReturnArmAndGunToDefault(mgr, false); x744_auxWeapon->StopComboFx(mgr, b1); - switch (x310_selectedBeam) + switch (x310_currentBeam) { - case 0: - case 2: - case 3: + case CPlayerState::EBeamId::Power: + case CPlayerState::EBeamId::Wave: + case CPlayerState::EBeamId::Plasma: // All except ice - if (x310_selectedBeam != 0 || x833_28_phazonBeamActive) + if (x310_currentBeam != CPlayerState::EBeamId::Power || x833_28_phazonBeamActive) { x72c_currentBeam->EnableSecondaryFx( b1 ? CGunWeapon::ESecondaryFxType::Zero : CGunWeapon::ESecondaryFxType::Three); @@ -829,7 +835,7 @@ void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1) if (static_cast(x72c_currentBeam)->IsFiring()) static_cast(x72c_currentBeam)->StopBeam(mgr, b1); } - else if (x310_selectedBeam == 3) // Plasma + else if (x310_currentBeam == CPlayerState::EBeamId::Plasma) // Plasma { if (static_cast(x72c_currentBeam)->IsFiring()) static_cast(x72c_currentBeam)->StopBeam(mgr, b1); @@ -843,28 +849,278 @@ void CPlayerGun::CMotionState::Update(bool b1, float dt, zeus::CTransform& xf, C void CPlayerGun::ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr) { + if (x730_outgoingBeam != nullptr && x72c_currentBeam != x730_outgoingBeam) + x730_outgoingBeam->Unload(mgr); + x734_loadingBeam = x760_selectableBeams[int(x314_nextBeam)]; + if (x734_loadingBeam && x72c_currentBeam != x734_loadingBeam) + { + x734_loadingBeam->Load(mgr, false); + x744_auxWeapon->Load(x314_nextBeam, mgr); + } + + x72c_currentBeam->EnableFx(false); + x834_28_ = x32c_ != 0; + ResetBeamParams(mgr, playerState, true); + x678_morph.StartWipe(CGunMorph::EDir::In); } void CPlayerGun::GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, const std::string& lctrName, - bool b1, bool b2) + bool shake, bool dyn) { + if (dyn) + xfOut = mData.GetScaledLocatorTransformDynamic(lctrName, nullptr); + else + xfOut = mData.GetScaledLocatorTransform(lctrName); + if (x834_24_charging && shake) + xfOut.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); } void CPlayerGun::UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr) { + if (x834_26_) + x740_grappleArm->AuxTransform() = zeus::CTransform::Identity(); + else + GetLctrWithShake(x740_grappleArm->AuxTransform(), mData, "elbow", true, false); + x740_grappleArm->AuxTransform().origin = x740_grappleArm->AuxTransform() * zeus::CVector3f(-0.9f, -0.4f, 0.4f); + x740_grappleArm->SetTransform(x3e8_xf); } +CPlayerGun::CGunMorph::EMorphEvent CPlayerGun::CGunMorph::Update(float inY, float outY, float dt) +{ + EMorphEvent ret = EMorphEvent::None; + + if (x20_gunState == EGunState::InWipeDone) + { + x14_remHoldTime -= dt; + if (x14_remHoldTime <= 0.f && x24_25_weaponChanged) + { + StartWipe(EDir::Out); + x24_25_weaponChanged = false; + x14_remHoldTime = 0.f; + ret = EMorphEvent::InWipeDone; + } + } + + if (x24_24_morphing) + { + float omt = x8_remTime * xc_speed; + float t = 1.f - omt; + if (x1c_dir == EDir::In) + { + x0_yLerp = omt * outY + t * inY; + x18_transitionFactor = omt; + } + else + { + x0_yLerp = omt * inY + t * outY; + x18_transitionFactor = t; + } + + if (x8_remTime <= 0.f) + { + x24_24_morphing = false; + x8_remTime = 0.f; + if (x1c_dir == EDir::In) + { + x20_gunState = EGunState::InWipeDone; + x18_transitionFactor = 0.f; + } + else + { + x18_transitionFactor = 1.f; + x20_gunState = EGunState::OutWipeDone; + x1c_dir = EDir::Done; + ret = EMorphEvent::OutWipeDone; + } + } + else + { + x8_remTime -= dt; + } + } + + return ret; +} + +void CPlayerGun::CGunMorph::StartWipe(EDir dir) +{ + x14_remHoldTime = x10_holoHoldTime; + if (dir == EDir::In && x20_gunState == EGunState::InWipeDone) + return; + + if (dir != x1c_dir && x20_gunState != EGunState::OutWipe) + { + x8_remTime = x4_gunTransformTime; + xc_speed = 1.f / x4_gunTransformTime; + } + else if (x20_gunState != EGunState::InWipe) + { + x8_remTime = x4_gunTransformTime - x8_remTime; + } + + x1c_dir = dir; + x20_gunState = x1c_dir == EDir::In ? EGunState::InWipe : EGunState::OutWipe; + x24_24_morphing = true; +} + +static const u16 skIntoBeamSound[] = { 0, 1821, 1827, 1825 }; + void CPlayerGun::ProcessGunMorph(float dt, CStateManager& mgr) { + bool isUnmorphed = mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; + switch (x678_morph.GetGunState()) + { + case CGunMorph::EGunState::InWipeDone: + if (x310_currentBeam != x314_nextBeam && x734_loadingBeam != nullptr) + { + if (!isUnmorphed) + x734_loadingBeam->Touch(mgr); + if (x734_loadingBeam->IsLoaded() && x744_auxWeapon->IsLoaded()) + { + x730_outgoingBeam = (x734_loadingBeam == x72c_currentBeam ? nullptr : x72c_currentBeam); + x734_loadingBeam = nullptr; + x310_currentBeam = x314_nextBeam; + x320_currentAuxBeam = x314_nextBeam; + x833_30_ = true; + x72c_currentBeam = x760_selectableBeams[int(x314_nextBeam)]; + x738_nextBeam = x72c_currentBeam; + x678_morph.SetWeaponChanged(); + mgr.GetPlayerState()->SetCurrentBeam(x314_nextBeam); + } + } + break; + case CGunMorph::EGunState::InWipe: + case CGunMorph::EGunState::OutWipe: + x774_holoTransitionGen->SetGlobalTranslation(zeus::CVector3f(0.f, x678_morph.GetYLerp(), 0.f)); + x774_holoTransitionGen->Update(dt); + break; + default: + break; + } + switch (x678_morph.Update(0.2f, 1.292392f, dt)) + { + case CGunMorph::EMorphEvent::InWipeDone: + CSfxManager::SfxStart(1775, 1.f, 0.f, true, 0x74, false, kInvalidAreaId); + break; + case CGunMorph::EMorphEvent::OutWipeDone: + if (x730_outgoingBeam != nullptr && x72c_currentBeam != x730_outgoingBeam) + { + x730_outgoingBeam->Unload(mgr); + x730_outgoingBeam = nullptr; + } + if (isUnmorphed) + PlaySfx(skIntoBeamSound[int(x310_currentBeam)], x834_27_underwater, false, 0.165f); + x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); + x72c_currentBeam->EnableFx(true); + PlayAnim(NWeaponTypes::EGunAnimType::Ten, false); + if (x833_31_) + EnterFreeLook(mgr); + else if (x832_30_) + ReturnArmAndGunToDefault(mgr, false); + if (x834_28_ || (x2ec_lastFireButtonStates & 0x1) != 0) + { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) + x32c_ = 1; + x834_28_ = false; + } + x832_30_ = false; + x338_ = 6; + break; + default: + break; + } +} + +void CPlayerGun::SetPhazonBeamFeedback(bool active) +{ + const char16_t* str = g_MainStringTable->GetString(21); // Hyper-mode + CHUDMemoParms parms(5.f, true, !active, false); + MP1::CSamusHud::DisplayHudMemo(str, parms); + if (CSfxManager::IsPlaying(x2e8_phazonBeamSfx)) + CSfxManager::SfxStop(x2e8_phazonBeamSfx); + x2e8_phazonBeamSfx.reset(); + if (active) + x2e8_phazonBeamSfx = PlaySfx(3141, x834_27_underwater, false, 0.165f); +} + +void CPlayerGun::StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState) +{ + if (x833_28_phazonBeamActive == active) + return; + x760_selectableBeams[int(x310_currentBeam)]->Unload(mgr); + x760_selectableBeams[int(x310_currentBeam)] = active ? x75c_phazonBeam.get() : x738_nextBeam; + ResetBeamParams(mgr, playerState, false); + x72c_currentBeam = x760_selectableBeams[int(x310_currentBeam)]; + x833_28_phazonBeamActive = active; + SetPhazonBeamFeedback(active); + x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); + x72c_currentBeam->EnableFx(true); + x72c_currentBeam->SetLeavingBeam(false); + PlayAnim(NWeaponTypes::EGunAnimType::Ten, false); + if (x833_31_) + EnterFreeLook(mgr); + else if (x832_30_) + ReturnArmAndGunToDefault(mgr, false); + x832_30_ = false; } void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) { + if (x835_26_phazonBeamMorphing) + { + if (x835_27_intoPhazonBeam) + { + x39c_phazonMorphT += 15.f * dt; + if (x39c_phazonMorphT > 1.f) + x39c_phazonMorphT = 1.f; + } + else + { + x39c_phazonMorphT -= 2.f * dt; + if (x39c_phazonMorphT < 0.f) + { + x835_26_phazonBeamMorphing = false; + x39c_phazonMorphT = 0.f; + } + } + } + switch (x33c_gunOverrideMode) + { + case EGunOverrideMode::One: + if (x75c_phazonBeam) + { + x75c_phazonBeam->Update(dt, mgr); + if (x75c_phazonBeam->IsLoaded()) + { + StartPhazonBeamTransition(true, mgr, *mgr.GetPlayerState()); + SetPhazonBeamMorph(false); + x33c_gunOverrideMode = EGunOverrideMode::Three; + x338_ = 6; + } + } + break; + case EGunOverrideMode::Two: + if (x738_nextBeam) + { + x738_nextBeam->Update(dt, mgr); + if (x738_nextBeam->IsLoaded()) + { + x835_25_inPhazonBeam = false; + StartPhazonBeamTransition(false, mgr, *mgr.GetPlayerState()); + SetPhazonBeamMorph(false); + x33c_gunOverrideMode = EGunOverrideMode::Normal; + x338_ = 6; + } + } + break; + default: + break; + } } void CPlayerGun::UpdateChargeState(float dt, CStateManager& mgr) @@ -910,7 +1166,7 @@ void CPlayerGun::ResetCharged(float dt, CStateManager& mgr) } else if (x32c_ != 0) { - x320_ = x310_selectedBeam; + x320_currentAuxBeam = x310_currentBeam; x833_30_ = true; x32c_ = 10; } @@ -938,7 +1194,7 @@ void CPlayerGun::ProcessChargeState(u32 releasedStates, u32 pressedStates, CStat { if (x32c_ >= 4) { - if (mgr.GetPlayerState()->HasPowerUp(skBeamComboArr[x310_selectedBeam])) + if (mgr.GetPlayerState()->HasPowerUp(skBeamComboArr[int(x310_currentBeam)])) ActivateCombo(mgr); } else if (x32c_ == 0) @@ -960,7 +1216,7 @@ void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr) return; if (mgr.GetCameraManager()->IsInCinematicCamera()) return; - x832_25_ = x833_28_phazonBeamActive || x310_selectedBeam != 3 || x32c_ != 0; + x832_25_ = x833_28_phazonBeamActive || x310_currentBeam != CPlayerState::EBeamId::Plasma || x32c_ != 0; x30c_ += 1; zeus::CTransform xf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; if (!x833_29_pointBlankWorldSurface && x364_ <= 0.f) @@ -1102,7 +1358,8 @@ void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CSt { if ((x2f8_ & 0x10) == 0x10 && x744_auxWeapon->IsComboFxActive(mgr)) { - if (x2ec_lastFireButtonStates == 0 || (x310_selectedBeam == 2 && x833_29_pointBlankWorldSurface)) + if (x2ec_lastFireButtonStates == 0 || + (x310_currentBeam == CPlayerState::EBeamId::Wave && x833_29_pointBlankWorldSurface)) { StopContinuousBeam(mgr, (x2f8_ & 0x8) == 0x8); } @@ -1124,7 +1381,7 @@ void CPlayerGun::EnterFreeLook(CStateManager& mgr) { if (!x832_30_) x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::FreeLook, mgr, 0.f, false); - x740_grappleArm->EnterFreeLook(x835_25_inPhazonBeam ? 1 : x310_selectedBeam, + x740_grappleArm->EnterFreeLook(x835_25_inPhazonBeam ? 1 : s32(x310_currentBeam), x73c_gunMotion->GetFreeLookSetId(), mgr); } @@ -1162,7 +1419,7 @@ void CPlayerGun::AsyncLoadFidget(CStateManager& mgr) SetFidgetAnimBits(x3a4_fidget.GetParm2(), x3a4_fidget.GetState() == CFidget::EState::Three); if ((x2fc_fidgetAnimBits & 0x1) == 0x1) x73c_gunMotion->GunController().LoadFidgetAnimAsync(mgr, s32(x3a4_fidget.GetType()), - x310_selectedBeam, x3a4_fidget.GetParm2()); + s32(x310_currentBeam), x3a4_fidget.GetParm2()); if ((x2fc_fidgetAnimBits & 0x2) == 0x2) { x72c_currentBeam->AsyncLoadFidget(mgr, (x3a4_fidget.GetState() == CFidget::EState::Three ? @@ -1172,7 +1429,7 @@ void CPlayerGun::AsyncLoadFidget(CStateManager& mgr) if ((x2fc_fidgetAnimBits & 0x4) == 0x4) if (CGunController* gc = x740_grappleArm->GunController()) gc->LoadFidgetAnimAsync(mgr, s32(x3a4_fidget.GetType()), - x3a4_fidget.GetType() != SamusGun::EFidgetType::Zero ? x310_selectedBeam : 0, + x3a4_fidget.GetType() != SamusGun::EFidgetType::Zero ? s32(x310_currentBeam) : 0, x3a4_fidget.GetParm2()); } @@ -1207,7 +1464,7 @@ void CPlayerGun::EnterFidget(CStateManager& mgr) if ((x2fc_fidgetAnimBits & 0x4) == 0x4) x740_grappleArm->EnterFidget(mgr, x3a4_fidget.GetType(), - x3a4_fidget.GetType() != SamusGun::EFidgetType::Zero ? x310_selectedBeam : 0, + x3a4_fidget.GetType() != SamusGun::EFidgetType::Zero ? s32(x310_currentBeam) : 0, x3a4_fidget.GetParm2()); UnLoadFidget(); @@ -1379,13 +1636,13 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM else advDt = dt; - bool r23 = x678_morph.GetGunState() != CGunMorph::EGunState::One; + bool r23 = x678_morph.GetGunState() != CGunMorph::EGunState::OutWipeDone; if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay || r23) x6e0_rightHandModel.AdvanceAnimation(advDt, mgr, kInvalidAreaId, true); - if (r23 && x734_ != 0 && x734_ != x72c_currentBeam) + if (r23 && x734_loadingBeam != 0 && x734_loadingBeam != x72c_currentBeam) { x744_auxWeapon->LoadIdle(); - x734_->Update(advDt, mgr); + x734_loadingBeam->Update(advDt, mgr); } if (!x744_auxWeapon->IsLoaded()) x744_auxWeapon->LoadIdle(); @@ -1413,7 +1670,7 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM if (x338_ != 0) { - if (x678_morph.GetGunState() == CGunMorph::EGunState::Zero) + if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipeDone) { if (x338_ == 5) { @@ -1468,14 +1725,14 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM case 8: if (x75c_phazonBeam->IsLoaded()) break; - x72c_currentBeam->SetLeavingBeam(); + x72c_currentBeam->SetLeavingBeam(true); x75c_phazonBeam->Load(mgr, false); x33c_gunOverrideMode = EGunOverrideMode::One; break; case 9: if (x738_nextBeam->IsLoaded()) break; - x72c_currentBeam->SetLeavingBeam(); + x72c_currentBeam->SetLeavingBeam(true); x738_nextBeam->Load(mgr, false); x33c_gunOverrideMode = EGunOverrideMode::Two; break; @@ -1558,7 +1815,7 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM bool emitting = x833_30_ ? x344_ < 1.f : false; zeus::CVector3f scale((emitting && x832_26_) ? (1.f - x344_) * 2.f : 2.f); x72c_currentBeam->UpdateMuzzleFx(advDt, scale, x418_beamLocalXf.origin, emitting); - CElementGen& gen = *x800_auxMuzzleGenerators[x320_]; + CElementGen& gen = *x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]; gen.SetGlobalOrientAndTrans(x418_beamLocalXf); gen.SetGlobalScale(scale); gen.SetParticleEmission(emitting); @@ -1661,17 +1918,227 @@ void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateM void CPlayerGun::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) { + const CPlayerState& playerState = *mgr.GetPlayerState(); + if (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) + return; + CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr); + switch (activeVisor) + { + case CPlayerState::EPlayerVisor::Thermal: + x0_lights.BuildConstantAmbientLighting( + zeus::CColor(zeus::clamp(0.6f, 0.5f * x380_ + 0.6f - x378_, 1.f), 1.f)); + break; + case CPlayerState::EPlayerVisor::Combat: + { + zeus::CAABox aabb = x72c_currentBeam->GetBounds(zeus::CTransform::Translate(camPos) * x4a8_gunWorldXf); + if (mgr.GetNextAreaId() != kInvalidAreaId) + { + x0_lights.SetFindShadowLight(true); + x0_lights.SetShadowDynamicRangeThreshold(0.25f); + x0_lights.BuildAreaLightList(mgr, *mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()), aabb); + } + x0_lights.BuildDynamicLightList(mgr, aabb); + if (x0_lights.HasShadowLight()) + { + if (x72c_currentBeam->IsLoaded()) + { + x82c_shadow->BuildLightShadowTexture(mgr, mgr.GetNextAreaId(), + x0_lights.GetShadowLightIndex(), aabb, true, false); + } + } + else + { + x82c_shadow->ResetBlur(); + } + break; + } + default: + break; + } + + if (x740_grappleArm->GetActive()) + x740_grappleArm->PreRender(mgr, frustum, camPos); + + if (x678_morph.GetGunState() != CGunMorph::EGunState::OutWipeDone || + activeVisor == CPlayerState::EPlayerVisor::XRay) + x6e0_rightHandModel.AnimationData()->PreRender(); + + if (x833_28_phazonBeamActive) + g_Renderer->AllocatePhazonSuitMaskTexture(); } +static const CModelFlags kThermalFlags[] = +{ + {0, 0, 3, zeus::CColor::skWhite}, + {5, 0, 3, zeus::CColor(0.f, 0.5f)}, + {0, 0, 3, zeus::CColor::skWhite}, + {0, 0, 3, zeus::CColor::skWhite} +}; + +void CPlayerGun::RenderEnergyDrainEffects(const CStateManager& mgr) const +{ + if (TCastToConstPtr player = mgr.GetObjectById(x538_playerId)) + { + for (const auto& source : player->GetEnergyDrain().GetEnergyDrainSources()) + { + if (auto* metroid = + CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) + { + metroid->RenderHitGunEffect(); + return; + } + } + } +} + +void CPlayerGun::DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const +{ + const CPlayer& player = mgr.GetPlayer(); + if (!x740_grappleArm->GetActive() || x740_grappleArm->GetAnimState() == CGrappleArm::EArmState::Ten) + return; + + if (player.GetGrappleState() != CPlayer::EGrappleState::None || + x740_grappleArm->GetTransform().basis[1].dot(player.GetTransform().basis[1]) > 0.1f) + { + CModelFlags useFlags; + if (x740_grappleArm->IsArmMoving()) + useFlags = flags; + else + useFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); + + x740_grappleArm->Render(mgr, pos, useFlags, &x0_lights); + } +} + +zeus::CVector3f CPlayerGun::ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const +{ + zeus::CVector3f camToPosLocal = cam.GetTransform().transposeRotate(pos - cam.GetTranslation()); + if (!camToPosLocal.isZero()) + return CGraphics::GetPerspectiveProjectionMatrix(false).multiplyOneOverW(camToPosLocal); + else + return {-1.f, -1.f, 1.f}; +} + +static void CopyScreenTex() {} +static void DrawScreenTex(float f1) {} +static void DrawClipCube(const zeus::CAABox& aabb) {} + +static const CModelFlags kHandThermalFlag = {7, 0, 3, zeus::CColor::skWhite}; +static const CModelFlags kHandHoloFlag = {1, 0, 3, zeus::CColor(0.75f, 0.5f, 0.f, 1.f)}; + void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const { + CGraphics::CProjectionState projState = CGraphics::GetProjectionState(); + CModelFlags useFlags; + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) + { + useFlags = kThermalFlags[int(x310_currentBeam)]; + } + else + { + if (x835_26_phazonBeamMorphing) + useFlags = CModelFlags(1, 0, 3, zeus::CColor::lerp(zeus::CColor::skWhite, zeus::CColor::skBlack, + x39c_phazonMorphT)); + else + useFlags = flags; + } + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + CGraphics::SetDepthRange(0.03125f, 0.125f); + zeus::CTransform offsetWorldXf = zeus::CTransform::Translate(pos) * x4a8_gunWorldXf; + zeus::CTransform elbowOffsetXf = offsetWorldXf * x508_elbowLocalXf; + if (x32c_ && (x2f8_ & 0x10) != 0x10) + offsetWorldXf.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); + + zeus::CTransform oldViewMtx = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + if (x32c_ >= 4 && x32c_ < 5) + x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->Render(); + + if (x832_25_ && (x38c_ > 0.f || x32c_ > 2)) + x72c_currentBeam->DrawMuzzleFx(mgr); + + if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipe || + x678_morph.GetGunState() == CGunMorph::EGunState::OutWipe) + x774_holoTransitionGen->Render(); + + CGraphics::SetViewPointMatrix(oldViewMtx); + if ((x2f8_ & 0x10) == 0x10) + x744_auxWeapon->RenderMuzzleFx(); + + x72c_currentBeam->PreRenderGunFx(mgr, offsetWorldXf); + bool r26 = !x740_grappleArm->IsGrappling() && + mgr.GetPlayer().GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn; + x73c_gunMotion->Draw(mgr, offsetWorldXf); + + switch (x678_morph.GetGunState()) + { + case CGunMorph::EGunState::OutWipeDone: + if (x0_lights.HasShadowLight()) + x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) + { + x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ? + kHandThermalFlag : kHandHoloFlag); + } + DrawArm(mgr, pos, flags); + x72c_currentBeam->Draw(r26, mgr, offsetWorldXf, useFlags, &x0_lights); + x82c_shadow->DisableModelProjectedShadow(); + break; + case CGunMorph::EGunState::InWipeDone: + case CGunMorph::EGunState::InWipe: + case CGunMorph::EGunState::OutWipe: + if (x678_morph.GetGunState() != CGunMorph::EGunState::InWipeDone) + { + zeus::CTransform morphXf = elbowOffsetXf * zeus::CTransform::Translate(0.f, x678_morph.GetYLerp(), 0.f); + CopyScreenTex(); + x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ? + kHandThermalFlag : kHandHoloFlag); + x72c_currentBeam->DrawHologram(mgr, offsetWorldXf, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + DrawScreenTex(ConvertToScreenSpace(morphXf.origin, *cam).z); + if (x0_lights.HasShadowLight()) + x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); + CGraphics::SetModelMatrix(morphXf); + DrawClipCube(x6c8_hologramClipCube); + x72c_currentBeam->Draw(r26, mgr, offsetWorldXf, useFlags, &x0_lights); + x82c_shadow->DisableModelProjectedShadow(); + } + else + { + x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ? + kHandThermalFlag : kHandHoloFlag); + x72c_currentBeam->DrawHologram(mgr, offsetWorldXf, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + if (x0_lights.HasShadowLight()) + x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); + DrawArm(mgr, pos, flags); + x82c_shadow->DisableModelProjectedShadow(); + } + break; + } + + oldViewMtx = CGraphics::g_ViewMatrix; + CGraphics::SetModelMatrix(offsetWorldXf.inverse() * oldViewMtx); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf); + if (x832_26_ && x77c_) + x77c_->Render(); + CGraphics::SetViewPointMatrix(oldViewMtx); + + RenderEnergyDrainEffects(mgr); + + CGraphics::SetDepthRange(0.125f, 1.f); + CGraphics::SetProjectionState(projState); } void CPlayerGun::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { - + if (x72c_currentBeam->HasSolidModelData()) + x72c_currentBeam->GetSolidModelData().RenderParticles(frustum); } void CPlayerGun::DropBomb(EBWeapon weapon, CStateManager& mgr) diff --git a/Runtime/Weapon/CPlayerGun.hpp b/Runtime/Weapon/CPlayerGun.hpp index 3a6d23b79..ca949a15e 100644 --- a/Runtime/Weapon/CPlayerGun.hpp +++ b/Runtime/Weapon/CPlayerGun.hpp @@ -51,26 +51,40 @@ private: public: enum class EGunState { - Zero, - One + InWipeDone, + OutWipeDone, + InWipe, + OutWipe + }; + enum class EMorphEvent + { + None, + InWipeDone, + OutWipeDone + }; + enum class EDir + { + In, + Out, + Done }; private: - float x0_ = 0.f; + float x0_yLerp = 0.f; float x4_gunTransformTime; - float x8_ = 0.f; - float xc_ = 0.1f; + float x8_remTime = 0.f; + float xc_speed = 0.1f; float x10_holoHoldTime; - float x14_ = 2.f; + float x14_remHoldTime = 2.f; float x18_transitionFactor = 1.f; - u32 x1c_ = 2; - EGunState x20_gunState = EGunState::One; + EDir x1c_dir = EDir::Done; + EGunState x20_gunState = EGunState::OutWipeDone; union { struct { - bool x24_24_ : 1; - bool x24_25_ : 1; + bool x24_24_morphing : 1; + bool x24_25_weaponChanged : 1; }; u32 _dummy = 0; }; @@ -78,8 +92,12 @@ private: public: CGunMorph(float gunTransformTime, float holoHoldTime) : x4_gunTransformTime(gunTransformTime), x10_holoHoldTime(std::fabs(holoHoldTime)) {} + float GetYLerp() const { return x0_yLerp; } float GetTransitionFactor() const { return x18_transitionFactor; } EGunState GetGunState() const { return x20_gunState; } + void SetWeaponChanged() { x24_25_weaponChanged = true; } + EMorphEvent Update(float inY, float outY, float dt); + void StartWipe(EDir dir); }; class CMotionState @@ -113,7 +131,7 @@ private: CActorLights x0_lights; CSfxHandle x2e0_chargeSfx; CSfxHandle x2e4_invalidSfx; - u32 x2e8_ = 0; + CSfxHandle x2e8_phazonBeamSfx; // 0x1: FireOrBomb, 0x2: MissileOrPowerBomb u32 x2ec_lastFireButtonStates = 0; u32 x2f0_pressedFireButtonStates = 0; @@ -124,11 +142,11 @@ private: u32 x304_ = 0; u32 x308_bombCount = 3; u32 x30c_ = 0; - u32 x310_selectedBeam = 0; - u32 x314_pendingSelectedBeam = 0; + CPlayerState::EBeamId x310_currentBeam = CPlayerState::EBeamId::Power; + CPlayerState::EBeamId x314_nextBeam = CPlayerState::EBeamId::Power; u32 x318_ = 0; EMissleMode x31c_missileMode = EMissleMode::Inactive; - u32 x320_ = 0; + CPlayerState::EBeamId x320_currentAuxBeam = CPlayerState::EBeamId::Power; u32 x324_ = 4; u32 x328_ = 0x2000; u32 x32c_ = 0; @@ -159,7 +177,7 @@ private: float x390_cooldown = 0.f; float x394_damageTimer = 0.f; float x398_damageAmt = 0.f; - float x39c_ = 0.f; + float x39c_phazonMorphT = 0.f; float x3a0_ = 0.f; CFidget x3a4_fidget; zeus::CVector3f x3dc_damageLocation; @@ -185,11 +203,11 @@ private: u32 x674_ = 0; CGunMorph x678_morph; CMotionState x6a0_motionState; - zeus::CAABox x6c8_; + zeus::CAABox x6c8_hologramClipCube; CModelData x6e0_rightHandModel; CGunWeapon* x72c_currentBeam = nullptr; - u32 x730_ = 0; - CGunWeapon* x734_ = nullptr; + CGunWeapon* x730_outgoingBeam = nullptr; + CGunWeapon* x734_loadingBeam = nullptr; CGunWeapon* x738_nextBeam = nullptr; std::unique_ptr x73c_gunMotion; std::unique_ptr x740_grappleArm; @@ -274,9 +292,11 @@ private: void ReturnToRestPose(); void ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr); void GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, const std::string& lctrName, - bool b1, bool b2); + bool shake, bool dyn); void UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr); void ProcessGunMorph(float dt, CStateManager& mgr); + void SetPhazonBeamFeedback(bool active); + void StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState); void ProcessPhazonGunMorph(float dt, CStateManager& mgr); void UpdateChargeState(float dt, CStateManager& mgr); void UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr); @@ -297,6 +317,9 @@ private: bool IsFidgetLoaded() const; void EnterFidget(CStateManager& mgr); void UpdateGunIdle(bool b1, float camBobT, float dt, CStateManager& mgr); + void RenderEnergyDrainEffects(const CStateManager& mgr) const; + void DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const; + zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const; public: explicit CPlayerGun(TUniqueId playerId); @@ -311,8 +334,8 @@ public: bool IsBombReady() const { return x835_28_bombReady; } u32 GetBombCount() const { return x308_bombCount; } bool IsPowerBombReady() const { return x835_29_powerBombReady; } - u32 GetSelectedBeam() const { return x310_selectedBeam; } - u32 GetPendingSelectedBeam() const { return x314_pendingSelectedBeam; } + CPlayerState::EBeamId GetCurrentBeam() const { return x310_currentBeam; } + CPlayerState::EBeamId GetNextBeam() const { return x314_nextBeam; } const CGunMorph& GetGunMorph() const { return x678_morph; } float GetHoloTransitionFactor() const { return x678_morph.GetTransitionFactor(); } void SetTransform(const zeus::CTransform& xf) { x3e8_xf = xf; } diff --git a/Runtime/Weapon/WeaponCommon.hpp b/Runtime/Weapon/WeaponCommon.hpp index 521c1a4e0..7bd88b667 100644 --- a/Runtime/Weapon/WeaponCommon.hpp +++ b/Runtime/Weapon/WeaponCommon.hpp @@ -44,7 +44,8 @@ enum class EGunAnimType ToMissile, Seven, MissileReload, - FromBeam + FromBeam, + Ten }; void primitive_set_to_token_vector(const CAnimData& animData, const std::set& primSet, diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index c641cf4c0..624d76a34 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -150,8 +150,7 @@ public: static T* CastTo(CEntity* ent) { if (TCastToPtr patterned = ent) - if (patterned->x34c_character == T::CharacterType) - return static_cast(patterned.GetPtr()); + return CastTo(patterned.GetPtr()); return nullptr; } @@ -159,8 +158,23 @@ public: static const T* CastTo(const CEntity* ent) { if (TCastToConstPtr patterned = ent) - if (patterned->x34c_character == T::CharacterType) - return static_cast(patterned.GetPtr()); + return CastTo(patterned.GetPtr()); + return nullptr; + } + + template + static T* CastTo(CPatterned* patterned) + { + if (patterned->x34c_character == T::CharacterType) + return static_cast(patterned); + return nullptr; + } + + template + static const T* CastTo(const CPatterned* patterned) + { + if (patterned->x34c_character == T::CharacterType) + return static_cast(patterned); return nullptr; } diff --git a/Runtime/World/CWorldShadow.cpp b/Runtime/World/CWorldShadow.cpp index f8c9f0e1a..dd81914eb 100644 --- a/Runtime/World/CWorldShadow.cpp +++ b/Runtime/World/CWorldShadow.cpp @@ -7,4 +7,25 @@ CWorldShadow::CWorldShadow(u32, u32, bool) { } +void CWorldShadow::EnableModelProjectedShadow(const zeus::CTransform& pos, s32 lightIdx, float f1) +{ + +} + +void CWorldShadow::DisableModelProjectedShadow() +{ + +} + +void CWorldShadow::BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, s32 lightIdx, + const zeus::CAABox& aabb, bool b1, bool b2) +{ + +} + +void CWorldShadow::ResetBlur() +{ + +} + } diff --git a/Runtime/World/CWorldShadow.hpp b/Runtime/World/CWorldShadow.hpp index 8a87226ab..4be8827a3 100644 --- a/Runtime/World/CWorldShadow.hpp +++ b/Runtime/World/CWorldShadow.hpp @@ -2,14 +2,21 @@ #define __URDE_CWORLDSHADOW_HPP__ #include "RetroTypes.hpp" +#include "zeus/CAABox.hpp" namespace urde { +class CStateManager; class CWorldShadow { public: CWorldShadow(u32, u32, bool); + void EnableModelProjectedShadow(const zeus::CTransform& pos, s32 lightIdx, float f1); + void DisableModelProjectedShadow(); + void BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, s32 lightIdx, + const zeus::CAABox& aabb, bool b1, bool b2); + void ResetBlur(); }; }