metaforce/Runtime/MP1/World/CBabygoth.hpp

323 lines
11 KiB
C++
Raw Normal View History

2018-10-07 03:42:33 +00:00
#pragma once
2018-12-31 08:37:52 +00:00
#include <Runtime/Collision/CJointCollisionDescription.hpp>
#include "World/CPatterned.hpp"
2018-12-31 08:37:52 +00:00
#include "World/CPathFindSearch.hpp"
#include "Weapon/CProjectileInfo.hpp"
#include "Character/CBoneTracking.hpp"
namespace urde {
class CCollisionActorManager;
class CWeaponDescription;
2019-01-20 22:28:25 +00:00
} // namespace urde
2018-12-08 05:30:43 +00:00
namespace urde::MP1 {
2018-12-31 08:37:52 +00:00
struct CBabygothData {
2019-06-30 07:29:49 +00:00
float x0_fireballAttackTime;
float x4_fireballAttackTimeVariance;
CAssetId x8_fireballWeapon;
CDamageInfo xc_fireballDamage;
CDamageInfo x28_attackContactDamage;
CAssetId x44_fireBreathWeapon;
2018-12-31 08:37:52 +00:00
CAssetId x48_fireBreathRes;
CDamageInfo x4c_fireBreathDamage;
2019-06-30 07:29:49 +00:00
CDamageVulnerability x68_mouthVulnerabilities;
2018-12-31 08:37:52 +00:00
CDamageVulnerability xd0_shellVulnerabilities;
2019-06-30 07:29:49 +00:00
CAssetId x138_noShellModel;
CAssetId x13c_noShellSkin;
2018-12-31 08:37:52 +00:00
float x140_shellHitPoints;
s16 x144_shellCrackSfx;
2019-06-30 07:29:49 +00:00
CAssetId x148_intermediateCrackParticle;
CAssetId x14c_crackOneParticle;
CAssetId x150_crackTwoParticle;
CAssetId x154_destroyShellParticle;
s16 x158_crackOneSfx;
s16 x15a_crackTwoSfx;
s16 x15c_destroyShellSfx;
float x160_timeUntilAttack;
float x164_attackCooldownTime;
float x168_interestTime;
CAssetId x16c_flamePlayerSteamTxtr;
s16 x170_flamePlayerHitSfx;
CAssetId x174_flamePlayerIceTxtr;
2018-12-08 05:30:43 +00:00
public:
2018-12-08 05:30:43 +00:00
CBabygothData(CInputStream&);
2019-06-30 07:29:49 +00:00
const CDamageInfo& GetFireballDamage() const { return xc_fireballDamage; }
CAssetId GetFireballResID() const { return x8_fireballWeapon; }
float GetFireballAttackVariance() const { return x4_fireballAttackTimeVariance; }
float GetFireballAttackTime() const { return x0_fireballAttackTime; }
2018-12-31 08:37:52 +00:00
CAssetId GetFireBreathResId() const { return x48_fireBreathRes; }
2019-06-30 07:29:49 +00:00
const CDamageInfo& GetFireBreathDamage() const { return x4c_fireBreathDamage; }
2018-12-31 08:37:52 +00:00
const CDamageVulnerability& GetShellDamageVulnerability() const { return xd0_shellVulnerabilities; }
2019-01-20 22:28:25 +00:00
float GetShellHitPoints() const { return x140_shellHitPoints; }
s16 GetShellCrackSfx() const { return x144_shellCrackSfx; }
};
2018-12-31 08:37:52 +00:00
class CBabygoth final : public CPatterned {
public:
2019-06-30 07:29:49 +00:00
enum class EPathFindMode { Normal, Approach };
enum class EShellState { Default, CrackOne, CrackTwo, Destroyed };
2019-01-20 22:28:25 +00:00
2018-12-31 08:37:52 +00:00
private:
static constexpr s32 skSphereJointCount = 5;
static const SSphereJointInfo skSphereJointList[skSphereJointCount];
static const std::string_view skpMouthDamageJoint;
2019-06-30 07:29:49 +00:00
s32 x568_stateProg = -1;
EShellState x56c_shellState = EShellState::Default;
2018-12-31 08:37:52 +00:00
CBabygothData x570_babyData;
TUniqueId x6e8_teamMgr = kInvalidUniqueId;
2019-06-30 07:29:49 +00:00
CPathFindSearch x6ec_pathSearch;
CPathFindSearch x7d0_approachPathSearch;
2018-12-31 08:37:52 +00:00
EPathFindMode x8b4_pathFindMode;
2019-06-30 07:29:49 +00:00
zeus::CVector3f x8b8_backupDestPos;
zeus::CVector3f x8c4_initialFaceDir;
float x8d0_initialSpeed;
2018-12-31 08:37:52 +00:00
float x8d4_stepBackwardDist = 0.f;
2019-06-30 07:29:49 +00:00
float x8d8_attackTimeLeft = 0.f;
float x8dc_attackTimer = 0.f;
float x8e0_attackCooldownTimeLeft = 0.f;
float x8e4_fireballAttackTimeLeft = 0.f;
float x8e8_interestTimer = 0.f;
float x8ec_bodyHP = 0.f;
2018-12-31 08:37:52 +00:00
CBoneTracking x8f0_boneTracking;
std::unique_ptr<CCollisionActorManager> x928_colActMgr;
CCollidableAABox x930_aabox;
2019-06-30 07:29:49 +00:00
CProjectileInfo x958_iceProjectile;
2018-12-31 08:37:52 +00:00
TUniqueId x980_flameThrower = kInvalidUniqueId;
TToken<CWeaponDescription> x984_flameThrowerDesc;
2019-06-30 07:29:49 +00:00
CDamageVulnerability x98c_dVuln;
2018-12-31 08:37:52 +00:00
CSegId x9f4_mouthLocator;
2019-06-30 07:29:49 +00:00
TUniqueId x9f6_mouthCollisionActor = kInvalidUniqueId;
2019-07-07 08:22:35 +00:00
rstl::reserved_vector<TUniqueId, 2> x9f8_shellIds;
2018-12-31 08:37:52 +00:00
float xa00_shellHitPoints;
2019-06-30 07:29:49 +00:00
u32 xa04_drawMaterialIdx = 0;
2018-12-31 08:37:52 +00:00
TLockedToken<CSkinnedModel> xa08_noShellModel;
2019-06-30 07:29:49 +00:00
TToken<CGenDescription> xa14_crackOneParticle;
TToken<CGenDescription> xa20_crackTwoParticle;
TToken<CGenDescription> xa2c_destroyShellParticle;
TLockedToken<CGenDescription> xa38_intermediateCrackParticle; // Used to be an optional, not necessary in URDE
2018-12-31 08:37:52 +00:00
union {
struct {
bool xa48_24_isAlert : 1;
bool xa48_25_ : 1;
2019-06-30 07:29:49 +00:00
bool xa48_26_inProjectileAttack : 1;
2018-12-31 08:37:52 +00:00
bool xa48_27_ : 1;
2019-06-30 07:29:49 +00:00
bool xa48_28_pendingAttackContactDamage : 1;
bool xa48_29_hasBeenEnraged : 1;
bool xa48_30_heardPlayerFire : 1;
bool xa48_31_approachNeedsPathSearch : 1;
bool xa49_24_gettingUp : 1;
bool xa49_25_shouldStepBackwards : 1;
bool xa49_26_readyForTeam : 1;
bool xa49_27_locomotionValid : 1;
bool xa49_28_onApproachPath : 1;
bool xa49_29_objectSpaceCollision : 1;
2018-12-31 08:37:52 +00:00
};
u32 _dummy = 0;
};
2018-12-31 08:37:52 +00:00
void AddSphereCollisionList(const SSphereJointInfo*, s32, std::vector<CJointCollisionDescription>&);
2018-12-31 08:37:52 +00:00
void SetupCollisionManager(CStateManager&);
2018-12-31 08:37:52 +00:00
void SetupHealthInfo(CStateManager&);
2018-12-31 08:37:52 +00:00
void CreateFlameThrower(CStateManager&);
2018-12-31 08:37:52 +00:00
void ApplyContactDamage(TUniqueId, CStateManager&);
2018-12-31 08:37:52 +00:00
void RemoveFromTeam(CStateManager&);
2019-01-20 22:28:25 +00:00
void ApplySeparationBehavior(CStateManager&);
bool IsMouthCollisionActor(TUniqueId uid) const { return x9f6_mouthCollisionActor == uid; }
bool IsShell(TUniqueId uid) const {
2018-12-31 08:37:52 +00:00
for (TUniqueId shellId : x9f8_shellIds) {
if (shellId == uid)
return true;
}
return false;
}
void ApplyDamage(CStateManager& mgr, TUniqueId uid);
2019-01-20 22:28:25 +00:00
void AvoidPlayerCollision(float, CStateManager&);
void AddToTeam(CStateManager& mgr);
2019-06-30 07:29:49 +00:00
void UpdateTimers(float);
2019-06-30 07:29:49 +00:00
void UpdateHealthInfo(CStateManager& mgr);
2018-12-31 08:37:52 +00:00
void UpdateParticleEffects(float, CStateManager&);
2018-12-31 08:37:52 +00:00
void TryToGetUp(CStateManager& mgr);
2018-12-31 08:37:52 +00:00
bool CheckShouldWakeUp(CStateManager&, float);
2019-01-20 22:28:25 +00:00
void SetProjectilePasshtrough(CStateManager&);
2018-12-31 08:37:52 +00:00
void UpdateTouchBounds();
2019-01-20 22:28:25 +00:00
void UpdateAttackPosition(CStateManager&, zeus::CVector3f&);
2019-06-30 07:29:49 +00:00
void UpdateShellHealth(CStateManager&);
2019-01-20 22:28:25 +00:00
bool IsDestinationObstructed(CStateManager&);
2019-06-30 07:29:49 +00:00
void DestroyShell(CStateManager& mgr);
void CrackShell(CStateManager&, const TLockedToken<CGenDescription>&, const zeus::CTransform&, u16, bool);
2019-06-30 07:29:49 +00:00
void UpdateHealth(CStateManager&);
float CalculateShellCrackHP(EShellState state) const;
2019-06-30 07:29:49 +00:00
void UpdateAttackTimeLeft(CStateManager& mgr);
void ExtendCollisionActorTouchBounds(CStateManager& mgr, const zeus::CVector3f& extents);
void UpdateAttack(CStateManager& mgr, float dt);
2018-10-11 22:57:05 +00:00
public:
2018-12-08 05:30:43 +00:00
DEFINE_PATTERNED(Babygoth)
2018-12-08 05:30:43 +00:00
CBabygoth(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
const CPatternedInfo&, const CActorParameters&, const CBabygothData&);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override {
2018-12-31 08:37:52 +00:00
CPatterned::PreRender(mgr, frustum);
2019-06-30 07:29:49 +00:00
xb4_drawFlags.x1_matSetIdx = u8(xa04_drawMaterialIdx);
2018-12-31 08:37:52 +00:00
}
void Think(float, CStateManager&) override;
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
float GetGravityConstant() const override { return 10.f * CPhysicsActor::GravityConstant(); }
2018-12-31 08:37:52 +00:00
void SetPathFindMode(EPathFindMode mode) { x8b4_pathFindMode = mode; }
const CCollisionPrimitive* GetCollisionPrimitive() const override { return &x930_aabox; }
2018-12-31 08:37:52 +00:00
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f& v1, const zeus::CVector3f& v2,
const CWeaponMode& wMode,
EProjectileAttrib attrib) const override {
2018-12-31 08:37:52 +00:00
if (wMode.GetType() == EWeaponType::Ice)
return EWeaponCollisionResponseTypes::None;
2019-06-30 07:29:49 +00:00
if (x56c_shellState != EShellState::Destroyed)
2018-12-31 08:37:52 +00:00
return EWeaponCollisionResponseTypes::Unknown66;
return CPatterned::GetCollisionResponseType(v1, v2, wMode, attrib);
}
const CDamageVulnerability* GetDamageVulnerability() const override {
return &CDamageVulnerability::ReflectVulnerabilty();
}
const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&,
const CDamageInfo&) const override {
return &CDamageVulnerability::ReflectVulnerabilty();
}
zeus::CVector3f GetAimPosition(const CStateManager& mgr, float dt) const override;
2019-06-30 07:29:49 +00:00
zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role,
const zeus::CVector3f& aimPos) const override;
2019-06-30 07:29:49 +00:00
void TakeDamage(const zeus::CVector3f&, float) override {
2018-12-31 08:37:52 +00:00
if (x400_25_alive)
x428_damageCooldownTimer = 0.33f;
}
bool IsListening() const override { return true; }
2019-06-30 07:29:49 +00:00
void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, bool inDeferred,
float magnitude) override;
2019-06-30 07:29:49 +00:00
void Shock(CStateManager&, float, float) override;
2018-12-31 08:37:52 +00:00
void TurnAround(CStateManager&, EStateMsg, float) override;
void GetUp(CStateManager&, EStateMsg, float) override;
void Enraged(CStateManager&, EStateMsg, float) override;
void FollowPattern(CStateManager&, EStateMsg, float) override;
void Taunt(CStateManager&, EStateMsg, float) override;
void Crouch(CStateManager&, EStateMsg, float) override;
void Deactivate(CStateManager&, EStateMsg, float) override;
void Generate(CStateManager&, EStateMsg, float) override;
void TargetPatrol(CStateManager&, EStateMsg, float) override;
void Patrol(CStateManager&, EStateMsg, float) override;
void Approach(CStateManager&, EStateMsg, float) override;
void PathFind(CStateManager&, EStateMsg, float) override;
void SpecialAttack(CStateManager&, EStateMsg, float) override;
void Attack(CStateManager&, EStateMsg, float) override;
void ProjectileAttack(CStateManager&, EStateMsg, float) override;
2019-01-20 22:28:25 +00:00
bool Leash(CStateManager&, float) override;
2019-06-30 07:29:49 +00:00
bool AnimOver(CStateManager&, float) override { return x568_stateProg == 4; }
2019-01-20 22:28:25 +00:00
bool SpotPlayer(CStateManager& mgr, float arg) override {
2018-12-31 08:37:52 +00:00
if (xa48_24_isAlert)
return true;
return CPatterned::SpotPlayer(mgr, arg);
}
bool InPosition(CStateManager&, float) override { return (x8b8_backupDestPos - GetTranslation()).magSquared() < 9.f; }
2019-06-30 07:29:49 +00:00
bool InMaxRange(CStateManager&, float) override;
2019-01-20 22:28:25 +00:00
bool InDetectionRange(CStateManager&, float) override;
2019-06-30 07:29:49 +00:00
bool ShotAt(CStateManager&, float) override { return x400_24_hitByPlayerProjectile; }
bool OffLine(CStateManager& mgr, float arg) override {
2019-06-30 07:29:49 +00:00
SetPathFindMode(EPathFindMode::Normal);
return PathShagged(mgr, arg);
}
2019-06-30 07:29:49 +00:00
bool ShouldTurn(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool ShouldAttack(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool ShouldSpecialAttack(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool ShouldFire(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool TooClose(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool LineOfSight(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool AggressionCheck(CStateManager& mgr, float arg) override {
2019-06-30 07:29:49 +00:00
return x400_25_alive && !xa48_29_hasBeenEnraged && x56c_shellState == EShellState::Destroyed;
}
bool LostInterest(CStateManager& mgr, float arg) override;
2019-06-30 07:29:49 +00:00
bool Listen(const zeus::CVector3f&, EListenNoiseType) override;
2019-06-30 07:29:49 +00:00
CPathFindSearch* GetSearchPath() override {
2019-06-30 07:29:49 +00:00
return x8b4_pathFindMode == EPathFindMode::Normal ? &x6ec_pathSearch : &x7d0_approachPathSearch;
}
CProjectileInfo* GetProjectileInfo() override { return &x958_iceProjectile; }
2018-10-11 22:57:05 +00:00
};
2018-12-08 05:30:43 +00:00
} // namespace urde::MP1