Finish CSpacePirate implementation

This commit is contained in:
Jack Andersen 2018-12-12 21:39:16 -10:00
parent 14747e39e1
commit ec1cb75b25
37 changed files with 2337 additions and 503 deletions

View File

@ -12,6 +12,25 @@
<option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" /> <option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" />
</Objective-C> </Objective-C>
<Objective-C-extensions> <Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions> <extensions>
<pair source="cpp" header="hpp" fileNamingConvention="NONE" /> <pair source="cpp" header="hpp" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" /> <pair source="c" header="h" fileNamingConvention="NONE" />

View File

@ -268,7 +268,7 @@ struct PatternedInfo : BigDNA {
Value<float> intoFreezeDur; Value<float> intoFreezeDur;
Value<float> outOfFreezeDur; Value<float> outOfFreezeDur;
Value<float> unknown10; Value<float> unknown10;
Value<atUint32> particle1Frames; Value<atUint32> pathfindingIndex;
Value<atVec3f> particle1Scale; Value<atVec3f> particle1Scale;
UniqueID32 particle1; UniqueID32 particle1;
UniqueID32 electric; UniqueID32 electric;

View File

@ -14,57 +14,76 @@ struct SpacePirate : IScriptObject {
Value<atVec3f> scale; Value<atVec3f> scale;
PatternedInfo patternedInfo; PatternedInfo patternedInfo;
ActorParameters actorParameters; ActorParameters actorParameters;
Value<float> unknown1; Value<float> AggressionCheck;
Value<float> unknown2; Value<float> CoverCheck;
Value<float> unknown3; Value<float> SearchRadius;
Value<float> unknown4; Value<float> FallBackCheck;
Value<float> unknown5; Value<float> FallBackRadius;
Value<float> unknown6; Value<float> HearingRadius;
Value<atUint32> unknown7; /*
* 0x1: pendingAmbush
* 0x2: ceilingAmbush
* 0x4: nonAggressive
* 0x8: melee
* 0x10: noShuffleCloseCheck
* 0x20: onlyAttackInRange
* 0x40: unk
* 0x80: noKnockbackImpulseReset
* 0x200: noMeleeAttack
* 0x400: breakAttack
* 0x1000: seated
* 0x2000: shadowPirate
* 0x4000: alertBeforeCloak
* 0x8000: noBreakDodge
* 0x10000: floatingCorpse
* 0x20000: ragdollNoAiCollision
* 0x40000: trooper
*/
Value<atUint32> flags;
Value<bool> unknown8; Value<bool> unknown8;
UniqueID32 wpsc1; UniqueID32 Projectile;
DamageInfo damageInfo1; DamageInfo ProjectileDamage;
Value<atUint32> soundID1; Value<atUint32> Sound_Projectile;
DamageInfo damageInfo2; DamageInfo BladeDamage;
Value<float> unknown9; Value<float> KneelAttackChance;
UniqueID32 wpsc2; UniqueID32 KneelAttackShot;
DamageInfo damageInfo3; DamageInfo KneelAttackDamage;
Value<float> unknown10; Value<float> DodgeCheck;
Value<atUint32> soundID2; Value<atUint32> Sound_Impact;
Value<float> unknown11; Value<float> averageNextShotTime;
Value<float> unknown12; Value<float> nextShotTimeVariation;
Value<atUint32> soundID3; Value<atUint32> Sound_Alert;
Value<float> unknown13; Value<float> GunTrackDelay;
Value<atUint32> unknown14; Value<atUint32> firstBurstCount;
Value<float> unknown15; Value<float> CloakOpacity;
Value<float> unknown16; Value<float> MaxCloakOpacity;
Value<float> unknown17; Value<float> dodgeDelayTimeMin;
Value<float> unknown18; Value<float> dodgeDelayTimeMax;
Value<atUint32> soundID4; Value<atUint32> Sound_Hurled;
Value<atUint32> soundID5; Value<atUint32> Sound_Death;
Value<float> unknown19; Value<float> unknown19;
Value<float> unknown20; Value<float> AvoidDistance;
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const { void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const {
actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters);
} }
void nameIDs(PAKRouter<PAKBridge>& pakRouter) const { void nameIDs(PAKRouter<PAKBridge>& pakRouter) const {
if (wpsc1) { if (Projectile) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(Projectile);
ent->name = name + "_wpsc1"; ent->name = name + "_Projectile";
} }
if (wpsc2) { if (KneelAttackShot) {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(KneelAttackShot);
ent->name = name + "_wpsc2"; ent->name = name + "_KneelAttackShot";
} }
patternedInfo.nameIDs(pakRouter, name + "_patterned"); patternedInfo.nameIDs(pakRouter, name + "_patterned");
actorParameters.nameIDs(pakRouter, name + "_actp"); actorParameters.nameIDs(pakRouter, name + "_actp");
} }
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, std::vector<hecl::ProjectPath>& lazyOut) const { void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, std::vector<hecl::ProjectPath>& lazyOut) const {
g_curSpec->flattenDependencies(wpsc1, pathsOut); g_curSpec->flattenDependencies(Projectile, pathsOut);
g_curSpec->flattenDependencies(wpsc2, pathsOut); g_curSpec->flattenDependencies(KneelAttackShot, pathsOut);
patternedInfo.depIDs(pathsOut); patternedInfo.depIDs(pathsOut);
actorParameters.depIDs(pathsOut, lazyOut); actorParameters.depIDs(pathsOut, lazyOut);
} }

View File

