Implement CBodyController

This commit is contained in:
Jack Andersen 2017-07-13 19:14:19 -10:00
parent daef773f39
commit 8a493615c4
23 changed files with 467 additions and 74 deletions

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<Objective-C>
<option name="INDENT_NAMESPACE_MEMBERS" value="0" />
<option name="SPACE_WITHIN_TEMPLATE_DOUBLE_GT" value="false" />
<option name="SPACE_BEFORE_POINTER_IN_DECLARATION" value="false" />
<option name="SPACE_AFTER_POINTER_IN_DECLARATION" value="true" />
<option name="SPACE_BEFORE_REFERENCE_IN_DECLARATION" value="false" />
<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" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
<codeStyleSettings language="ObjectiveC">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
</value>
</option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</component>
</project>

View File

@ -156,9 +156,7 @@ struct SpecMP1 : SpecBase
{ {
bool checkStandaloneID(const char* id) const bool checkStandaloneID(const char* id) const
{ {
if (!memcmp(id, "GM8", 3)) return !memcmp(id, "GM8", 3);
return true;
return false;
} }
std::vector<const nod::Node*> m_nonPaks; std::vector<const nod::Node*> m_nonPaks;

View File

@ -424,6 +424,7 @@ public:
CRelayTracker* GetRelayTracker() { return x8bc_relayTracker.get(); } CRelayTracker* GetRelayTracker() { return x8bc_relayTracker.get(); }
CCameraManager* GetCameraManager() const { return x870_cameraManager; } CCameraManager* GetCameraManager() const { return x870_cameraManager; }
CFluidPlaneManager* GetFluidPlaneManager() const { return x87c_fluidPlaneManager; } CFluidPlaneManager* GetFluidPlaneManager() const { return x87c_fluidPlaneManager; }
CActorModelParticles* GetActorModelParticles() const { return x884_actorModelParticles; }
const std::shared_ptr<CMapWorldInfo>& MapWorldInfo() const { return x8c0_mapWorldInfo; } const std::shared_ptr<CMapWorldInfo>& MapWorldInfo() const { return x8c0_mapWorldInfo; }
const std::shared_ptr<CWorldLayerState>& LayerState() const { return x8c8_worldLayerState; } const std::shared_ptr<CWorldLayerState>& LayerState() const { return x8c8_worldLayerState; }

View File

@ -175,7 +175,7 @@ void CABSReaction::Start(CBodyController& bc, CStateManager& mgr)
pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc) pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc)
{ {
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) && if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) &&
xc_type == pas::EReactionType::Three) xc_type == pas::EAdditiveReactionType::IceBreakout)
return pas::EAnimationState::AdditiveReaction; return pas::EAnimationState::AdditiveReaction;
return pas::EAnimationState::Invalid; return pas::EAnimationState::Invalid;
} }
@ -191,7 +191,7 @@ pas::EAnimationState CABSReaction::UpdateBody(float dt, CBodyController& bc, CSt
CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData();
if (x10_active) if (x10_active)
{ {
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::TwentySeven)) if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::StopReaction))
{ {
StopAnimation(bc); StopAnimation(bc);
bc.GetOwner().RemoveEmitter(); bc.GetOwner().RemoveEmitter();

View File

@ -61,7 +61,7 @@ class CABSReaction : public CAdditiveBodyState
{ {
float x4_weight = 1.f; float x4_weight = 1.f;
s32 x8_anim = -1; s32 x8_anim = -1;
pas::EReactionType xc_type = pas::EReactionType::Invalid; pas::EAdditiveReactionType xc_type = pas::EAdditiveReactionType::Invalid;
bool x10_active = false; bool x10_active = false;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
void StopAnimation(CBodyController& bc); void StopAnimation(CBodyController& bc);

View File

@ -2,13 +2,17 @@
#include "World/CActor.hpp" #include "World/CActor.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "World/CPhysicsActor.hpp" #include "World/CPhysicsActor.hpp"
#include "World/CActorModelParticles.hpp"
#include "Character/CPASAnimParm.hpp"
#include "Character/CPASAnimParmData.hpp"
#include "CStateManager.hpp"
namespace urde namespace urde
{ {
CBodyController::CBodyController(CActor& actor, float f1, EBodyType bodyType) CBodyController::CBodyController(CActor& actor, float turnSpeed, EBodyType bodyType)
: x0_actor(actor), x2a4_bodyStateInfo(actor, bodyType), : x0_actor(actor), x2a4_bodyStateInfo(actor, bodyType),
x2f4_bodyType(bodyType), x2fc_rotRate(f1) x2f4_bodyType(bodyType), x2fc_turnSpeed(turnSpeed)
{ {
x300_28_playDeathAnims = true; x300_28_playDeathAnims = true;
x2a4_bodyStateInfo.x18_bodyController = this; x2a4_bodyStateInfo.x18_bodyController = this;
@ -19,19 +23,118 @@ void CBodyController::EnableAnimation(bool e)
x0_actor.ModelData()->AnimationData()->EnableAnimation(e); x0_actor.ModelData()->AnimationData()->EnableAnimation(e);
} }
void CBodyController::Activate(CStateManager& mgr)
{
x300_25_active = true;
x2a4_bodyStateInfo.SetState(pas::EAnimationState(GetPASDatabase().GetDefaultState()));
x2a4_bodyStateInfo.GetCurrentState()->Start(*this, mgr);
x2a4_bodyStateInfo.GetCurrentAdditiveState()->Start(*this, mgr);
}
void CBodyController::UpdateBody(float dt, CStateManager& mgr)
{
UpdateFrozenInfo(dt, mgr);
if (x320_fireDur > 0.f)
{
if (x328_timeOnFire > x320_fireDur)
{
x328_timeOnFire = 0.f;
x320_fireDur = 0.f;
}
else
{
x328_timeOnFire += dt;
}
}
else if (x324_electrocutionDur > 0.f)
{
if (x32c_timeElectrocuting > x324_electrocutionDur)
{
x32c_timeElectrocuting = 0.f;
x324_electrocutionDur = 0.f;
}
else
{
x32c_timeElectrocuting += dt;
}
}
if (GetPercentageFrozen() < 1.f && x300_28_playDeathAnims)
{
pas::EAnimationState nextState = x2a4_bodyStateInfo.GetCurrentState()->UpdateBody(dt, *this, mgr);
if (nextState != pas::EAnimationState::Invalid)
{
x2a4_bodyStateInfo.GetCurrentState()->Shutdown(*this);
x2a4_bodyStateInfo.SetState(nextState);
x2a4_bodyStateInfo.GetCurrentState()->Start(*this, mgr);
}
nextState = x2a4_bodyStateInfo.GetCurrentAdditiveState()->UpdateBody(dt, *this, mgr);
if (nextState != pas::EAnimationState::Invalid)
{
x2a4_bodyStateInfo.GetCurrentAdditiveState()->Shutdown(*this);
x2a4_bodyStateInfo.SetAdditiveState(nextState);
x2a4_bodyStateInfo.GetCurrentAdditiveState()->Start(*this, mgr);
}
}
}
void CBodyController::SetTurnSpeed(float s)
{
x2fc_turnSpeed = std::max(0.f, s);
}
void CBodyController::Update(float dt, CStateManager& mgr)
{
SetPlaybackRate(1.f);
if (x300_25_active)
{
x300_24_animationOver =
!x0_actor.GetModelData()->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body");
x4_cmdMgr.BlendSteeringCmds();
x2dc_rot = zeus::CQuaternion::skNoRotation;
UpdateBody(dt, mgr);
if (TCastToPtr<CPhysicsActor> act = x0_actor)
act->RotateInOneFrameOR(x2dc_rot, dt);
x4_cmdMgr.Reset();
}
}
bool CBodyController::HasBodyState(pas::EAnimationState s) const
{
return GetPASDatabase().HasState(s32(s));
}
void CBodyController::SetCurrentAnimation(const CAnimPlaybackParms& parms, bool loop, bool noTrans)
{
x0_actor.ModelData()->AnimationData()->SetAnimation(parms, noTrans);
x0_actor.ModelData()->EnableLooping(loop);
x2f8_curAnim = parms.GetAnimationId();
}
float CBodyController::GetAnimTimeRemaining() const float CBodyController::GetAnimTimeRemaining() const
{ {
return x0_actor.GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"); return x0_actor.GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body");
} }
void CBodyController::SetPlaybackRate(float r)
{
x0_actor.ModelData()->AnimationData()->SetPlaybackRate(r);
}
const CPASDatabase& CBodyController::GetPASDatabase() const const CPASDatabase& CBodyController::GetPASDatabase() const
{ {
return x0_actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); return x0_actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase();
} }
void CBodyController::MultiplyPlaybackRate(float r)
{
x0_actor.ModelData()->AnimationData()->MultiplyPlaybackRate(r);
}
void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt) void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt)
{ {
if (x300_26_) if (x300_26_frozen)
return; return;
zeus::CVector3f noZ = v0; zeus::CVector3f noZ = v0;
noZ.z = 0.f; noZ.z = 0.f;
@ -41,7 +144,7 @@ void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt)
{ {
zeus::CQuaternion rot = zeus::CQuaternion rot =
zeus::CQuaternion::lookAt(act->GetTransform().basis[1], zeus::CQuaternion::lookAt(act->GetTransform().basis[1],
noZ.normalized(), zeus::degToRad(dt * x2fc_rotRate)); noZ.normalized(), zeus::degToRad(dt * x2fc_turnSpeed));
rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary())); rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary()));
act->RotateInOneFrameOR(rot, dt); act->RotateInOneFrameOR(rot, dt);
} }
@ -50,7 +153,7 @@ void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt)
void CBodyController::FaceDirection3D(const zeus::CVector3f& v0, const zeus::CVector3f& v1, float dt) void CBodyController::FaceDirection3D(const zeus::CVector3f& v0, const zeus::CVector3f& v1, float dt)
{ {
if (x300_26_) if (x300_26_frozen)
return; return;
if (v0.canBeNormalized() && v1.canBeNormalized()) if (v0.canBeNormalized() && v1.canBeNormalized())
{ {
@ -65,17 +168,169 @@ void CBodyController::FaceDirection3D(const zeus::CVector3f& v0, const zeus::CVe
{ {
zeus::CQuaternion rot = zeus::CQuaternion rot =
zeus::CQuaternion::fromAxisAngle(act->GetTransform().basis[2], zeus::CQuaternion::fromAxisAngle(act->GetTransform().basis[2],
zeus::degToRad(dt * x2fc_rotRate)); zeus::degToRad(dt * x2fc_turnSpeed));
rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary())); rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary()));
act->RotateInOneFrameOR(rot, dt); act->RotateInOneFrameOR(rot, dt);
} }
else else
{ {
/* TODO: Finish */ zeus::CQuaternion rot =
zeus::CQuaternion::clampedRotateTo(uv1, uv0, zeus::degToRad(dt * x2fc_turnSpeed));
rot.setImaginary(x0_actor.GetTransform().transposeRotate(rot.getImaginary()));
act->RotateInOneFrameOR(rot, dt);
} }
} }
} }
} }
} }
bool CBodyController::HasBodyInfo(CActor& act)
{
return act.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().GetNumAnimStates() != 0;
}
void CBodyController::PlayBestAnimation(const CPASAnimParmData& parms, CRandom16& r)
{
std::pair<float, s32> best = GetPASDatabase().FindBestAnimation(parms, r, -1);
CAnimPlaybackParms playParms(best.second, -1, 1.f, true);
SetCurrentAnimation(playParms, false, false);
}
void CBodyController::LoopBestAnimation(const CPASAnimParmData& parms, CRandom16& r)
{
std::pair<float, s32> best = GetPASDatabase().FindBestAnimation(parms, r, -1);
CAnimPlaybackParms playParms(best.second, -1, 1.f, true);
SetCurrentAnimation(playParms, true, false);
}
void CBodyController::Freeze(float intoFreezeDur, float frozenDur, float breakoutDur)
{
x304_intoFreezeDur = intoFreezeDur;
x308_frozenDur = frozenDur;
x30c_breakoutDur = breakoutDur;
x300_26_frozen = true;
x300_27_hasBeenFrozen = true;
if (TCastToPtr<CPhysicsActor> act = x0_actor)
{
x314_backedUpForce = act->GetConstantForce();
act->SetConstantForce(zeus::CVector3f::skZero);
act->SetMomentumWR(zeus::CVector3f::skZero);
}
x320_fireDur = 0.f;
x328_timeOnFire = 0.f;
x310_timeFrozen = 0.f;
}
void CBodyController::UnFreeze()
{
SetPlaybackRate(1.f);
x300_26_frozen = false;
x304_intoFreezeDur = 0.f;
x308_frozenDur = 0.f;
x30c_breakoutDur = 0.f;
x310_timeFrozen = 0.f;
x0_actor.SetVolume(1.f);
if (TCastToPtr<CPhysicsActor> act = x0_actor)
{
act->SetConstantForce(x314_backedUpForce);
act->SetVelocityWR(x314_backedUpForce * (1.f / act->GetMass()));
}
}
float CBodyController::GetPercentageFrozen() const
{
float sum = x304_intoFreezeDur + x308_frozenDur + x30c_breakoutDur;
if (x310_timeFrozen == 0.f || sum == 0.f)
return 0.f;
if (x310_timeFrozen <= x304_intoFreezeDur && x304_intoFreezeDur > 0.f)
return x310_timeFrozen / x304_intoFreezeDur;
if (x310_timeFrozen < sum - x30c_breakoutDur)
return 1.f;
if (x30c_breakoutDur <= 0.f)
return 1.f;
return 1.f - (x310_timeFrozen - (x308_frozenDur + x304_intoFreezeDur)) / x30c_breakoutDur;
}
void CBodyController::SetOnFire(float dur)
{
x320_fireDur = dur;
x328_timeOnFire = 0.f;
if (IsFrozen())
UnFreeze();
}
void CBodyController::DouseFlames()
{
if (x320_fireDur <= 0.f)
return;
x320_fireDur = 0.f;
x328_timeOnFire = 0.f;
}
void CBodyController::SetElectrocuting(float dur)
{
if (!IsElectrocuting())
{
CBCAdditiveReactionCmd reaction(pas::EAdditiveReactionType::Electrocution, 1.f, true);
x4_cmdMgr.DeliverCmd(reaction);
}
x324_electrocutionDur = dur;
x32c_timeElectrocuting = 0.f;
if (IsFrozen())
UnFreeze();
else if (IsOnFire())
DouseFlames();
}
void CBodyController::DouseElectrocuting()
{
x324_electrocutionDur = 0.f;
x32c_timeElectrocuting = 0.f;
CBodyStateCmd cmd(EBodyStateCmd::StopReaction);
x4_cmdMgr.DeliverCmd(cmd);
}
void CBodyController::UpdateFrozenInfo(float dt, CStateManager& mgr)
{
if (x300_26_frozen)
{
float totalTime = x304_intoFreezeDur + x308_frozenDur + x30c_breakoutDur;
if (x310_timeFrozen > totalTime &&
x2a4_bodyStateInfo.GetCurrentAdditiveStateId() != pas::EAnimationState::AdditiveReaction)
{
UnFreeze();
x0_actor.SendScriptMsgs(EScriptObjectState::UnFrozen, mgr, EScriptObjectMessage::None);
mgr.GetActorModelParticles()->StartIce(x0_actor, mgr);
return;
}
if (x310_timeFrozen <= totalTime)
{
float percUnfrozen = 1.f;
if (x310_timeFrozen < totalTime - x30c_breakoutDur)
percUnfrozen = 1.f - GetPercentageFrozen();
MultiplyPlaybackRate(percUnfrozen);
x310_timeFrozen += dt;
x0_actor.SetVolume(percUnfrozen);
if (x310_timeFrozen > totalTime && HasIceBreakoutState())
{
CBCAdditiveReactionCmd cmd(pas::EAdditiveReactionType::IceBreakout, 1.f, false);
x4_cmdMgr.DeliverCmd(cmd);
}
}
}
}
bool CBodyController::HasIceBreakoutState() const
{
CPASAnimParmData parms(24, CPASAnimParm::FromEnum(3));
std::pair<float, s32> best = GetPASDatabase().FindBestAnimation(parms, -1);
return best.first > 0.f;
}
} }

