Merge branch 'chozoghosts'

This commit is contained in:
Luke Street 2020-03-11 17:17:00 -04:00
commit cfd568bb39
14 changed files with 910 additions and 195 deletions

View File

@ -970,6 +970,14 @@ void CStateManager::DrawWorldCubeFaces() const {
} }
} }
void CStateManager::SetupFogForArea3XRange(TAreaId area) const {
if (area == kInvalidAreaId)
area = x8cc_nextAreaId;
const CGameArea* areaObj = x850_world->GetAreaAlways(area);
if (areaObj->IsPostConstructed())
SetupFogForArea3XRange(*areaObj);
}
void CStateManager::SetupFogForArea(TAreaId area) const { void CStateManager::SetupFogForArea(TAreaId area) const {
if (area == kInvalidAreaId) if (area == kInvalidAreaId)
area = x8cc_nextAreaId; area = x8cc_nextAreaId;
@ -986,6 +994,15 @@ void CStateManager::SetupFogForAreaNonCurrent(TAreaId area) const {
SetupFogForAreaNonCurrent(*areaObj); SetupFogForAreaNonCurrent(*areaObj);
} }
void CStateManager::SetupFogForArea3XRange(const CGameArea& area) const {
if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::XRay) {
float fogDist = area.GetXRayFogDistance();
float farz = (g_tweakGui->GetXRayFogNearZ() * (1.f - fogDist) + g_tweakGui->GetXRayFogFarZ() * fogDist) * 3.f;
g_Renderer->SetWorldFog(ERglFogMode(g_tweakGui->GetXRayFogMode()), g_tweakGui->GetXRayFogNearZ(), farz,
g_tweakGui->GetXRayFogColor());
}
}
void CStateManager::SetupFogForArea(const CGameArea& area) const { void CStateManager::SetupFogForArea(const CGameArea& area) const {
if (SetupFogForDraw()) if (SetupFogForDraw())
return; return;

View File

@ -261,8 +261,10 @@ public:
void DrawWorld() const; void DrawWorld() const;
void DrawActorCubeFaces(CActor& actor, int& cubeInst) const; void DrawActorCubeFaces(CActor& actor, int& cubeInst) const;
void DrawWorldCubeFaces() const; void DrawWorldCubeFaces() const;
void SetupFogForArea3XRange(TAreaId area) const;
void SetupFogForArea(TAreaId area) const; void SetupFogForArea(TAreaId area) const;
void SetupFogForAreaNonCurrent(TAreaId area) const; void SetupFogForAreaNonCurrent(TAreaId area) const;
void SetupFogForArea3XRange(const CGameArea& area) const;
void SetupFogForArea(const CGameArea& area) const; void SetupFogForArea(const CGameArea& area) const;
void SetupFogForAreaNonCurrent(const CGameArea& area) const; void SetupFogForAreaNonCurrent(const CGameArea& area) const;
bool SetupFogForDraw() const; bool SetupFogForDraw() const;

View File

@ -2,21 +2,18 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cfloat>
namespace urde { namespace urde {
CCharAnimTime CCharAnimTime::Infinity() { CCharAnimTime CCharAnimTime::Infinity() {
CCharAnimTime ret(1.f); return {EType::Infinity, 1.f};
ret.x4_type = EType::Infinity;
return ret;
} }
bool CCharAnimTime::EqualsZero() const { bool CCharAnimTime::EqualsZero() const {
if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing) if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing)
return true; return true;
return (x0_time == 0.f); return x0_time == 0.f;
} }
bool CCharAnimTime::EpsilonZero() const { return (std::fabs(x0_time) < 0.00001f); } bool CCharAnimTime::EpsilonZero() const { return (std::fabs(x0_time) < 0.00001f); }
@ -24,7 +21,7 @@ bool CCharAnimTime::EpsilonZero() const { return (std::fabs(x0_time) < 0.00001f)
bool CCharAnimTime::GreaterThanZero() const { bool CCharAnimTime::GreaterThanZero() const {
if (EqualsZero()) if (EqualsZero())
return false; return false;
return (x0_time > 0.f); return x0_time > 0.f;
} }
bool CCharAnimTime::operator==(const CCharAnimTime& other) const { bool CCharAnimTime::operator==(const CCharAnimTime& other) const {
@ -69,14 +66,14 @@ bool CCharAnimTime::operator>=(const CCharAnimTime& other) const {
if (*this == other) if (*this == other)
return true; return true;
return (*this > other); return *this > other;
} }
bool CCharAnimTime::operator<=(const CCharAnimTime& other) const { bool CCharAnimTime::operator<=(const CCharAnimTime& other) const {
if (*this == other) if (*this == other)
return true; return true;
return (*this < other); return *this < other;
} }
bool CCharAnimTime::operator>(const CCharAnimTime& other) const { return (!(*this == other) && !(*this < other)); } bool CCharAnimTime::operator>(const CCharAnimTime& other) const { return (!(*this == other) && !(*this < other)); }
@ -123,19 +120,17 @@ bool CCharAnimTime::operator<(const CCharAnimTime& other) const {
} }
CCharAnimTime& CCharAnimTime::operator*=(const CCharAnimTime& other) { CCharAnimTime& CCharAnimTime::operator*=(const CCharAnimTime& other) {
*this = *this * other; return *this = *this * other;
return *this;
} }
CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other) { CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other) {
*this = *this + other; return *this = *this + other;
return *this;
} }
CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const { CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const {
if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) { if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
if (other.x0_time != x0_time) if (other.x0_time != x0_time)
return CCharAnimTime(); return {};
return *this; return *this;
} else if (x4_type == EType::Infinity) } else if (x4_type == EType::Infinity)
return *this; return *this;
@ -143,58 +138,46 @@ CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const {
return other; return other;
if (!EqualsZero() || !other.EqualsZero()) if (!EqualsZero() || !other.EqualsZero())
return CCharAnimTime(x0_time + other.x0_time); return {x0_time + other.x0_time};
int type = -1; int type = -1;
if (x4_type != EType::ZeroDecreasing) { if (x4_type != EType::ZeroDecreasing) {
if (x4_type != EType::ZeroSteady) type = x4_type == EType::ZeroSteady ? 0 : 1;
type = 1;
else
type = 0;
} }
int otherType = -1; int otherType = -1;
if (other.x4_type != EType::ZeroDecreasing) { if (other.x4_type != EType::ZeroDecreasing) {
if (other.x4_type != EType::ZeroSteady) otherType = other.x4_type == EType::ZeroSteady ? 0 : 1;
otherType = 1;
else
otherType = 0;
} }
type += otherType; type += otherType;
otherType = std::max(-1, std::min(type, 1)); otherType = std::max(-1, std::min(type, 1));
CCharAnimTime ret;
if (otherType == -1) if (otherType == -1)
ret.x4_type = EType::ZeroDecreasing; return {EType::ZeroDecreasing, 0.f};
else if (otherType == 0) else if (otherType == 0)
ret.x4_type = EType::ZeroSteady; return {EType::ZeroSteady, 0.f};
else else
ret.x4_type = EType::ZeroIncreasing; return {EType::ZeroIncreasing, 0.f};
return ret;
} }
CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other) { CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other) {
*this = *this - other; return *this = *this - other;
return *this;
} }
CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const { CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const {
if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) { if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
if (other.x0_time == x0_time) if (other.x0_time == x0_time)
return CCharAnimTime(); return {};
return *this; return *this;
} else if (x4_type == EType::Infinity) } else if (x4_type == EType::Infinity)
return *this; return *this;
else if (other.x4_type == EType::Infinity) { else if (other.x4_type == EType::Infinity) {
CCharAnimTime ret(-other.x0_time); return {EType::Infinity, -other.x0_time};
ret.x4_type = EType::Infinity;
return ret;
} }
if (!EqualsZero() || !other.EqualsZero()) if (!EqualsZero() || !other.EqualsZero())
return CCharAnimTime(x0_time - other.x0_time); return {x0_time - other.x0_time};
int type = -1; int type = -1;
if (x4_type != EType::ZeroDecreasing) { if (x4_type != EType::ZeroDecreasing) {
@ -212,22 +195,19 @@ CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const {
otherType = 0; otherType = 0;
} }
CCharAnimTime ret;
type -= otherType; type -= otherType;
if (type == -1) if (type == -1)
ret.x4_type = EType::ZeroDecreasing; return {EType::ZeroDecreasing, 0.f};
else if (type == 0) else if (type == 0)
ret.x4_type = EType::ZeroSteady; return {EType::ZeroSteady, 0.f};
else else
ret.x4_type = EType::ZeroIncreasing; return {EType::ZeroIncreasing, 0.f};
return ret;
} }
CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const { CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const {
if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) { if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
if (other.x0_time != x0_time) if (other.x0_time != x0_time)
return CCharAnimTime(); return {};
return *this; return *this;
} else if (x4_type == EType::Infinity) } else if (x4_type == EType::Infinity)
return *this; return *this;
@ -235,7 +215,7 @@ CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const {
return other; return other;
if (!EqualsZero() || !other.EqualsZero()) if (!EqualsZero() || !other.EqualsZero())
return CCharAnimTime(x0_time * other.x0_time); return {x0_time * other.x0_time};
int type = -1; int type = -1;
if (x4_type != EType::ZeroDecreasing) { if (x4_type != EType::ZeroDecreasing) {
@ -256,31 +236,31 @@ CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const {
type += otherType; type += otherType;
otherType = std::max(-1, std::min(type, 1)); otherType = std::max(-1, std::min(type, 1));
CCharAnimTime ret;
if (otherType == -1) if (otherType == -1)
ret.x4_type = EType::ZeroDecreasing; return {EType::ZeroDecreasing, 0.f};
else if (otherType == 0) else if (otherType == 0)
ret.x4_type = EType::ZeroSteady; return {EType::ZeroSteady, 0.f};
else else
ret.x4_type = EType::ZeroIncreasing; return {EType::ZeroIncreasing, 0.f};
return ret;
} }
CCharAnimTime CCharAnimTime::operator*(const float& other) const { CCharAnimTime CCharAnimTime::operator*(const float& other) const {
CCharAnimTime ret;
if (other == 0.f) if (other == 0.f)
return ret; return {};
if (!EqualsZero()) if (!EqualsZero())
return CCharAnimTime(x0_time * other); return {x0_time * other};
if (other > 0.f) if (other > 0.f)
return *this; return *this;
else if (other == 0.f)
return ret;
ret.x4_type = x4_type; if (x4_type == EType::ZeroDecreasing) {
return ret; return {EType::ZeroIncreasing, 0.f};
} else if (x4_type == EType::ZeroSteady) {
return {EType::ZeroSteady, 0.f};
} else {
return {EType::ZeroDecreasing, 0.f};
}
} }
float CCharAnimTime::operator/(const CCharAnimTime& other) const { float CCharAnimTime::operator/(const CCharAnimTime& other) const {

View File

@ -54,7 +54,7 @@ enum class EWeaponCollisionResponseTypes {
Unknown35, Unknown35,
Unknown36, Unknown36,
Unknown37, Unknown37,
Unknown38, ChozoGhost,
Unknown39, Unknown39,
Unknown40, Unknown40,
Unknown41, Unknown41,

View File

@ -1,105 +1,771 @@
#include "Runtime/MP1/World/CChozoGhost.hpp" #include "Runtime/MP1/World/CChozoGhost.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/CStateManager.hpp" #include "Runtime/CStateManager.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CRandom16.hpp" #include "Runtime/CRandom16.hpp"
#include "Runtime/Character/CPASAnimParmData.hpp"
#include "Runtime/Weapon/CGameProjectile.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CScriptCoverPoint.hpp"
#include "Runtime/World/CScriptWaypoint.hpp"
#include "Runtime/World/CTeamAiMgr.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path #include "TCastTo.hpp" // Generated file, do not modify include path
namespace urde::MP1 { namespace urde::MP1 {
CChozoGhost::CBehaveChance::CBehaveChance(CInputStream& in) CChozoGhost::CBehaveChance::CBehaveChance(CInputStream& in)
: x0_propertyCount(in.readUint32Big()) : x0_propertyCount(in.readUint32Big())
, x4_(in.readFloatBig()) , x4_lurk(in.readFloatBig())
, x8_(in.readFloatBig()) , x8_taunt(in.readFloatBig())
, xc_(in.readFloatBig()) , xc_attack(in.readFloatBig())
, x10_(in.readFloatBig()) , x10_move(in.readFloatBig())
, x14_(in.readFloatBig()) , x14_lurkTime(in.readFloatBig())
, x18_(x0_propertyCount <= 5 ? 0.5f : in.readFloatBig() * .01f) , x18_chargeAttack(x0_propertyCount < 6 ? 0.5f : in.readFloatBig() * .01f)
, x1c_(x0_propertyCount <= 6 ? 2 : in.readUint32Big()) { , x1c_numBolts(x0_propertyCount < 7 ? 2 : in.readUint32Big()) {
float f2 = 1.f / (x10_ + xc_ + x4_ + x8_); float f2 = 1.f / (x10_move + xc_attack + x4_lurk + x8_taunt);
x4_ *= f2; x4_lurk *= f2;
x8_ *= f2; x8_taunt *= f2;
xc_ *= f2; xc_attack *= f2;
x10_ *= f2; x10_move *= f2;
} }
u32 CChozoGhost::CBehaveChance::GetBehave(EBehaveType type, CStateManager& mgr) const { EBehaveType CChozoGhost::CBehaveChance::GetBehave(EBehaveType type, CStateManager& mgr) const {
float dVar5 = x4_; float lurkChance = x4_lurk;
float dVar4 = x8_; float tauntChance = x8_taunt;
float dVar3 = xc_; float attackChance = xc_attack;
if (type == EBehaveType::Zero) { if (type == EBehaveType::Lurk) {
float dVar2 = dVar5 / 3.f; float delta = lurkChance / 3.f;
dVar5 = 0.f; lurkChance = 0.f;
dVar4 += dVar2; tauntChance += delta;
dVar3 += dVar2; attackChance += delta;
} else if (type == EBehaveType::One) { } else if (type == EBehaveType::Taunt) {
float dVar2 = dVar4 / 3.f; float delta = tauntChance / 3.f;
dVar4 = 0.f; tauntChance = 0.f;
dVar5 += dVar2; lurkChance += delta;
dVar3 += dVar2; attackChance += delta;
} else if (type == EBehaveType::Two) { } else if (type == EBehaveType::Attack) {
float dVar2 = dVar3 / 3.f; float delta = attackChance / 3.f;
dVar3 = 0.f; attackChance = 0.f;
dVar5 += dVar2; lurkChance += delta;
dVar4 += dVar2; tauntChance += delta;
} else if (type == EBehaveType::Three) { } else if (type == EBehaveType::Move) {
float dVar2 = x10_ / 3.f; float delta = x10_move / 3.f;
dVar5 += dVar2; lurkChance += delta;
dVar4 += dVar2; tauntChance += delta;
dVar3 += dVar2; attackChance += delta;
} }
float rnd = mgr.GetActiveRandom()->Float(); float rnd = mgr.GetActiveRandom()->Float();
if (dVar5 > rnd) if (lurkChance > rnd)
return 0; return EBehaveType::Lurk;
else if (dVar4 > (rnd - dVar5)) else if (tauntChance > rnd - lurkChance)
return 1; return EBehaveType::Taunt;
else if (dVar3 > (rnd - dVar5) - dVar4) else if (attackChance > rnd - lurkChance - tauntChance)
return 2; return EBehaveType::Attack;
return 3; return EBehaveType::Move;
} }
CChozoGhost::CChozoGhost(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CChozoGhost::CChozoGhost(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float f1, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo,
float f2, float f3, float f4, CAssetId wpsc1, const CDamageInfo& dInfo1, CAssetId wpsc2, float hearingRadius, float fadeOutDelay, float attackDelay, float freezeTime, CAssetId wpsc1,
const CDamageInfo& dInfo2, const CBehaveChance& chance1, const CBehaveChance& chance2, const CDamageInfo& dInfo1, CAssetId wpsc2, const CDamageInfo& dInfo2,
const CBehaveChance& chance3, u16 sId1, float f5, u16 sId2, u16 sId3, u32 w1, float f6, u32 w2, const CBehaveChance& chance1, const CBehaveChance& chance2, const CBehaveChance& chance3,
float f7, CAssetId partId, s16 sId4, float f8, float f9, u32 w3, u32 w4) u16 soundImpact, float f5, u16 sId2, u16 sId3, u32 w1, float f6, u32 w2, float hurlRecoverTime,
CAssetId projectileVisorEffect, s16 soundProjectileVisor, float f8, float f9, u32 nearChance,
u32 midChance)
: CPatterned(ECharacter::ChozoGhost, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::ChozoGhost, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::Zero, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) EMovementType::Flyer, EColliderType::Zero, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium)
, x568_(f1) , x568_hearingRadius(hearingRadius)
, x56c_(f2) , x56c_fadeOutDelay(fadeOutDelay)
, x570_(f3) , x570_attackDelay(attackDelay)
, x574_(f4) , x574_freezeTime(freezeTime)
, x578_(wpsc1, dInfo1) , x578_(wpsc1, dInfo1)
, x5a0_(wpsc2, dInfo2) , x5a0_(wpsc2, dInfo2)
, x5c8_(chance1) , x5c8_(chance1)
, x5e8_(chance2) , x5e8_(chance2)
, x608_(chance3) , x608_(chance3)
, x628_(sId1) , x628_soundImpact(soundImpact)
, x62c_(f5) , x62c_(f5)
, x630_(sId2) , x630_sfxFadeIn(sId2)
, x632_(sId3) , x632_sfxFadeOut(sId3)
, x634_(f6) , x634_(f6)
, x638_(f7) , x638_hurlRecoverTime(hurlRecoverTime)
, x63c_(w2) , x63c_(w2)
, x650_(sId4) , x650_sound_ProjectileVisor(soundProjectileVisor)
, x654_(f8) , x654_(f8)
, x658_(f9) , x658_(f9)
, x65c_(w3) , x65c_nearChance(nearChance)
, x660_(w4) , x660_midChance(midChance)
, x664_24_(w1) , x664_24_behaviorEnabled(w1)
, x664_25_(w1) , x664_25_flinch(!w1)
, x664_26_(false) , x664_26_alert(false)
, x664_27_(false) , x664_27_onGround(false)
, x664_28_(false) , x664_28_(false)
, x664_29_(false) , x664_29_fadedIn(false)
, x664_30_(false) , x664_30_fadedOut(false)
, x664_31_(false) , x664_31_(false)
, x665_24_(true) , x665_24_(true)
, x665_25_(false) , x665_25_(false)
, x665_26_(false) , x665_26_shouldSwoosh(false)
, x665_27_(false) , x665_27_playerInLeashRange(false)
, x665_28_(false) , x665_28_inRange(false)
, x665_29_(false) , x665_29_aggressive(false)
, x680_behaveType(x664_24_behaviorEnabled ? EBehaveType::Attack : EBehaveType::None)
, x68c_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), , x68c_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f),
EBoneTrackingFlags::None) {} EBoneTrackingFlags::None) {
x578_.Token().Lock();
x5a0_.Token().Lock();
x668_ = GetModelData()->GetScale().z() *
GetAnimationDistance(CPASAnimParmData(13, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(0)));
x66c_ = GetModelData()->GetScale().z() *
GetAnimationDistance(CPASAnimParmData(15, CPASAnimParm::FromEnum(1), CPASAnimParm::FromReal32(90.f)));
x670_ = GetModelData()->GetScale().z() *
GetAnimationDistance(CPASAnimParmData(7, CPASAnimParm::FromEnum(2), CPASAnimParm::FromEnum(1)));
if (projectileVisorEffect.IsValid())
x640_projectileVisor = g_SimplePool->GetObj({SBIG('PART'), projectileVisorEffect});
x460_knockBackController.SetEnableBurn(false);
x460_knockBackController.SetEnableLaggedBurnDeath(false);
x460_knockBackController.SetEnableShock(false);
x460_knockBackController.SetEnableFreeze(false);
CreateShadow(false);
MakeThermalColdAndHot();
}
void CChozoGhost::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
switch (msg) {
case EScriptObjectMessage::Activate:
AddToTeam(mgr);
break;
case EScriptObjectMessage::Deactivate:
case EScriptObjectMessage::Deleted:
RemoveFromTeam(mgr);
break;
case EScriptObjectMessage::Action:
if (x664_25_flinch)
x665_29_aggressive = true;
break;
case EScriptObjectMessage::Alert:
if (x664_26_alert)
break;
x664_26_alert = true;
x400_24_hitByPlayerProjectile = true;
break;
case EScriptObjectMessage::Falling:
case EScriptObjectMessage::Jumped: {
if (!x328_25_verticalMovement)
x150_momentum = {0.f, 0.f, -(GetGravityConstant() * GetMass())};
break;
}
case EScriptObjectMessage::InitializedInArea:
if (GetActive())
AddToTeam(mgr);
break;
default:
break;
}
}
void CChozoGhost::Think(float dt, CStateManager& mgr) {
if (!GetActive())
return;
CPatterned::Think(dt, mgr);
UpdateThermalFrozenState(false);
x68c_boneTracking.Update(dt);
x6c8_spaceWarpTime = std::max(0.f, x6c8_spaceWarpTime - dt);
xe7_31_targetable = IsVisibleEnough(mgr);
}
void CChozoGhost::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
x402_29_drawParticles = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay;
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) {
SetCalculateLighting(false);
x90_actorLights->BuildConstantAmbientLighting(zeus::skWhite);
} else {
SetCalculateLighting(true);
}
u8 alpha = GetModelAlphau8(mgr);
u8 r, g, b, a;
x42c_color.toRGBA8(r, g, b, a);
if (alpha < 255 || r == 0) {
zeus::CColor col;
if (r == 0) {
col = zeus::skWhite;
} else {
float v = std::max<s8>(0, r - 255) * (1.f / 255.f);
col.r() = 1.f;
col.g() = v;
col.b() = v;
}
col.a() = alpha * (1.f / 255.f);
xb4_drawFlags = CModelFlags(5, 0, 3, col);
} else {
xb4_drawFlags = CModelFlags(0, 0, 3, zeus::skWhite);
}
CPatterned::PreRender(mgr, frustum);
x68c_boneTracking.PreRender(mgr, *GetModelData()->GetAnimationData(), GetTransform(), GetModelData()->GetScale(),
*GetBodyController());
}
void CChozoGhost::Render(const CStateManager& mgr) const {
if (x6c8_spaceWarpTime > 0.f)
mgr.DrawSpaceWarp(x6cc_spaceWarpPosition, std::sin((M_PIF * x6c8_spaceWarpTime) / x56c_fadeOutDelay));
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) {
CElementGen::SetSubtractBlend(true);
CElementGen::g_ParticleSystemInitialized = true;
CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 75.f, zeus::skBlack);
mgr.SetupFogForArea3XRange(GetAreaIdAlways());
}
CPatterned::Render(mgr);
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) {
CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 75.f, zeus::skBlack);
GetModelData()->GetAnimationData()->GetParticleDB().RenderSystemsToBeDrawnLast();
mgr.SetupFogForArea(GetAreaIdAlways());
CElementGen::SetSubtractBlend(false);
CElementGen::g_ParticleSystemInitialized = false;
}
}
void CChozoGhost::Touch(CActor& act, CStateManager& mgr) {
if (IsVisibleEnough(mgr)) {
if (TCastToPtr<CPlayer> pl = act) {
if (x420_curDamageRemTime <= 0.f) {
mgr.ApplyDamage(GetUniqueId(), pl->GetUniqueId(), GetUniqueId(), GetContactDamage(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
x420_curDamageRemTime = x424_damageWaitTime;
}
}
}
CPatterned::Touch(act, mgr);
}
EWeaponCollisionResponseTypes CChozoGhost::GetCollisionResponseType(const zeus::CVector3f& pos,
const zeus::CVector3f& dir, const CWeaponMode& mode,
EProjectileAttrib attrib) const {
return EWeaponCollisionResponseTypes::ChozoGhost;
}
void CChozoGhost::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
if (type == EUserEventType::FadeIn) {
if (x664_30_fadedOut) {
x3e8_alphaDelta = 2.f;
CSfxManager::AddEmitter(x630_sfxFadeIn, GetTranslation(), {}, false, false, 127, -1);
}
AddMaterial(EMaterialTypes::Target, mgr);
x664_30_fadedOut = false;
x664_29_fadedIn = true;
return;
} else if (type == EUserEventType::Projectile) {
const zeus::CTransform& xf =
zeus::lookAt(GetLctrTransform(node.GetLocatorName()).origin, mgr.GetPlayer().GetAimPosition(mgr, 0.f));
if (x67c_attackType == 2) {
CGameProjectile* proj =
LaunchProjectile(xf, mgr, 2, EProjectileAttrib::BigStrike | EProjectileAttrib::StaticInterference, true,
x640_projectileVisor, x650_sound_ProjectileVisor, false, zeus::skOne3f);
if (proj) {
proj->AddAttrib(EProjectileAttrib::BigStrike);
proj->SetDamageDuration(x62c_);
proj->AddAttrib(EProjectileAttrib::StaticInterference);
proj->SetInterferenceDuration(x62c_);
proj->SetMinHomingDistance(x634_);
}
} else {
CGameProjectile* proj =
LaunchProjectile(xf, mgr, 5, EProjectileAttrib::DamageFalloff | EProjectileAttrib::StaticInterference, true,
{x640_projectileVisor}, x650_sound_ProjectileVisor, false, zeus::skOne3f);
if (proj) {
proj->AddAttrib(EProjectileAttrib::BigStrike);
proj->SetDamageDuration(x62c_);
proj->AddAttrib(EProjectileAttrib::StaticInterference);
proj->SetInterferenceDuration(x62c_);
proj->SetMinHomingDistance(x634_);
}
}
return;
} else if (type == EUserEventType::FadeOut) {
if (x664_29_fadedIn) {
x3e8_alphaDelta = -2.f;
CSfxManager::AddEmitter(x632_sfxFadeOut, GetTranslation(), {}, false, false, 127, -1);
}
RemoveMaterial(EMaterialTypes::Target, mgr);
x664_29_fadedIn = false;
x664_30_fadedOut = true;
x665_26_shouldSwoosh = true;
return;
}
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
if (type == EUserEventType::Delete)
x3e8_alphaDelta = -1.f;
}
void CChozoGhost::KnockBack(const zeus::CVector3f& dir, CStateManager& mgr, const CDamageInfo& info,
EKnockBackType type, bool inDeferred, float magnitude) {
if (!IsAlive())
x460_knockBackController.SetAvailableState(EKnockBackAnimationState::Hurled, false);
else if (!x460_knockBackController.TestAvailableState(EKnockBackAnimationState::KnockBack) &&
info.GetWeaponMode().IsCharged())
x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::Hurled, EKnockBackAnimationState::Fall);
CPatterned::KnockBack(dir, mgr, info, type, inDeferred, magnitude);
if (!IsAlive()) {
Stop();
x150_momentum.zeroOut();
} else if (x460_knockBackController.GetActiveParms().x0_animState == EKnockBackAnimationState::Hurled) {
x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Hurled"sv);
}
}
bool CChozoGhost::CanBeShot(const CStateManager& mgr, int) { return IsVisibleEnough(mgr); }
void CChozoGhost::Dead(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
ReleaseCoverPoint(mgr, x674_coverPoint);
x3e8_alphaDelta = 4.f;
x664_30_fadedOut = false;
x664_29_fadedIn = false;
x68c_boneTracking.SetActive(false);
Stop();
}
}
void CChozoGhost::SelectTarget(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate)
FindBestAnchor(mgr);
}
void CChozoGhost::Run(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Lurk);
x400_24_hitByPlayerProjectile = false;
x460_knockBackController.SetAvailableState(EKnockBackAnimationState::KnockBack, false);
x665_28_inRange = false;
} else if (msg == EStateMsg::Update) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(x688_.Seek(*this, x2e0_destPos), {}, 1.f));
if (x665_26_shouldSwoosh) {
x678_floorLevel = x2e0_destPos.z();
FloatToLevel(x678_floorLevel, dt);
GetModelData()->GetAnimationData()->SetParticleEffectState("SpeedSwoosh", true, mgr);
x665_24_ = false;
if (!x665_28_inRange) {
const float range = 2.5f * (dt * x138_velocity.magnitude()) + x66c_;
x665_28_inRange = (GetTranslation() - x2e0_destPos).magSquared() < range * range;
}
}
} else if (msg == EStateMsg::Deactivate) {
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Crouch);
SetDestPos(mgr.GetPlayer().GetTranslation());
GetModelData()->GetAnimationData()->SetParticleEffectState("SpeedSwoosh", false, mgr);
x460_knockBackController.SetAvailableState(EKnockBackAnimationState::KnockBack, true);
x665_28_inRange = false;
}
}
void CChozoGhost::Generate(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x330_stateMachineState.SetDelay(x56c_fadeOutDelay);
x32c_animState = EAnimState::Ready;
x664_27_onGround = false;
const CRayCastResult& res = mgr.RayStaticIntersection(GetTranslation(), zeus::skDown, 100.f,
CMaterialFilter::MakeInclude({EMaterialTypes::Floor}));
if (res.IsInvalid()) {
x678_floorLevel = mgr.GetPlayer().GetTranslation().z();
} else {
x678_floorLevel = res.GetPoint().z();
}
x3e8_alphaDelta = 1.f;
x664_29_fadedIn = true;
if (x56c_fadeOutDelay > 0.f) {
x6c8_spaceWarpTime = x56c_fadeOutDelay;
FindSpaceWarpPosition(mgr, zeus::skDown);
}
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Jump, &CPatterned::TryJump, 0);
if (x32c_animState == EAnimState::Over) {
x68c_boneTracking.SetActive(true);
x68c_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
FloatToLevel(x678_floorLevel, dt);
} else if (x32c_animState == EAnimState::Repeat) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
if (!x664_27_onGround) {
const zeus::CVector3f& pos = GetTranslation();
SetTranslation({pos.x(), pos.y(), x678_floorLevel + x668_});
x664_27_onGround = true;
}
}
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
x665_24_ = false;
x664_27_onGround = false;
}
}
void CChozoGhost::Deactivate(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x68c_boneTracking.SetActive(false);
ReleaseCoverPoint(mgr, x674_coverPoint);
x32c_animState = EAnimState::Ready;
x665_24_ = true;
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 1);
if (x32c_animState == EAnimState::Repeat)
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
}
}
void CChozoGhost::Attack(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Melee, mgr, x6c4_teamMgr, GetUniqueId());
x32c_animState = EAnimState::Ready;
if (x6d8_ == 1)
x67c_attackType = 3;
else if (x6d8_ == 2)
x67c_attackType = 4;
else if (x6d8_ == 3)
x67c_attackType = 5;
const CRayCastResult& res = mgr.RayStaticIntersection(GetTranslation() + (zeus::skUp * 0.5f), zeus::skUp, x670_,
CMaterialFilter::MakeInclude({EMaterialTypes::Solid}));
if (x665_26_shouldSwoosh && res.IsValid()) {
x67c_attackType = 2;
x460_knockBackController.SetAvailableState(EKnockBackAnimationState::KnockBack, false);
}
x150_momentum.zeroOut();
xfc_constantForce.zeroOut();
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, x67c_attackType);
GetBodyController()->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
if (x67c_attackType != 2)
FloatToLevel(x678_floorLevel, dt);
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
x665_26_shouldSwoosh = false;
x460_knockBackController.SetAvailableState(EKnockBackAnimationState::KnockBack, true);
CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x6c4_teamMgr, GetUniqueId(), true);
}
}
void CChozoGhost::Shuffle(CStateManager& mgr, EStateMsg msg, float) {
if (msg != EStateMsg::Activate)
return;
const CBehaveChance& chance1 = ChooseBehaveChanceRange(mgr);
CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x6c4_teamMgr, GetUniqueId());
if (role && role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Ranged &&
!CTeamAiMgr::CanAcceptAttacker(CTeamAiMgr::EAttackType::Ranged, mgr, x6c4_teamMgr, GetUniqueId())) {
x680_behaveType = EBehaveType::Attack;
}
const CBehaveChance& chance2 = ChooseBehaveChanceRange(mgr);
x680_behaveType = chance2.GetBehave(x680_behaveType, mgr);
if (x680_behaveType == EBehaveType::Lurk)
x684_lurkDelay = chance1.GetLurkTime();
else if (x680_behaveType == EBehaveType::Attack) {
x665_25_ = mgr.GetActiveRandom()->Float() < chance1.GetChargeAttack();
const int rnd = mgr.GetActiveRandom()->Next();
x6d8_ = (rnd - (rnd / chance1.GetNumBolts()) * chance1.GetNumBolts()) + 1;
}
x664_31_ = false;
x665_27_playerInLeashRange = false;
}
void CChozoGhost::InActive(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
if (!x450_bodyController->GetActive())
x450_bodyController->Activate(mgr);
if (x63c_ == 3) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
x42c_color.a() = 1.f;
} else {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
x42c_color.a() = 0.f;
}
RemoveMaterial(EMaterialTypes::Solid, mgr);
x150_momentum.zeroOut();
x665_24_ = true;
}
}
void CChozoGhost::Taunt(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::Taunt, &CPatterned::TryTaunt, 0);
FloatToLevel(x678_floorLevel, dt);
} else {
x32c_animState = EAnimState::NotReady;
x665_26_shouldSwoosh = false;
}
}
void CChozoGhost::Hurled(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x328_25_verticalMovement = false;
x664_27_onGround = false;
x665_24_ = true;
} else if (msg == EStateMsg::Update) {
x3e8_alphaDelta = 2.f;
if (x664_27_onGround)
return;
if (x138_velocity.z() < 0.f) {
const CRayCastResult& res = mgr.RayStaticIntersection(GetTranslation() + zeus::skUp, zeus::skDown, 2.f,
CMaterialFilter::MakeInclude({EMaterialTypes::Floor}));
if (res.IsValid()) {
x664_27_onGround = true;
x150_momentum.zeroOut();
SetVelocityWR({x138_velocity.x(), x138_velocity.y(), 0.f});
x678_floorLevel = res.GetPoint().z();
x330_stateMachineState.SetCodeTrigger();
}
}
if (!x664_27_onGround && x638_hurlRecoverTime < x330_stateMachineState.GetTime()) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Lurk);
x330_stateMachineState.SetCodeTrigger();
}
} else if (msg == EStateMsg::Deactivate) {
x328_25_verticalMovement = true;
x150_momentum.zeroOut();
}
}
void CChozoGhost::WallDetach(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x330_stateMachineState.SetDelay(x56c_fadeOutDelay);
x3e8_alphaDelta = 0.f;
x664_29_fadedIn = false;
if (x56c_fadeOutDelay > 0.f) {
x6c8_spaceWarpTime = x56c_fadeOutDelay;
FindSpaceWarpPosition(mgr, GetTransform().basis[1]);
}
TUniqueId wpId = GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow);
TCastToConstPtr<CScriptWaypoint> wp;
if (wpId != kInvalidUniqueId) {
wp = TCastToConstPtr<CScriptWaypoint>(mgr.GetObjectById(wpId));
}
if (wp)
SetDestPos(wp->GetTranslation());
else
SetDestPos(GetTranslation() + (2.f * x66c_) * GetTranslation());
SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::Follow);
} else if (msg == EStateMsg::Deactivate) {
x68c_boneTracking.SetActive(true);
x68c_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
x665_24_ = false;
x680_behaveType = EBehaveType::Move;
}
}
void CChozoGhost::Growth(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x330_stateMachineState.SetDelay(x56c_fadeOutDelay);
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Crouch);
x3e8_alphaDelta = 1.f;
x664_29_fadedIn = true;
if (x56c_fadeOutDelay > 0.f) {
x6c8_spaceWarpTime = x56c_fadeOutDelay;
FindSpaceWarpPosition(mgr, zeus::skUp);
}
} else if (msg == EStateMsg::Deactivate) {
x665_24_ = false;
x68c_boneTracking.SetActive(false);
x68c_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
}
}
void CChozoGhost::Land(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Update) {
FloatToLevel(x678_floorLevel, dt);
if (std::fabs(x678_floorLevel - GetTranslation().z()) < 0.05f) {
x330_stateMachineState.SetCodeTrigger();
}
}
}
void CChozoGhost::Lurk(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x330_stateMachineState.SetDelay(x684_lurkDelay);
} else if (msg == EStateMsg::Update) {
FloatToLevel(x678_floorLevel, dt);
}
}
bool CChozoGhost::Leash(CStateManager& mgr, float arg) {
return x665_27_playerInLeashRange || CPatterned::Leash(mgr, arg);
}
bool CChozoGhost::InRange(CStateManager& mgr, float arg) { return x665_28_inRange; }
bool CChozoGhost::ShouldAttack(CStateManager& mgr, float arg) { return x680_behaveType == EBehaveType::Attack; }
bool CChozoGhost::AggressionCheck(CStateManager& mgr, float arg) { return x665_29_aggressive; }
bool CChozoGhost::ShouldTaunt(CStateManager& mgr, float arg) { return x680_behaveType == EBehaveType::Taunt; }
bool CChozoGhost::ShouldFlinch(CStateManager& mgr, float arg) { return x664_25_flinch; }
bool CChozoGhost::ShouldMove(CStateManager& mgr, float arg) { return x680_behaveType == EBehaveType::Move; }
bool CChozoGhost::AIStage(CStateManager& mgr, float arg) { return arg == x63c_; }
u8 CChozoGhost::GetModelAlphau8(const CStateManager& mgr) const {
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay && IsAlive())
return 255;
return u8(x42c_color.a() * 255);
}
bool CChozoGhost::IsOnGround() const { return x664_27_onGround; }
CProjectileInfo* CChozoGhost::GetProjectileInfo() { return x67c_attackType == 2 ? &x578_ : &x5a0_; }
void CChozoGhost::AddToTeam(CStateManager& mgr) {
if (x6c4_teamMgr == kInvalidUniqueId)
x6c4_teamMgr = CTeamAiMgr::GetTeamAiMgr(*this, mgr);
if (x6c4_teamMgr == kInvalidUniqueId)
return;
if (TCastToPtr<CTeamAiMgr> teamMgr = mgr.ObjectById(x6c4_teamMgr))
teamMgr->AssignTeamAiRole(*this, CTeamAiRole::ETeamAiRole::Ranged, CTeamAiRole::ETeamAiRole::Unknown,
CTeamAiRole::ETeamAiRole::Invalid);
}
void CChozoGhost::RemoveFromTeam(CStateManager& mgr) {
if (x6c4_teamMgr == kInvalidUniqueId)
return;
if (TCastToPtr<CTeamAiMgr> teamMgr = mgr.ObjectById(x6c4_teamMgr)) {
if (teamMgr->IsPartOfTeam(GetUniqueId())) {
teamMgr->RemoveTeamAiRole(GetUniqueId());
x6c4_teamMgr = kInvalidUniqueId;
}
}
}
void CChozoGhost::FloatToLevel(float level, float dt) {
const zeus::CVector3f& pos = GetTranslation();
SetTranslation({pos.x(), pos.y(), 4.f * (level - pos.z()) * dt + pos.z()});
}
const CChozoGhost::CBehaveChance& CChozoGhost::ChooseBehaveChanceRange(CStateManager& mgr) {
const float dist = (GetTranslation() - mgr.GetPlayer().GetTranslation()).magnitude();
if (x654_ <= dist && x658_ > dist)
return x5e8_;
else if (x658_ <= dist)
return x608_;
else
return x5c8_;
}
void CChozoGhost::FindSpaceWarpPosition(CStateManager& mgr, const zeus::CVector3f& dir) {
const zeus::CVector3f& center = GetBoundingBox().center();
const CRayCastResult& res =
mgr.RayStaticIntersection(center + (dir * 8.f), -dir, 8.f, CMaterialFilter::MakeInclude({EMaterialTypes::Solid}));
if (res.IsInvalid()) {
x6cc_spaceWarpPosition = center + dir;
} else {
x6cc_spaceWarpPosition = res.GetPoint();
}
}
void CChozoGhost::FindBestAnchor(CStateManager& mgr) {
x665_27_playerInLeashRange = false;
u32 chance = mgr.GetActiveRandom()->Next() % 100;
chance = chance < x65c_nearChance ? 0 : (chance < (x65c_nearChance + x660_midChance)) + 2;
float dVar15 = 10.f * x658_;
float dVar14 = dVar15;
float dVar13 = dVar15;
if (chance == 0) {
dVar13 = dVar15 * 10.f;
dVar14 = dVar15 * 5.f;
} else if (chance == 1) {
dVar13 = dVar15 * 5.f;
dVar15 *= 10.f;
} else if (chance == 2) {
dVar14 = dVar15 * 5.f;
dVar15 *= 10.f;
}
float prevDist = FLT_MAX;
CScriptCoverPoint* target = nullptr;
for (CEntity* ent : mgr.GetAiWaypointObjectList()) {
if (TCastToPtr<CScriptCoverPoint> cover = ent) {
if (cover->GetActive() && !cover->GetInUse(kInvalidUniqueId) && cover->GetAreaIdAlways() == GetAreaId()) {
float fVar17 = (cover->GetTranslation() - GetTranslation()).magnitude();
if (2.f * x66c_ <= fVar17) {
float dist = std::max(0.f, x654_ - fVar17);
zeus::CVector3f diff = cover->GetTranslation() - mgr.GetPlayer().GetTranslation();
fVar17 = diff.magnitude();
if (x2fc_minAttackRange <= fVar17) {
if (std::fabs(diff.z()) / fVar17 < 0.2f) {
dist = (20.f * x658_) * ((std::fabs(diff.z()) / fVar17) - 0.2f) + dist;
}
if (x654_ <= fVar17) {
if (x658_ <= fVar17) {
dist = (dist + dVar13);
} else {
dist = (dist + dVar14);
if (dist < prevDist) {
fVar17 = 1.f / fVar17;
diff = diff * fVar17;
dist += (10.f * x658_) * (1.f - mgr.GetPlayer().GetTransform().basis[1].dot(diff));
}
}
} else {
dist += dVar15;
if (dist < prevDist) {
fVar17 = 1.f / fVar17;
diff = diff * fVar17;
dist += (10.f * x658_) * (1.f - mgr.GetPlayer().GetTransform().basis[1].dot(diff));
}
}
if (dist < prevDist) {
dist += x658_ * mgr.GetActiveRandom()->Float();
if (dist < prevDist) {
x665_27_playerInLeashRange = false;
target = cover;
prevDist = dist;
}
}
}
}
}
}
}
if (target) {
x2dc_destObj = target->GetUniqueId();
SetDestPos(target->GetTranslation());
ReleaseCoverPoint(mgr, x674_coverPoint);
SetCoverPoint(target, x674_coverPoint);
} else if (mgr.GetPlayer().GetAreaIdAlways() == GetAreaIdAlways()) {
x2dc_destObj = mgr.GetPlayer().GetUniqueId();
zeus::CVector3f destPos =
mgr.GetPlayer().GetTranslation() - x654_ * (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized();
const CRayCastResult& res =
mgr.RayStaticIntersection(destPos, zeus::skDown, 8.f, CMaterialFilter::MakeInclude(EMaterialTypes::Floor));
if (res.IsValid())
destPos = res.GetPoint();
SetDestPos(destPos);
} else {
x2dc_destObj = kInvalidUniqueId;
x2e0_destPos = GetTranslation();
}
}
} // namespace urde::MP1 } // namespace urde::MP1