@ -11,20 +11,20 @@ class CRandom16 {
public: public:
CRandom16(u32 p = 99) : m_seed(p) {} CRandom16(u32 p = 99) : m_seed(p) {}
inline u32 Next() { u32 Next() {
m_seed = (m_seed * 0x41c64e6d) + 0x00003039; m_seed = (m_seed * 0x41c64e6d) + 0x00003039;
return m_seed >> 16; return m_seed >> 16;
} }
inline u32 GetSeed() const { return m_seed; } u32 GetSeed() const { return m_seed; }
inline void SetSeed(u32 p) { m_seed = p; } void SetSeed(u32 p) { m_seed = p; }
inline float Float() { return Next() * 0.000015259022f; } float Float() { return Next() * 0.000015259022f; }
inline float Range(float min, float max) { return min + Float() * (max - min); } float Range(float min, float max) { return min + Float() * (max - min); }
inline s32 Range(s32 min, s32 max) { return min + (Next() % ((max - min) + 1)); } s32 Range(s32 min, s32 max) { return min + (Next() % ((max - min) + 1)); }
static CRandom16* GetRandomNumber() { return g_randomNumber; } static CRandom16* GetRandomNumber() { return g_randomNumber; }
static void SetRandomNumber(CRandom16* rnd) { g_randomNumber = rnd; } static void SetRandomNumber(CRandom16* rnd) { g_randomNumber = rnd; }

View File

@ -2281,6 +2281,14 @@ CRayCastResult CStateManager::RayWorldIntersection(TUniqueId& idOut, const zeus:
return CGameCollision::RayWorldIntersection(*this, idOut, pos, dir, length, filter, list); return CGameCollision::RayWorldIntersection(*this, idOut, pos, dir, length, filter, list);
} }
zeus::CVector3f CStateManager::Random2f(float scaleMin, float scaleMax) {
zeus::CVector3f ret(x900_activeRandom->Float() - 0.5f, x900_activeRandom->Float() - 0.5f, 0.f);
if (std::fabs(ret.x()) < 0.001f)
ret.x() = 0.001f;
ret.normalize();
return ret * ((scaleMax - scaleMin) * x900_activeRandom->Float() + scaleMin);
}
void CStateManager::UpdateObjectInLists(CEntity& ent) { void CStateManager::UpdateObjectInLists(CEntity& ent) {
for (auto& list : x808_objLists) { for (auto& list : x808_objLists) {
if (list->GetValidObjectById(ent.GetUniqueId())) if (list->GetValidObjectById(ent.GetUniqueId()))

View File

@ -363,6 +363,7 @@ public:
const std::shared_ptr<CPlayerState>& GetPlayerState() const { return x8b8_playerState; } const std::shared_ptr<CPlayerState>& GetPlayerState() const { return x8b8_playerState; }
CRandom16* GetActiveRandom() { return x900_activeRandom; } CRandom16* GetActiveRandom() { return x900_activeRandom; }
zeus::CVector3f Random2f(float scaleMin, float scaleMax);
void SetActiveRandomToDefault() { x900_activeRandom = &x8fc_random; } void SetActiveRandomToDefault() { x900_activeRandom = &x8fc_random; }
void ClearActiveRandom() { x900_activeRandom = nullptr; } void ClearActiveRandom() { x900_activeRandom = nullptr; }
CRumbleManager& GetRumbleManager() { return *x88c_rumbleManager; } CRumbleManager& GetRumbleManager() { return *x88c_rumbleManager; }

View File

@ -6,7 +6,7 @@ namespace urde {
CBodyStateCmdMgr::CBodyStateCmdMgr() { CBodyStateCmdMgr::CBodyStateCmdMgr() {
x40_commandTable.push_back(&xb8_getup); x40_commandTable.push_back(&xb8_getup);
x40_commandTable.push_back(&xc4_step); x40_commandTable.push_back(&xc4_step);
x40_commandTable.push_back(&xd4_); x40_commandTable.push_back(&xd4_die);
x40_commandTable.push_back(&xdc_knockDown); x40_commandTable.push_back(&xdc_knockDown);
x40_commandTable.push_back(&xf4_knockBack); x40_commandTable.push_back(&xf4_knockBack);
x40_commandTable.push_back(&x10c_meleeAttack); x40_commandTable.push_back(&x10c_meleeAttack);
@ -14,10 +14,10 @@ CBodyStateCmdMgr::CBodyStateCmdMgr() {
x40_commandTable.push_back(&x144_loopAttack); x40_commandTable.push_back(&x144_loopAttack);
x40_commandTable.push_back(&x154_loopReaction); x40_commandTable.push_back(&x154_loopReaction);
x40_commandTable.push_back(&x160_loopHitReaction); x40_commandTable.push_back(&x160_loopHitReaction);
x40_commandTable.push_back(&x16c_); x40_commandTable.push_back(&x16c_exitState);
x40_commandTable.push_back(&x174_); x40_commandTable.push_back(&x174_leanFromCover);
x40_commandTable.push_back(&x17c_); x40_commandTable.push_back(&x17c_nextState);
x40_commandTable.push_back(&x184_); x40_commandTable.push_back(&x184_maintainVelocity);
x40_commandTable.push_back(&x18c_generate); x40_commandTable.push_back(&x18c_generate);
x40_commandTable.push_back(&x1ac_hurled); x40_commandTable.push_back(&x1ac_hurled);
x40_commandTable.push_back(&x1d0_jump); x40_commandTable.push_back(&x1d0_jump);
@ -26,12 +26,12 @@ CBodyStateCmdMgr::CBodyStateCmdMgr() {
x40_commandTable.push_back(&x21c_scripted); x40_commandTable.push_back(&x21c_scripted);
x40_commandTable.push_back(&x230_cover); x40_commandTable.push_back(&x230_cover);
x40_commandTable.push_back(&x254_wallHang); x40_commandTable.push_back(&x254_wallHang);
x40_commandTable.push_back(&x260_); x40_commandTable.push_back(&x260_locomotion);
x40_commandTable.push_back(&x268_); x40_commandTable.push_back(&x268_additiveIdle);
x40_commandTable.push_back(&x270_additiveAim); x40_commandTable.push_back(&x270_additiveAim);
x40_commandTable.push_back(&x278_additiveFlinch); x40_commandTable.push_back(&x278_additiveFlinch);
x40_commandTable.push_back(&x284_additiveReaction); x40_commandTable.push_back(&x284_additiveReaction);
x40_commandTable.push_back(&x298_); x40_commandTable.push_back(&x298_stopReaction);
} }
void CBodyStateCmdMgr::DeliverCmd(const CBCLocomotionCmd& cmd) { void CBodyStateCmdMgr::DeliverCmd(const CBCLocomotionCmd& cmd) {

View File

@ -315,7 +315,7 @@ class CBodyStateCmdMgr {
u32 xb4_deliveredCmdMask = 0; u32 xb4_deliveredCmdMask = 0;
CBCGetupCmd xb8_getup; CBCGetupCmd xb8_getup;
CBCStepCmd xc4_step; CBCStepCmd xc4_step;
CBodyStateCmd xd4_ = {EBodyStateCmd::Die}; CBodyStateCmd xd4_die = {EBodyStateCmd::Die};
CBCKnockDownCmd xdc_knockDown; CBCKnockDownCmd xdc_knockDown;
CBCKnockBackCmd xf4_knockBack; CBCKnockBackCmd xf4_knockBack;
CBCMeleeAttackCmd x10c_meleeAttack; CBCMeleeAttackCmd x10c_meleeAttack;
@ -323,10 +323,10 @@ class CBodyStateCmdMgr {
CBCLoopAttackCmd x144_loopAttack; CBCLoopAttackCmd x144_loopAttack;
CBCLoopReactionCmd x154_loopReaction; CBCLoopReactionCmd x154_loopReaction;
CBCLoopHitReactionCmd x160_loopHitReaction; CBCLoopHitReactionCmd x160_loopHitReaction;
CBodyStateCmd x16c_ = {EBodyStateCmd::ExitState}; CBodyStateCmd x16c_exitState = {EBodyStateCmd::ExitState};
CBodyStateCmd x174_ = {EBodyStateCmd::LeanFromCover}; CBodyStateCmd x174_leanFromCover = {EBodyStateCmd::LeanFromCover};
CBodyStateCmd x17c_ = {EBodyStateCmd::NextState}; CBodyStateCmd x17c_nextState = {EBodyStateCmd::NextState};
CBodyStateCmd x184_ = {EBodyStateCmd::MaintainVelocity}; CBodyStateCmd x184_maintainVelocity = {EBodyStateCmd::MaintainVelocity};
CBCGenerateCmd x18c_generate; CBCGenerateCmd x18c_generate;
CBCHurledCmd x1ac_hurled; CBCHurledCmd x1ac_hurled;
CBCJumpCmd x1d0_jump; CBCJumpCmd x1d0_jump;
@ -335,12 +335,12 @@ class CBodyStateCmdMgr {
CBCScriptedCmd x21c_scripted; CBCScriptedCmd x21c_scripted;
CBCCoverCmd x230_cover; CBCCoverCmd x230_cover;
CBCWallHangCmd x254_wallHang; CBCWallHangCmd x254_wallHang;
CBodyStateCmd x260_ = {EBodyStateCmd::Locomotion}; CBodyStateCmd x260_locomotion = {EBodyStateCmd::Locomotion};
CBodyStateCmd x268_ = {EBodyStateCmd::AdditiveIdle}; CBodyStateCmd x268_additiveIdle = {EBodyStateCmd::AdditiveIdle};
CBCAdditiveAimCmd x270_additiveAim; CBCAdditiveAimCmd x270_additiveAim;
CBCAdditiveFlinchCmd x278_additiveFlinch; CBCAdditiveFlinchCmd x278_additiveFlinch;
CBCAdditiveReactionCmd x284_additiveReaction; CBCAdditiveReactionCmd x284_additiveReaction;
CBodyStateCmd x298_ = {EBodyStateCmd::StopReaction}; CBodyStateCmd x298_stopReaction = {EBodyStateCmd::StopReaction};
void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); } void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); }
public: public:

View File

@ -9,16 +9,15 @@
namespace urde { namespace urde {
CBoneTracking::CBoneTracking(const CAnimData& animData, std::string_view bone, float f1, float f2, bool b1) CBoneTracking::CBoneTracking(const CAnimData& animData, std::string_view bone,
float maxTrackingAngle, float angSpeed, bool parentIk)
: x14_segId(animData.GetCharLayoutInfo().GetSegIdFromString(bone)) : x14_segId(animData.GetCharLayoutInfo().GetSegIdFromString(bone))
, x1c_(f1) , x1c_maxTrackingAngle(maxTrackingAngle)
, x20_(f2) , x20_angSpeed(angSpeed)
, x36_24_active(false) , x36_26_noParent(parentIk)
, x36_25_(false) , x36_27_noParentOrigin(parentIk)
, x36_26_(b1) , x36_28_noHorizontalAim(parentIk)
, x36_27_(b1) , x36_29_parentIk(parentIk) {}
, x36_28_(b1)
, x36_29_(b1) {}
void CBoneTracking::Update(float dt) { x18_time += dt; } void CBoneTracking::Update(float dt) { x18_time += dt; }
@ -30,11 +29,71 @@ void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, con
(bodyController.GetBodyStateInfo().ApplyHeadTracking() && patterned && patterned->ApplyBoneTracking())); (bodyController.GetBodyStateInfo().ApplyHeadTracking() && patterned && patterned->ApplyBoneTracking()));
} }
void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf, void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& worldXf,
const zeus::CVector3f& vec, bool b) { const zeus::CVector3f& localOffsetScale, bool tracking) {
if (x14_segId == 0) if (x14_segId == 0)
return; return;
CHierarchyPoseBuilder& pb = animData.PoseBuilder();
TCastToConstPtr<CPatterned> targetAct = mgr.GetObjectById(x34_target);
if (x36_24_active && tracking && (targetAct || x24_targetPosition)) {
x36_25_hasTrackedRotation = true;
auto layoutInfo = pb.CharLayoutInfo();
CSegId bone;
if (x36_26_noParent)
bone = x14_segId;
else
bone = layoutInfo->GetRootNode()->GetBoneMap()[x14_segId].x0_parentId;
zeus::CTransform parentBoneXf;
pb.BuildTransform(bone, parentBoneXf);
zeus::CVector3f pos = parentBoneXf.origin;
if (x36_27_noParentOrigin && !x36_26_noParent) {
zeus::CTransform thisBoneXf;
pb.BuildTransform(x14_segId, thisBoneXf);
pos = thisBoneXf.origin;
}
parentBoneXf.origin = pos * localOffsetScale;
zeus::CTransform finalXf = worldXf * parentBoneXf;
zeus::CVector3f localDir = finalXf.transposeRotate(
(targetAct ? targetAct->GetAimPosition(mgr, 0.f) : *x24_targetPosition) - finalXf.origin).normalized();
if (x36_28_noHorizontalAim)
localDir = zeus::CVector3f(0.f, localDir.toVec2f().magnitude(), localDir.z());
if (x36_29_parentIk) {
float negElev = -parentBoneXf.basis[1].z();
zeus::CVector3f ikBase(0.f, std::sqrt(1.f - negElev * negElev), negElev);
float angle = zeus::CVector3f::getAngleDiff(ikBase, localDir);
angle = std::min(angle, x1c_maxTrackingAngle);
localDir = zeus::CVector3f::slerp(ikBase, localDir, angle);
} else {
float angle = zeus::CVector3f::getAngleDiff(zeus::CVector3f::skForward, localDir);
angle = std::min(angle, x1c_maxTrackingAngle);
localDir = zeus::CVector3f::slerp(zeus::CVector3f::skForward, localDir, angle);
}
float angle = zeus::CVector3f::getAngleDiff(x0_curRotation.transform(zeus::CVector3f::skForward), localDir);
float clampedAngle = std::min(angle, x18_time * x20_angSpeed);
if (clampedAngle > 1.0e-05f) {
x0_curRotation = zeus::CQuaternion::slerpShort(x0_curRotation,
zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, zeus::CUnitVector3f(localDir), 2.f * M_PIF),
clampedAngle / angle);
}
pb.GetTreeMap()[x14_segId].x4_rotation = x0_curRotation;
animData.MarkPoseDirty();
} else if (x36_25_hasTrackedRotation) {
zeus::CQuaternion qb = pb.GetTreeMap()[x14_segId].x4_rotation;
float angle = zeus::CVector3f::getAngleDiff(x0_curRotation.transform(zeus::CVector3f::skForward),
qb.transform(zeus::CVector3f::skForward));
float maxAngDelta = x18_time * x20_angSpeed;
float clampedAngle = std::min(angle, maxAngDelta);
if (clampedAngle > 0.5f * maxAngDelta) {
x0_curRotation = zeus::CQuaternion::slerpShort(x0_curRotation, qb, clampedAngle / angle);
pb.GetTreeMap()[x14_segId].x4_rotation = x0_curRotation;
animData.MarkPoseDirty();
} else {
x36_25_hasTrackedRotation = false;
x0_curRotation = qb;
}
} else {
x0_curRotation = pb.GetTreeMap()[x14_segId].x4_rotation;
}
x18_time = 0.f; x18_time = 0.f;
} }
@ -42,5 +101,9 @@ void CBoneTracking::SetActive(bool) { x36_24_active = true; }
void CBoneTracking::SetTarget(TUniqueId target) { x34_target = target; } void CBoneTracking::SetTarget(TUniqueId target) { x34_target = target; }
void CBoneTracking::UnsetTarget() { x34_target = kInvalidUniqueId; }
void CBoneTracking::SetTargetPosition(const zeus::CVector3f& targetPos) { x24_targetPosition = targetPos; } void CBoneTracking::SetTargetPosition(const zeus::CVector3f& targetPos) { x24_targetPosition = targetPos; }
void CBoneTracking::SetNoHorizontalAim(bool b) { x36_28_noHorizontalAim = b; }
} // namespace urde } // namespace urde

View File

@ -12,28 +12,38 @@ class CAnimData;
class CStateManager; class CStateManager;
class CBodyController; class CBodyController;
class CBoneTracking { class CBoneTracking {
zeus::CQuaternion x0_ = zeus::CQuaternion::skNoRotation; zeus::CQuaternion x0_curRotation = zeus::CQuaternion::skNoRotation;
float x10_ = 0.f;
CSegId x14_segId; CSegId x14_segId;
float x18_time = 0.f; float x18_time = 0.f;
float x1c_; float x1c_maxTrackingAngle;
float x20_; float x20_angSpeed;
std::experimental::optional<zeus::CVector3f> x24_targetPosition; std::experimental::optional<zeus::CVector3f> x24_targetPosition;
TUniqueId x34_target = kInvalidUniqueId; TUniqueId x34_target = kInvalidUniqueId;
bool x36_24_active : 1; union {
bool x36_25_ : 1; struct {
bool x36_26_ : 1; bool x36_24_active : 1;
bool x36_27_ : 1; bool x36_25_hasTrackedRotation : 1;
bool x36_28_ : 1; bool x36_26_noParent : 1;
bool x36_29_ : 1; bool x36_27_noParentOrigin : 1;
bool x36_28_noHorizontalAim : 1;
bool x36_29_parentIk : 1;
};
u32 _dummy = 0;
};
public: public:
CBoneTracking(const CAnimData&, std::string_view, float, float, bool); CBoneTracking(const CAnimData& animData, std::string_view bone,
float maxTrackingAngle, float angSpeed, bool parentIk);
void Update(float dt); void Update(float dt);
void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, void PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf,
const CBodyController&); const zeus::CVector3f& vec, const CBodyController& bodyController);
void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, bool); void PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& worldXf,
void SetActive(bool); const zeus::CVector3f& localOffsetScale, bool tracking);
void SetTarget(TUniqueId); void SetActive(bool b);
void SetTargetPosition(const zeus::CVector3f&); void SetTarget(TUniqueId id);
void UnsetTarget();
void SetTargetPosition(const zeus::CVector3f& pos);
void SetNoHorizontalAim(bool b);
}; };
} // namespace urde } // namespace urde

View File

@ -76,11 +76,11 @@ enum class EJumpState { Invalid = -1, IntoJump, AmbushJump, Loop, OutOfJump, Wal
enum class EStepDirection { Invalid = -1, Forward = 0, Backward = 1, Left = 2, Right = 3, Up = 4, Down = 5 }; enum class EStepDirection { Invalid = -1, Forward = 0, Backward = 1, Left = 2, Right = 3, Up = 4, Down = 5 };
enum class EStepType { Normal = 0, Dodge = 1 }; enum class EStepType { Normal = 0, Dodge = 1, BreakDodge = 2, RollDodge = 3 };
enum class ESeverity { Invalid = -1, Zero = 0, One = 1 }; enum class ESeverity { Invalid = -1, Zero = 0, One = 1, Two = 2 };
enum class EGetupType { Invalid = -1 }; enum class EGetupType { Invalid = -1, Zero = 0 };
enum class ELoopState { Invalid = -1, Begin, Loop, End }; enum class ELoopState { Invalid = -1, Begin, Loop, End };
@ -90,7 +90,7 @@ enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four };
enum class ESlideType { Invalid = -1 }; enum class ESlideType { Invalid = -1 };
enum class ETauntType { Invalid = -1 }; enum class ETauntType { Invalid = -1, Zero, One, Two };
enum class ECoverState { Invalid = -1, IntoCover, Cover, Lean, OutOfCover }; enum class ECoverState { Invalid = -1, IntoCover, Cover, Lean, OutOfCover };

View File