View File

@ -28,42 +28,41 @@ class CBodyController
pas::EFallState x2f0_fallState = pas::EFallState::Zero; pas::EFallState x2f0_fallState = pas::EFallState::Zero;
EBodyType x2f4_bodyType; EBodyType x2f4_bodyType;
s32 x2f8_curAnim = -1; s32 x2f8_curAnim = -1;
float x2fc_rotRate; float x2fc_turnSpeed;
union union
{ {
struct struct
{ {
bool x300_24_animationOver : 1; bool x300_24_animationOver : 1;
bool x300_25_ : 1; bool x300_25_active : 1;
bool x300_26_ : 1; bool x300_26_frozen : 1;
bool x300_27_ : 1; bool x300_27_hasBeenFrozen : 1;
bool x300_28_playDeathAnims : 1; bool x300_28_playDeathAnims : 1;
}; };
u32 _dummy = 0; u32 _dummy = 0;
}; };
float x304_ = 0.f; float x304_intoFreezeDur = 0.f;
float x308_ = 0.f; float x308_frozenDur = 0.f;
float x30c_ = 0.f; float x30c_breakoutDur = 0.f;
float x310_ = 0.f; float x310_timeFrozen = 0.f;
zeus::CVector3f x314_; zeus::CVector3f x314_backedUpForce;
float x320_ = 0.f; float x320_fireDur = 0.f;
float x324_ = 0.f; float x324_electrocutionDur = 0.f;
float x328_ = 0.f; float x328_timeOnFire = 0.f;
float x32c_ = 0.f; float x32c_timeElectrocuting = 0.f;
float x330_restrictedFlyerMoveSpeed = 0.f; float x330_restrictedFlyerMoveSpeed = 0.f;
public: public:
CBodyController(CActor& owner, float f1, EBodyType bodyType); CBodyController(CActor& owner, float turnSpeed, EBodyType bodyType);
void GetCurrentStateId() const; pas::EAnimationState GetCurrentStateId() const { return x2a4_bodyStateInfo.GetCurrentStateId(); }
CBodyStateCmdMgr& GetCommandMgr() { return x4_cmdMgr; } CBodyStateCmdMgr& GetCommandMgr() { return x4_cmdMgr; }
const CBodyStateCmdMgr& GetCommandMgr() const { return x4_cmdMgr; } const CBodyStateCmdMgr& GetCommandMgr() const { return x4_cmdMgr; }
void SetDoDeathAnims(bool d) { x300_28_playDeathAnims = d; } void SetDoDeathAnims(bool d) { x300_28_playDeathAnims = d; }
bool IsElectrocuting() const; bool IsElectrocuting() const { return x324_electrocutionDur > 0.f; }
bool IsOnFire() const; bool IsOnFire() const { return x320_fireDur > 0.f; }
bool IsFrozen() const; bool IsFrozen() const { return x300_26_frozen; }
const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; } const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; }
bool GetIsActive() const; CBodyStateInfo& BodyStateInfo() { return x2a4_bodyStateInfo; }
void BodyStateInfo(); float GetTurnSpeed() const { return x2fc_turnSpeed; }
float GetTurnSpeed() const;
pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; } pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; }
CActor& GetOwner() const { return x0_actor; } CActor& GetOwner() const { return x0_actor; }
bool IsAnimationOver() const { return x300_24_animationOver; } bool IsAnimationOver() const { return x300_24_animationOver; }
@ -71,40 +70,41 @@ public:
bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; } bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; }
s32 GetCurrentAnimId() const { return x2f8_curAnim; } s32 GetCurrentAnimId() const { return x2f8_curAnim; }
void Activate(CStateManager&); void Activate(CStateManager&);
void GetCurrentAdditiveState(); CAdditiveBodyState* GetCurrentAdditiveState()
void SetState(pas::EAnimationState); { return x2a4_bodyStateInfo.GetCurrentAdditiveState(); }
void SetState(pas::EAnimationState s) { x2a4_bodyStateInfo.SetState(s); }
void Update(float, CStateManager&); void Update(float, CStateManager&);
void Deactivate(); bool ShouldBeHurled() const { return HasBodyState(pas::EAnimationState::Hurled); }
bool ShouldBeHurled() const; bool HasBodyState(pas::EAnimationState s) const;
bool HasBodyState(pas::EAnimationState); pas::EFallState GetFallState() const { return x2f0_fallState; }
pas::EFallState GetFallState() const; void SetFallState(pas::EFallState s) { x2f0_fallState = s; }
void SetFallState(pas::EFallState);
void UpdateBody(float, CStateManager&); void UpdateBody(float, CStateManager&);
void SetAdditiveState(pas::EAnimationState); void SetAdditiveState(pas::EAnimationState s) { x2a4_bodyStateInfo.SetAdditiveState(s); }
void SetTurnSpeed(float); void SetTurnSpeed(float s);
void SetCurrentAnimation(const CAnimPlaybackParms&, bool, bool); void SetCurrentAnimation(const CAnimPlaybackParms& parms, bool loop, bool noTrans);
float GetAnimTimeRemaining() const; float GetAnimTimeRemaining() const;
void SetPlaybackRate(float); void SetPlaybackRate(float);
void MultiplyPlaybackRate(float); void MultiplyPlaybackRate(float);
void SetDeltaRotation(const zeus::CQuaternion& q) { x2dc_rot *= q; } void SetDeltaRotation(const zeus::CQuaternion& q) { x2dc_rot *= q; }
void FaceDirection(const zeus::CVector3f&, float); void FaceDirection(const zeus::CVector3f&, float);
void FaceDirection3D(const zeus::CVector3f&, const zeus::CVector3f&, float); void FaceDirection3D(const zeus::CVector3f&, const zeus::CVector3f&, float);
void HasBodyInfo(CActor&); static bool HasBodyInfo(CActor& act);
void ProcessInput(const CFinalInput&);
const CPASDatabase& GetPASDatabase() const; const CPASDatabase& GetPASDatabase() const;
void PlayBestAnimation(const CPASAnimParmData&, CRandom16&); void PlayBestAnimation(const CPASAnimParmData&, CRandom16&);
void LoopBestAnimation(const CPASAnimParmData&, CRandom16&); void LoopBestAnimation(const CPASAnimParmData&, CRandom16&);
void Freeze(float, float, float); void Freeze(float intoFreezeDur, float frozenDur, float breakoutDur);
void UnFreeze(); void UnFreeze();
void GetPercentageFrozen() const; float GetPercentageFrozen() const;
void SetOnFire(float); void SetOnFire(float);
void DouseFlames(); void DouseFlames();
void SetElectrocuting(float); void SetElectrocuting(float dur);
void DouseElectrocuting(); void DouseElectrocuting();
void UpdateFrozenInfo(float, CStateManager&); void UpdateFrozenInfo(float, CStateManager&);
void GetCurrentAdditiveStateId() const; bool HasIceBreakoutState() const;
pas::EAnimationState GetCurrentAdditiveStateId() const
{ return x2a4_bodyStateInfo.GetCurrentAdditiveStateId(); }
EBodyType GetBodyType() const { return x2f4_bodyType; } EBodyType GetBodyType() const { return x2f4_bodyType; }
bool HasBeenFrozen() const; bool HasBeenFrozen() const { return x300_27_hasBeenFrozen; }
float GetRestrictedFlyerMoveSpeed() const { return x330_restrictedFlyerMoveSpeed; } float GetRestrictedFlyerMoveSpeed() const { return x330_restrictedFlyerMoveSpeed; }
}; };
} }