View File

@ -10,88 +10,93 @@
#include <zeus/CVector3f.hpp> #include <zeus/CVector3f.hpp>
namespace urde::MP1 { namespace urde::MP1 {
enum class EBehaveType { enum class EBehaveType { Lurk, Taunt, Attack, Move, None };
Zero,
One,
Two,
Three
};
class CChozoGhost : public CPatterned { class CChozoGhost : public CPatterned {
public: public:
class CBehaveChance { class CBehaveChance {
u32 x0_propertyCount; u32 x0_propertyCount;
float x4_; float x4_lurk;
float x8_; float x8_taunt;
float xc_; float xc_attack;
float x10_; float x10_move;
float x14_; float x14_lurkTime;
float x18_; float x18_chargeAttack;
u32 x1c_; u32 x1c_numBolts;
public: public:
CBehaveChance(CInputStream&); CBehaveChance(CInputStream&);
u32 GetBehave(EBehaveType type, CStateManager& mgr) const; EBehaveType GetBehave(EBehaveType type, CStateManager& mgr) const;
float GetLurk() const { return x4_lurk; }
float GetTaunt() const { return x8_taunt; }
float GetAttack() const { return xc_attack; }
float GetMove() const { return x10_move; }
float GetLurkTime() const { return x14_lurkTime; }
float GetChargeAttack() const { return x18_chargeAttack; }
u32 GetNumBolts() const { return x1c_numBolts; }
}; };
private: private:
float x568_; float x568_hearingRadius;
float x56c_; float x56c_fadeOutDelay;
float x570_; float x570_attackDelay;
float x574_; float x574_freezeTime;
CProjectileInfo x578_; CProjectileInfo x578_;
CProjectileInfo x5a0_; CProjectileInfo x5a0_;
CBehaveChance x5c8_; CBehaveChance x5c8_;
CBehaveChance x5e8_; CBehaveChance x5e8_;
CBehaveChance x608_; CBehaveChance x608_;
s16 x628_; s16 x628_soundImpact;
float x62c_; float x62c_;
s16 x630_; s16 x630_sfxFadeIn;
s16 x632_; s16 x632_sfxFadeOut;
float x634_; float x634_;
float x638_; float x638_hurlRecoverTime;
u32 x63c_; u32 x63c_;
TLockedToken<CGenDescription> x640_; std::optional<TLockedToken<CGenDescription>> x640_projectileVisor;
s16 x650_; s16 x650_sound_ProjectileVisor;
float x654_; float x654_;
float x658_; float x658_;
u32 x65c_; u32 x65c_nearChance;
u32 x660_; u32 x660_midChance;
union { bool x664_24_behaviorEnabled : 1;
struct { bool x664_25_flinch : 1;
bool x664_24_ : 1; bool x664_26_alert : 1;
bool x664_25_ : 1; bool x664_27_onGround : 1;
bool x664_26_ : 1;
bool x664_27_ : 1;
bool x664_28_ : 1; bool x664_28_ : 1;
bool x664_29_ : 1; bool x664_29_fadedIn : 1;
bool x664_30_ : 1; bool x664_30_fadedOut : 1;
bool x664_31_ : 1; bool x664_31_ : 1;
bool x665_24_ : 1; bool x665_24_ : 1;
bool x665_25_ : 1; bool x665_25_ : 1;
bool x665_26_ : 1; bool x665_26_shouldSwoosh : 1;
bool x665_27_ : 1; bool x665_27_playerInLeashRange : 1;
bool x665_28_ : 1; bool x665_28_inRange : 1;
bool x665_29_ : 1; bool x665_29_aggressive : 1;
};
u32 _dummy = 0;
};
float x668_ = 0.f; float x668_ = 0.f;
float x66c_ = 0.f; float x66c_ = 0.f;
float x670_ = 0.f; float x670_ = 0.f;
TUniqueId x674_ = kInvalidUniqueId; TUniqueId x674_coverPoint = kInvalidUniqueId;
float x678_ = 0.f; float x678_floorLevel = 0.f;
u32 x67c_ = -1; u32 x67c_attackType = -1;
u32 x680_ = 0; EBehaveType x680_behaveType = EBehaveType::Lurk;
float x684_ = 1.f; float x684_lurkDelay = 1.f;
CSteeringBehaviors x688_; CSteeringBehaviors x688_;
CBoneTracking x68c_boneTracking; CBoneTracking x68c_boneTracking;
TUniqueId x6c4_ = kInvalidUniqueId; TUniqueId x6c4_teamMgr = kInvalidUniqueId;
float x6c8_ = 0.f; float x6c8_spaceWarpTime = 0.f;
zeus::CVector3f x6cc_; zeus::CVector3f x6cc_spaceWarpPosition;
u32 x6d8_ = 1; u32 x6d8_ = 1;
u32 x6dc_;
void AddToTeam(CStateManager& mgr);
void RemoveFromTeam(CStateManager& mgr);
void FloatToLevel(float f1, float dt);
const CBehaveChance& ChooseBehaveChanceRange(CStateManager& mgr);
bool IsVisibleEnough(const CStateManager& mgr) const { return GetModelAlphau8(mgr) > 31; }
void FindSpaceWarpPosition(CStateManager& mgr, const zeus::CVector3f& dir);
void FindBestAnchor(CStateManager& mgr);
public: public:
DEFINE_PATTERNED(ChozoGhost) DEFINE_PATTERNED(ChozoGhost)
@ -101,6 +106,47 @@ public:
const CBehaveChance&, u16, float, u16, u16, u32, float, u32, float, CAssetId, s16, float, float, u32, const CBehaveChance&, u16, float, u16, u16, u32, float, u32, float, CAssetId, s16, float, float, u32,
u32); u32);
float GetGravityConstant() const { return 60.f; } void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
void Think(float dt, CStateManager&) override;
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
void Render(const CStateManager& mgr) const override;
void Touch(CActor& act, CStateManager& mgr) override;
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
const CWeaponMode& mode,
EProjectileAttrib attrib) const override;
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
void KnockBack(const zeus::CVector3f& dir, CStateManager& mgr, const CDamageInfo& info, EKnockBackType type,
bool inDeferred, float magnitude) override;
bool CanBeShot(const CStateManager& mgr, int w1) override;
zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role,
const zeus::CVector3f& aimPos) const override {
return x34_transform.origin;
}
void Dead(CStateManager& mgr, EStateMsg msg, float arg) override;
void SelectTarget(CStateManager& mgr, EStateMsg msg, float arg) override;
void Run(CStateManager& mgr, EStateMsg msg, float dt) override;
void Generate(CStateManager& mgr, EStateMsg msg, float dt) override;
void Deactivate(CStateManager& mgr, EStateMsg msg, float arg) override;
void Attack(CStateManager& mgr, EStateMsg msg, float dt) override;
void Shuffle(CStateManager& mgr, EStateMsg msg, float arg) override;
void InActive(CStateManager& mgr, EStateMsg msg, float arg) override;
void Taunt(CStateManager& mgr, EStateMsg msg, float dt) override;
void Hurled(CStateManager& mgr, EStateMsg msg, float arg) override;
void WallDetach(CStateManager& mgr, EStateMsg msg, float arg) override;
void Growth(CStateManager& mgr, EStateMsg msg, float dt) override;
void Land(CStateManager& mgr, EStateMsg msg, float dt) override;
void Lurk(CStateManager& mgr, EStateMsg msg, float dt) override;
bool Leash(CStateManager& mgr, float arg) override;
bool InRange(CStateManager& mgr, float arg) override;
bool ShouldAttack(CStateManager& mgr, float arg) override;
bool AggressionCheck(CStateManager& mgr, float arg) override;
bool ShouldTaunt(CStateManager& mgr, float arg) override;
bool ShouldFlinch(CStateManager& mgr, float arg) override;
bool ShouldMove(CStateManager& mgr, float arg) override;
bool AIStage(CStateManager& mgr, float arg) override;
u8 GetModelAlphau8(const CStateManager&) const override;
bool IsOnGround() const override;
float GetGravityConstant() const override { return 60.f; }
CProjectileInfo* GetProjectileInfo() override;
}; };
} // namespace urde::MP1 } // namespace urde::MP1