@ -143,12 +143,12 @@ void CEyeball::Cover(CStateManager&, EStateMsg msg, float) {
void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg) { void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) { if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::One; x32c_animState = EAnimState::Ready;
x330_stateMachineState.SetDelay(x568_attackDelay); x330_stateMachineState.SetDelay(x568_attackDelay);
} else if (msg == EStateMsg::Update) } else if (msg == EStateMsg::Update)
TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0); TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0);
else if (msg == EStateMsg::Deactivate) else if (msg == EStateMsg::Deactivate)
x32c_animState = EAnimState::Zero; x32c_animState = EAnimState::NotReady;
} }
void CEyeball::TryFlinch(CStateManager&, int arg) { void CEyeball::TryFlinch(CStateManager&, int arg) {

View File

@ -25,11 +25,18 @@ public:
}; };
class CMetroid : public CPatterned { class CMetroid : public CPatterned {
union {
struct {
bool x9bf_29_ : 1;
};
u32 _dummy = 0;
};
public: public:
DEFINE_PATTERNED(Metroid) DEFINE_PATTERNED(Metroid)
CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms,
const CMetroidData& metroidData); const CMetroidData& metroidData);
bool GetX9BF_29() const { return x9bf_29_; }
}; };
} // namespace urde::MP1 } // namespace urde::MP1

View File

@ -554,7 +554,7 @@ void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) { switch (msg) {
case EStateMsg::Activate: case EStateMsg::Activate:
x330_stateMachineState.SetDelay(x710_haltDelay); x330_stateMachineState.SetDelay(x710_haltDelay);
x32c_animState = EAnimState::One; x32c_animState = EAnimState::Ready;
x743_24_halted = true; x743_24_halted = true;
x5d6_24_alignToFloor = true; x5d6_24_alignToFloor = true;
if (x5d0_walkerType == EWalkerType::Geemer) if (x5d0_walkerType == EWalkerType::Geemer)
@ -567,7 +567,7 @@ void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float) {
break; break;
case EStateMsg::Deactivate: case EStateMsg::Deactivate:
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
x32c_animState = EAnimState::Zero; x32c_animState = EAnimState::NotReady;
x743_24_halted = false; x743_24_halted = false;
x5d6_24_alignToFloor = false; x5d6_24_alignToFloor = false;
break; break;

View File

@ -179,18 +179,18 @@ void CSeedling::Enraged(CStateManager&, EStateMsg msg, float) {
void CSeedling::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) { void CSeedling::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) if (msg == EStateMsg::Activate)
x32c_animState = EAnimState::One; x32c_animState = EAnimState::Ready;
else if (msg == EStateMsg::Update) else if (msg == EStateMsg::Update)
TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0); TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0);
else if (msg == EStateMsg::Deactivate) { else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::Zero; x32c_animState = EAnimState::NotReady;
x71c_attackCoolOff = (x300_maxAttackRange * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime; x71c_attackCoolOff = (x300_maxAttackRange * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime;
} }
} }
void CSeedling::Generate(CStateManager& mgr, EStateMsg msg, float) { void CSeedling::Generate(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) if (msg == EStateMsg::Activate)
x32c_animState = EAnimState::One; x32c_animState = EAnimState::Ready;
else if (msg == EStateMsg::Update) else if (msg == EStateMsg::Update)
TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0); TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0);
} }

File diff suppressed because it is too large Load Diff

View File

@ -32,40 +32,58 @@ public:
class CSpacePirate : public CPatterned { class CSpacePirate : public CPatterned {
friend class CPirateRagDoll; friend class CPirateRagDoll;
public: public:
DEFINE_PATTERNED(SpacePirate) DEFINE_PATTERNED(SpacePirate)
private: private:
class CSpacePirateData { class CSpacePirateData {
friend class CSpacePirate; friend class CSpacePirate;
float x0_; float x0_AggressionCheck;
float x4_; float x4_CoverCheck;
float x8_; float x8_SearchRadius;
float xc_; float xc_FallBackCheck;
float x10_; float x10_FallBackRadius;
float x14_hearNoiseRange; float x14_HearingRadius;
/*
* 0x1: pendingAmbush
* 0x2: ceilingAmbush
* 0x4: nonAggressive
* 0x8: melee
* 0x10: noShuffleCloseCheck
* 0x20: onlyAttackInRange
* 0x40: unk
* 0x80: noKnockbackImpulseReset
* 0x200: noMeleeAttack
* 0x400: breakAttack
* 0x1000: seated
* 0x2000: shadowPirate
* 0x4000: alertBeforeCloak
* 0x8000: noBreakDodge
* 0x10000: floatingCorpse
* 0x20000: ragdollNoAiCollision
* 0x40000: trooper
*/
u32 x18_flags; u32 x18_flags;
bool x1c_; bool x1c_;
CProjectileInfo x20_mainProjectileInfo; CProjectileInfo x20_Projectile;
u16 x48_; u16 x48_Sound_Projectile;
CDamageInfo x4c_; CDamageInfo x4c_BladeDamage;
float x68_; float x68_KneelAttackChance;
CProjectileInfo x6c_; CProjectileInfo x6c_KneelAttackShot;
float x94_; float x94_DodgeCheck;
u16 x98_ragdollThudSfx; u16 x98_Sound_Impact;
float x9c_averageNextShotTime; float x9c_averageNextShotTime;
float xa0_nextShotTimeVariation; float xa0_nextShotTimeVariation;
u16 xa4_; u16 xa4_Sound_Alert;
float xa8_aimDelayTime; float xa8_GunTrackDelay;
u32 xac_firstBurstCount; u32 xac_firstBurstCount;
float xb0_minCloakAlpha; float xb0_CloakOpacity;
float xb4_maxCloakAlpha; float xb4_MaxCloakOpacity;
float xb8_; float xb8_dodgeDelayTimeMin;
float xbc_; float xbc_dodgeDelayTimeMax;
u16 xc0_; u16 xc0_Sound_Hurled;
u16 xc2_; u16 xc2_Sound_Death;
float xc4_; float xc4_;
float xc8_; float xc8_AvoidDistance;
public: public:
CSpacePirateData(CInputStream&, u32); CSpacePirateData(CInputStream&, u32);
@ -76,94 +94,94 @@ private:
struct { struct {
bool x634_24_pendingAmbush : 1; bool x634_24_pendingAmbush : 1;
bool x634_25_ceilingAmbush : 1; bool x634_25_ceilingAmbush : 1;
bool x634_26_ : 1; bool x634_26_nonAggressive : 1;
bool x634_27_melee : 1; bool x634_27_melee : 1;
bool x634_28_ : 1; bool x634_28_noShuffleCloseCheck : 1;
bool x634_29_onlyAttackInRange : 1; bool x634_29_onlyAttackInRange : 1;
bool x634_30_ : 1; bool x634_30_ : 1;
bool x634_31_ : 1; bool x634_31_noKnockbackImpulseReset : 1;
bool x635_24_ : 1; bool x635_24_noMeleeAttack : 1;
bool x635_25_ : 1; bool x635_25_breakAttack : 1;
bool x635_26_ : 1; bool x635_26_seated : 1;
bool x635_27_shadowPirate : 1; bool x635_27_shadowPirate : 1;
bool x635_28_ : 1; bool x635_28_alertBeforeCloak : 1;
bool x635_29_ : 1; bool x635_29_noBreakDodge : 1;
bool x635_30_floatingCorpse : 1; bool x635_30_floatingCorpse : 1;
bool x635_31_ragdollNoAiCollision : 1; bool x635_31_ragdollNoAiCollision : 1;
bool x636_24_trooper : 1; bool x636_24_trooper : 1;
bool x636_25_hearNoise : 1; bool x636_25_hearNoise : 1;
bool x636_26_ : 1; bool x636_26_enableMeleeAttack : 1;
bool x636_27_ : 1; bool x636_27_ : 1;
bool x636_28_ : 1; bool x636_28_ : 1;
bool x636_29_ : 1; bool x636_29_enableRetreat : 1;
bool x636_30_ : 1; bool x636_30_shuffleClose : 1;
bool x636_31_ : 1; bool x636_31_inAttackState : 1;
bool x637_24_ : 1; bool x637_24_enablePatrol : 1;
bool x637_25_ : 1; bool x637_25_enableAim : 1;
bool x637_26_hearPlayerFire : 1; bool x637_26_hearPlayerFire : 1;
bool x637_27_inProjectilePath : 1; bool x637_27_inProjectilePath : 1;
bool x637_28_ : 1; bool x637_28_noPlayerLos : 1;
bool x637_29_ : 1; bool x637_29_inWallHang : 1;
bool x637_30_ : 1; bool x637_30_jumpVelSet : 1;
bool x637_31_prevInCineCam : 1; bool x637_31_prevInCineCam : 1;
bool x638_24_pendingFrenzyChance : 1; bool x638_24_pendingFrenzyChance : 1;
bool x638_25_ : 1; bool x638_25_appliedBladeDamage : 1;
bool x638_26_ : 1; bool x638_26_alwaysAggressive : 1;
bool x638_27_ : 1; bool x638_27_coverCheck : 1;
bool x638_28_ : 1; bool x638_28_enableDodge : 1;
bool x638_29_ : 1; bool x638_29_noPlayerDodge : 1;
bool x638_30_ragdollOver : 1; bool x638_30_ragdollOver : 1;
bool x638_31_ : 1; bool x638_31_mayStartAttack : 1;
bool x639_24_ : 1; bool x639_24_ : 1;
bool x639_25_ : 1; bool x639_25_useJumpBackJump : 1;
bool x639_26_started : 1; bool x639_26_started : 1;
bool x639_27_ : 1; bool x639_27_inRange : 1;
bool x639_28_ : 1; bool x639_28_satUp : 1;
bool x639_29_ : 1; bool x639_29_enableBreakDodge : 1;
bool x639_30_ : 1; bool x639_30_closeMelee : 1;
bool x639_31_ : 1; bool x639_31_sentAttackMsg : 1;
bool x63a_24_ : 1; bool x63a_24_normalDodge : 1;
}; };
u64 _dummy = 0; u64 _dummy = 0;
}; };
s32 x63c_frenzyFrames = 0; s32 x63c_frenzyFrames = 0;
TUniqueId x640_ = kInvalidUniqueId; TUniqueId x640_coverPoint = kInvalidUniqueId;
TUniqueId x642_ = kInvalidUniqueId; TUniqueId x642_previousCoverPoint = kInvalidUniqueId;
float x644_ = 1.f; float x644_steeringSpeed = 1.f;
zeus::CVector3f x648_ = zeus::CVector3f::skForward; zeus::CVector3f x648_targetDelta = zeus::CVector3f::skForward;
zeus::CVector3f x654_; zeus::CVector3f x654_coverPointRearDir;
CPathFindSearch x660_pathFindSearch; CPathFindSearch x660_pathFindSearch;
float x744_ = 0.f; float x744_unkTimer = 0.f;
float x748_ = 0.f; float x748_steeringDelayTimer = 0.f;
u32 x74c_ = 0; u32 x74c_ = 0;
float x750_initialHP; float x750_initialHP;
float x754_ = 0.f; float x754_fsmRange = 0.f;
CSegId x758_headSeg; CSegId x758_headSeg;
u32 x75c_ = 0; u32 x75c_ = 0;
s32 x760_ = -1; pas::ETauntType x760_taunt = pas::ETauntType::Invalid;
CBoneTracking x764_boneTracking; CBoneTracking x764_boneTracking;
s32 x79c_ = -1; pas::ECoverDirection x79c_coverDir = pas::ECoverDirection::Invalid;
float x7a4_intoJumpDist = 1.f; float x7a4_intoJumpDist = 1.f;
float x7a8_ = 2.f; float x7a8_eyeHeight = 2.f;
float x7ac_ = 0.f; float x7ac_timeNoPlayerLos = 0.f;
u32 x7b0_ = 0; u32 x7b0_cantSeePlayerCycleCounter = 0;
TUniqueId x7b4_ = kInvalidUniqueId; TUniqueId x7b4_attachedActor = kInvalidUniqueId;
CSegId x7b6_gunSeg; CSegId x7b6_gunSeg;
CSegId x7b7_elbowSeg; CSegId x7b7_elbowSeg;
CSegId x7b8_wristSeg; CSegId x7b8_wristSeg;
CSegId x7b9_swooshSeg; CSegId x7b9_swooshSeg;
float x7bc_ = 1.f; float x7bc_attackRemTime = 1.f;
TUniqueId x7c0_targetId = kInvalidUniqueId; TUniqueId x7c0_targetId = kInvalidUniqueId;
CBurstFire x7c4_burstFire; CBurstFire x7c4_burstFire;
float x824_ = 3.f; float x824_jumpHeight = 3.f;
zeus::CVector3f x828_; zeus::CVector3f x828_patrolDestPos;
s32 x834_ = -1; pas::EStepDirection x834_skidDir = pas::EStepDirection::Invalid;
float x838_ = 0.f; float x838_strafeDelayTimer = 0.f;
s32 x83c_ = -1; pas::ESeverity x83c_meleeSeverity = pas::ESeverity::Invalid;
TUniqueId x840_ = kInvalidUniqueId; TUniqueId x840_jumpPoint = kInvalidUniqueId;
s32 x844_ = -1; pas::EStepDirection x844_dodgeDir = pas::EStepDirection::Invalid;
float x848_dodgeDist = 3.f; float x848_dodgeDist = 3.f;
float x84c_breakDodgeDist = 3.f; float x84c_breakDodgeDist = 3.f;
float x850_timeSinceHitByPlayer = FLT_MAX; float x850_timeSinceHitByPlayer = FLT_MAX;
@ -177,13 +195,13 @@ private:
float x8b4_shadowPirateAlpha = 0.5f; float x8b4_shadowPirateAlpha = 0.5f;
float x8b8_minCloakAlpha; float x8b8_minCloakAlpha;
float x8bc_maxCloakAlpha; float x8bc_maxCloakAlpha;
float x8c0_; float x8c0_dodgeDelayTimer;
float x8c4_aimDelayTimer; float x8c4_aimDelayTimer;
TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId; TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId;
zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite; zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite;
zeus::CVector2f x8d0_; zeus::CVector2f x8d0_heldPosition;
float x8d8_ = 0.f; float x8d8_holdPositionTime = 0.f;
float x8dc_ = 0.f; float x8dc_leashTimer = 0.f;
static const SBurst skBurstsSeatedOOV[]; static const SBurst skBurstsSeatedOOV[];
static const SBurst skBurstsInjuredOOV[]; static const SBurst skBurstsInjuredOOV[];
@ -207,7 +225,7 @@ private:
void AssignTeamAiRole(CStateManager& mgr); void AssignTeamAiRole(CStateManager& mgr);
void RemoveTeamAiRole(CStateManager& mgr); void RemoveTeamAiRole(CStateManager& mgr);
bool CheckTargetable(CStateManager& mgr); bool CheckTargetable(CStateManager& mgr);
void FireProjectile(float dt, CStateManager& mgr); bool FireProjectile(float dt, CStateManager& mgr);
void UpdateAttacks(float dt, CStateManager& mgr); void UpdateAttacks(float dt, CStateManager& mgr);
zeus::CVector3f GetTargetPos(CStateManager& mgr); zeus::CVector3f GetTargetPos(CStateManager& mgr);
void UpdateAimBodyState(float dt, CStateManager& mgr); void UpdateAimBodyState(float dt, CStateManager& mgr);
@ -216,6 +234,15 @@ private:
void CheckForProjectiles(CStateManager& mgr); void CheckForProjectiles(CStateManager& mgr);
void SetEyeParticleActive(CStateManager& mgr, bool active); void SetEyeParticleActive(CStateManager& mgr, bool active);
void SetVelocityForJump(); void SetVelocityForJump();
void AvoidActors(CStateManager& mgr);
void UpdateCantSeePlayer(CStateManager& mgr);
bool LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& eyePos, const zeus::CVector3f& targetPos,
const CMaterialList& excludeList) const;
void UpdateHeldPosition(CStateManager& mgr, float dt);
void CheckBlade(CStateManager& mgr);
bool CantJumpBack(CStateManager& mgr, const zeus::CVector3f& dir, float dist) const;
void UpdateLeashTimer(float dt);
pas::EStepDirection GetStrafeDir(CStateManager& mgr, float dist) const;
public: public:
CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
@ -237,10 +264,13 @@ public:
bool IsListening() const; bool IsListening() const;
bool Listen(const zeus::CVector3f&, EListenNoiseType); bool Listen(const zeus::CVector3f&, EListenNoiseType);
zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const; zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const;
void DetachActorFromPirate() { x7b4_attachedActor = kInvalidUniqueId; }
bool AttachActorToPirate(TUniqueId id);
void SetAttackTarget(TUniqueId id);
void Patrol(CStateManager&, EStateMsg, float); void Patrol(CStateManager&, EStateMsg, float);
void Dead(CStateManager&, EStateMsg, float); void Dead(CStateManager&, EStateMsg, float);
void PathFind(CStateManager&, EStateMsg, float); void PathFind(CStateManager& mgr, EStateMsg msg, float dt);
void TargetPatrol(CStateManager&, EStateMsg, float); void TargetPatrol(CStateManager&, EStateMsg, float);
void TargetCover(CStateManager&, EStateMsg, float); void TargetCover(CStateManager&, EStateMsg, float);
void Halt(CStateManager&, EStateMsg, float); void Halt(CStateManager&, EStateMsg, float);
@ -279,7 +309,7 @@ public:
bool PatternShagged(CStateManager&, float); bool PatternShagged(CStateManager&, float);
bool AnimOver(CStateManager&, float); bool AnimOver(CStateManager&, float);
bool ShouldAttack(CStateManager&, float); bool ShouldAttack(CStateManager&, float);
bool ShouldJumpBack(CStateManager&, float); bool ShouldJumpBack(CStateManager& mgr, float arg);
bool Stuck(CStateManager&, float); bool Stuck(CStateManager&, float);
bool Landed(CStateManager&, float); bool Landed(CStateManager&, float);
bool HearShot(CStateManager&, float); bool HearShot(CStateManager&, float);
@ -300,10 +330,10 @@ public:
bool ShouldWallHang(CStateManager&, float); bool ShouldWallHang(CStateManager&, float);
bool StartAttack(CStateManager&, float); bool StartAttack(CStateManager&, float);
bool BreakAttack(CStateManager&, float); bool BreakAttack(CStateManager&, float);
bool ShouldStrafe(CStateManager&, float); bool ShouldStrafe(CStateManager& mgr, float arg);
bool ShouldSpecialAttack(CStateManager&, float); bool ShouldSpecialAttack(CStateManager&, float);
bool LostInterest(CStateManager&, float); bool LostInterest(CStateManager&, float);
bool BounceFind(CStateManager&, float); bool BounceFind(CStateManager& mgr, float arg);
CPathFindSearch* GetSearchPath(); CPathFindSearch* GetSearchPath();
u8 GetModelAlphau8(const CStateManager& mgr) const; u8 GetModelAlphau8(const CStateManager& mgr) const;

View File

@ -1,6 +1,9 @@
#include "CProjectileInfo.hpp" #include "CProjectileInfo.hpp"
#include "World/CDamageInfo.hpp" #include "World/CDamageInfo.hpp"
#include "GameGlobalObjects.hpp" #include "GameGlobalObjects.hpp"
#include "CProjectileWeapon.hpp"
#include "World/CPlayer.hpp"
#include "Character/CSteeringBehaviors.hpp"
#include "CSimplePool.hpp" #include "CSimplePool.hpp"
namespace urde { namespace urde {
@ -11,9 +14,56 @@ CProjectileInfo::CProjectileInfo(urde::CInputStream& in)
CProjectileInfo::CProjectileInfo(CAssetId proj, const CDamageInfo& dInfo) CProjectileInfo::CProjectileInfo(CAssetId proj, const CDamageInfo& dInfo)
: x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), proj})), xc_damageInfo(dInfo) {} : x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), proj})), xc_damageInfo(dInfo) {}
zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f&, const zeus::CVector3f&, const CPlayer&, zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f& gunPos, const zeus::CVector3f& aimPos,
bool) { const CPlayer& player, bool gravity, float speed, float dt) {
return {}; zeus::CVector3f ret;
zeus::CVector3f playerVel = player.GetDampedClampedVelocityWR();
zeus::CVector3f gravVec(0.f, 0.f, player.GetGravity());
bool result;
switch (player.GetOrbitState()) {
case CPlayer::EPlayerOrbitState::OrbitObject:
case CPlayer::EPlayerOrbitState::OrbitPoint:
case CPlayer::EPlayerOrbitState::OrbitCarcass:
case CPlayer::EPlayerOrbitState::ForcedOrbitObject:
case CPlayer::EPlayerOrbitState::Grapple: {
if (gravity && player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::ApplyJump) {
result = CSteeringBehaviors::ProjectOrbitalIntersection(gunPos, speed, dt, aimPos, playerVel, gravVec,
player.GetOrbitPoint(), ret);
break;
}
zeus::CVector3f vel;
if (playerVel.canBeNormalized())
vel = playerVel.normalized() * player.GetAverageSpeed();
else
vel = playerVel;
result = CSteeringBehaviors::ProjectOrbitalIntersection(gunPos, speed, dt, aimPos, vel,
player.GetOrbitPoint(), ret);
break;
}
case CPlayer::EPlayerOrbitState::NoOrbit:
if (gravity && player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::ApplyJump)
result = CSteeringBehaviors::ProjectLinearIntersection(gunPos, speed, aimPos, playerVel, gravVec, ret);
else
result = CSteeringBehaviors::ProjectLinearIntersection(gunPos, speed, aimPos, playerVel, ret);
}
if (!result)
ret = playerVel * 1.5f + aimPos;
return ret;
}
float CProjectileInfo::GetProjectileSpeed() const {
auto wpsc = x0_weaponDescription;
if (wpsc->x4_IVEC) {
zeus::CVector3f vec;
wpsc->x4_IVEC->GetValue(0, vec);
return vec.magnitude() / CProjectileWeapon::GetTickPeriod();
}
return 45000.0f;
}
zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f& gunPos, const zeus::CVector3f& aimPos,
const CPlayer& player, bool gravity, float dt) {
return PredictInterceptPos(gunPos, aimPos, player, gravity, GetProjectileSpeed(), dt);
} }
} // namespace urde } // namespace urde