View File

@ -3,7 +3,6 @@
#include "World/CActor.hpp" #include "World/CActor.hpp"
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "World/CPhysicsActor.hpp"
#include "CPASAnimParmData.hpp" #include "CPASAnimParmData.hpp"
#include "World/CPatterned.hpp" #include "World/CPatterned.hpp"

View File

@ -243,13 +243,14 @@ public:
class CBCAdditiveReactionCmd : public CBodyStateCmd class CBCAdditiveReactionCmd : public CBodyStateCmd
{ {
float x8_weight = 1.f; float x8_weight = 1.f;
pas::EReactionType xc_type = pas::EReactionType::Invalid; pas::EAdditiveReactionType xc_type = pas::EAdditiveReactionType::Invalid;
bool x10_active = false; bool x10_active = false;
public: public:
CBCAdditiveReactionCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveReaction) {} CBCAdditiveReactionCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveReaction) {}
CBCAdditiveReactionCmd(pas::EReactionType type, float f) CBCAdditiveReactionCmd(pas::EAdditiveReactionType type, float f, bool active)
: CBodyStateCmd(EBodyStateCmd::AdditiveReaction), x8_weight(f), xc_type(type) {} : CBodyStateCmd(EBodyStateCmd::AdditiveReaction), x8_weight(f),
pas::EReactionType GetType() const { return xc_type; } xc_type(type), x10_active(active) {}
pas::EAdditiveReactionType GetType() const { return xc_type; }
float GetWeight() const { return x8_weight; } float GetWeight() const { return x8_weight; }
bool GetIsActive() const { return x10_active; } bool GetIsActive() const { return x10_active; }
}; };
@ -335,7 +336,7 @@ class CBodyStateCmdMgr
CBCAdditiveAimCmd x270_additiveAim; CBCAdditiveAimCmd x270_additiveAim;
CBCAdditiveFlinchCmd x278_additiveFlinch; CBCAdditiveFlinchCmd x278_additiveFlinch;
CBCAdditiveReactionCmd x284_additiveReaction; CBCAdditiveReactionCmd x284_additiveReaction;
CBodyStateCmd x298_ = {EBodyStateCmd::TwentySeven}; CBodyStateCmd x298_ = {EBodyStateCmd::StopReaction};
void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); } void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); }
public: public:
CBodyStateCmdMgr(); CBodyStateCmdMgr();

