mirror of https://github.com/AxioDL/metaforce.git
Finish CSpacePirate implementation
This commit is contained in:
parent
14747e39e1
commit
ec1cb75b25
|
@ -12,6 +12,25 @@
|
|||
<option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" />
|
||||
</Objective-C>
|
||||
<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>
|
||||
<pair source="cpp" header="hpp" fileNamingConvention="NONE" />
|
||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||
|
|
|
@ -268,7 +268,7 @@ struct PatternedInfo : BigDNA {
|
|||
Value<float> intoFreezeDur;
|
||||
Value<float> outOfFreezeDur;
|
||||
Value<float> unknown10;
|
||||
Value<atUint32> particle1Frames;
|
||||
Value<atUint32> pathfindingIndex;
|
||||
Value<atVec3f> particle1Scale;
|
||||
UniqueID32 particle1;
|
||||
UniqueID32 electric;
|
||||
|
|
|
@ -14,57 +14,76 @@ struct SpacePirate : IScriptObject {
|
|||
Value<atVec3f> scale;
|
||||
PatternedInfo patternedInfo;
|
||||
ActorParameters actorParameters;
|
||||
Value<float> unknown1;
|
||||
Value<float> unknown2;
|
||||
Value<float> unknown3;
|
||||
Value<float> unknown4;
|
||||
Value<float> unknown5;
|
||||
Value<float> unknown6;
|
||||
Value<atUint32> unknown7;
|
||||
Value<float> AggressionCheck;
|
||||
Value<float> CoverCheck;
|
||||
Value<float> SearchRadius;
|
||||
Value<float> FallBackCheck;
|
||||
Value<float> FallBackRadius;
|
||||
Value<float> 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
|
||||
*/
|
||||
Value<atUint32> flags;
|
||||
Value<bool> unknown8;
|
||||
UniqueID32 wpsc1;
|
||||
DamageInfo damageInfo1;
|
||||
Value<atUint32> soundID1;
|
||||
DamageInfo damageInfo2;
|
||||
Value<float> unknown9;
|
||||
UniqueID32 wpsc2;
|
||||
DamageInfo damageInfo3;
|
||||
Value<float> unknown10;
|
||||
Value<atUint32> soundID2;
|
||||
Value<float> unknown11;
|
||||
Value<float> unknown12;
|
||||
Value<atUint32> soundID3;
|
||||
Value<float> unknown13;
|
||||
Value<atUint32> unknown14;
|
||||
Value<float> unknown15;
|
||||
Value<float> unknown16;
|
||||
Value<float> unknown17;
|
||||
Value<float> unknown18;
|
||||
Value<atUint32> soundID4;
|
||||
Value<atUint32> soundID5;
|
||||
UniqueID32 Projectile;
|
||||
DamageInfo ProjectileDamage;
|
||||
Value<atUint32> Sound_Projectile;
|
||||
DamageInfo BladeDamage;
|
||||
Value<float> KneelAttackChance;
|
||||
UniqueID32 KneelAttackShot;
|
||||
DamageInfo KneelAttackDamage;
|
||||
Value<float> DodgeCheck;
|
||||
Value<atUint32> Sound_Impact;
|
||||
Value<float> averageNextShotTime;
|
||||
Value<float> nextShotTimeVariation;
|
||||
Value<atUint32> Sound_Alert;
|
||||
Value<float> GunTrackDelay;
|
||||
Value<atUint32> firstBurstCount;
|
||||
Value<float> CloakOpacity;
|
||||
Value<float> MaxCloakOpacity;
|
||||
Value<float> dodgeDelayTimeMin;
|
||||
Value<float> dodgeDelayTimeMax;
|
||||
Value<atUint32> Sound_Hurled;
|
||||
Value<atUint32> Sound_Death;
|
||||
Value<float> unknown19;
|
||||
Value<float> unknown20;
|
||||
Value<float> AvoidDistance;
|
||||
|
||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const {
|
||||
actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters);
|
||||
}
|
||||
|
||||
void nameIDs(PAKRouter<PAKBridge>& pakRouter) const {
|
||||
if (wpsc1) {
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1);
|
||||
ent->name = name + "_wpsc1";
|
||||
if (Projectile) {
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(Projectile);
|
||||
ent->name = name + "_Projectile";
|
||||
}
|
||||
if (wpsc2) {
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2);
|
||||
ent->name = name + "_wpsc2";
|
||||
if (KneelAttackShot) {
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(KneelAttackShot);
|
||||
ent->name = name + "_KneelAttackShot";
|
||||
}
|
||||
patternedInfo.nameIDs(pakRouter, name + "_patterned");
|
||||
actorParameters.nameIDs(pakRouter, name + "_actp");
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, std::vector<hecl::ProjectPath>& lazyOut) const {
|
||||
g_curSpec->flattenDependencies(wpsc1, pathsOut);
|
||||
g_curSpec->flattenDependencies(wpsc2, pathsOut);
|
||||
g_curSpec->flattenDependencies(Projectile, pathsOut);
|
||||
g_curSpec->flattenDependencies(KneelAttackShot, pathsOut);
|
||||
patternedInfo.depIDs(pathsOut);
|
||||
actorParameters.depIDs(pathsOut, lazyOut);
|
||||
}
|
||||
|
|
|
@ -11,20 +11,20 @@ class CRandom16 {
|
|||
public:
|
||||
CRandom16(u32 p = 99) : m_seed(p) {}
|
||||
|
||||
inline u32 Next() {
|
||||
u32 Next() {
|
||||
m_seed = (m_seed * 0x41c64e6d) + 0x00003039;
|
||||
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 void SetRandomNumber(CRandom16* rnd) { g_randomNumber = rnd; }
|
||||
|
|
|
@ -2281,6 +2281,14 @@ CRayCastResult CStateManager::RayWorldIntersection(TUniqueId& idOut, const zeus:
|
|||
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) {
|
||||
for (auto& list : x808_objLists) {
|
||||
if (list->GetValidObjectById(ent.GetUniqueId()))
|
||||
|
|
|
@ -363,6 +363,7 @@ public:
|
|||
|
||||
const std::shared_ptr<CPlayerState>& GetPlayerState() const { return x8b8_playerState; }
|
||||
CRandom16* GetActiveRandom() { return x900_activeRandom; }
|
||||
zeus::CVector3f Random2f(float scaleMin, float scaleMax);
|
||||
void SetActiveRandomToDefault() { x900_activeRandom = &x8fc_random; }
|
||||
void ClearActiveRandom() { x900_activeRandom = nullptr; }
|
||||
CRumbleManager& GetRumbleManager() { return *x88c_rumbleManager; }
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace urde {
|
|||
CBodyStateCmdMgr::CBodyStateCmdMgr() {
|
||||
x40_commandTable.push_back(&xb8_getup);
|
||||
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(&xf4_knockBack);
|
||||
x40_commandTable.push_back(&x10c_meleeAttack);
|
||||
|
@ -14,10 +14,10 @@ CBodyStateCmdMgr::CBodyStateCmdMgr() {
|
|||
x40_commandTable.push_back(&x144_loopAttack);
|
||||
x40_commandTable.push_back(&x154_loopReaction);
|
||||
x40_commandTable.push_back(&x160_loopHitReaction);
|
||||
x40_commandTable.push_back(&x16c_);
|
||||
x40_commandTable.push_back(&x174_);
|
||||
x40_commandTable.push_back(&x17c_);
|
||||
x40_commandTable.push_back(&x184_);
|
||||
x40_commandTable.push_back(&x16c_exitState);
|
||||
x40_commandTable.push_back(&x174_leanFromCover);
|
||||
x40_commandTable.push_back(&x17c_nextState);
|
||||
x40_commandTable.push_back(&x184_maintainVelocity);
|
||||
x40_commandTable.push_back(&x18c_generate);
|
||||
x40_commandTable.push_back(&x1ac_hurled);
|
||||
x40_commandTable.push_back(&x1d0_jump);
|
||||
|
@ -26,12 +26,12 @@ CBodyStateCmdMgr::CBodyStateCmdMgr() {
|
|||
x40_commandTable.push_back(&x21c_scripted);
|
||||
x40_commandTable.push_back(&x230_cover);
|
||||
x40_commandTable.push_back(&x254_wallHang);
|
||||
x40_commandTable.push_back(&x260_);
|
||||
x40_commandTable.push_back(&x268_);
|
||||
x40_commandTable.push_back(&x260_locomotion);
|
||||
x40_commandTable.push_back(&x268_additiveIdle);
|
||||
x40_commandTable.push_back(&x270_additiveAim);
|
||||
x40_commandTable.push_back(&x278_additiveFlinch);
|
||||
x40_commandTable.push_back(&x284_additiveReaction);
|
||||
x40_commandTable.push_back(&x298_);
|
||||
x40_commandTable.push_back(&x298_stopReaction);
|
||||
}
|
||||
|
||||
void CBodyStateCmdMgr::DeliverCmd(const CBCLocomotionCmd& cmd) {
|
||||
|
|
|
@ -315,7 +315,7 @@ class CBodyStateCmdMgr {
|
|||
u32 xb4_deliveredCmdMask = 0;
|
||||
CBCGetupCmd xb8_getup;
|
||||
CBCStepCmd xc4_step;
|
||||
CBodyStateCmd xd4_ = {EBodyStateCmd::Die};
|
||||
CBodyStateCmd xd4_die = {EBodyStateCmd::Die};
|
||||
CBCKnockDownCmd xdc_knockDown;
|
||||
CBCKnockBackCmd xf4_knockBack;
|
||||
CBCMeleeAttackCmd x10c_meleeAttack;
|
||||
|
@ -323,10 +323,10 @@ class CBodyStateCmdMgr {
|
|||
CBCLoopAttackCmd x144_loopAttack;
|
||||
CBCLoopReactionCmd x154_loopReaction;
|
||||
CBCLoopHitReactionCmd x160_loopHitReaction;
|
||||
CBodyStateCmd x16c_ = {EBodyStateCmd::ExitState};
|
||||
CBodyStateCmd x174_ = {EBodyStateCmd::LeanFromCover};
|
||||
CBodyStateCmd x17c_ = {EBodyStateCmd::NextState};
|
||||
CBodyStateCmd x184_ = {EBodyStateCmd::MaintainVelocity};
|
||||
CBodyStateCmd x16c_exitState = {EBodyStateCmd::ExitState};
|
||||
CBodyStateCmd x174_leanFromCover = {EBodyStateCmd::LeanFromCover};
|
||||
CBodyStateCmd x17c_nextState = {EBodyStateCmd::NextState};
|
||||
CBodyStateCmd x184_maintainVelocity = {EBodyStateCmd::MaintainVelocity};
|
||||
CBCGenerateCmd x18c_generate;
|
||||
CBCHurledCmd x1ac_hurled;
|
||||
CBCJumpCmd x1d0_jump;
|
||||
|
@ -335,12 +335,12 @@ class CBodyStateCmdMgr {
|
|||
CBCScriptedCmd x21c_scripted;
|
||||
CBCCoverCmd x230_cover;
|
||||
CBCWallHangCmd x254_wallHang;
|
||||
CBodyStateCmd x260_ = {EBodyStateCmd::Locomotion};
|
||||
CBodyStateCmd x268_ = {EBodyStateCmd::AdditiveIdle};
|
||||
CBodyStateCmd x260_locomotion = {EBodyStateCmd::Locomotion};
|
||||
CBodyStateCmd x268_additiveIdle = {EBodyStateCmd::AdditiveIdle};
|
||||
CBCAdditiveAimCmd x270_additiveAim;
|
||||
CBCAdditiveFlinchCmd x278_additiveFlinch;
|
||||
CBCAdditiveReactionCmd x284_additiveReaction;
|
||||
CBodyStateCmd x298_ = {EBodyStateCmd::StopReaction};
|
||||
CBodyStateCmd x298_stopReaction = {EBodyStateCmd::StopReaction};
|
||||
void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); }
|
||||
|
||||
public:
|
||||
|
|
|
@ -9,16 +9,15 @@
|
|||
|
||||
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))
|
||||
, x1c_(f1)
|
||||
, x20_(f2)
|
||||
, x36_24_active(false)
|
||||
, x36_25_(false)
|
||||
, x36_26_(b1)
|
||||
, x36_27_(b1)
|
||||
, x36_28_(b1)
|
||||
, x36_29_(b1) {}
|
||||
, x1c_maxTrackingAngle(maxTrackingAngle)
|
||||
, x20_angSpeed(angSpeed)
|
||||
, x36_26_noParent(parentIk)
|
||||
, x36_27_noParentOrigin(parentIk)
|
||||
, x36_28_noHorizontalAim(parentIk)
|
||||
, x36_29_parentIk(parentIk) {}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf,
|
||||
const zeus::CVector3f& vec, bool b) {
|
||||
void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& worldXf,
|
||||
const zeus::CVector3f& localOffsetScale, bool tracking) {
|
||||
if (x14_segId == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -42,5 +101,9 @@ void CBoneTracking::SetActive(bool) { x36_24_active = true; }
|
|||
|
||||
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::SetNoHorizontalAim(bool b) { x36_28_noHorizontalAim = b; }
|
||||
} // namespace urde
|
|
@ -12,28 +12,38 @@ class CAnimData;
|
|||
class CStateManager;
|
||||
class CBodyController;
|
||||
class CBoneTracking {
|
||||
zeus::CQuaternion x0_ = zeus::CQuaternion::skNoRotation;
|
||||
zeus::CQuaternion x0_curRotation = zeus::CQuaternion::skNoRotation;
|
||||
float x10_ = 0.f;
|
||||
CSegId x14_segId;
|
||||
float x18_time = 0.f;
|
||||
float x1c_;
|
||||
float x20_;
|
||||
float x1c_maxTrackingAngle;
|
||||
float x20_angSpeed;
|
||||
std::experimental::optional<zeus::CVector3f> x24_targetPosition;
|
||||
TUniqueId x34_target = kInvalidUniqueId;
|
||||
union {
|
||||
struct {
|
||||
bool x36_24_active : 1;
|
||||
bool x36_25_ : 1;
|
||||
bool x36_26_ : 1;
|
||||
bool x36_27_ : 1;
|
||||
bool x36_28_ : 1;
|
||||
bool x36_29_ : 1;
|
||||
bool x36_25_hasTrackedRotation : 1;
|
||||
bool x36_26_noParent : 1;
|
||||
bool x36_27_noParentOrigin : 1;
|
||||
bool x36_28_noHorizontalAim : 1;
|
||||
bool x36_29_parentIk : 1;
|
||||
};
|
||||
u32 _dummy = 0;
|
||||
};
|
||||
|
||||
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 PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&,
|
||||
const CBodyController&);
|
||||
void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, bool);
|
||||
void SetActive(bool);
|
||||
void SetTarget(TUniqueId);
|
||||
void SetTargetPosition(const zeus::CVector3f&);
|
||||
void PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf,
|
||||
const zeus::CVector3f& vec, const CBodyController& bodyController);
|
||||
void PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& worldXf,
|
||||
const zeus::CVector3f& localOffsetScale, bool tracking);
|
||||
void SetActive(bool b);
|
||||
void SetTarget(TUniqueId id);
|
||||
void UnsetTarget();
|
||||
void SetTargetPosition(const zeus::CVector3f& pos);
|
||||
void SetNoHorizontalAim(bool b);
|
||||
};
|
||||
} // namespace urde
|
|
@ -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 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 };
|
||||
|
||||
|
@ -90,7 +90,7 @@ enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four };
|
|||
|
||||
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 };
|
||||
|
||||
|
|
|
@ -143,12 +143,12 @@ void CEyeball::Cover(CStateManager&, EStateMsg msg, float) {
|
|||
|
||||
void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg) {
|
||||
if (msg == EStateMsg::Activate) {
|
||||
x32c_animState = EAnimState::One;
|
||||
x32c_animState = EAnimState::Ready;
|
||||
x330_stateMachineState.SetDelay(x568_attackDelay);
|
||||
} else if (msg == EStateMsg::Update)
|
||||
TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0);
|
||||
else if (msg == EStateMsg::Deactivate)
|
||||
x32c_animState = EAnimState::Zero;
|
||||
x32c_animState = EAnimState::NotReady;
|
||||
}
|
||||
|
||||
void CEyeball::TryFlinch(CStateManager&, int arg) {
|
||||
|
|
|
@ -25,11 +25,18 @@ public:
|
|||
};
|
||||
|
||||
class CMetroid : public CPatterned {
|
||||
union {
|
||||
struct {
|
||||
bool x9bf_29_ : 1;
|
||||
};
|
||||
u32 _dummy = 0;
|
||||
};
|
||||
public:
|
||||
DEFINE_PATTERNED(Metroid)
|
||||
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 CMetroidData& metroidData);
|
||||
bool GetX9BF_29() const { return x9bf_29_; }
|
||||
};
|
||||
|
||||
} // namespace urde::MP1
|
||||
|
|
|
@ -554,7 +554,7 @@ void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float) {
|
|||
switch (msg) {
|
||||
case EStateMsg::Activate:
|
||||
x330_stateMachineState.SetDelay(x710_haltDelay);
|
||||
x32c_animState = EAnimState::One;
|
||||
x32c_animState = EAnimState::Ready;
|
||||
x743_24_halted = true;
|
||||
x5d6_24_alignToFloor = true;
|
||||
if (x5d0_walkerType == EWalkerType::Geemer)
|
||||
|
@ -567,7 +567,7 @@ void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float) {
|
|||
break;
|
||||
case EStateMsg::Deactivate:
|
||||
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
|
||||
x32c_animState = EAnimState::Zero;
|
||||
x32c_animState = EAnimState::NotReady;
|
||||
x743_24_halted = false;
|
||||
x5d6_24_alignToFloor = false;
|
||||
break;
|
||||
|
|
|
@ -179,18 +179,18 @@ void CSeedling::Enraged(CStateManager&, EStateMsg msg, float) {
|
|||
|
||||
void CSeedling::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) {
|
||||
if (msg == EStateMsg::Activate)
|
||||
x32c_animState = EAnimState::One;
|
||||
x32c_animState = EAnimState::Ready;
|
||||
else if (msg == EStateMsg::Update)
|
||||
TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0);
|
||||
else if (msg == EStateMsg::Deactivate) {
|
||||
x32c_animState = EAnimState::Zero;
|
||||
x32c_animState = EAnimState::NotReady;
|
||||
x71c_attackCoolOff = (x300_maxAttackRange * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime;
|
||||
}
|
||||
}
|
||||
|
||||
void CSeedling::Generate(CStateManager& mgr, EStateMsg msg, float) {
|
||||
if (msg == EStateMsg::Activate)
|
||||
x32c_animState = EAnimState::One;
|
||||
x32c_animState = EAnimState::Ready;
|
||||
else if (msg == EStateMsg::Update)
|
||||
TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,40 +32,58 @@ public:
|
|||
|
||||
class CSpacePirate : public CPatterned {
|
||||
friend class CPirateRagDoll;
|
||||
|
||||
public:
|
||||
DEFINE_PATTERNED(SpacePirate)
|
||||
private:
|
||||
class CSpacePirateData {
|
||||
friend class CSpacePirate;
|
||||
float x0_;
|
||||
float x4_;
|
||||
float x8_;
|
||||
float xc_;
|
||||
float x10_;
|
||||
float x14_hearNoiseRange;
|
||||
float x0_AggressionCheck;
|
||||
float x4_CoverCheck;
|
||||
float x8_SearchRadius;
|
||||
float xc_FallBackCheck;
|
||||
float x10_FallBackRadius;
|
||||
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;
|
||||
bool x1c_;
|
||||
CProjectileInfo x20_mainProjectileInfo;
|
||||
u16 x48_;
|
||||
CDamageInfo x4c_;
|
||||
float x68_;
|
||||
CProjectileInfo x6c_;
|
||||
float x94_;
|
||||
u16 x98_ragdollThudSfx;
|
||||
CProjectileInfo x20_Projectile;
|
||||
u16 x48_Sound_Projectile;
|
||||
CDamageInfo x4c_BladeDamage;
|
||||
float x68_KneelAttackChance;
|
||||
CProjectileInfo x6c_KneelAttackShot;
|
||||
float x94_DodgeCheck;
|
||||
u16 x98_Sound_Impact;
|
||||
float x9c_averageNextShotTime;
|
||||
float xa0_nextShotTimeVariation;
|
||||
u16 xa4_;
|
||||
float xa8_aimDelayTime;
|
||||
u16 xa4_Sound_Alert;
|
||||
float xa8_GunTrackDelay;
|
||||
u32 xac_firstBurstCount;
|
||||
float xb0_minCloakAlpha;
|
||||
float xb4_maxCloakAlpha;
|
||||
float xb8_;
|
||||
float xbc_;
|
||||
u16 xc0_;
|
||||
u16 xc2_;
|
||||
float xb0_CloakOpacity;
|
||||
float xb4_MaxCloakOpacity;
|
||||
float xb8_dodgeDelayTimeMin;
|
||||
float xbc_dodgeDelayTimeMax;
|
||||
u16 xc0_Sound_Hurled;
|
||||
u16 xc2_Sound_Death;
|
||||
float xc4_;
|
||||
float xc8_;
|
||||
float xc8_AvoidDistance;
|
||||
|
||||
public:
|
||||
CSpacePirateData(CInputStream&, u32);
|
||||
|
@ -76,94 +94,94 @@ private:
|
|||
struct {
|
||||
bool x634_24_pendingAmbush : 1;
|
||||
bool x634_25_ceilingAmbush : 1;
|
||||
bool x634_26_ : 1;
|
||||
bool x634_26_nonAggressive : 1;
|
||||
bool x634_27_melee : 1;
|
||||
bool x634_28_ : 1;
|
||||
bool x634_28_noShuffleCloseCheck : 1;
|
||||
bool x634_29_onlyAttackInRange : 1;
|
||||
bool x634_30_ : 1;
|
||||
bool x634_31_ : 1;
|
||||
bool x635_24_ : 1;
|
||||
bool x635_25_ : 1;
|
||||
bool x635_26_ : 1;
|
||||
bool x634_31_noKnockbackImpulseReset : 1;
|
||||
bool x635_24_noMeleeAttack : 1;
|
||||
bool x635_25_breakAttack : 1;
|
||||
bool x635_26_seated : 1;
|
||||
bool x635_27_shadowPirate : 1;
|
||||
bool x635_28_ : 1;
|
||||
bool x635_29_ : 1;
|
||||
bool x635_28_alertBeforeCloak : 1;
|
||||
bool x635_29_noBreakDodge : 1;
|
||||
bool x635_30_floatingCorpse : 1;
|
||||
bool x635_31_ragdollNoAiCollision : 1;
|
||||
bool x636_24_trooper : 1;
|
||||
bool x636_25_hearNoise : 1;
|
||||
bool x636_26_ : 1;
|
||||
bool x636_26_enableMeleeAttack : 1;
|
||||
bool x636_27_ : 1;
|
||||
bool x636_28_ : 1;
|
||||
bool x636_29_ : 1;
|
||||
bool x636_30_ : 1;
|
||||
bool x636_31_ : 1;
|
||||
bool x637_24_ : 1;
|
||||
bool x637_25_ : 1;
|
||||
bool x636_29_enableRetreat : 1;
|
||||
bool x636_30_shuffleClose : 1;
|
||||
bool x636_31_inAttackState : 1;
|
||||
bool x637_24_enablePatrol : 1;
|
||||
bool x637_25_enableAim : 1;
|
||||
bool x637_26_hearPlayerFire : 1;
|
||||
bool x637_27_inProjectilePath : 1;
|
||||
bool x637_28_ : 1;
|
||||
bool x637_29_ : 1;
|
||||
bool x637_30_ : 1;
|
||||
bool x637_28_noPlayerLos : 1;
|
||||
bool x637_29_inWallHang : 1;
|
||||
bool x637_30_jumpVelSet : 1;
|
||||
bool x637_31_prevInCineCam : 1;
|
||||
bool x638_24_pendingFrenzyChance : 1;
|
||||
bool x638_25_ : 1;
|
||||
bool x638_26_ : 1;
|
||||
bool x638_27_ : 1;
|
||||
bool x638_28_ : 1;
|
||||
bool x638_29_ : 1;
|
||||
bool x638_25_appliedBladeDamage : 1;
|
||||
bool x638_26_alwaysAggressive : 1;
|
||||
bool x638_27_coverCheck : 1;
|
||||
bool x638_28_enableDodge : 1;
|
||||
bool x638_29_noPlayerDodge : 1;
|
||||
bool x638_30_ragdollOver : 1;
|
||||
bool x638_31_ : 1;
|
||||
bool x638_31_mayStartAttack : 1;
|
||||
bool x639_24_ : 1;
|
||||
bool x639_25_ : 1;
|
||||
bool x639_25_useJumpBackJump : 1;
|
||||
bool x639_26_started : 1;
|
||||
bool x639_27_ : 1;
|
||||
bool x639_28_ : 1;
|
||||
bool x639_29_ : 1;
|
||||
bool x639_30_ : 1;
|
||||
bool x639_31_ : 1;
|
||||
bool x63a_24_ : 1;
|
||||
bool x639_27_inRange : 1;
|
||||
bool x639_28_satUp : 1;
|
||||
bool x639_29_enableBreakDodge : 1;
|
||||
bool x639_30_closeMelee : 1;
|
||||
bool x639_31_sentAttackMsg : 1;
|
||||
bool x63a_24_normalDodge : 1;
|
||||
};
|
||||
|
||||
u64 _dummy = 0;
|
||||
};
|
||||
|
||||
s32 x63c_frenzyFrames = 0;
|
||||
TUniqueId x640_ = kInvalidUniqueId;
|
||||
TUniqueId x642_ = kInvalidUniqueId;
|
||||
float x644_ = 1.f;
|
||||
zeus::CVector3f x648_ = zeus::CVector3f::skForward;
|
||||
zeus::CVector3f x654_;
|
||||
TUniqueId x640_coverPoint = kInvalidUniqueId;
|
||||
TUniqueId x642_previousCoverPoint = kInvalidUniqueId;
|
||||
float x644_steeringSpeed = 1.f;
|
||||
zeus::CVector3f x648_targetDelta = zeus::CVector3f::skForward;
|
||||
zeus::CVector3f x654_coverPointRearDir;
|
||||
CPathFindSearch x660_pathFindSearch;
|
||||
float x744_ = 0.f;
|
||||
float x748_ = 0.f;
|
||||
float x744_unkTimer = 0.f;
|
||||
float x748_steeringDelayTimer = 0.f;
|
||||
u32 x74c_ = 0;
|
||||
float x750_initialHP;
|
||||
float x754_ = 0.f;
|
||||
float x754_fsmRange = 0.f;
|
||||
CSegId x758_headSeg;
|
||||
u32 x75c_ = 0;
|
||||
s32 x760_ = -1;
|
||||
pas::ETauntType x760_taunt = pas::ETauntType::Invalid;
|
||||
CBoneTracking x764_boneTracking;
|
||||
s32 x79c_ = -1;
|
||||
pas::ECoverDirection x79c_coverDir = pas::ECoverDirection::Invalid;
|
||||
float x7a4_intoJumpDist = 1.f;
|
||||
float x7a8_ = 2.f;
|
||||
float x7ac_ = 0.f;
|
||||
u32 x7b0_ = 0;
|
||||
TUniqueId x7b4_ = kInvalidUniqueId;
|
||||
float x7a8_eyeHeight = 2.f;
|
||||
float x7ac_timeNoPlayerLos = 0.f;
|
||||
u32 x7b0_cantSeePlayerCycleCounter = 0;
|
||||
TUniqueId x7b4_attachedActor = kInvalidUniqueId;
|
||||
CSegId x7b6_gunSeg;
|
||||
CSegId x7b7_elbowSeg;
|
||||
CSegId x7b8_wristSeg;
|
||||
CSegId x7b9_swooshSeg;
|
||||
float x7bc_ = 1.f;
|
||||
float x7bc_attackRemTime = 1.f;
|
||||
TUniqueId x7c0_targetId = kInvalidUniqueId;
|
||||
CBurstFire x7c4_burstFire;
|
||||
float x824_ = 3.f;
|
||||
zeus::CVector3f x828_;
|
||||
s32 x834_ = -1;
|
||||
float x838_ = 0.f;
|
||||
s32 x83c_ = -1;
|
||||
TUniqueId x840_ = kInvalidUniqueId;
|
||||
s32 x844_ = -1;
|
||||
float x824_jumpHeight = 3.f;
|
||||
zeus::CVector3f x828_patrolDestPos;
|
||||
pas::EStepDirection x834_skidDir = pas::EStepDirection::Invalid;
|
||||
float x838_strafeDelayTimer = 0.f;
|
||||
pas::ESeverity x83c_meleeSeverity = pas::ESeverity::Invalid;
|
||||
TUniqueId x840_jumpPoint = kInvalidUniqueId;
|
||||
pas::EStepDirection x844_dodgeDir = pas::EStepDirection::Invalid;
|
||||
float x848_dodgeDist = 3.f;
|
||||
float x84c_breakDodgeDist = 3.f;
|
||||
float x850_timeSinceHitByPlayer = FLT_MAX;
|
||||
|
@ -177,13 +195,13 @@ private:
|
|||
float x8b4_shadowPirateAlpha = 0.5f;
|
||||
float x8b8_minCloakAlpha;
|
||||
float x8bc_maxCloakAlpha;
|
||||
float x8c0_;
|
||||
float x8c0_dodgeDelayTimer;
|
||||
float x8c4_aimDelayTimer;
|
||||
TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId;
|
||||
zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite;
|
||||
zeus::CVector2f x8d0_;
|
||||
float x8d8_ = 0.f;
|
||||
float x8dc_ = 0.f;
|
||||
zeus::CVector2f x8d0_heldPosition;
|
||||
float x8d8_holdPositionTime = 0.f;
|
||||
float x8dc_leashTimer = 0.f;
|
||||
|
||||
static const SBurst skBurstsSeatedOOV[];
|
||||
static const SBurst skBurstsInjuredOOV[];
|
||||
|
@ -207,7 +225,7 @@ private:
|
|||
void AssignTeamAiRole(CStateManager& mgr);
|
||||
void RemoveTeamAiRole(CStateManager& mgr);
|
||||
bool CheckTargetable(CStateManager& mgr);
|
||||
void FireProjectile(float dt, CStateManager& mgr);
|
||||
bool FireProjectile(float dt, CStateManager& mgr);
|
||||
void UpdateAttacks(float dt, CStateManager& mgr);
|
||||
zeus::CVector3f GetTargetPos(CStateManager& mgr);
|
||||
void UpdateAimBodyState(float dt, CStateManager& mgr);
|
||||
|
@ -216,6 +234,15 @@ private:
|
|||
void CheckForProjectiles(CStateManager& mgr);
|
||||
void SetEyeParticleActive(CStateManager& mgr, bool active);
|
||||
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:
|
||||
CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
|
||||
|
@ -237,10 +264,13 @@ public:
|
|||
bool IsListening() const;
|
||||
bool Listen(const zeus::CVector3f&, EListenNoiseType);
|
||||
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 Dead(CStateManager&, EStateMsg, float);
|
||||
void PathFind(CStateManager&, EStateMsg, float);
|
||||
void PathFind(CStateManager& mgr, EStateMsg msg, float dt);
|
||||
void TargetPatrol(CStateManager&, EStateMsg, float);
|
||||
void TargetCover(CStateManager&, EStateMsg, float);
|
||||
void Halt(CStateManager&, EStateMsg, float);
|
||||
|
@ -279,7 +309,7 @@ public:
|
|||
bool PatternShagged(CStateManager&, float);
|
||||
bool AnimOver(CStateManager&, float);
|
||||
bool ShouldAttack(CStateManager&, float);
|
||||
bool ShouldJumpBack(CStateManager&, float);
|
||||
bool ShouldJumpBack(CStateManager& mgr, float arg);
|
||||
bool Stuck(CStateManager&, float);
|
||||
bool Landed(CStateManager&, float);
|
||||
bool HearShot(CStateManager&, float);
|
||||
|
@ -300,10 +330,10 @@ public:
|
|||
bool ShouldWallHang(CStateManager&, float);
|
||||
bool StartAttack(CStateManager&, float);
|
||||
bool BreakAttack(CStateManager&, float);
|
||||
bool ShouldStrafe(CStateManager&, float);
|
||||
bool ShouldStrafe(CStateManager& mgr, float arg);
|
||||
bool ShouldSpecialAttack(CStateManager&, float);
|
||||
bool LostInterest(CStateManager&, float);
|
||||
bool BounceFind(CStateManager&, float);
|
||||
bool BounceFind(CStateManager& mgr, float arg);
|
||||
|
||||
CPathFindSearch* GetSearchPath();
|
||||
u8 GetModelAlphau8(const CStateManager& mgr) const;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "CProjectileInfo.hpp"
|
||||
#include "World/CDamageInfo.hpp"
|
||||
#include "GameGlobalObjects.hpp"
|
||||
#include "CProjectileWeapon.hpp"
|
||||
#include "World/CPlayer.hpp"
|
||||
#include "Character/CSteeringBehaviors.hpp"
|
||||
#include "CSimplePool.hpp"
|
||||
|
||||
namespace urde {
|
||||
|
@ -11,9 +14,56 @@ CProjectileInfo::CProjectileInfo(urde::CInputStream& in)
|
|||
CProjectileInfo::CProjectileInfo(CAssetId proj, const CDamageInfo& dInfo)
|
||||
: x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), proj})), xc_damageInfo(dInfo) {}
|
||||
|
||||
zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f&, const zeus::CVector3f&, const CPlayer&,
|
||||
bool) {
|
||||
return {};
|
||||
zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f& gunPos, const zeus::CVector3f& aimPos,
|
||||
const CPlayer& player, bool gravity, float speed, float dt) {
|
||||
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
|
||||
|
|
|
@ -15,7 +15,11 @@ public:
|
|||
CProjectileInfo(CInputStream&);
|
||||
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; }
|
||||
const TToken<CWeaponDescription>& Token() { return x0_weaponDescription; }
|
||||
|
|
|
@ -96,5 +96,6 @@ public:
|
|||
static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; }
|
||||
CElementGen* GetAttachedPS1() const { return xfc_APSMGen.get(); }
|
||||
double GameTime() const { return xd0_curTime; }
|
||||
static float GetTickPeriod() { return 0.0166667f; }
|
||||
};
|
||||
} // namespace urde
|
||||
|
|
|
@ -264,7 +264,7 @@ void CActor::Render(const CStateManager& mgr) const {
|
|||
}
|
||||
if (xe5_31_pointGeneratorParticles) {
|
||||
CSkinnedModel::ClearPointGeneratorFunc();
|
||||
mgr.GetActorModelParticles()->Render(*this);
|
||||
mgr.GetActorModelParticles()->Render(mgr, *this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -192,5 +192,6 @@ public:
|
|||
void SetPointGeneratorParticles(bool s) { xe5_31_pointGeneratorParticles = s; }
|
||||
CSimpleShadow* Shadow() { return x94_simpleShadow.get(); }
|
||||
void MoveScannableObjectInfoToActor(CActor*, CStateManager&);
|
||||
const zeus::CAABox& GetRenderBounds() const { return x9c_renderBounds; }
|
||||
};
|
||||
} // namespace urde
|
||||
|
|
|
@ -22,124 +22,114 @@ static bool IsMediumOrLarge(CActor& act) {
|
|||
|
||||
CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& 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;
|
||||
u32 ret;
|
||||
float lastMag = 0.f;
|
||||
s32 ret = start;
|
||||
float maxMag = 0.f;
|
||||
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;
|
||||
float mag = (startVec - rndVec).magSquared();
|
||||
if (mag > lastMag) {
|
||||
if (mag > maxMag) {
|
||||
ret = idx;
|
||||
lastMag = mag;
|
||||
maxMag = mag;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
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) {
|
||||
CRandom16 rnd(pair.second);
|
||||
const zeus::CVector3f& vec = vn[u32(rnd.Float() * (vn.size() - 1))].first;
|
||||
pair.first->SetTranslation(xec_ * vec);
|
||||
const zeus::CVector3f& vec = vn[rnd.Float() * (vn.size() - 1)].first;
|
||||
pair.first->SetTranslation(xec_particleOffsetScale * vec);
|
||||
}
|
||||
}
|
||||
|
||||
if (x84_ > 0) {
|
||||
CRandom16 rnd(x88_seed1);
|
||||
u32 count = (x84_ >= 16 ? 16 : x84_);
|
||||
u32 idx = x80_;
|
||||
if (x84_ashMaxParticles > 0) {
|
||||
CRandom16 rnd(x88_ashSeed);
|
||||
s32 count = (x84_ashMaxParticles >= 16 ? 16 : x84_ashMaxParticles);
|
||||
s32 idx = x80_ashPointIterator;
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
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;
|
||||
if (v.canBeNormalized()) {
|
||||
v.normalize();
|
||||
x78_->SetOrientation(
|
||||
zeus::CTransform{zeus::CVector3f::skUp.cross(v), v, zeus::CVector3f::skUp, zeus::CVector3f::skZero});
|
||||
x78_ashGen->SetOrientation(
|
||||
zeus::CTransform{v.cross(zeus::CVector3f::skUp), v, zeus::CVector3f::skUp, zeus::CVector3f::skZero});
|
||||
}
|
||||
x78_->ForceParticleCreation(1);
|
||||
x78_ashGen->ForceParticleCreation(1);
|
||||
}
|
||||
x84_ -= count;
|
||||
x88_seed1 = rnd.GetSeed();
|
||||
x84_ashMaxParticles -= count;
|
||||
x88_ashSeed = rnd.GetSeed();
|
||||
x80_ashPointIterator = idx;
|
||||
}
|
||||
|
||||
if (xb0_ != -1) {
|
||||
CRandom16 rnd(xb4_seed2);
|
||||
if (xb0_icePointIterator != -1) {
|
||||
CRandom16 rnd(xb4_iceSeed);
|
||||
|
||||
std::unique_ptr<CElementGen> iceGen = x128_parent.MakeIceGen();
|
||||
iceGen->SetGlobalOrientAndTrans(xf8_);
|
||||
iceGen->SetGlobalOrientAndTrans(xf8_iceXf);
|
||||
|
||||
u32 next = GetNextBestPt(xb0_, vn, rnd);
|
||||
iceGen->SetTranslation(xec_ * vn[next].first);
|
||||
s32 idx = GetNextBestPt(xb0_icePointIterator, vn, rnd);
|
||||
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));
|
||||
xb0_ = (x8c_thermalColdParticles.size() == 4 ? -1 : next);
|
||||
x8c_iceGens.push_back(std::move(iceGen));
|
||||
xb0_icePointIterator = (x8c_iceGens.size() == 4 ? -1 : idx);
|
||||
}
|
||||
// TODO: Verify behavior
|
||||
if (xc0_particleElectric && xc0_particleElectric->GetParticleEmission()) {
|
||||
CRandom16 rnd(xcc_seed3);
|
||||
|
||||
if (xc0_electricGen && xc0_electricGen->GetParticleEmission()) {
|
||||
CRandom16 rnd(xcc_electricSeed);
|
||||
u32 end = 1;
|
||||
#if 0
|
||||
if (4 < 1)
|
||||
end = 4;
|
||||
#endif
|
||||
u32 lastRnd;
|
||||
s32 idx = xc8_electricPointIterator;
|
||||
for (u32 i = 0; i < end; ++i) {
|
||||
xc0_particleElectric->SetOverrideIPos(vn[u32(rnd.Range(0, s32(vn.size()) - 1))].first * xec_);
|
||||
lastRnd = u32(rnd.Range(0, s32(vn.size()) - 1));
|
||||
xc0_particleElectric->SetOverrideFPos(vn[lastRnd].first * xec_);
|
||||
xc0_particleElectric->ForceParticleCreation(1);
|
||||
xc0_electricGen->SetOverrideIPos(vn[rnd.Range(0, s32(vn.size()) - 1)].first * xec_particleOffsetScale);
|
||||
idx = rnd.Range(0, s32(vn.size()) - 1);
|
||||
xc0_electricGen->SetOverrideFPos(vn[idx].first * xec_particleOffsetScale);
|
||||
xc0_electricGen->ForceParticleCreation(1);
|
||||
}
|
||||
|
||||
xcc_seed3 = rnd.GetSeed();
|
||||
xc8_ = lastRnd;
|
||||
xcc_electricSeed = rnd.GetSeed();
|
||||
xc8_electricPointIterator = idx;
|
||||
}
|
||||
|
||||
// TODO: Finish
|
||||
#if 0
|
||||
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));
|
||||
}
|
||||
if (xd4_rainSplashGen)
|
||||
xd4_rainSplashGen->GeneratePoints(vn);
|
||||
}
|
||||
|
||||
bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateManager& mgr) {
|
||||
bool r30 = false;
|
||||
bool r31 = false;
|
||||
bool effectActive = false;
|
||||
bool sfxActive = false;
|
||||
x6c_onFireDelayTimer -= dt;
|
||||
if (x6c_onFireDelayTimer < 0.f)
|
||||
x6c_onFireDelayTimer = 0.f;
|
||||
if (x134_lockDeps & 0x1) {
|
||||
if (x128_parent.xe6_bits2 & 0x1) {
|
||||
if (x128_parent.xe6_loadedDeps & 0x1) {
|
||||
if (x70_onFire && actor) {
|
||||
bool r26 = true;
|
||||
if (x78_ || xdc_ashy) {
|
||||
r26 = false;
|
||||
bool doCreate = true;
|
||||
if (x78_ashGen || xdc_ashy) {
|
||||
doCreate = false;
|
||||
} else if (!IsMediumOrLarge(*actor)) {
|
||||
int r3 = 0;
|
||||
for (const auto& p : x8_thermalHotParticles)
|
||||
int activeParts = 0;
|
||||
for (const auto& p : x8_onFireGens)
|
||||
if (p.first)
|
||||
++r3;
|
||||
if (r3 >= 4)
|
||||
r26 = false;
|
||||
++activeParts;
|
||||
if (activeParts >= 4)
|
||||
doCreate = false;
|
||||
}
|
||||
if (r26) {
|
||||
for (auto& p : x8_thermalHotParticles) {
|
||||
if (doCreate) {
|
||||
for (auto& p : x8_onFireGens) {
|
||||
if (!p.first) {
|
||||
p.second = mgr.GetActiveRandom()->Next();
|
||||
p.first = x128_parent.MakeOnFireGen();
|
||||
|
@ -154,83 +144,203 @@ bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateMa
|
|||
}
|
||||
x70_onFire = false;
|
||||
}
|
||||
for (auto& p : x8_thermalHotParticles) {
|
||||
for (auto& p : x8_onFireGens) {
|
||||
if (p.first) {
|
||||
if (p.first->IsSystemDeletable())
|
||||
p.first.reset();
|
||||
else if (actor)
|
||||
p.first->SetGlobalOrientAndTrans(actor->GetTransform());
|
||||
p.first->Update(dt);
|
||||
r30 = true;
|
||||
r31 = true;
|
||||
effectActive = true;
|
||||
sfxActive = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r30 = true;
|
||||
effectActive = true;
|
||||
}
|
||||
}
|
||||
if (x74_sfx) {
|
||||
if (r31) {
|
||||
CSfxManager::UpdateEmitter(x74_sfx, xf8_.origin, zeus::CVector3f::skZero, 1.f);
|
||||
if (sfxActive) {
|
||||
CSfxManager::UpdateEmitter(x74_sfx, xf8_iceXf.origin, zeus::CVector3f::skZero, 1.f);
|
||||
} else {
|
||||
CSfxManager::RemoveEmitter(x74_sfx);
|
||||
x74_sfx.reset();
|
||||
}
|
||||
}
|
||||
if (!r30) {
|
||||
if (!effectActive)
|
||||
Unlock(EDependency::OnFire);
|
||||
}
|
||||
return r30;
|
||||
return effectActive;
|
||||
}
|
||||
|
||||
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) {
|
||||
CActor* act = static_cast<CActor*>(mgr.ObjectById(x0_id));
|
||||
if (act && act->HasModelData() && !act->ModelData()->IsNull()) {
|
||||
xec_ = act->ModelData()->GetScale();
|
||||
xf8_ = act->GetTransform();
|
||||
xec_particleOffsetScale = act->ModelData()->GetScale();
|
||||
xf8_iceXf = act->GetTransform();
|
||||
x4_areaId = act->GetAreaIdAlways();
|
||||
} else {
|
||||
x0_id = kInvalidUniqueId;
|
||||
x84_ = 0;
|
||||
xb0_ = -1;
|
||||
if (xc0_particleElectric)
|
||||
xc0_particleElectric->SetParticleEmission(false);
|
||||
x84_ashMaxParticles = 0;
|
||||
xb0_icePointIterator = -1;
|
||||
if (xc0_electricGen)
|
||||
xc0_electricGen->SetParticleEmission(false);
|
||||
if (x74_sfx) {
|
||||
CSfxManager::RemoveEmitter(x74_sfx);
|
||||
x74_sfx.reset();
|
||||
}
|
||||
x130_ -= dt;
|
||||
if (x130_ <= 0.f)
|
||||
x130_remTime -= dt;
|
||||
if (x130_remTime <= 0.f)
|
||||
return false;
|
||||
}
|
||||
bool ret = false;
|
||||
if (UpdateOnFire(dt, act, mgr))
|
||||
ret = true;
|
||||
if (UpdateAsh(dt, act, mgr))
|
||||
if (UpdateAshGen(dt, act, mgr))
|
||||
ret = true;
|
||||
if (sub_801e65bc(dt, act, mgr))
|
||||
if (UpdateIceGen(dt, act, mgr))
|
||||
ret = true;
|
||||
if (UpdateFirePop(dt, act, mgr))
|
||||
ret = true;
|
||||
if (UpdateElectric(dt, act, mgr))
|
||||
ret = true;
|
||||
if (sub_801e69f0(dt, act, mgr))
|
||||
if (UpdateRainSplash(dt, act, mgr))
|
||||
ret = true;
|
||||
if (sub_801e5e98(dt, act, mgr))
|
||||
if (UpdateBurn(dt, act, mgr))
|
||||
ret = true;
|
||||
if (UpdateIcePop(dt, act, mgr))
|
||||
ret = true;
|
||||
|
@ -255,21 +365,21 @@ void CActorModelParticles::DecrementDependency(EDependency d) {
|
|||
Dependency& dep = x50_dgrps[int(d)];
|
||||
dep.Decrement();
|
||||
if (dep.x10_refCount == 0) {
|
||||
xe4_bits &= ~(1 << int(d));
|
||||
xe6_bits2 &= ~(1 << int(d));
|
||||
xe5_bits1 &= ~(1 << int(d));
|
||||
xe4_loadingDeps &= ~(1 << int(d));
|
||||
xe6_loadedDeps &= ~(1 << int(d));
|
||||
xe5_justLoadedDeps &= ~(1 << int(d));
|
||||
}
|
||||
}
|
||||
|
||||
void CActorModelParticles::IncrementDependency(EDependency d) {
|
||||
x50_dgrps[int(d)].Increment();
|
||||
if (!(xe6_bits2 & (1 << int(d))))
|
||||
xe4_bits |= (1 << int(d));
|
||||
if (!(xe6_loadedDeps & (1 << int(d))))
|
||||
xe4_loadingDeps |= (1 << int(d));
|
||||
}
|
||||
|
||||
static const char* ParticleDGRPs[] = {
|
||||
"Effect_OnFire_DGRP", "Effect_Ash_DGRP", "Effect_IceBreak_DGRP",
|
||||
"Effect_FirePop_DGRP", "Effect_IcePop_DGRP", "Effect_Electric_DGRP",
|
||||
"Effect_OnFire_DGRP", "Effect_IceBreak_DGRP", "Effect_Ash_DGRP",
|
||||
"Effect_FirePop_DGRP", "Effect_Electric_DGRP", "Effect_IcePop_DGRP",
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
return std::make_unique<CElementGen>(x28_iceBreak);
|
||||
|
@ -342,23 +454,23 @@ void CActorModelParticles::AddStragglersToRenderer(const CStateManager& mgr) {
|
|||
if (isNotCold) {
|
||||
/* Hot Draw */
|
||||
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)
|
||||
g_Renderer->AddParticleGen(*gen);
|
||||
}
|
||||
if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && item.x78_)
|
||||
g_Renderer->AddParticleGen(*item.x78_);
|
||||
if (item.xb8_)
|
||||
g_Renderer->AddParticleGen(*item.xb8_);
|
||||
if (item.xc0_particleElectric)
|
||||
g_Renderer->AddParticleGen(*item.xc0_particleElectric);
|
||||
if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && item.x78_ashGen)
|
||||
g_Renderer->AddParticleGen(*item.x78_ashGen);
|
||||
if (item.xb8_firePopGen)
|
||||
g_Renderer->AddParticleGen(*item.xb8_firePopGen);
|
||||
if (item.xc0_electricGen)
|
||||
g_Renderer->AddParticleGen(*item.xc0_electricGen);
|
||||
}
|
||||
if (isNotHot) {
|
||||
/* Cold Draw */
|
||||
for (std::unique_ptr<CElementGen>& gen : item.x8c_thermalColdParticles)
|
||||
for (std::unique_ptr<CElementGen>& gen : item.x8c_iceGens)
|
||||
g_Renderer->AddParticleGen(*gen);
|
||||
if (item.xe4_)
|
||||
g_Renderer->AddParticleGen(*item.xe4_);
|
||||
if (item.xe4_icePopGen)
|
||||
g_Renderer->AddParticleGen(*item.xe4_icePopGen);
|
||||
}
|
||||
if (isNotCold) {
|
||||
/* 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,
|
||||
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) {
|
||||
auto iter = FindOrCreateSystem(act);
|
||||
iter->Lock(EDependency::Ash);
|
||||
iter->Lock(EDependency::Ice);
|
||||
}
|
||||
|
||||
void CActorModelParticles::StartElectric(CActor& act) {
|
||||
auto iter = FindOrCreateSystem(act);
|
||||
if (iter->xc0_particleElectric && !iter->xc0_particleElectric->GetParticleEmission())
|
||||
iter->xc0_particleElectric->SetParticleEmission(true);
|
||||
if (iter->xc0_electricGen && !iter->xc0_electricGen->GetParticleEmission())
|
||||
iter->xc0_electricGen->SetParticleEmission(true);
|
||||
}
|
||||
|
||||
void CActorModelParticles::StopElectric(CActor& act) {
|
||||
if (act.GetPointGeneratorParticles()) {
|
||||
auto iter = FindSystem(act.GetUniqueId());
|
||||
if (iter != x0_items.cend() && iter->xc0_particleElectric)
|
||||
iter->xc0_particleElectric->SetParticleEmission(false);
|
||||
if (iter != x0_items.cend() && iter->xc0_electricGen)
|
||||
iter->xc0_electricGen->SetParticleEmission(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CActorModelParticles::sub_801e51d0(CActor& act) {
|
||||
void CActorModelParticles::LoadAndStartElectric(CActor& act) {
|
||||
auto iter = FindOrCreateSystem(act);
|
||||
if (!iter->xc0_particleElectric)
|
||||
iter->Lock(EDependency::IcePop);
|
||||
if (!iter->xc0_electricGen)
|
||||
iter->Lock(EDependency::Electric);
|
||||
else {
|
||||
if (!iter->xc0_particleElectric->GetParticleEmission())
|
||||
iter->xc0_particleElectric->SetParticleEmission(true);
|
||||
if (!iter->xc0_electricGen->GetParticleEmission())
|
||||
iter->xc0_electricGen->SetParticleEmission(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,7 +571,7 @@ void CActorModelParticles::StopThermalHotParticles(CActor& act) {
|
|||
if (act.GetPointGeneratorParticles()) {
|
||||
auto iter = FindSystem(act.GetUniqueId());
|
||||
if (iter != x0_items.cend()) {
|
||||
for (auto& part : iter->x8_thermalHotParticles)
|
||||
for (auto& part : iter->x8_onFireGens)
|
||||
if (part.first)
|
||||
part.first->SetParticleEmission(false);
|
||||
}
|
||||
|
@ -448,7 +587,7 @@ void CActorModelParticles::StartBurnDeath(CActor& act) {
|
|||
|
||||
void CActorModelParticles::EnsureElectricLoaded(CActor& act) {
|
||||
auto iter = FindOrCreateSystem(act);
|
||||
iter->Lock(EDependency::Electric);
|
||||
iter->Lock(EDependency::IcePop);
|
||||
}
|
||||
|
||||
void CActorModelParticles::EnsureFirePopLoaded(CActor& act) {
|
||||
|
@ -458,7 +597,7 @@ void CActorModelParticles::EnsureFirePopLoaded(CActor& act) {
|
|||
|
||||
void CActorModelParticles::EnsureIceBreakLoaded(CActor& act) {
|
||||
auto iter = FindOrCreateSystem(act);
|
||||
iter->Lock(EDependency::IceBreak);
|
||||
iter->Lock(EDependency::Ash);
|
||||
}
|
||||
|
||||
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,
|
||||
float minZ) {
|
||||
auto it = FindOrCreateSystem(act);
|
||||
if (it->xd4_rainSplashGenerator)
|
||||
if (it->xd4_rainSplashGen)
|
||||
return;
|
||||
|
||||
if (act.GetModelData() && !act.GetModelData()->IsNull())
|
||||
it->xd4_rainSplashGenerator =
|
||||
it->xd4_rainSplashGen =
|
||||
std::make_unique<CRainSplashGenerator>(act.GetModelData()->GetScale(), maxSplashes, genRate, minZ, 0.1875f);
|
||||
}
|
||||
|
||||
void CActorModelParticles::RemoveRainSplashGenerator(CActor& 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
|
||||
|
|
|
@ -19,33 +19,33 @@ class CScriptPlayerActor;
|
|||
|
||||
class CActorModelParticles {
|
||||
public:
|
||||
enum class EDependency { OnFire, Ash, IceBreak, FirePop, IcePop, Electric };
|
||||
enum class EDependency { OnFire, Ice, Ash, FirePop, Electric, IcePop };
|
||||
|
||||
class CItem {
|
||||
friend class CActorModelParticles;
|
||||
TUniqueId x0_id;
|
||||
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;
|
||||
bool x70_onFire = false;
|
||||
CSfxHandle x74_sfx;
|
||||
std::unique_ptr<CElementGen> x78_;
|
||||
u32 x80_ = 0;
|
||||
s32 x84_ = -1;
|
||||
u32 x88_seed1 = 99;
|
||||
rstl::reserved_vector<std::unique_ptr<CElementGen>, 4> x8c_thermalColdParticles;
|
||||
s32 xb0_ = -1;
|
||||
u32 xb4_seed2 = 99;
|
||||
std::unique_ptr<CElementGen> xb8_;
|
||||
std::unique_ptr<CParticleElectric> xc0_particleElectric;
|
||||
u32 xc8_ = 0;
|
||||
u32 xcc_seed3 = 99;
|
||||
zeus::CColor xd0_;
|
||||
std::unique_ptr<CRainSplashGenerator> xd4_rainSplashGenerator;
|
||||
std::unique_ptr<CElementGen> x78_ashGen;
|
||||
s32 x80_ashPointIterator = 0;
|
||||
s32 x84_ashMaxParticles = -1;
|
||||
u32 x88_ashSeed = 99;
|
||||
rstl::reserved_vector<std::unique_ptr<CElementGen>, 4> x8c_iceGens;
|
||||
s32 xb0_icePointIterator = -1;
|
||||
u32 xb4_iceSeed = 99;
|
||||
std::unique_ptr<CElementGen> xb8_firePopGen;
|
||||
std::unique_ptr<CParticleElectric> xc0_electricGen;
|
||||
s32 xc8_electricPointIterator = 0;
|
||||
u32 xcc_electricSeed = 99;
|
||||
zeus::CColor xd0_electricColor;
|
||||
std::unique_ptr<CRainSplashGenerator> xd4_rainSplashGen;
|
||||
TToken<CTexture> xdc_ashy;
|
||||
std::unique_ptr<CElementGen> xe4_;
|
||||
zeus::CVector3f xec_ = zeus::CVector3f::skOne;
|
||||
zeus::CTransform xf8_;
|
||||
std::unique_ptr<CElementGen> xe4_icePopGen;
|
||||
zeus::CVector3f xec_particleOffsetScale = zeus::CVector3f::skOne;
|
||||
zeus::CTransform xf8_iceXf;
|
||||
CActorModelParticles& x128_parent;
|
||||
union {
|
||||
struct {
|
||||
|
@ -54,16 +54,15 @@ public:
|
|||
};
|
||||
u16 _dummy = 0;
|
||||
};
|
||||
float x130_ = 10.f;
|
||||
u8 x134_lockDeps = 0;
|
||||
void sub_801e59a8(EDependency i);
|
||||
float x130_remTime = 10.f;
|
||||
mutable u8 x134_lockDeps = 0;
|
||||
bool UpdateOnFire(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateAsh(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool sub_801e65bc(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateAshGen(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateIceGen(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateFirePop(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateElectric(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool sub_801e69f0(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool sub_801e5e98(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateRainSplash(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateBurn(float dt, CActor* actor, CStateManager& mgr);
|
||||
bool UpdateIcePop(float dt, CActor* actor, CStateManager& mgr);
|
||||
|
||||
public:
|
||||
|
@ -113,11 +112,22 @@ private:
|
|||
tok.Unlock();
|
||||
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;
|
||||
u8 xe4_bits = 0;
|
||||
u8 xe5_bits1 = 0;
|
||||
u8 xe6_bits2 = 0;
|
||||
u8 xe4_loadingDeps = 0;
|
||||
u8 xe5_justLoadedDeps = 0;
|
||||
u8 xe6_loadedDeps = 0;
|
||||
|
||||
Dependency GetParticleDGRPTokens(const char* name);
|
||||
void LoadParticleDGRPs();
|
||||
|
@ -132,6 +142,8 @@ private:
|
|||
void DecrementDependency(EDependency d);
|
||||
void IncrementDependency(EDependency d);
|
||||
|
||||
void UpdateLoad();
|
||||
|
||||
public:
|
||||
CActorModelParticles();
|
||||
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 AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate, float minZ);
|
||||
void RemoveRainSplashGenerator(CActor& act);
|
||||
void Render(const CActor& actor) const;
|
||||
void Render(const CStateManager& mgr, const CActor& actor) const;
|
||||
void StartElectric(CActor& act);
|
||||
void StopElectric(CActor& act);
|
||||
void sub_801e51d0(CActor& act);
|
||||
void LoadAndStartElectric(CActor& act);
|
||||
void StopThermalHotParticles(CActor& act);
|
||||
void StartBurnDeath(CActor& act);
|
||||
void EnsureElectricLoaded(CActor& act);
|
||||
|
|
|
@ -137,6 +137,8 @@ public:
|
|||
const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
|
||||
EKnockBackVariant GetVariant() const { return x0_variant; }
|
||||
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
|
|
@ -40,6 +40,9 @@ public:
|
|||
void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const;
|
||||
void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, float lookahead) const;
|
||||
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
|
||||
|
|
|
@ -59,4 +59,15 @@ void CPathFindSearch::GetSplinePointWithLookahead(zeus::CVector3f& pOut, const z
|
|||
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
|
|
@ -20,6 +20,7 @@
|
|||
#include "World/CScriptWaypoint.hpp"
|
||||
#include "World/CScriptActorKeyframe.hpp"
|
||||
#include "Weapon/CEnergyProjectile.hpp"
|
||||
#include "World/CScriptCoverPoint.hpp"
|
||||
|
||||
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) {
|
||||
if (state == x450_bodyController->GetCurrentStateId())
|
||||
x32c_animState = EAnimState::Repeat;
|
||||
else if (x32c_animState == EAnimState::One)
|
||||
else if (x32c_animState == EAnimState::Ready)
|
||||
(this->*func)(mgr, arg);
|
||||
else
|
||||
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));
|
||||
}
|
||||
|
||||
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) {
|
||||
if (x450_bodyController)
|
||||
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,
|
||||
EScriptObjectMessage msg) const {
|
||||
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));
|
||||
if (xe5_31_pointGeneratorParticles) {
|
||||
CSkinnedModel::ClearPointGeneratorFunc();
|
||||
mgr.GetActorModelParticles()->Render(*this);
|
||||
mgr.GetActorModelParticles()->Render(mgr, *this);
|
||||
}
|
||||
} else {
|
||||
CPhysicsActor::Render(mgr);
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
enum class EBehaviourOrient { MoveDir, Constant, Destination };
|
||||
enum class EBehaviourModifiers { Zero };
|
||||
enum class EPatrolState { Invalid = -1, Patrol, Pause, Done };
|
||||
enum class EAnimState { Zero, One, Repeat, Over };
|
||||
enum class EAnimState { NotReady, Ready, Repeat, Over };
|
||||
class CPatternNode {
|
||||
zeus::CVector3f x0_pos;
|
||||
zeus::CVector3f xc_forward;
|
||||
|
@ -131,7 +131,7 @@ protected:
|
|||
u32 _dummy = 0;
|
||||
};
|
||||
|
||||
EAnimState x32c_animState = EAnimState::Zero;
|
||||
EAnimState x32c_animState = EAnimState::NotReady;
|
||||
CStateMachineState x330_stateMachineState;
|
||||
ECharacter x34c_character;
|
||||
zeus::CVector3f x350_patternStartPos;
|
||||
|
@ -319,6 +319,17 @@ public:
|
|||
void TryLoopReaction(CStateManager& mgr, int arg);
|
||||
void TryProjectileAttack(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 void MassiveDeath(CStateManager& mgr);
|
||||
|
@ -357,6 +368,9 @@ public:
|
|||
void SetModelAlpha(float a) { x42c_color.a() = a; }
|
||||
float CalcDyingThinkRate();
|
||||
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 IsMakingBigStrike() const { return x402_28_isMakingBigStrike; }
|
||||
|
|
|
@ -5674,4 +5674,10 @@ bool CPlayer::AttachActorToPlayer(TUniqueId id, bool disableGun) {
|
|||
return false;
|
||||
}
|
||||
|
||||
float CPlayer::GetAverageSpeed() const {
|
||||
if (auto avg = x4a4_moveSpeedAvg.GetAverage())
|
||||
return *avg;
|
||||
return x4f8_moveSpeed;
|
||||
}
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -610,5 +610,7 @@ public:
|
|||
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
|
||||
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
|
||||
void Set_X590(bool b) { x590_ = b; }
|
||||
const zeus::CVector3f& GetOrbitPoint() const { return x314_orbitPoint; }
|
||||
float GetAverageSpeed() const;
|
||||
};
|
||||
} // namespace urde
|
||||
|
|
|
@ -9,7 +9,7 @@ CScriptAiJumpPoint::CScriptAiJumpPoint(TUniqueId uid, std::string_view name, con
|
|||
zeus::CTransform& xf, bool active, float f1)
|
||||
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic),
|
||||
CActorParameters::None(), kInvalidUniqueId)
|
||||
, xe8_(f1)
|
||||
, xe8_apex(f1)
|
||||
, xec_touchBounds(xf.origin, xf.origin) {}
|
||||
|
||||
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; }
|
||||
|
||||
bool CScriptAiJumpPoint::GetInUse(TUniqueId uid) const {
|
||||
if (x108_24 || x110_timeRemaining > 0.f || x10a_occupant != kInvalidUniqueId || uid != kInvalidUniqueId ||
|
||||
uid != x10a_occupant)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return x108_24 || x110_timeRemaining > 0.f || x10a_occupant != kInvalidUniqueId || uid != kInvalidUniqueId ||
|
||||
uid != x10a_occupant;
|
||||
}
|
||||
} // namespace urde
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace urde {
|
||||
class CScriptAiJumpPoint : public CActor {
|
||||
private:
|
||||
float xe8_;
|
||||
float xe8_apex;
|
||||
zeus::CAABox xec_touchBounds;
|
||||
union {
|
||||
struct {
|
||||
|
@ -28,5 +28,8 @@ public:
|
|||
void Render(const CStateManager&) const {}
|
||||
std::experimental::optional<zeus::CAABox> GetTouchBounds() 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
|
||||
|
|
|
@ -655,7 +655,7 @@ void CScriptGunTurret::sub80218f50(s32 state, CStateManager& mgr, float dt) {
|
|||
zeus::CVector3f rotatedBlastVec = GetTransform().rotate(blastXf.origin) + GetTranslation();
|
||||
x404_ = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
||||
vec = x37c_projectileInfo.PredictInterceptPos(rotatedBlastVec, mgr.GetPlayer().GetAimPosition(mgr, dt),
|
||||
mgr.GetPlayer(), false);
|
||||
mgr.GetPlayer(), false, dt);
|
||||
}
|
||||
|
||||
zeus::CVector3f compensated =
|
||||
|
|
|
@ -106,6 +106,7 @@ public:
|
|||
float GetTime() const { return x8_time; }
|
||||
float GetRandom() const { return xc_random; }
|
||||
float GetDelay() const { return x10_delay; }
|
||||
void SetCodeTrigger() { x18_24_codeTrigger = true; }
|
||||
|
||||
const char* GetName() const {
|
||||
if (x4_state)
|
||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit 82a7890e99da98fcc9770fb21c73f7837f285f66
|
||||
Subproject commit 40d23980dec1cf5addab4b0dbd2539d460c37fe0
|
2
specter
2
specter
|
@ -1 +1 @@
|
|||
Subproject commit a3a3f90d8ce1d7f4c73c70c690f9bce4da69c50a
|
||||
Subproject commit f81efb25b53e90cf9e77c06a09095a433929ddb4
|
Loading…
Reference in New Issue