View File

@ -15,7 +15,11 @@ public:
CProjectileInfo(CInputStream&); CProjectileInfo(CInputStream&);
CProjectileInfo(CAssetId, const CDamageInfo&); CProjectileInfo(CAssetId, const CDamageInfo&);
zeus::CVector3f PredictInterceptPos(const zeus::CVector3f&, const zeus::CVector3f&, const CPlayer&, bool); float GetProjectileSpeed() const;
static zeus::CVector3f PredictInterceptPos(const zeus::CVector3f& gunPos, const zeus::CVector3f& aimPos,
const CPlayer& player, bool gravity, float speed, float dt);
zeus::CVector3f PredictInterceptPos(const zeus::CVector3f& gunPos, const zeus::CVector3f& aimPos,
const CPlayer& player, bool gravity, float dt);
CDamageInfo GetDamage() const { return xc_damageInfo; } CDamageInfo GetDamage() const { return xc_damageInfo; }
const TToken<CWeaponDescription>& Token() { return x0_weaponDescription; } const TToken<CWeaponDescription>& Token() { return x0_weaponDescription; }

View File

@ -96,5 +96,6 @@ public:
static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; }
CElementGen* GetAttachedPS1() const { return xfc_APSMGen.get(); } CElementGen* GetAttachedPS1() const { return xfc_APSMGen.get(); }
double GameTime() const { return xd0_curTime; } double GameTime() const { return xd0_curTime; }
static float GetTickPeriod() { return 0.0166667f; }
}; };
} // namespace urde } // namespace urde

View File

@ -264,7 +264,7 @@ void CActor::Render(const CStateManager& mgr) const {
} }
if (xe5_31_pointGeneratorParticles) { if (xe5_31_pointGeneratorParticles) {
CSkinnedModel::ClearPointGeneratorFunc(); CSkinnedModel::ClearPointGeneratorFunc();
mgr.GetActorModelParticles()->Render(*this); mgr.GetActorModelParticles()->Render(mgr, *this);
} }
} }

View File

@ -192,5 +192,6 @@ public:
void SetPointGeneratorParticles(bool s) { xe5_31_pointGeneratorParticles = s; } void SetPointGeneratorParticles(bool s) { xe5_31_pointGeneratorParticles = s; }
CSimpleShadow* Shadow() { return x94_simpleShadow.get(); } CSimpleShadow* Shadow() { return x94_simpleShadow.get(); }
void MoveScannableObjectInfoToActor(CActor*, CStateManager&); void MoveScannableObjectInfoToActor(CActor*, CStateManager&);
const zeus::CAABox& GetRenderBounds() const { return x9c_renderBounds; }
}; };
} // namespace urde } // namespace urde

View File