View File

@ -42,14 +42,14 @@ CBodyStateInfo::CBodyStateInfo(CActor& actor, EBodyType type)
} }
if (bs) if (bs)
x0_stateMap[state->GetStateId()] = std::move(bs); x0_stateMap[pas::EAnimationState(state->GetStateId())] = std::move(bs);
} }
x1c_additiveStates.reserve(4); x1c_additiveStates.reserve(4);
x1c_additiveStates.push_back({21, std::make_unique<CABSIdle>()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveIdle, std::make_unique<CABSIdle>()});
x1c_additiveStates.push_back({22, std::make_unique<CABSAim>()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveAim, std::make_unique<CABSAim>()});
x1c_additiveStates.push_back({23, std::make_unique<CABSFlinch>()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveFlinch, std::make_unique<CABSFlinch>()});
x1c_additiveStates.push_back({24, std::make_unique<CABSReaction>()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveReaction, std::make_unique<CABSReaction>()});
} }
std::unique_ptr<CBodyState> CBodyStateInfo::SetupRestrictedFlyerBodyStates(int stateId, CActor& actor) std::unique_ptr<CBodyState> CBodyStateInfo::SetupRestrictedFlyerBodyStates(int stateId, CActor& actor)
@ -389,7 +389,7 @@ std::unique_ptr<CBodyState> CBodyStateInfo::SetupBiPedalBodyStates(int stateId,
float CBodyStateInfo::GetLocomotionSpeed(pas::ELocomotionAnim anim) const float CBodyStateInfo::GetLocomotionSpeed(pas::ELocomotionAnim anim) const
{ {
auto search = x0_stateMap.find(5); auto search = x0_stateMap.find(pas::EAnimationState::Locomotion);
if (search != x0_stateMap.cend() && search->second && x18_bodyController) if (search != x0_stateMap.cend() && search->second && x18_bodyController)
{ {
const CBSLocomotion& bs = static_cast<const CBSLocomotion&>(*search->second); const CBSLocomotion& bs = static_cast<const CBSLocomotion&>(*search->second);
@ -413,4 +413,57 @@ float CBodyStateInfo::GetMaxSpeed() const
return ret; return ret;
} }
CBodyState* CBodyStateInfo::GetCurrentState()
{
auto search = x0_stateMap.find(x14_state);
if (search == x0_stateMap.end())
return nullptr;
return search->second.get();
}
const CBodyState* CBodyStateInfo::GetCurrentState() const
{
auto search = x0_stateMap.find(x14_state);
if (search == x0_stateMap.end())
return nullptr;
return search->second.get();
}
void CBodyStateInfo::SetState(pas::EAnimationState s)
{
auto search = x0_stateMap.find(s);
if (search == x0_stateMap.end())
return;
x14_state = s;
}
CAdditiveBodyState* CBodyStateInfo::GetCurrentAdditiveState()
{
for (auto& state : x1c_additiveStates)
{
if (x2c_additiveState == state.first)
return state.second.get();
}
return nullptr;
}
void CBodyStateInfo::SetAdditiveState(pas::EAnimationState s)
{
for (auto& state : x1c_additiveStates)
{
if (s == state.first)
{
x2c_additiveState = s;
return;
}
}
}
bool CBodyStateInfo::ApplyHeadTracking() const
{
if (x14_state == pas::EAnimationState::Invalid)
return false;
return GetCurrentState()->ApplyHeadTracking();
}
} }

View File

@ -13,11 +13,11 @@ class CActor;
class CBodyStateInfo class CBodyStateInfo
{ {
friend class CBodyController; friend class CBodyController;
std::map<int, std::unique_ptr<CBodyState>> x0_stateMap; std::map<pas::EAnimationState, std::unique_ptr<CBodyState>> x0_stateMap;
int x14_ = -1; pas::EAnimationState x14_state = pas::EAnimationState::Invalid;
CBodyController* x18_bodyController = nullptr; CBodyController* x18_bodyController = nullptr;
std::vector<std::pair<int, std::unique_ptr<CAdditiveBodyState>>> x1c_additiveStates; std::vector<std::pair<pas::EAnimationState, std::unique_ptr<CAdditiveBodyState>>> x1c_additiveStates;
u32 x2c_ = 0x15; pas::EAnimationState x2c_additiveState = pas::EAnimationState::AdditiveIdle;
float x30_maxPitch = 0.f; float x30_maxPitch = 0.f;
bool x34_24_changeLocoAtEndOfAnimOnly; bool x34_24_changeLocoAtEndOfAnimOnly;
std::unique_ptr<CBodyState> SetupRestrictedFlyerBodyStates(int stateId, CActor& actor); std::unique_ptr<CBodyState> SetupRestrictedFlyerBodyStates(int stateId, CActor& actor);
@ -34,6 +34,14 @@ public:
float GetMaximumPitch() const { return x30_maxPitch; } float GetMaximumPitch() const { return x30_maxPitch; }
bool GetLocoAnimChangeAtEndOfAnimOnly() const { return x34_24_changeLocoAtEndOfAnimOnly; } bool GetLocoAnimChangeAtEndOfAnimOnly() const { return x34_24_changeLocoAtEndOfAnimOnly; }
void SetLocoAnimChangeAtEndOfAnimOnly(bool s) { x34_24_changeLocoAtEndOfAnimOnly = s; } void SetLocoAnimChangeAtEndOfAnimOnly(bool s) { x34_24_changeLocoAtEndOfAnimOnly = s; }
CBodyState* GetCurrentState();
const CBodyState* GetCurrentState() const;
pas::EAnimationState GetCurrentStateId() const { return x14_state; }
void SetState(pas::EAnimationState s);
CAdditiveBodyState* GetCurrentAdditiveState();
pas::EAnimationState GetCurrentAdditiveStateId() const { return x2c_additiveState; }
void SetAdditiveState(pas::EAnimationState s);
bool ApplyHeadTracking() const;
}; };
} }