View File

@ -92,5 +92,6 @@ public:
const CProjectileWeapon& GetProjectileWeapon() const { return x170_projectile; } const CProjectileWeapon& GetProjectileWeapon() const { return x170_projectile; }
TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; } TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; }
zeus::CVector3f GetPreviousPos() const { return x298_previousPos; } zeus::CVector3f GetPreviousPos() const { return x298_previousPos; }
void SetMinHomingDistance(float dist) { x2e0_minHomingDist = dist; }
}; };
} // namespace urde } // namespace urde

View File

@ -30,6 +30,7 @@ public:
void Accept(IVisitor& visitor) override; void Accept(IVisitor& visitor) override;
bool HasAttrib(EProjectileAttrib attrib) const { return (int(xe8_projectileAttribs) & int(attrib)) == int(attrib); } bool HasAttrib(EProjectileAttrib attrib) const { return (int(xe8_projectileAttribs) & int(attrib)) == int(attrib); }
EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; } EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; }
void AddAttrib(EProjectileAttrib attrib) { xe8_projectileAttribs |= attrib; }
const CMaterialFilter& GetFilter() const { return xf8_filter; } const CMaterialFilter& GetFilter() const { return xf8_filter; }
void SetFilter(const CMaterialFilter& filter) { xf8_filter = filter; } void SetFilter(const CMaterialFilter& filter) { xf8_filter = filter; }
TUniqueId GetOwnerId() const { return xec_ownerId; } TUniqueId GetOwnerId() const { return xec_ownerId; }
@ -39,7 +40,9 @@ public:
CDamageInfo& DamageInfo() { return x12c_curDamageInfo; } CDamageInfo& DamageInfo() { return x12c_curDamageInfo; }
void SetDamageInfo(const CDamageInfo& dInfo) { x12c_curDamageInfo = dInfo; } void SetDamageInfo(const CDamageInfo& dInfo) { x12c_curDamageInfo = dInfo; }
float GetDamageDuration() const { return x150_damageDuration; } float GetDamageDuration() const { return x150_damageDuration; }
void SetDamageDuration(float dur) { x150_damageDuration = dur; }
float GetInterferenceDuration() const { return x154_interferenceDuration; } float GetInterferenceDuration() const { return x154_interferenceDuration; }
void SetInterferenceDuration(float dur) { x154_interferenceDuration = dur; }
void Think(float, CStateManager&) override; void Think(float, CStateManager&) override;
void Render(const CStateManager&) const override; void Render(const CStateManager&) const override;

