Add CPlayerState (#5)

* Start CPlayerState

* CPlayerState::CalculateHealth symbol rename

* Add inline constructor for CHealthInfo

* Add skeleton for the rest of CPlayerState

* Match CPlayerState::DecrPickUp

* Match more methods in CPlayerState

* Run formatting

* Fix function order

* Improving the constants
This commit is contained in:
Henrique Gemignani Passos Lima 2022-10-01 17:08:15 +03:00 committed by GitHub
parent 77b921601a
commit 1e30daa096
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 603 additions and 36 deletions

View File

@ -742,7 +742,7 @@ lbl_801D40C0:
/* 801D4168 001D10C8 80 7E 00 98 */ lwz r3, 0x98(r30)
/* 801D416C 001D10CC 7F E4 FB 78 */ mr r4, r31
/* 801D4170 001D10D0 80 63 00 00 */ lwz r3, 0(r3)
/* 801D4174 001D10D4 4B EB DD 49 */ bl PutTo__12CPlayerStateFR13COutPutStream
/* 801D4174 001D10D4 4B EB DD 49 */ bl PutTo__12CPlayerStateFR13COutputStream
/* 801D4178 001D10D8 7F E4 FB 78 */ mr r4, r31
/* 801D417C 001D10DC 38 7E 01 7C */ addi r3, r30, 0x17c
/* 801D4180 001D10E0 48 03 B1 15 */ bl PutTo__12CGameOptionsFR16CMemoryStreamOut

View File

@ -122,8 +122,8 @@ GetMissileComboChargeFactor__12CPlayerStateFv:
.global GetComboFireAmmoPeriod__12CPlayerStateCFv
GetComboFireAmmoPeriod__12CPlayerStateCFv:
/* 80091204 0008E164 80 03 00 08 */ lwz r0, 8(r3)
/* 80091208 0008E168 3C 60 80 3D */ lis r3, lbl_803CD778@ha
/* 8009120C 0008E16C 38 63 D7 78 */ addi r3, r3, lbl_803CD778@l
/* 80091208 0008E168 3C 60 80 3D */ lis r3, kComboAmmoPeriods@ha
/* 8009120C 0008E16C 38 63 D7 78 */ addi r3, r3, kComboAmmoPeriods@l
/* 80091210 0008E170 54 00 10 3A */ slwi r0, r0, 2
/* 80091214 0008E174 7C 23 04 2E */ lfsx f1, r3, r0
/* 80091218 0008E178 4E 80 00 20 */ blr
@ -131,8 +131,8 @@ GetComboFireAmmoPeriod__12CPlayerStateCFv:
.global GetMissileCostForAltAttack__12CPlayerStateCFv
GetMissileCostForAltAttack__12CPlayerStateCFv:
/* 8009121C 0008E17C 80 03 00 08 */ lwz r0, 8(r3)
/* 80091220 0008E180 3C 60 80 3D */ lis r3, lbl_803CD764@ha
/* 80091224 0008E184 38 63 D7 64 */ addi r3, r3, lbl_803CD764@l
/* 80091220 0008E180 3C 60 80 3D */ lis r3, kMissileCosts@ha
/* 80091224 0008E184 38 63 D7 64 */ addi r3, r3, kMissileCosts@l
/* 80091228 0008E188 54 00 10 3A */ slwi r0, r0, 2
/* 8009122C 0008E18C 7C 63 00 2E */ lwzx r3, r3, r0
/* 80091230 0008E190 4E 80 00 20 */ blr
@ -860,18 +860,12 @@ DecrPickUp__12CPlayerStateFQ212CPlayerState9EItemTypei:
/* 80091B98 0008EAF8 4D 80 00 20 */ bltlr
/* 80091B9C 0008EAFC 2C 04 00 28 */ cmpwi r4, 0x28
/* 80091BA0 0008EB00 40 81 00 08 */ ble lbl_80091BA8
.global sub_80091ba4
sub_80091ba4:
/* 80091BA4 0008EB04 4E 80 00 20 */ blr
lbl_80091BA8:
/* 80091BA8 0008EB08 2C 04 00 07 */ cmpwi r4, 7
/* 80091BAC 0008EB0C 40 80 00 10 */ bge lbl_80091BBC
/* 80091BB0 0008EB10 2C 04 00 04 */ cmpwi r4, 4
/* 80091BB4 0008EB14 41 82 00 10 */ beq lbl_80091BC4
.global sub_80091bb8
sub_80091bb8:
/* 80091BB8 0008EB18 4E 80 00 20 */ blr
lbl_80091BBC:
/* 80091BBC 0008EB1C 2C 04 00 09 */ cmpwi r4, 9
@ -917,7 +911,6 @@ lbl_80091C28:
/* 80091C48 0008EBA8 7C 04 00 2E */ lwzx r0, r4, r0
/* 80091C4C 0008EBAC 7C 09 03 A6 */ mtctr r0
/* 80091C50 0008EBB0 4E 80 04 20 */ bctr
.global lbl_80091C54
lbl_80091C54:
/* 80091C54 0008EBB4 57 C0 18 38 */ slwi r0, r30, 3
/* 80091C58 0008EBB8 7C 9D 02 14 */ add r4, r29, r0
@ -930,7 +923,6 @@ lbl_80091C54:
/* 80091C74 0008EBD4 40 81 00 50 */ ble lbl_80091CC4
/* 80091C78 0008EBD8 90 64 00 28 */ stw r3, 0x28(r4)
/* 80091C7C 0008EBDC 48 00 00 48 */ b lbl_80091CC4
.global lbl_80091C80
lbl_80091C80:
/* 80091C80 0008EBE0 37 FD 00 0C */ addic. r31, r29, 0xc
/* 80091C84 0008EBE4 41 82 00 40 */ beq lbl_80091CC4
@ -943,14 +935,13 @@ lbl_80091C80:
/* 80091CA0 0008EC00 C8 21 00 08 */ lfd f1, 8(r1)
/* 80091CA4 0008EC04 EC 21 10 28 */ fsubs f1, f1, f2
/* 80091CA8 0008EC08 EF E1 00 2A */ fadds f31, f1, f0
/* 80091CAC 0008EC0C 48 00 00 85 */ bl CalculateHealth__12CPlayerStateFUi
/* 80091CAC 0008EC0C 48 00 00 85 */ bl CalculateHealth__12CPlayerStateFv
/* 80091CB0 0008EC10 FC 1F 08 40 */ fcmpo cr0, f31, f1
/* 80091CB4 0008EC14 40 81 00 0C */ ble lbl_80091CC0
/* 80091CB8 0008EC18 D0 3F 00 00 */ stfs f1, 0(r31)
/* 80091CBC 0008EC1C 48 00 00 08 */ b lbl_80091CC4
lbl_80091CC0:
/* 80091CC0 0008EC20 D3 FF 00 00 */ stfs f31, 0(r31)
.global lbl_80091CC4
lbl_80091CC4:
/* 80091CC4 0008EC24 2C 1E 00 18 */ cmpwi r30, 0x18
/* 80091CC8 0008EC28 40 82 00 14 */ bne lbl_80091CDC
@ -984,8 +975,8 @@ ResetAndIncrPickUp__12CPlayerStateFQ212CPlayerState9EItemTypei:
/* 80091D28 0008EC88 38 21 00 10 */ addi r1, r1, 0x10
/* 80091D2C 0008EC8C 4E 80 00 20 */ blr
.global CalculateHealth__12CPlayerStateFUi
CalculateHealth__12CPlayerStateFUi:
.global CalculateHealth__12CPlayerStateFv
CalculateHealth__12CPlayerStateFv:
/* 80091D30 0008EC90 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 80091D34 0008EC94 3C 00 43 30 */ lis r0, 0x4330
/* 80091D38 0008EC98 C8 42 8B 20 */ lfd f2, lbl_805AA840@sda21(r2)
@ -1017,11 +1008,11 @@ InitializePowerUp__12CPlayerStateFQ212CPlayerState9EItemTypei:
/* 80091D94 0008ECF4 48 00 00 DC */ b lbl_80091E70
lbl_80091D98:
/* 80091D98 0008ECF8 57 A0 18 38 */ slwi r0, r29, 3
/* 80091D9C 0008ECFC 3C 60 80 3D */ lis r3, lbl_803CD6C0@ha
/* 80091D9C 0008ECFC 3C 60 80 3D */ lis r3, kPowerUpMaxValues@ha
/* 80091DA0 0008ED00 7F DF 02 14 */ add r30, r31, r0
/* 80091DA4 0008ED04 57 A6 10 3A */ slwi r6, r29, 2
/* 80091DA8 0008ED08 80 FE 00 2C */ lwz r7, 0x2c(r30)
/* 80091DAC 0008ED0C 38 03 D6 C0 */ addi r0, r3, lbl_803CD6C0@l
/* 80091DAC 0008ED0C 38 03 D6 C0 */ addi r0, r3, kPowerUpMaxValues@l
/* 80091DB0 0008ED10 38 81 00 08 */ addi r4, r1, 8
/* 80091DB4 0008ED14 3B DE 00 28 */ addi r30, r30, 0x28
/* 80091DB8 0008ED18 7C 65 3A 14 */ add r3, r5, r7
@ -1099,8 +1090,8 @@ ReInitializePowerUp__12CPlayerStateFQ212CPlayerState9EItemTypei:
/* 80091EB4 0008EE14 38 21 00 10 */ addi r1, r1, 0x10
/* 80091EB8 0008EE18 4E 80 00 20 */ blr
.global PutTo__12CPlayerStateFR13COutPutStream
PutTo__12CPlayerStateFR13COutPutStream:
.global PutTo__12CPlayerStateFR13COutputStream
PutTo__12CPlayerStateFR13COutputStream:
/* 80091EBC 0008EE1C 94 21 FF C0 */ stwu r1, -0x40(r1)
/* 80091EC0 0008EE20 7C 08 02 A6 */ mflr r0
/* 80091EC4 0008EE24 90 01 00 44 */ stw r0, 0x44(r1)
@ -1131,9 +1122,9 @@ PutTo__12CPlayerStateFR13COutPutStream:
/* 80091F28 0008EE88 7C 65 1B 78 */ mr r5, r3
/* 80091F2C 0008EE8C 7F E3 FB 78 */ mr r3, r31
/* 80091F30 0008EE90 48 2A D4 8D */ bl WriteBits__13COutputStreamFii
/* 80091F34 0008EE94 3C 60 80 3D */ lis r3, lbl_803CD6C0@ha
/* 80091F34 0008EE94 3C 60 80 3D */ lis r3, kPowerUpMaxValues@ha
/* 80091F38 0008EE98 3B 9E 00 28 */ addi r28, r30, 0x28
/* 80091F3C 0008EE9C 3B A3 D6 C0 */ addi r29, r3, lbl_803CD6C0@l
/* 80091F3C 0008EE9C 3B A3 D6 C0 */ addi r29, r3, kPowerUpMaxValues@l
/* 80091F40 0008EEA0 3B 60 00 00 */ li r27, 0
lbl_80091F44:
/* 80091F44 0008EEA4 80 7D 00 00 */ lwz r3, 0(r29)
@ -1264,9 +1255,9 @@ __ct__12CPlayerStateFR12CInputStream:
/* 80092118 0008F078 7C 64 1B 78 */ mr r4, r3
/* 8009211C 0008F07C 7F E3 FB 78 */ mr r3, r31
/* 80092120 0008F080 48 2A CC 19 */ bl ReadBits__12CInputStreamFUi
/* 80092124 0008F084 3C 80 80 3D */ lis r4, lbl_803CD6C0@ha
/* 80092124 0008F084 3C 80 80 3D */ lis r4, kPowerUpMaxValues@ha
/* 80092128 0008F088 90 7E 00 20 */ stw r3, 0x20(r30)
/* 8009212C 0008F08C 3B 64 D6 C0 */ addi r27, r4, lbl_803CD6C0@l
/* 8009212C 0008F08C 3B 64 D6 C0 */ addi r27, r4, kPowerUpMaxValues@l
/* 80092130 0008F090 3B 9E 00 24 */ addi r28, r30, 0x24
/* 80092134 0008F094 3B A0 00 00 */ li r29, 0
lbl_80092138:
@ -1749,8 +1740,8 @@ sub_800926c4:
.section .rodata
.balign 8
.global lbl_803CD6C0
lbl_803CD6C0:
.global kPowerUpMaxValues
kPowerUpMaxValues:
# ROM: 0x3CA6C0
.4byte 0x00000001
.4byte 0x00000001
@ -1794,8 +1785,8 @@ lbl_803CD6C0:
.4byte 0x00000001
.4byte 0x00000001
.global lbl_803CD764
lbl_803CD764:
.global kMissileCosts
kMissileCosts:
# ROM: 0x3CA764
.4byte 0x00000005
.4byte 0x0000000A
@ -1803,8 +1794,8 @@ lbl_803CD764:
.4byte 0x0000000A
.4byte 0x00000001
.global lbl_803CD778
lbl_803CD778:
.global kComboAmmoPeriods
kComboAmmoPeriods:
# ROM: 0x3CA778
.float 0.2
.float 0.1

View File

@ -569,7 +569,7 @@ lbl_8015E630:
/* 8015E634 0015B594 41 82 00 20 */ beq lbl_8015E654
/* 8015E638 0015B598 C3 C3 00 00 */ lfs f30, 0(r3)
/* 8015E63C 0015B59C 7F E3 FB 78 */ mr r3, r31
/* 8015E640 0015B5A0 4B F3 36 F1 */ bl CalculateHealth__12CPlayerStateFUi
/* 8015E640 0015B5A0 4B F3 36 F1 */ bl CalculateHealth__12CPlayerStateFv
/* 8015E644 0015B5A4 FC 1E 08 40 */ fcmpo cr0, f30, f1
/* 8015E648 0015B5A8 40 80 00 0C */ bge lbl_8015E654
/* 8015E64C 0015B5AC 3B 20 00 01 */ li r25, 1

View File

@ -5,8 +5,9 @@
class CHealthInfo {
public:
CHealthInfo(f32 hp, f32 resist);
// TODO
CHealthInfo(f32 hp, f32 resist) : x0_health(hp), x4_knockbackResistance(resist) {}
void SetHP(float hp) { x0_health = hp; }
float GetHP() const { return x0_health; }
private:
f32 x0_health;

View File

@ -1,12 +1,66 @@
#ifndef _CPLAYERSTATE_HPP
#define _CPLAYERSTATE_HPP
#include "Kyoto/IObjectStore.hpp"
#include "MetroidPrime/CHealthInfo.hpp"
#include "MetroidPrime/Player/CStaticInterference.hpp"
#include "rstl/pair.hpp"
#include "rstl/reserved_vector.hpp"
#include "rstl/vector.hpp"
#include "types.h"
class CStateManager;
class CPlayerState {
public:
enum EItemType {
kIT_Invalid = -1,
kIT_PowerBeam = 0,
kIT_IceBeam = 1,
kIT_WaveBeam = 2,
kIT_PlasmaBeam = 3,
kIT_Missiles = 4,
kIT_ScanVisor = 5,
kIT_MorphBallBombs = 6,
kIT_PowerBombs = 7,
kIT_Flamethrower = 8,
kIT_ThermalVisor = 9,
kIT_ChargeBeam = 10,
kIT_SuperMissile = 11,
kIT_GrappleBeam = 12,
kIT_XRayVisor = 13,
kIT_IceSpreader = 14,
kIT_SpaceJumpBoots = 15,
kIT_MorphBall = 16,
kIT_CombatVisor = 17,
kIT_BoostBall = 18,
kIT_SpiderBall = 19,
kIT_PowerSuit = 20,
kIT_GravitySuit = 21,
kIT_VariaSuit = 22,
kIT_PhazonSuit = 23,
kIT_EnergyTanks = 24,
kIT_UnknownItem1 = 25,
kIT_HealthRefill = 26,
kIT_UnknownItem2 = 27,
kIT_Wavebuster = 28,
kIT_Truth = 29,
kIT_Strength = 30,
kIT_Elder = 31,
kIT_Wild = 32,
kIT_Lifegiver = 33,
kIT_Warrior = 34,
kIT_Chozo = 35,
kIT_Nature = 36,
kIT_Sun = 37,
kIT_World = 38,
kIT_Spirit = 39,
kIT_Newborn = 40,
/* This must remain at the end of the list */
kIT_Max
};
enum EPlayerVisor {
kPV_Combat,
kPV_XRay,
@ -34,12 +88,91 @@ public:
kBI_Phazon2 = 27,
};
EPlayerVisor GetActiveVisor(const CStateManager& mgr) const;
CPlayerState();
explicit CPlayerState(CInputStream& stream);
void PutTo(COutputStream& stream);
u32 GetMissileCostForAltAttack() const;
float GetComboFireAmmoPeriod() const;
static float GetMissileComboChargeFactor();
u32 CalculateItemCollectionRate();
u32 GetTotalPickupCount();
void SetIsFusionEnabled(bool v);
bool GetIsFusionEnabled();
EPlayerSuit GetCurrentSuit();
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; }
EPlayerVisor GetActiveVisor(const CStateManager& mgr) const;
void UpdateStaticInterference(CStateManager& stateMgr, const float& dt);
void IncreaseScanTime(u32 time, float val);
void SetScanTime(CAssetId res, float time);
float GetScanTime(CAssetId time) const;
bool GetIsVisorTransitioning() const;
float GetVisorTransitionFactor() const;
void UpdateVisorTransition(float dt);
void StartTransitionToVisor(EPlayerVisor visor);
void ResetVisor();
bool ItemEnabled(EItemType type) const;
void DisableItem(EItemType type);
void EnableItem(EItemType type);
bool HasPowerUp(EItemType type) const;
u32 GetPowerUp(EItemType type);
u32 GetItemCapacity(EItemType type) const;
u32 GetItemAmount(EItemType type) const;
void DecrPickUp(EItemType type, int amount);
void IncrPickUp(EItemType type, int amount);
void ResetAndIncrPickUp(EItemType type, int amount);
static float GetEnergyTankCapacity();
static float GetBaseHealthCapacity();
float CalculateHealth();
void InitializePowerUp(CPlayerState::EItemType type, int capacity);
void ReInitializePowerUp(CPlayerState::EItemType type, int capacity);
void InitializeScanTimes();
static uint GetBitCount(uint);
CStaticInterference& GetStaticInterference() { return x188_staticIntf; }
const rstl::vector< rstl::pair< CAssetId, float > >& GetScanTimes() const {
return x170_scanTimes;
}
CHealthInfo& GetHealthInfo() { return xc_health; }
const CHealthInfo& GetHealthInfo() const { return xc_health; }
private:
u8 pad[0x198];
struct CPowerUp {
int x0_amount;
int x4_capacity;
CPowerUp() : x0_amount(0), x4_capacity(0) {}
CPowerUp(int amount, int capacity);
};
bool x0_24_alive : 1;
bool x0_25_firingComboBeam : 1;
bool x0_26_fusion : 1;
u32 x4_enabledItems;
EBeamId x8_currentBeam;
CHealthInfo xc_health;
EPlayerVisor x14_currentVisor;
EPlayerVisor x18_transitioningVisor;
float x1c_visorTransitionFactor;
EPlayerSuit x20_currentSuit;
rstl::reserved_vector< CPowerUp, 41 > x24_powerups;
rstl::vector< rstl::pair< CAssetId, float > > x170_scanTimes;
rstl::pair< u32, u32 > x180_scanCompletionRate;
CStaticInterference x188_staticIntf;
};
#endif

View File

@ -0,0 +1,23 @@
#ifndef _CSTATICINTERFERENCE_HPP
#define _CSTATICINTERFERENCE_HPP
#include "types.h"
#include "MetroidPrime/TGameTypes.hpp"
#include "rstl/vector.hpp"
struct CStaticInterferenceSource {
TUniqueId x0_id;
float x4_magnitude;
float x8_timeLeft;
};
class CStaticInterference {
public:
CStaticInterference(int);
private:
rstl::vector< CStaticInterferenceSource > sources;
};
#endif

View File

@ -0,0 +1,419 @@
#include "MetroidPrime/Player/CPlayerState.hpp"
#include "Kyoto/Math/CMath.hpp"
#include "rstl/math.hpp"
#include <math.h>
static const int kPowerUpMaxValues[] = {
1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
static const int kMissileCosts[] = {
5, 10, 10, 10, 1,
};
static const float kComboAmmoPeriods[] = {
0.2f, 0.1f, 0.2f, 0.2f, 1.f,
};
static const float kEnergyTankCapacity = 100.f;
static const float kBaseHealthCapacity = 99.f;
uint CPlayerState::GetBitCount(uint val) {
int bits = 0;
for (; val != 0; val >>= 1) {
bits += 1;
}
return bits;
}
CPlayerState::CPowerUp::CPowerUp(int amount, int capacity)
: x0_amount(amount), x4_capacity(capacity) {}
CPlayerState::CPlayerState()
: x0_24_alive(true)
, x0_25_firingComboBeam(false)
, x0_26_fusion(false)
, x4_enabledItems(0)
, x8_currentBeam(kBI_Power)
, xc_health(99.f, 50.f)
, x14_currentVisor(kPV_Combat)
, x18_transitioningVisor(x14_currentVisor)
, x1c_visorTransitionFactor(0.2f)
, x20_currentSuit(kPS_Power)
, x24_powerups(CPowerUp(0, 0))
, x170_scanTimes()
, x180_scanCompletionRate(0, 0)
, x188_staticIntf(5) {}
CPlayerState::CPlayerState(CInputStream& stream)
: x0_24_alive(true)
, x0_25_firingComboBeam(false)
, x0_26_fusion(false)
, x4_enabledItems(0)
, x8_currentBeam(kBI_Power)
, xc_health(99.f, 50.f)
, x14_currentVisor(kPV_Combat)
, x18_transitioningVisor(x14_currentVisor)
, x1c_visorTransitionFactor(0.2f)
, x20_currentSuit(kPS_Power)
, x24_powerups()
, x170_scanTimes()
, x180_scanCompletionRate(0, 0)
, x188_staticIntf(5) {
// TODO
}
void CPlayerState::PutTo(COutputStream& stream) {
/*
stream.WriteBits(x4_enabledItems, 32);
const float realHP = xc_health.GetHP();
u32 integralHP;
std::memcpy(&integralHP, &realHP, sizeof(u32));
stream.WriteBits(integralHP, 32);
stream.WriteBits(u32(x8_currentBeam), COutputStream::GetBitCount(5));
stream.WriteBits(u32(x20_currentSuit), COutputStream::GetBitCount(4));
for (size_t i = 0; i < x24_powerups.size(); ++i) {
const CPowerUp& pup = x24_powerups[i];
stream.WriteBits(pup.x0_amount, COutputStream::GetBitCount(PowerUpMaxValues[i]));
stream.WriteBits(pup.x4_capacity, COutputStream::GetBitCount(PowerUpMaxValues[i]));
}
for (const auto& scanTime : x170_scanTimes) {
if (scanTime.second >= 1.f)
stream.WriteBits(true, 1);
else
stream.WriteBits(false, 1);
}
stream.WriteBits(x180_scanCompletionRate.first, COutputStream::GetBitCount(0x100));
stream.WriteBits(x180_scanCompletionRate.second, COutputStream::GetBitCount(0x100));
*/
}
void CPlayerState::ReInitializePowerUp(CPlayerState::EItemType type, int capacity) {
x24_powerups[u32(type)].x4_capacity = 0;
InitializePowerUp(type, capacity);
}
void CPlayerState::InitializePowerUp(CPlayerState::EItemType type, int capacity) {
if (type >= kIT_Max)
return;
CPowerUp& pup = x24_powerups[u32(type)];
pup.x4_capacity = CMath::Clamp(0, pup.x4_capacity + capacity, kPowerUpMaxValues[u32(type)]);
pup.x0_amount = rstl::min_val(pup.x0_amount, pup.x4_capacity);
if (type >= kIT_PowerSuit && type <= kIT_PhazonSuit) {
if (HasPowerUp(kIT_PhazonSuit))
x20_currentSuit = kPS_Phazon;
else if (HasPowerUp(kIT_GravitySuit))
x20_currentSuit = kPS_Gravity;
else if (HasPowerUp(kIT_VariaSuit))
x20_currentSuit = kPS_Varia;
else
x20_currentSuit = kPS_Power;
}
}
float CPlayerState::CalculateHealth() {
return (kEnergyTankCapacity * x24_powerups[kIT_EnergyTanks].x0_amount) + kBaseHealthCapacity;
}
void CPlayerState::ResetAndIncrPickUp(CPlayerState::EItemType type, int amount) {
x24_powerups[u32(type)].x0_amount = 0;
IncrPickUp(type, amount);
}
void CPlayerState::IncrPickUp(EItemType type, int amount) {
if (type < 0 || kIT_Max - 1 < type) {
return;
}
if (0 <= amount) {
switch (type) {
case kIT_Missiles:
case kIT_PowerBombs:
case kIT_ChargeBeam:
case kIT_SpaceJumpBoots:
case kIT_EnergyTanks:
case kIT_Truth:
case kIT_Strength:
case kIT_Elder:
case kIT_Wild:
case kIT_Lifegiver:
case kIT_Warrior:
case kIT_Chozo:
case kIT_Nature:
case kIT_Sun:
case kIT_World:
case kIT_Spirit:
case kIT_Newborn: {
int oldCapacity = x24_powerups[type].x4_capacity;
x24_powerups[type].x0_amount += amount;
if (oldCapacity < x24_powerups[type].x0_amount) {
x24_powerups[type].x0_amount = oldCapacity;
}
break;
}
case kIT_HealthRefill: {
CHealthInfo* info = &xc_health;
if (info != NULL) {
float newHealth = float(amount) + info->GetHP();
float maxHealth = CalculateHealth();
if (newHealth <= newHealth) {
info->SetHP(newHealth);
} else {
info->SetHP(maxHealth);
}
}
}
}
if (type == kIT_EnergyTanks)
IncrPickUp(kIT_HealthRefill, 9999);
}
}
void CPlayerState::DecrPickUp(CPlayerState::EItemType type, int amount) {
if (type < 0 || kIT_Max - 1 < type) {
return;
}
switch (type) {
case kIT_Missiles:
case kIT_PowerBombs:
case kIT_Flamethrower:
x24_powerups[type].x0_amount -= amount;
if (x24_powerups[type].x0_amount < 0) {
x24_powerups[type].x0_amount = 0;
}
default:
return;
}
}
u32 CPlayerState::GetItemAmount(CPlayerState::EItemType type) const {
if (type < 0 || kIT_Max - 1 < type) {
return 0;
}
switch (type) {
case kIT_SpaceJumpBoots:
case kIT_PowerBombs:
case kIT_Flamethrower:
case kIT_EnergyTanks:
case kIT_Missiles:
case kIT_Truth:
case kIT_Strength:
case kIT_Elder:
case kIT_Wild:
case kIT_Lifegiver:
case kIT_Warrior:
case kIT_Chozo:
case kIT_Nature:
case kIT_Sun:
case kIT_World:
case kIT_Spirit:
case kIT_Newborn:
return x24_powerups[u32(type)].x0_amount;
}
return 0;
}
u32 CPlayerState::GetItemCapacity(CPlayerState::EItemType type) const {
if (type < 0 || kIT_Max - 1 < type) {
return 0;
}
return x24_powerups[u32(type)].x4_capacity;
}
bool CPlayerState::HasPowerUp(CPlayerState::EItemType type) const {
if (type < 0 || kIT_Max - 1 < type) {
return false;
}
return x24_powerups[u32(type)].x4_capacity != 0;
}
u32 CPlayerState::GetPowerUp(CPlayerState::EItemType type) {
if (type < 0 || kIT_Max - 1 < type) {
return 0;
}
return x24_powerups[u32(type)].x4_capacity;
}
void CPlayerState::EnableItem(CPlayerState::EItemType type) {
if (HasPowerUp(type))
x4_enabledItems |= (1 << u32(type));
}
void CPlayerState::DisableItem(CPlayerState::EItemType type) {
if (HasPowerUp(type))
x4_enabledItems &= ~(1 << u32(type));
}
bool CPlayerState::ItemEnabled(CPlayerState::EItemType type) const {
if (HasPowerUp(type))
return (x4_enabledItems & (1 << u32(type)));
return false;
}
void CPlayerState::ResetVisor() {
x18_transitioningVisor = x14_currentVisor = kPV_Combat;
x1c_visorTransitionFactor = 0.0f;
}
void CPlayerState::StartTransitionToVisor(CPlayerState::EPlayerVisor visor) {
if (x18_transitioningVisor == visor)
return;
x18_transitioningVisor = visor;
}
void CPlayerState::UpdateVisorTransition(float dt) {
if (!GetIsVisorTransitioning())
return;
if (x14_currentVisor == x18_transitioningVisor) {
x1c_visorTransitionFactor += dt;
if (x1c_visorTransitionFactor > 0.2f)
x1c_visorTransitionFactor = 0.2f;
} else {
x1c_visorTransitionFactor -= dt;
if (x1c_visorTransitionFactor < 0.f) {
x14_currentVisor = x18_transitioningVisor;
x1c_visorTransitionFactor = fabs(x1c_visorTransitionFactor);
if (x1c_visorTransitionFactor > 0.19999f)
x1c_visorTransitionFactor = 0.19999f;
}
}
}
float CPlayerState::GetVisorTransitionFactor() const { return x1c_visorTransitionFactor / 0.2f; }
bool CPlayerState::GetIsVisorTransitioning() const {
return x14_currentVisor != x18_transitioningVisor || x1c_visorTransitionFactor < 0.2f;
}
float CPlayerState::GetBaseHealthCapacity() { return kBaseHealthCapacity; }
float CPlayerState::GetEnergyTankCapacity() { return kEnergyTankCapacity; }
void CPlayerState::InitializeScanTimes() {
if (x170_scanTimes.size())
return;
// TODO
// const auto& scanStates = g_MemoryCardSys->GetScanStates();
// x170_scanTimes.reserve(scanStates.size());
// for (const auto& state : scanStates)
// x170_scanTimes.emplace_back(state.first, 0.f);
}
float CPlayerState::GetScanTime(CAssetId res) const {
// TODO
rstl::vector< rstl::pair< CAssetId, float > >::const_iterator it = x170_scanTimes.end();
// const auto it = std::find_if(x170_scanTimes.cbegin(), x170_scanTimes.cend(),
// [&](const auto& test) -> bool { return test.first == res; });
if (it == x170_scanTimes.end())
return 0.f;
return it->second;
}
void CPlayerState::SetScanTime(CAssetId res, float time) {
// TODO
rstl::vector< rstl::pair< CAssetId, float > >::iterator it = x170_scanTimes.end();
// auto it = std::find_if(x170_scanTimes.begin(), x170_scanTimes.end(),
// [&](const auto& test) -> bool { return test.first == res; });
if (it != x170_scanTimes.end())
it->second = time;
}
void CPlayerState::UpdateStaticInterference(CStateManager& stateMgr, const float& dt) {
// TODO
// x188_staticIntf.Update(stateMgr, dt);
}
CPlayerState::EPlayerVisor CPlayerState::GetActiveVisor(const CStateManager& stateMgr) const {
void* cam = NULL;
// const CFirstPersonCamera* cam =
// TCastToConstPtr<CFirstPersonCamera>(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)).GetPtr();
return (cam ? x14_currentVisor : kPV_Combat);
}
bool CPlayerState::CanVisorSeeFog(const CStateManager& stateMgr) const {
EPlayerVisor activeVisor = GetActiveVisor(stateMgr);
if (activeVisor == kPV_Combat || activeVisor == kPV_Scan)
return true;
return true;
}
CPlayerState::EPlayerSuit CPlayerState::GetCurrentSuit() {
if (GetIsFusionEnabled())
return kPS_FusionPower;
return x20_currentSuit;
}
bool CPlayerState::GetIsFusionEnabled() { return x0_26_fusion; }
void CPlayerState::SetIsFusionEnabled(bool val) { x0_26_fusion = val; }
u32 CPlayerState::GetTotalPickupCount() { return 99; }
u32 CPlayerState::CalculateItemCollectionRate() {
u32 total = GetItemCapacity(kIT_PowerBombs);
if (total >= 4)
total -= 3;
total += GetItemCapacity(kIT_WaveBeam);
total += GetItemCapacity(kIT_IceBeam);
total += GetItemCapacity(kIT_PlasmaBeam);
total += GetItemCapacity(kIT_Missiles) / 5;
total += GetItemCapacity(kIT_MorphBallBombs);
total += GetItemCapacity(kIT_Flamethrower);
total += GetItemCapacity(kIT_ThermalVisor);
total += GetItemCapacity(kIT_ChargeBeam);
total += GetItemCapacity(kIT_SuperMissile);
total += GetItemCapacity(kIT_GrappleBeam);
total += GetItemCapacity(kIT_XRayVisor);
total += GetItemCapacity(kIT_IceSpreader);
total += GetItemCapacity(kIT_SpaceJumpBoots);
total += GetItemCapacity(kIT_MorphBall);
total += GetItemCapacity(kIT_BoostBall);
total += GetItemCapacity(kIT_SpiderBall);
total += GetItemCapacity(kIT_GravitySuit);
total += GetItemCapacity(kIT_VariaSuit);
total += GetItemCapacity(kIT_EnergyTanks);
total += GetItemCapacity(kIT_Truth);
total += GetItemCapacity(kIT_Strength);
total += GetItemCapacity(kIT_Elder);
total += GetItemCapacity(kIT_Wild);
total += GetItemCapacity(kIT_Lifegiver);
total += GetItemCapacity(kIT_Warrior);
total += GetItemCapacity(kIT_Chozo);
total += GetItemCapacity(kIT_Nature);
total += GetItemCapacity(kIT_Sun);
total += GetItemCapacity(kIT_World);
total += GetItemCapacity(kIT_Spirit);
total += GetItemCapacity(kIT_Newborn);
return total + GetItemCapacity(kIT_Wavebuster);
}
u32 CPlayerState::GetMissileCostForAltAttack() const {
return kMissileCosts[size_t(x8_currentBeam)];
}
float CPlayerState::GetComboFireAmmoPeriod() const {
return kComboAmmoPeriods[size_t(x8_currentBeam)];
}
float CPlayerState::GetMissileComboChargeFactor() { return 1.8f; }