View File

@ -98,7 +98,11 @@ enum class EReactionType
enum class EAdditiveReactionType enum class EAdditiveReactionType
{ {
Invalid = -1,
Electrocution,
One,
Two,
IceBreakout
}; };
enum class EJumpType enum class EJumpType
@ -254,7 +258,7 @@ enum class EBodyStateCmd
AdditiveAim, AdditiveAim,
AdditiveFlinch, AdditiveFlinch,
AdditiveReaction, AdditiveReaction,
TwentySeven StopReaction
}; };
} }

View File

@ -133,6 +133,12 @@ void CActor::RemoveEmitter()
} }
} }
void CActor::SetVolume(float vol)
{
if (x8c_loopingSfxHandle)
CSfxManager::UpdateEmitter(x8c_loopingSfxHandle, GetTranslation(), zeus::CVector3f::skZero, vol);
}
const zeus::CTransform CActor::GetScaledLocatorTransform(const std::string& segName) const const zeus::CTransform CActor::GetScaledLocatorTransform(const std::string& segName) const
{ {
return x64_modelData->GetScaledLocatorTransform(segName); return x64_modelData->GetScaledLocatorTransform(segName);

View File

@ -125,6 +125,7 @@ public:
virtual void DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt); virtual void DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt);
void RemoveEmitter(); void RemoveEmitter();
void SetVolume(float vol);
const zeus::CTransform& GetTransform() const { return x34_transform; } const zeus::CTransform& GetTransform() const { return x34_transform; }
const zeus::CVector3f& GetTranslation() const { return x34_transform.origin; } const zeus::CVector3f& GetTranslation() const { return x34_transform.origin; }
const zeus::CTransform GetScaledLocatorTransform(const std::string& segName) const; const zeus::CTransform GetScaledLocatorTransform(const std::string& segName) const;