@ -22,124 +22,114 @@ static bool IsMediumOrLarge(CActor& act) {
CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& parent) CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& parent)
: x0_id(ent.GetUniqueId()), x4_areaId(ent.GetAreaIdAlways()), xdc_ashy(parent.x48_ashy), x128_parent(parent) { : x0_id(ent.GetUniqueId()), x4_areaId(ent.GetAreaIdAlways()), xdc_ashy(parent.x48_ashy), x128_parent(parent) {
x8_thermalHotParticles.resize(8); x8_onFireGens.resize(8);
} }
u32 GetNextBestPt(s32 start, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, CRandom16& rnd) { static s32 GetNextBestPt(s32 start, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn,
CRandom16& rnd) {
const zeus::CVector3f& startVec = vn[start].first; const zeus::CVector3f& startVec = vn[start].first;
u32 ret; s32 ret = start;
float lastMag = 0.f; float maxMag = 0.f;
for (s32 i = 0; i < 10; ++i) { for (s32 i = 0; i < 10; ++i) {
u32 idx = u32(rnd.Range(0, s32(vn.size()) - 1)); s32 idx = rnd.Range(0, s32(vn.size()) - 1);
const zeus::CVector3f& rndVec = vn[idx].first; const zeus::CVector3f& rndVec = vn[idx].first;
float mag = (startVec - rndVec).magSquared(); float mag = (startVec - rndVec).magSquared();
if (mag > lastMag) { if (mag > maxMag) {
ret = idx; ret = idx;
lastMag = mag; maxMag = mag;
} }
} }
return ret; return ret;
} }
void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) { void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
for (std::pair<std::unique_ptr<CElementGen>, u32>& pair : x8_thermalHotParticles) { for (std::pair<std::unique_ptr<CElementGen>, u32>& pair : x8_onFireGens) {
if (pair.first) { if (pair.first) {
CRandom16 rnd(pair.second); CRandom16 rnd(pair.second);
const zeus::CVector3f& vec = vn[u32(rnd.Float() * (vn.size() - 1))].first; const zeus::CVector3f& vec = vn[rnd.Float() * (vn.size() - 1)].first;
pair.first->SetTranslation(xec_ * vec); pair.first->SetTranslation(xec_particleOffsetScale * vec);
} }
} }
if (x84_ > 0) { if (x84_ashMaxParticles > 0) {
CRandom16 rnd(x88_seed1); CRandom16 rnd(x88_ashSeed);
u32 count = (x84_ >= 16 ? 16 : x84_); s32 count = (x84_ashMaxParticles >= 16 ? 16 : x84_ashMaxParticles);
u32 idx = x80_; s32 idx = x80_ashPointIterator;
for (u32 i = 0; i < count; ++i) { for (u32 i = 0; i < count; ++i) {
idx = GetNextBestPt(idx, vn, rnd); idx = GetNextBestPt(idx, vn, rnd);
x78_->SetTranslation(xec_ * vn[idx].first); x78_ashGen->SetTranslation(xec_particleOffsetScale * vn[idx].first);
zeus::CVector3f v = vn[idx].second; zeus::CVector3f v = vn[idx].second;
if (v.canBeNormalized()) { if (v.canBeNormalized()) {
v.normalize(); v.normalize();
x78_->SetOrientation( x78_ashGen->SetOrientation(
zeus::CTransform{zeus::CVector3f::skUp.cross(v), v, zeus::CVector3f::skUp, zeus::CVector3f::skZero}); zeus::CTransform{v.cross(zeus::CVector3f::skUp), v, zeus::CVector3f::skUp, zeus::CVector3f::skZero});
} }
x78_->ForceParticleCreation(1); x78_ashGen->ForceParticleCreation(1);
} }
x84_ -= count; x84_ashMaxParticles -= count;
x88_seed1 = rnd.GetSeed(); x88_ashSeed = rnd.GetSeed();
x80_ashPointIterator = idx;
} }
if (xb0_ != -1) { if (xb0_icePointIterator != -1) {
CRandom16 rnd(xb4_seed2); CRandom16 rnd(xb4_iceSeed);
std::unique_ptr<CElementGen> iceGen = x128_parent.MakeIceGen(); std::unique_ptr<CElementGen> iceGen = x128_parent.MakeIceGen();
iceGen->SetGlobalOrientAndTrans(xf8_); iceGen->SetGlobalOrientAndTrans(xf8_iceXf);
u32 next = GetNextBestPt(xb0_, vn, rnd); s32 idx = GetNextBestPt(xb0_icePointIterator, vn, rnd);
iceGen->SetTranslation(xec_ * vn[next].first); iceGen->SetTranslation(xec_particleOffsetScale * vn[idx].first);
iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(vn[next].second))); iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(vn[idx].second)));
x8c_thermalColdParticles.push_back(std::move(iceGen)); x8c_iceGens.push_back(std::move(iceGen));
xb0_ = (x8c_thermalColdParticles.size() == 4 ? -1 : next); xb0_icePointIterator = (x8c_iceGens.size() == 4 ? -1 : idx);
} }
// TODO: Verify behavior
if (xc0_particleElectric && xc0_particleElectric->GetParticleEmission()) { if (xc0_electricGen && xc0_electricGen->GetParticleEmission()) {
CRandom16 rnd(xcc_seed3); CRandom16 rnd(xcc_electricSeed);
u32 end = 1; u32 end = 1;
#if 0 #if 0
if (4 < 1) if (4 < 1)
end = 4; end = 4;
#endif #endif
u32 lastRnd; s32 idx = xc8_electricPointIterator;
for (u32 i = 0; i < end; ++i) { for (u32 i = 0; i < end; ++i) {
xc0_particleElectric->SetOverrideIPos(vn[u32(rnd.Range(0, s32(vn.size()) - 1))].first * xec_); xc0_electricGen->SetOverrideIPos(vn[rnd.Range(0, s32(vn.size()) - 1)].first * xec_particleOffsetScale);
lastRnd = u32(rnd.Range(0, s32(vn.size()) - 1)); idx = rnd.Range(0, s32(vn.size()) - 1);
xc0_particleElectric->SetOverrideFPos(vn[lastRnd].first * xec_); xc0_electricGen->SetOverrideFPos(vn[idx].first * xec_particleOffsetScale);
xc0_particleElectric->ForceParticleCreation(1); xc0_electricGen->ForceParticleCreation(1);
} }
xcc_seed3 = rnd.GetSeed(); xcc_electricSeed = rnd.GetSeed();
xc8_ = lastRnd; xc8_electricPointIterator = idx;
} }
// TODO: Finish if (xd4_rainSplashGen)
#if 0 xd4_rainSplashGen->GeneratePoints(vn);
if (xd4_)
{
xd4_->sub_8026A5E0(v1, v2, w1);
}
#endif
}
void CActorModelParticles::CItem::sub_801e59a8(EDependency i) {
if (x134_lockDeps & (1 << int(i))) {
// x128_parent.sub_801e3a94(i);
x134_lockDeps &= ~(1 << int(i));
}
} }
bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateManager& mgr) { bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateManager& mgr) {
bool r30 = false; bool effectActive = false;
bool r31 = false; bool sfxActive = false;
x6c_onFireDelayTimer -= dt; x6c_onFireDelayTimer -= dt;
if (x6c_onFireDelayTimer < 0.f) if (x6c_onFireDelayTimer < 0.f)
x6c_onFireDelayTimer = 0.f; x6c_onFireDelayTimer = 0.f;
if (x134_lockDeps & 0x1) { if (x134_lockDeps & 0x1) {
if (x128_parent.xe6_bits2 & 0x1) { if (x128_parent.xe6_loadedDeps & 0x1) {
if (x70_onFire && actor) { if (x70_onFire && actor) {
bool r26 = true; bool doCreate = true;
if (x78_ || xdc_ashy) { if (x78_ashGen || xdc_ashy) {
r26 = false; doCreate = false;
} else if (!IsMediumOrLarge(*actor)) { } else if (!IsMediumOrLarge(*actor)) {
int r3 = 0; int activeParts = 0;
for (const auto& p : x8_thermalHotParticles) for (const auto& p : x8_onFireGens)
if (p.first) if (p.first)
++r3; ++activeParts;
if (r3 >= 4) if (activeParts >= 4)
r26 = false; doCreate = false;
} }
if (r26) { if (doCreate) {
for (auto& p : x8_thermalHotParticles) { for (auto& p : x8_onFireGens) {
if (!p.first) { if (!p.first) {
p.second = mgr.GetActiveRandom()->Next(); p.second = mgr.GetActiveRandom()->Next();
p.first = x128_parent.MakeOnFireGen(); p.first = x128_parent.MakeOnFireGen();
@ -154,83 +144,203 @@ bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateMa
} }
x70_onFire = false; x70_onFire = false;
} }
for (auto& p : x8_thermalHotParticles) { for (auto& p : x8_onFireGens) {
if (p.first) { if (p.first) {
if (p.first->IsSystemDeletable()) if (p.first->IsSystemDeletable())
p.first.reset(); p.first.reset();
else if (actor) else if (actor)
p.first->SetGlobalOrientAndTrans(actor->GetTransform()); p.first->SetGlobalOrientAndTrans(actor->GetTransform());
p.first->Update(dt); p.first->Update(dt);
r30 = true; effectActive = true;
r31 = true; sfxActive = true;
} }
} }
} else { } else {
r30 = true; effectActive = true;
} }
} }
if (x74_sfx) { if (x74_sfx) {
if (r31) { if (sfxActive) {
CSfxManager::UpdateEmitter(x74_sfx, xf8_.origin, zeus::CVector3f::skZero, 1.f); CSfxManager::UpdateEmitter(x74_sfx, xf8_iceXf.origin, zeus::CVector3f::skZero, 1.f);
} else { } else {
CSfxManager::RemoveEmitter(x74_sfx); CSfxManager::RemoveEmitter(x74_sfx);
x74_sfx.reset(); x74_sfx.reset();
} }
} }
if (!r30) { if (!effectActive)
Unlock(EDependency::OnFire); Unlock(EDependency::OnFire);
} return effectActive;
return r30;
} }
bool CActorModelParticles::CItem::UpdateAsh(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateAshGen(float dt, CActor* actor, CStateManager& mgr) {
if (x78_ashGen) {
if (x84_ashMaxParticles == 0 && x78_ashGen->IsSystemDeletable()) {
x78_ashGen.reset();
} else {
if (actor)
x78_ashGen->SetGlobalOrientAndTrans(actor->GetTransform());
x78_ashGen->Update(dt);
return true;
}
} else if (x134_lockDeps & 0x4 && actor) {
if (x128_parent.xe6_loadedDeps & 0x4) {
x78_ashGen = x128_parent.MakeAshGen();
x80_ashPointIterator = 0;
x78_ashGen->SetGlobalOrientAndTrans(actor->GetTransform());
x84_ashMaxParticles = s32((IsMediumOrLarge(*actor) ? 1.f : 0.3f) * x78_ashGen->GetMaxParticles());
x88_ashSeed = mgr.GetActiveRandom()->Next();
}
return true;
}
Unlock(EDependency::Ash);
return false;
}
bool CActorModelParticles::CItem::sub_801e65bc(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateIceGen(float dt, CActor* actor, CStateManager& mgr) {
if (xb0_icePointIterator != -1)
return true;
if (!x8c_iceGens.empty()) {
bool active = false;
for (auto& p : x8c_iceGens) {
if (!p->IsSystemDeletable())
active = true;
p->Update(dt);
}
if (!active)
x8c_iceGens.clear();
else
return true;
} else if (x134_lockDeps & 0x2 && actor) {
if (x128_parent.xe6_loadedDeps & 0x2) {
xb0_icePointIterator = 0;
xb4_iceSeed = mgr.GetActiveRandom()->Next();
}
return true;
}
Unlock(EDependency::Ice);
return false;
}
bool CActorModelParticles::CItem::UpdateFirePop(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateFirePop(float dt, CActor* actor, CStateManager& mgr) {
if (xb8_firePopGen) {
if (xb8_firePopGen->IsSystemDeletable()) {
xb8_firePopGen.reset();
} else {
xb8_firePopGen->Update(dt);
return true;
}
} else if (x134_lockDeps & 0x8 && actor) {
if (x128_parent.xe6_loadedDeps & 0x8) {
xb8_firePopGen = x128_parent.MakeFirePopGen();
xb8_firePopGen->SetGlobalOrientation(actor->GetTransform());
xb8_firePopGen->SetGlobalTranslation(actor->GetRenderBounds().center());
}
return true;
}
Unlock(EDependency::FirePop);
return false;
}
bool CActorModelParticles::CItem::UpdateElectric(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateElectric(float dt, CActor* actor, CStateManager& mgr) {
if (xc0_electricGen) {
if (xc0_electricGen->IsSystemDeletable()) {
xc0_electricGen.reset();
} else {
if (actor && actor->GetActive()) {
xc0_electricGen->SetGlobalOrientation(actor->GetTransform().getRotation());
xc0_electricGen->SetGlobalTranslation(actor->GetTranslation());
}
if (!actor || actor->GetActive()) {
xc0_electricGen->SetModulationColor(xd0_electricColor);
xc0_electricGen->Update(dt);
return true;
}
}
} else if (x134_lockDeps & 0x10) {
if (x128_parent.xe6_loadedDeps & 0x10) {
xc0_electricGen = x128_parent.MakeElectricGen();
xc0_electricGen->SetModulationColor(xd0_electricColor);
xc8_electricPointIterator = 0;
xcc_electricSeed = mgr.GetActiveRandom()->Next();
}
return true;
}
Unlock(EDependency::Electric);
return false;
}
bool CActorModelParticles::CItem::sub_801e69f0(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateRainSplash(float dt, CActor* actor, CStateManager& mgr) {
if (xd4_rainSplashGen) {
if (!xd4_rainSplashGen->IsRaining()) {
xd4_rainSplashGen.reset();
} else {
xd4_rainSplashGen->Update(dt, mgr);
return true;
}
}
return false;
}
bool CActorModelParticles::CItem::sub_801e5e98(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateBurn(float dt, CActor* actor, CStateManager& mgr) {
if (!actor)
xdc_ashy.Unlock();
return xdc_ashy.IsLocked();
}
bool CActorModelParticles::CItem::UpdateIcePop(float dt, CActor* actor, CStateManager& mgr) { return false; } bool CActorModelParticles::CItem::UpdateIcePop(float dt, CActor* actor, CStateManager& mgr) {
if (xe4_icePopGen) {
if (xe4_icePopGen->IsSystemDeletable()) {
xe4_icePopGen.reset();
} else {
xe4_icePopGen->Update(dt);
return true;
}
} else if (x134_lockDeps & 0x20 && actor) {
if (x128_parent.xe6_loadedDeps & 0x20) {
xe4_icePopGen = x128_parent.MakeIcePopGen();
xe4_icePopGen->SetGlobalOrientation(actor->GetTransform());
xe4_icePopGen->SetGlobalTranslation(actor->GetRenderBounds().center());
}
return true;
}
Unlock(EDependency::IcePop);
return false;
}
bool CActorModelParticles::CItem::Update(float dt, CStateManager& mgr) { bool CActorModelParticles::CItem::Update(float dt, CStateManager& mgr) {
CActor* act = static_cast<CActor*>(mgr.ObjectById(x0_id)); CActor* act = static_cast<CActor*>(mgr.ObjectById(x0_id));
if (act && act->HasModelData() && !act->ModelData()->IsNull()) { if (act && act->HasModelData() && !act->ModelData()->IsNull()) {
xec_ = act->ModelData()->GetScale(); xec_particleOffsetScale = act->ModelData()->GetScale();
xf8_ = act->GetTransform(); xf8_iceXf = act->GetTransform();
x4_areaId = act->GetAreaIdAlways(); x4_areaId = act->GetAreaIdAlways();
} else { } else {
x0_id = kInvalidUniqueId; x0_id = kInvalidUniqueId;
x84_ = 0; x84_ashMaxParticles = 0;
xb0_ = -1; xb0_icePointIterator = -1;
if (xc0_particleElectric) if (xc0_electricGen)
xc0_particleElectric->SetParticleEmission(false); xc0_electricGen->SetParticleEmission(false);
if (x74_sfx) { if (x74_sfx) {
CSfxManager::RemoveEmitter(x74_sfx); CSfxManager::RemoveEmitter(x74_sfx);
x74_sfx.reset(); x74_sfx.reset();
} }
x130_ -= dt; x130_remTime -= dt;
if (x130_ <= 0.f) if (x130_remTime <= 0.f)
return false; return false;
} }
bool ret = false; bool ret = false;
if (UpdateOnFire(dt, act, mgr)) if (UpdateOnFire(dt, act, mgr))
ret = true; ret = true;
if (UpdateAsh(dt, act, mgr)) if (UpdateAshGen(dt, act, mgr))
ret = true; ret = true;
if (sub_801e65bc(dt, act, mgr)) if (UpdateIceGen(dt, act, mgr))
ret = true; ret = true;
if (UpdateFirePop(dt, act, mgr)) if (UpdateFirePop(dt, act, mgr))
ret = true; ret = true;
if (UpdateElectric(dt, act, mgr)) if (UpdateElectric(dt, act, mgr))
ret = true; ret = true;
if (sub_801e69f0(dt, act, mgr)) if (UpdateRainSplash(dt, act, mgr))
ret = true; ret = true;
if (sub_801e5e98(dt, act, mgr)) if (UpdateBurn(dt, act, mgr))
ret = true; ret = true;
if (UpdateIcePop(dt, act, mgr)) if (UpdateIcePop(dt, act, mgr))
ret = true; ret = true;
@ -255,21 +365,21 @@ void CActorModelParticles::DecrementDependency(EDependency d) {
Dependency& dep = x50_dgrps[int(d)]; Dependency& dep = x50_dgrps[int(d)];
dep.Decrement(); dep.Decrement();
if (dep.x10_refCount == 0) { if (dep.x10_refCount == 0) {
xe4_bits &= ~(1 << int(d)); xe4_loadingDeps &= ~(1 << int(d));
xe6_bits2 &= ~(1 << int(d)); xe6_loadedDeps &= ~(1 << int(d));
xe5_bits1 &= ~(1 << int(d)); xe5_justLoadedDeps &= ~(1 << int(d));
} }
} }
void CActorModelParticles::IncrementDependency(EDependency d) { void CActorModelParticles::IncrementDependency(EDependency d) {
x50_dgrps[int(d)].Increment(); x50_dgrps[int(d)].Increment();
if (!(xe6_bits2 & (1 << int(d)))) if (!(xe6_loadedDeps & (1 << int(d))))
xe4_bits |= (1 << int(d)); xe4_loadingDeps |= (1 << int(d));
} }
static const char* ParticleDGRPs[] = { static const char* ParticleDGRPs[] = {
"Effect_OnFire_DGRP", "Effect_Ash_DGRP", "Effect_IceBreak_DGRP", "Effect_OnFire_DGRP", "Effect_IceBreak_DGRP", "Effect_Ash_DGRP",
"Effect_FirePop_DGRP", "Effect_IcePop_DGRP", "Effect_Electric_DGRP", "Effect_FirePop_DGRP", "Effect_Electric_DGRP", "Effect_IcePop_DGRP",
}; };
CActorModelParticles::Dependency CActorModelParticles::GetParticleDGRPTokens(const char* name) { CActorModelParticles::Dependency CActorModelParticles::GetParticleDGRPTokens(const char* name) {
@ -291,7 +401,9 @@ std::unique_ptr<CElementGen> CActorModelParticles::MakeOnFireGen() const {
return std::make_unique<CElementGen>(x18_onFire); return std::make_unique<CElementGen>(x18_onFire);
} }
std::unique_ptr<CElementGen> CActorModelParticles::MakeAshGen() const { return std::make_unique<CElementGen>(x20_ash); } std::unique_ptr<CElementGen> CActorModelParticles::MakeAshGen() const {
return std::make_unique<CElementGen>(x20_ash);
}
std::unique_ptr<CElementGen> CActorModelParticles::MakeIceGen() const { std::unique_ptr<CElementGen> CActorModelParticles::MakeIceGen() const {
return std::make_unique<CElementGen>(x28_iceBreak); return std::make_unique<CElementGen>(x28_iceBreak);
@ -342,23 +454,23 @@ void CActorModelParticles::AddStragglersToRenderer(const CStateManager& mgr) {
if (isNotCold) { if (isNotCold) {
/* Hot Draw */ /* Hot Draw */
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
std::unique_ptr<CElementGen>& gen = item.x8_thermalHotParticles[i].first; std::unique_ptr<CElementGen>& gen = item.x8_onFireGens[i].first;
if (gen) if (gen)
g_Renderer->AddParticleGen(*gen); g_Renderer->AddParticleGen(*gen);
} }
if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && item.x78_) if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && item.x78_ashGen)
g_Renderer->AddParticleGen(*item.x78_); g_Renderer->AddParticleGen(*item.x78_ashGen);
if (item.xb8_) if (item.xb8_firePopGen)
g_Renderer->AddParticleGen(*item.xb8_); g_Renderer->AddParticleGen(*item.xb8_firePopGen);
if (item.xc0_particleElectric) if (item.xc0_electricGen)
g_Renderer->AddParticleGen(*item.xc0_particleElectric); g_Renderer->AddParticleGen(*item.xc0_electricGen);
} }
if (isNotHot) { if (isNotHot) {
/* Cold Draw */ /* Cold Draw */
for (std::unique_ptr<CElementGen>& gen : item.x8c_thermalColdParticles) for (std::unique_ptr<CElementGen>& gen : item.x8c_iceGens)
g_Renderer->AddParticleGen(*gen); g_Renderer->AddParticleGen(*gen);
if (item.xe4_) if (item.xe4_icePopGen)
g_Renderer->AddParticleGen(*item.xe4_); g_Renderer->AddParticleGen(*item.xe4_icePopGen);
} }
if (isNotCold) { if (isNotCold) {
/* Thermal Reset */ /* Thermal Reset */
@ -368,7 +480,34 @@ void CActorModelParticles::AddStragglersToRenderer(const CStateManager& mgr) {
} }
} }
void CActorModelParticles::Update(float dt, CStateManager& mgr) {} void CActorModelParticles::UpdateLoad() {
if (xe4_loadingDeps) {
xe5_justLoadedDeps = 0;
for (int i = 0; i < 6; ++i) {
if (xe4_loadingDeps & (1 << i)) {
x50_dgrps[i].UpdateLoad();
if (x50_dgrps[i].x14_loaded) {
xe5_justLoadedDeps |= (1 << i);
xe4_loadingDeps &= ~(1 << i);
}
}
}
xe6_loadedDeps |= xe5_justLoadedDeps;
}
}
void CActorModelParticles::Update(float dt, CStateManager& mgr) {
UpdateLoad();
for (auto it = x0_items.begin(); it != x0_items.end();) {
if (!it->Update(dt, mgr)) {
if (CActor* act = static_cast<CActor*>(mgr.ObjectById(it->x0_id)))
act->SetPointGeneratorParticles(false);
it = x0_items.erase(it);
continue;
}
++it;
}
}
void CActorModelParticles::PointGenerator(void* ctx, void CActorModelParticles::PointGenerator(void* ctx,
const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) { const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
@ -401,30 +540,30 @@ std::list<CActorModelParticles::CItem>::iterator CActorModelParticles::FindOrCre
void CActorModelParticles::StartIce(CActor& act) { void CActorModelParticles::StartIce(CActor& act) {
auto iter = FindOrCreateSystem(act); auto iter = FindOrCreateSystem(act);
iter->Lock(EDependency::Ash); iter->Lock(EDependency::Ice);
} }
void CActorModelParticles::StartElectric(CActor& act) { void CActorModelParticles::StartElectric(CActor& act) {
auto iter = FindOrCreateSystem(act); auto iter = FindOrCreateSystem(act);
if (iter->xc0_particleElectric && !iter->xc0_particleElectric->GetParticleEmission()) if (iter->xc0_electricGen && !iter->xc0_electricGen->GetParticleEmission())
iter->xc0_particleElectric->SetParticleEmission(true); iter->xc0_electricGen->SetParticleEmission(true);
} }
void CActorModelParticles::StopElectric(CActor& act) { void CActorModelParticles::StopElectric(CActor& act) {
if (act.GetPointGeneratorParticles()) { if (act.GetPointGeneratorParticles()) {
auto iter = FindSystem(act.GetUniqueId()); auto iter = FindSystem(act.GetUniqueId());
if (iter != x0_items.cend() && iter->xc0_particleElectric) if (iter != x0_items.cend() && iter->xc0_electricGen)
iter->xc0_particleElectric->SetParticleEmission(false); iter->xc0_electricGen->SetParticleEmission(false);
} }
} }
void CActorModelParticles::sub_801e51d0(CActor& act) { void CActorModelParticles::LoadAndStartElectric(CActor& act) {
auto iter = FindOrCreateSystem(act); auto iter = FindOrCreateSystem(act);
if (!iter->xc0_particleElectric) if (!iter->xc0_electricGen)
iter->Lock(EDependency::IcePop); iter->Lock(EDependency::Electric);
else { else {
if (!iter->xc0_particleElectric->GetParticleEmission()) if (!iter->xc0_electricGen->GetParticleEmission())
iter->xc0_particleElectric->SetParticleEmission(true); iter->xc0_electricGen->SetParticleEmission(true);
} }
} }
@ -432,7 +571,7 @@ void CActorModelParticles::StopThermalHotParticles(CActor& act) {
if (act.GetPointGeneratorParticles()) { if (act.GetPointGeneratorParticles()) {
auto iter = FindSystem(act.GetUniqueId()); auto iter = FindSystem(act.GetUniqueId());
if (iter != x0_items.cend()) { if (iter != x0_items.cend()) {
for (auto& part : iter->x8_thermalHotParticles) for (auto& part : iter->x8_onFireGens)
if (part.first) if (part.first)
part.first->SetParticleEmission(false); part.first->SetParticleEmission(false);
} }
@ -448,7 +587,7 @@ void CActorModelParticles::StartBurnDeath(CActor& act) {
void CActorModelParticles::EnsureElectricLoaded(CActor& act) { void CActorModelParticles::EnsureElectricLoaded(CActor& act) {
auto iter = FindOrCreateSystem(act); auto iter = FindOrCreateSystem(act);
iter->Lock(EDependency::Electric); iter->Lock(EDependency::IcePop);
} }
void CActorModelParticles::EnsureFirePopLoaded(CActor& act) { void CActorModelParticles::EnsureFirePopLoaded(CActor& act) {
@ -458,7 +597,7 @@ void CActorModelParticles::EnsureFirePopLoaded(CActor& act) {
void CActorModelParticles::EnsureIceBreakLoaded(CActor& act) { void CActorModelParticles::EnsureIceBreakLoaded(CActor& act) {
auto iter = FindOrCreateSystem(act); auto iter = FindOrCreateSystem(act);
iter->Lock(EDependency::IceBreak); iter->Lock(EDependency::Ash);
} }
void CActorModelParticles::LightDudeOnFire(CActor& act) { void CActorModelParticles::LightDudeOnFire(CActor& act) {
@ -480,19 +619,52 @@ const CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) {
void CActorModelParticles::AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate, void CActorModelParticles::AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate,
float minZ) { float minZ) {
auto it = FindOrCreateSystem(act); auto it = FindOrCreateSystem(act);
if (it->xd4_rainSplashGenerator) if (it->xd4_rainSplashGen)
return; return;
if (act.GetModelData() && !act.GetModelData()->IsNull()) if (act.GetModelData() && !act.GetModelData()->IsNull())
it->xd4_rainSplashGenerator = it->xd4_rainSplashGen =
std::make_unique<CRainSplashGenerator>(act.GetModelData()->GetScale(), maxSplashes, genRate, minZ, 0.1875f); std::make_unique<CRainSplashGenerator>(act.GetModelData()->GetScale(), maxSplashes, genRate, minZ, 0.1875f);
} }
void CActorModelParticles::RemoveRainSplashGenerator(CActor& act) { void CActorModelParticles::RemoveRainSplashGenerator(CActor& act) {
auto it = FindOrCreateSystem(act); auto it = FindOrCreateSystem(act);
it->xd4_rainSplashGenerator.reset(); it->xd4_rainSplashGen.reset();
} }
void CActorModelParticles::Render(const CActor& actor) const {} void CActorModelParticles::Render(const CStateManager& mgr, const CActor& actor) const {
zeus::CTransform backupModel = CGraphics::g_GXModelMatrix;
auto search = FindSystem(actor.GetUniqueId());
if (search == x0_items.end())
return;
if (search->x4_areaId != kInvalidAreaId) {
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(search->x4_areaId);
if (!area->IsPostConstructed())
return;
if (area->GetOcclusionState() == CGameArea::EOcclusionState::Occluded)
return;
}
if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Cold) {
for (const auto& gen : search->x8_onFireGens)
gen.first->Render();
if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && search->x78_ashGen)
search->x78_ashGen->Render();
if (search->xb8_firePopGen)
search->xb8_firePopGen->Render();
if (search->xc0_electricGen)
search->xc0_electricGen->Render();
search->x134_lockDeps |= 0x80;
}
if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot) {
for (const auto& gen : search->x8c_iceGens)
gen->Render();
if (search->xd4_rainSplashGen && actor.GetModelData() && !actor.GetModelData()->IsNull())
search->xd4_rainSplashGen->Draw(actor.GetTransform());
if (search->xe4_icePopGen)
search->xe4_icePopGen->Render();
search->x134_lockDeps |= 0x40;
}
CGraphics::SetModelMatrix(backupModel);
}
} // namespace urde } // namespace urde

View File

@ -19,33 +19,33 @@ class CScriptPlayerActor;
class CActorModelParticles { class CActorModelParticles {
public: public:
enum class EDependency { OnFire, Ash, IceBreak, FirePop, IcePop, Electric }; enum class EDependency { OnFire, Ice, Ash, FirePop, Electric, IcePop };
class CItem { class CItem {
friend class CActorModelParticles; friend class CActorModelParticles;
TUniqueId x0_id; TUniqueId x0_id;
TAreaId x4_areaId; TAreaId x4_areaId;
rstl::reserved_vector<std::pair<std::unique_ptr<CElementGen>, u32>, 8> x8_thermalHotParticles; rstl::reserved_vector<std::pair<std::unique_ptr<CElementGen>, u32>, 8> x8_onFireGens;
float x6c_onFireDelayTimer = 0.f; float x6c_onFireDelayTimer = 0.f;
bool x70_onFire = false; bool x70_onFire = false;
CSfxHandle x74_sfx; CSfxHandle x74_sfx;
std::unique_ptr<CElementGen> x78_; std::unique_ptr<CElementGen> x78_ashGen;
u32 x80_ = 0; s32 x80_ashPointIterator = 0;
s32 x84_ = -1; s32 x84_ashMaxParticles = -1;
u32 x88_seed1 = 99; u32 x88_ashSeed = 99;
rstl::reserved_vector<std::unique_ptr<CElementGen>, 4> x8c_thermalColdParticles; rstl::reserved_vector<std::unique_ptr<CElementGen>, 4> x8c_iceGens;
s32 xb0_ = -1; s32 xb0_icePointIterator = -1;
u32 xb4_seed2 = 99; u32 xb4_iceSeed = 99;
std::unique_ptr<CElementGen> xb8_; std::unique_ptr<CElementGen> xb8_firePopGen;
std::unique_ptr<CParticleElectric> xc0_particleElectric; std::unique_ptr<CParticleElectric> xc0_electricGen;
u32 xc8_ = 0; s32 xc8_electricPointIterator = 0;
u32 xcc_seed3 = 99; u32 xcc_electricSeed = 99;
zeus::CColor xd0_; zeus::CColor xd0_electricColor;
std::unique_ptr<CRainSplashGenerator> xd4_rainSplashGenerator; std::unique_ptr<CRainSplashGenerator> xd4_rainSplashGen;
TToken<CTexture> xdc_ashy; TToken<CTexture> xdc_ashy;
std::unique_ptr<CElementGen> xe4_; std::unique_ptr<CElementGen> xe4_icePopGen;
zeus::CVector3f xec_ = zeus::CVector3f::skOne; zeus::CVector3f xec_particleOffsetScale = zeus::CVector3f::skOne;
zeus::CTransform xf8_; zeus::CTransform xf8_iceXf;
CActorModelParticles& x128_parent; CActorModelParticles& x128_parent;
union { union {
struct { struct {
@ -54,16 +54,15 @@ public:
}; };
u16 _dummy = 0; u16 _dummy = 0;
}; };
float x130_ = 10.f; float x130_remTime = 10.f;
u8 x134_lockDeps = 0; mutable u8 x134_lockDeps = 0;
void sub_801e59a8(EDependency i);
bool UpdateOnFire(float dt, CActor* actor, CStateManager& mgr); bool UpdateOnFire(float dt, CActor* actor, CStateManager& mgr);
bool UpdateAsh(float dt, CActor* actor, CStateManager& mgr); bool UpdateAshGen(float dt, CActor* actor, CStateManager& mgr);
bool sub_801e65bc(float dt, CActor* actor, CStateManager& mgr); bool UpdateIceGen(float dt, CActor* actor, CStateManager& mgr);
bool UpdateFirePop(float dt, CActor* actor, CStateManager& mgr); bool UpdateFirePop(float dt, CActor* actor, CStateManager& mgr);
bool UpdateElectric(float dt, CActor* actor, CStateManager& mgr); bool UpdateElectric(float dt, CActor* actor, CStateManager& mgr);
bool sub_801e69f0(float dt, CActor* actor, CStateManager& mgr); bool UpdateRainSplash(float dt, CActor* actor, CStateManager& mgr);
bool sub_801e5e98(float dt, CActor* actor, CStateManager& mgr); bool UpdateBurn(float dt, CActor* actor, CStateManager& mgr);
bool UpdateIcePop(float dt, CActor* actor, CStateManager& mgr); bool UpdateIcePop(float dt, CActor* actor, CStateManager& mgr);
public: public:
@ -113,11 +112,22 @@ private:
tok.Unlock(); tok.Unlock();
x14_loaded = false; x14_loaded = false;
} }
void UpdateLoad() {
if (x14_loaded || x10_refCount == 0)
return;
bool loading = false;
for (CToken& tok : x0_tokens) {
if (!tok.IsLoaded())
loading = true;
}
if (!loading)
x14_loaded = true;
}
}; };
rstl::reserved_vector<Dependency, 6> x50_dgrps; rstl::reserved_vector<Dependency, 6> x50_dgrps;
u8 xe4_bits = 0; u8 xe4_loadingDeps = 0;
u8 xe5_bits1 = 0; u8 xe5_justLoadedDeps = 0;
u8 xe6_bits2 = 0; u8 xe6_loadedDeps = 0;
Dependency GetParticleDGRPTokens(const char* name); Dependency GetParticleDGRPTokens(const char* name);
void LoadParticleDGRPs(); void LoadParticleDGRPs();
@ -132,6 +142,8 @@ private:
void DecrementDependency(EDependency d); void DecrementDependency(EDependency d);
void IncrementDependency(EDependency d); void IncrementDependency(EDependency d);
void UpdateLoad();
public: public:
CActorModelParticles(); CActorModelParticles();
static void PointGenerator(void* item, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn); static void PointGenerator(void* item, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
@ -143,10 +155,10 @@ public:
void StartIce(CActor& actor); void StartIce(CActor& actor);
void AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate, float minZ); void AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate, float minZ);
void RemoveRainSplashGenerator(CActor& act); void RemoveRainSplashGenerator(CActor& act);
void Render(const CActor& actor) const; void Render(const CStateManager& mgr, const CActor& actor) const;
void StartElectric(CActor& act); void StartElectric(CActor& act);
void StopElectric(CActor& act); void StopElectric(CActor& act);
void sub_801e51d0(CActor& act); void LoadAndStartElectric(CActor& act);
void StopThermalHotParticles(CActor& act); void StopThermalHotParticles(CActor& act);
void StartBurnDeath(CActor& act); void StartBurnDeath(CActor& act);
void EnsureElectricLoaded(CActor& act); void EnsureElectricLoaded(CActor& act);

View File

@ -137,6 +137,8 @@ public:
const KnockBackParms& GetActiveParms() const { return x4_activeParms; } const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
EKnockBackVariant GetVariant() const { return x0_variant; } EKnockBackVariant GetVariant() const { return x0_variant; }
float GetFlinchRemTime() const { return x64_flinchRemTime; } float GetFlinchRemTime() const { return x64_flinchRemTime; }
void SetAvailableState(EKnockBackAnimationState s, bool b) { x80_availableStates.set(size_t(s), b); }
bool TestAvailableState(EKnockBackAnimationState s) const { return x80_availableStates.test(size_t(s)); }
}; };
} // namespace urde } // namespace urde

View File

@ -40,6 +40,9 @@ public:
void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const; void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const;
void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, float lookahead) const; void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, float lookahead) const;
void SetArea(CPFArea* area) { x0_area = area; } void SetArea(CPFArea* area) { x0_area = area; }
float GetCharacterHeight() const { return xd0_chHeight; }
void SetCharacterHeight(float h) { xd0_chHeight = h; }
float RemainingPathDistance(const zeus::CVector3f& pos) const;
}; };
} // namespace urde } // namespace urde

View File

@ -59,4 +59,15 @@ void CPathFindSearch::GetSplinePointWithLookahead(zeus::CVector3f& pOut, const z
GetSplinePointWithLookahead(pOut, p1, xc8_curWaypoint, lookahead); GetSplinePointWithLookahead(pOut, p1, xc8_curWaypoint, lookahead);
} }
float CPathFindSearch::RemainingPathDistance(const zeus::CVector3f& pos) const {
float f31 = 0.f;
if (xc8_curWaypoint < x4_waypoints.size() - 1) {
f31 += (x4_waypoints[xc8_curWaypoint + 1] - pos).magnitude();
for (int i = xc8_curWaypoint + 1; i < x4_waypoints.size() - 1; ++i) {
f31 += (x4_waypoints[i + 1] - x4_waypoints[i]).magnitude();
}
}
return f31;
}
} // namespace urde } // namespace urde

View File

@ -20,6 +20,7 @@
#include "World/CScriptWaypoint.hpp" #include "World/CScriptWaypoint.hpp"
#include "World/CScriptActorKeyframe.hpp" #include "World/CScriptActorKeyframe.hpp"
#include "Weapon/CEnergyProjectile.hpp" #include "Weapon/CEnergyProjectile.hpp"
#include "World/CScriptCoverPoint.hpp"
namespace urde { namespace urde {
@ -822,7 +823,7 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float dt) {
void CPatterned::TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg) { void CPatterned::TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg) {
if (state == x450_bodyController->GetCurrentStateId()) if (state == x450_bodyController->GetCurrentStateId())
x32c_animState = EAnimState::Repeat; x32c_animState = EAnimState::Repeat;
else if (x32c_animState == EAnimState::One) else if (x32c_animState == EAnimState::Ready)
(this->*func)(mgr, arg); (this->*func)(mgr, arg);
else else
x32c_animState = EAnimState::Over; x32c_animState = EAnimState::Over;
@ -840,6 +841,54 @@ void CPatterned::TryGenerate(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType(arg), x2e0_destPos, true)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType(arg), x2e0_destPos, true));
} }
void CPatterned::TryJump(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x2e0_destPos, pas::EJumpType(arg)));
}
void CPatterned::TryMeleeAttack(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity(arg)));
}
void CPatterned::TryTurn(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCLocomotionCmd(zeus::CVector3f::skZero, (x2e0_destPos - GetTranslation()).normalized(), 1.f));
}
void CPatterned::TryGetUp(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType(arg)));
}
void CPatterned::TryTaunt(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType(arg)));
}
void CPatterned::TryJumpInLoop(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x2e0_destPos, pas::EJumpType(arg), true));
}
void CPatterned::TryDodge(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCStepCmd(pas::EStepDirection(arg), pas::EStepType::Dodge));
}
void CPatterned::TryRollingDodge(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCStepCmd(pas::EStepDirection(arg), pas::EStepType::RollDodge));
}
void CPatterned::TryBreakDodge(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCStepCmd(pas::EStepDirection(arg), pas::EStepType::BreakDodge));
}
void CPatterned::TryCover(CStateManager& mgr, int arg) {
if (CScriptCoverPoint* cp = GetCoverPoint(mgr, x2dc_destObj)) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCCoverCmd(pas::ECoverDirection(arg), cp->GetTranslation(),
-cp->GetTransform().basis[1]));
}
}
void CPatterned::TryWallHang(CStateManager& mgr, int arg) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCWallHangCmd(x2dc_destObj));
}
void CPatterned::BuildBodyController(EBodyType bodyType) { void CPatterned::BuildBodyController(EBodyType bodyType) {
if (x450_bodyController) if (x450_bodyController)
return; return;
@ -1085,6 +1134,26 @@ void CPatterned::UpdateDamageColor(float dt) {
} }
} }
CScriptCoverPoint* CPatterned::GetCoverPoint(CStateManager& mgr, TUniqueId id) const {
if (id != kInvalidUniqueId) {
if (TCastToPtr<CScriptCoverPoint> cp = mgr.ObjectById(id))
return cp.GetPtr();
}
return nullptr;
}
void CPatterned::SetCoverPoint(CScriptCoverPoint* cp, TUniqueId& id) {
cp->SetInUse(true);
id = cp->GetUniqueId();
}
void CPatterned::ReleaseCoverPoint(CStateManager& mgr, TUniqueId& id) {
if (CScriptCoverPoint* cp = GetCoverPoint(mgr, id)) {
cp->SetInUse(false);
id = kInvalidUniqueId;
}
}
TUniqueId CPatterned::GetWaypointForState(CStateManager& mgr, EScriptObjectState state, TUniqueId CPatterned::GetWaypointForState(CStateManager& mgr, EScriptObjectState state,
EScriptObjectMessage msg) const { EScriptObjectMessage msg) const {
rstl::reserved_vector<TUniqueId, 12> ids; rstl::reserved_vector<TUniqueId, 12> ids;
@ -1476,7 +1545,7 @@ void CPatterned::Render(const CStateManager& mgr) const {
alpha * (x401_29_laggedBurnDeath ? 0.00787402f : 0.00392157f)); alpha * (x401_29_laggedBurnDeath ? 0.00787402f : 0.00392157f));
if (xe5_31_pointGeneratorParticles) { if (xe5_31_pointGeneratorParticles) {
CSkinnedModel::ClearPointGeneratorFunc(); CSkinnedModel::ClearPointGeneratorFunc();
mgr.GetActorModelParticles()->Render(*this); mgr.GetActorModelParticles()->Render(mgr, *this);
} }
} else { } else {
CPhysicsActor::Render(mgr); CPhysicsActor::Render(mgr);

View File

@ -75,7 +75,7 @@ public:
enum class EBehaviourOrient { MoveDir, Constant, Destination }; enum class EBehaviourOrient { MoveDir, Constant, Destination };
enum class EBehaviourModifiers { Zero }; enum class EBehaviourModifiers { Zero };
enum class EPatrolState { Invalid = -1, Patrol, Pause, Done }; enum class EPatrolState { Invalid = -1, Patrol, Pause, Done };
enum class EAnimState { Zero, One, Repeat, Over }; enum class EAnimState { NotReady, Ready, Repeat, Over };
class CPatternNode { class CPatternNode {
zeus::CVector3f x0_pos; zeus::CVector3f x0_pos;
zeus::CVector3f xc_forward; zeus::CVector3f xc_forward;
@ -131,7 +131,7 @@ protected:
u32 _dummy = 0; u32 _dummy = 0;
}; };
EAnimState x32c_animState = EAnimState::Zero; EAnimState x32c_animState = EAnimState::NotReady;
CStateMachineState x330_stateMachineState; CStateMachineState x330_stateMachineState;
ECharacter x34c_character; ECharacter x34c_character;
zeus::CVector3f x350_patternStartPos; zeus::CVector3f x350_patternStartPos;
@ -319,6 +319,17 @@ public:
void TryLoopReaction(CStateManager& mgr, int arg); void TryLoopReaction(CStateManager& mgr, int arg);
void TryProjectileAttack(CStateManager& mgr, int arg); void TryProjectileAttack(CStateManager& mgr, int arg);
void TryGenerate(CStateManager& mgr, int arg); void TryGenerate(CStateManager& mgr, int arg);
void TryJump(CStateManager& mgr, int arg);
void TryMeleeAttack(CStateManager& mgr, int arg);
void TryTurn(CStateManager& mgr, int arg);
void TryGetUp(CStateManager& mgr, int arg);
void TryTaunt(CStateManager& mgr, int arg);
void TryJumpInLoop(CStateManager& mgr, int arg);
void TryDodge(CStateManager& mgr, int arg);
void TryRollingDodge(CStateManager& mgr, int arg);
void TryBreakDodge(CStateManager& mgr, int arg);
void TryCover(CStateManager& mgr, int arg);
void TryWallHang(CStateManager& mgr, int arg);
virtual bool KnockbackWhenFrozen() const { return true; } virtual bool KnockbackWhenFrozen() const { return true; }
virtual void MassiveDeath(CStateManager& mgr); virtual void MassiveDeath(CStateManager& mgr);
@ -357,6 +368,9 @@ public:
void SetModelAlpha(float a) { x42c_color.a() = a; } void SetModelAlpha(float a) { x42c_color.a() = a; }
float CalcDyingThinkRate(); float CalcDyingThinkRate();
void UpdateDamageColor(float dt); void UpdateDamageColor(float dt);
CScriptCoverPoint* GetCoverPoint(CStateManager& mgr, TUniqueId id) const;
void SetCoverPoint(CScriptCoverPoint* cp, TUniqueId& id);
void ReleaseCoverPoint(CStateManager& mgr, TUniqueId& id);
bool CanLongJump() const { return x328_26_longJump; } bool CanLongJump() const { return x328_26_longJump; }
bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; } bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; }