View File

@ -1081,7 +1081,7 @@ void CPatterned::SetupPlayerCollision(bool v) {
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
} }
void CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, CGameProjectile* CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed,
EProjectileAttrib attrib, bool playerHoming, EProjectileAttrib attrib, bool playerHoming,
const std::optional<TLockedToken<CGenDescription>>& visorParticle, const std::optional<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale) { u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale) {
@ -1094,8 +1094,10 @@ void CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager&
pInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(), GetUniqueId(), homingId, pInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(), GetUniqueId(), homingId,
attrib, false, scale, visorParticle, visorSfx, sendCollideMsg); attrib, false, scale, visorParticle, visorSfx, sendCollideMsg);
mgr.AddObject(newProjectile); mgr.AddObject(newProjectile);
return newProjectile;
} }
} }
return nullptr;
} }
void CPatterned::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { void CPatterned::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {

View File

@ -373,9 +373,10 @@ public:
CBodyController* GetBodyController() { return x450_bodyController.get(); } CBodyController* GetBodyController() { return x450_bodyController.get(); }
const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; } const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; }
void SetupPlayerCollision(bool); void SetupPlayerCollision(bool);
void LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib, CGameProjectile* LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed,
bool playerHoming, const std::optional<TLockedToken<CGenDescription>>& visorParticle, EProjectileAttrib attrib, bool playerHoming,
u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale); const std::optional<TLockedToken<CGenDescription>>& visorParticle, u16 visorSfx,
bool sendCollideMsg, const zeus::CVector3f& scale);
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; }