View File

@ -184,4 +184,9 @@ std::list<CActorModelParticles::CItem>::const_iterator CActorModelParticles::Fin
return x0_items.cend(); return x0_items.cend();
} }
void CActorModelParticles::StartIce(CActor& actor, CStateManager& mgr)
{
}
} }

View File

@ -15,6 +15,7 @@ class CTexture;
class CElectricDescription; class CElectricDescription;
class CGenDescription; class CGenDescription;
class CParticleElectric; class CParticleElectric;
class CActor;
class CActorModelParticles class CActorModelParticles
{ {
@ -92,6 +93,7 @@ public:
void Update(float dt, CStateManager& mgr); void Update(float dt, CStateManager& mgr);
void SetupHook(TUniqueId uid); void SetupHook(TUniqueId uid);
std::list<CItem>::const_iterator FindSystem(TUniqueId uid) const; std::list<CItem>::const_iterator FindSystem(TUniqueId uid) const;
void StartIce(CActor& actor, CStateManager& mgr);
}; };
} }

View File

@ -82,6 +82,17 @@ private:
u32 _dummy = 0; u32 _dummy = 0;
}; };
ECharacter x34c_character; ECharacter x34c_character;
union
{
struct
{
bool x4e1_24_ : 1;
bool x4e1_25_ : 1;
bool x4e1_26_ : 1;
};
u32 _dummy2 = 0;
};
public: public:
CPatterned(ECharacter character, TUniqueId uid, const std::string& name, EFlavorType flavor, const CEntityInfo& info, CPatterned(ECharacter character, TUniqueId uid, const std::string& name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pinfo, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pinfo,

View File

@ -159,6 +159,7 @@ public:
void SetVelocityWR(const zeus::CVector3f& vel); void SetVelocityWR(const zeus::CVector3f& vel);
void SetVelocityOR(const zeus::CVector3f& vel); void SetVelocityOR(const zeus::CVector3f& vel);
void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; } void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; }
const zeus::CVector3f& GetConstantForce() { return xfc_constantForce; }
void SetConstantForce(const zeus::CVector3f& f) { xfc_constantForce = f; } void SetConstantForce(const zeus::CVector3f& f) { xfc_constantForce = f; }
void SetAngularMomentum(const zeus::CAxisAngle& m) { x108_angularMomentum = m; } void SetAngularMomentum(const zeus::CAxisAngle& m) { x108_angularMomentum = m; }
const zeus::CVector3f& GetMomentum() const { return x150_momentum; } const zeus::CVector3f& GetMomentum() const { return x150_momentum; }