View File

@ -5674,4 +5674,10 @@ bool CPlayer::AttachActorToPlayer(TUniqueId id, bool disableGun) {
return false; return false;
} }
float CPlayer::GetAverageSpeed() const {
if (auto avg = x4a4_moveSpeedAvg.GetAverage())
return *avg;
return x4f8_moveSpeed;
}
} // namespace urde } // namespace urde

View File

@ -610,5 +610,7 @@ public:
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; } bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; } bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
void Set_X590(bool b) { x590_ = b; } void Set_X590(bool b) { x590_ = b; }
const zeus::CVector3f& GetOrbitPoint() const { return x314_orbitPoint; }
float GetAverageSpeed() const;
}; };
} // namespace urde } // namespace urde

View File

@ -9,7 +9,7 @@ CScriptAiJumpPoint::CScriptAiJumpPoint(TUniqueId uid, std::string_view name, con
zeus::CTransform& xf, bool active, float f1) zeus::CTransform& xf, bool active, float f1)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic),
CActorParameters::None(), kInvalidUniqueId) CActorParameters::None(), kInvalidUniqueId)
, xe8_(f1) , xe8_apex(f1)
, xec_touchBounds(xf.origin, xf.origin) {} , xec_touchBounds(xf.origin, xf.origin) {}
void CScriptAiJumpPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } void CScriptAiJumpPoint::Accept(IVisitor& visitor) { visitor.Visit(this); }
@ -43,10 +43,7 @@ void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId oth
std::experimental::optional<zeus::CAABox> CScriptAiJumpPoint::GetTouchBounds() const { return xec_touchBounds; } std::experimental::optional<zeus::CAABox> CScriptAiJumpPoint::GetTouchBounds() const { return xec_touchBounds; }
bool CScriptAiJumpPoint::GetInUse(TUniqueId uid) const { bool CScriptAiJumpPoint::GetInUse(TUniqueId uid) const {
if (x108_24 || x110_timeRemaining > 0.f || x10a_occupant != kInvalidUniqueId || uid != kInvalidUniqueId || return x108_24 || x110_timeRemaining > 0.f || x10a_occupant != kInvalidUniqueId || uid != kInvalidUniqueId ||
uid != x10a_occupant) uid != x10a_occupant;
return true;
return false;
} }
} // namespace urde } // namespace urde