View File

@ -45,10 +45,7 @@ bool CScriptCoverPoint::GetInUse(TUniqueId uid) const {
if (xf8_25_inUse || x11c_timeLeft > 0.f) if (xf8_25_inUse || x11c_timeLeft > 0.f)
return true; return true;
if (xfa_occupant == kInvalidUniqueId || uid == kInvalidUniqueId || xfa_occupant == uid) return !(xfa_occupant == kInvalidUniqueId || uid == kInvalidUniqueId || xfa_occupant == uid);
return false;
return true;
} }
bool CScriptCoverPoint::Blown(const zeus::CVector3f& point) const { bool CScriptCoverPoint::Blown(const zeus::CVector3f& point) const {

View File

@ -111,7 +111,7 @@ void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, const CStateMachi
return; return;
if (!x0_machine) if (!x0_machine)
x0_machine = machine; Setup(machine);
s32 idx = machine->GetStateIndex(state); s32 idx = machine->GetStateIndex(state);
SetState(mgr, ai, idx); SetState(mgr, ai, idx);

View File

@ -27,7 +27,7 @@ public:
bool CallFunc(CStateManager& mgr, CAi& ai) const { bool CallFunc(CStateManager& mgr, CAi& ai) const {
if (x0_func) { if (x0_func) {
bool ret = (ai.*x0_func)(mgr, xc_arg); bool ret = (ai.*x0_func)(mgr, xc_arg);
return x18_lNot ? !ret : ret; return x18_lNot == !ret;
} }
return true; return true;
} }

View File

@ -1434,7 +1434,7 @@ CEntity* ScriptLoader::LoadMetroidBeta(CStateManager& mgr, CInputStream& in, int
} }
CEntity* ScriptLoader::LoadChozoGhost(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { CEntity* ScriptLoader::LoadChozoGhost(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
if (!EnsurePropertyCount(propCount, 32, "ChozoGhost")) if (!EnsurePropertyCount(propCount, 31, "ChozoGhost"))
return nullptr; return nullptr;
SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); SScaledActorHead actorHead = LoadScaledActorHead(in, mgr);