View File

@ -168,7 +168,7 @@ enum class EScriptObjectState
ScanStart, ScanStart,
ScanProcessing, ScanProcessing,
ScanDone, ScanDone,
UNKS9, UnFrozen,
DFST, DFST,
ReflectedDamage, ReflectedDamage,
InheritBounds InheritBounds

View File

@ -39,7 +39,7 @@ public:
size_t size() const { return x0_size; } size_t size() const { return x0_size; }
T& back() const { x4_data[(x0_size == 0) ? 0 : x0_size - 1]; } T& back() const { return x4_data[(x0_size == 0) ? 0 : x0_size - 1]; }
T& front() const { return x4_data[0]; } T& front() const { return x4_data[0]; }
T& operator[](size_t idx) { return x4_data[idx]; } T& operator[](size_t idx) { return x4_data[idx]; }
const T& operator[](size_t idx) const { return x4_data[idx]; } const T& operator[](size_t idx) const { return x4_data[idx]; }

2
hecl

@ -1 +1 @@
Subproject commit 4a3865ec8abe1e2c92dd2d4b70e0cb5039efdf38 Subproject commit 8a6ffc988577d52774e1a377a793c069517cf9a7

2
nod

@ -1 +1 @@
Subproject commit e99290e3c331cf5128b754a63612cd21afcd3c50 Subproject commit d597400f4a83f9bb759b1c1ce44517c2fe7f886d

@ -1 +1 @@
Subproject commit 34bdfdcad75e16e877e1962478ff195372df82a3 Subproject commit ea1f1f7b93352baf8b0142bc9458b6a0f512775e