View File

@ -5,7 +5,7 @@
namespace urde { namespace urde {
class CScriptAiJumpPoint : public CActor { class CScriptAiJumpPoint : public CActor {
private: private:
float xe8_; float xe8_apex;
zeus::CAABox xec_touchBounds; zeus::CAABox xec_touchBounds;
union { union {
struct { struct {
@ -28,5 +28,8 @@ public:
void Render(const CStateManager&) const {} void Render(const CStateManager&) const {}
std::experimental::optional<zeus::CAABox> GetTouchBounds() const; std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
bool GetInUse(TUniqueId uid) const; bool GetInUse(TUniqueId uid) const;
TUniqueId GetJumpPoint() const { return x10c_currentWaypoint; }
TUniqueId GetJumpTarget() const { return x10e_nextWaypoint; }
float GetJumpApex() const { return xe8_apex; }
}; };
} // namespace urde } // namespace urde

View File

@ -655,7 +655,7 @@ void CScriptGunTurret::sub80218f50(s32 state, CStateManager& mgr, float dt) {
zeus::CVector3f rotatedBlastVec = GetTransform().rotate(blastXf.origin) + GetTranslation(); zeus::CVector3f rotatedBlastVec = GetTransform().rotate(blastXf.origin) + GetTranslation();
x404_ = mgr.GetPlayer().GetAimPosition(mgr, 0.f); x404_ = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
vec = x37c_projectileInfo.PredictInterceptPos(rotatedBlastVec, mgr.GetPlayer().GetAimPosition(mgr, dt), vec = x37c_projectileInfo.PredictInterceptPos(rotatedBlastVec, mgr.GetPlayer().GetAimPosition(mgr, dt),
mgr.GetPlayer(), false); mgr.GetPlayer(), false, dt);
} }
zeus::CVector3f compensated = zeus::CVector3f compensated =

View File

@ -106,6 +106,7 @@ public:
float GetTime() const { return x8_time; } float GetTime() const { return x8_time; }
float GetRandom() const { return xc_random; } float GetRandom() const { return xc_random; }
float GetDelay() const { return x10_delay; } float GetDelay() const { return x10_delay; }
void SetCodeTrigger() { x18_24_codeTrigger = true; }
const char* GetName() const { const char* GetName() const {
if (x4_state) if (x4_state)

2
hecl

@ -1 +1 @@
Subproject commit 82a7890e99da98fcc9770fb21c73f7837f285f66 Subproject commit 40d23980dec1cf5addab4b0dbd2539d460c37fe0

@ -1 +1 @@
Subproject commit a3a3f90d8ce1d7f4c73c70c690f9bce4da69c50a Subproject commit f81efb25b53e90cf9e77c06a09095a433929ddb4