From b7b65b04a44288c11252f728c812d524919e9e44 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Mon, 10 Jun 2019 01:28:33 -0700 Subject: [PATCH] Initial Flaahgra implementations --- Runtime/Character/CActorLights.hpp | 2 + .../Collision/CJointCollisionDescription.hpp | 6 + Runtime/MP1/World/CFlaahgra.cpp | 407 ++++++++++++++++++ Runtime/MP1/World/CFlaahgra.hpp | 148 +++++++ Runtime/World/CPatterned.cpp | 6 +- Runtime/World/ScriptLoader.cpp | 27 +- 6 files changed, 593 insertions(+), 3 deletions(-) diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp index 6164f4941..146ae3035 100644 --- a/Runtime/Character/CActorLights.hpp +++ b/Runtime/Character/CActorLights.hpp @@ -68,10 +68,12 @@ public: std::vector BuildLightVector() const; void ActivateLights(CBooModel& model) const; void SetCastShadows(bool v) { x298_25_castShadows = v; } + void SetHasAreaLights(bool v) { x298_26_hasAreaLights = v; } void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; } void SetAmbienceGenerated(bool v) { x298_29_ambienceGenerated = v; } void DisableAreaLights(); + void SetMaxAreaLights(int l) { x2b8_maxAreaLights = l; } void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; } void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; } void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; } diff --git a/Runtime/Collision/CJointCollisionDescription.hpp b/Runtime/Collision/CJointCollisionDescription.hpp index 11366a66f..b08ec09d1 100644 --- a/Runtime/Collision/CJointCollisionDescription.hpp +++ b/Runtime/Collision/CJointCollisionDescription.hpp @@ -4,6 +4,12 @@ #include "zeus/CAABox.hpp" namespace urde { +struct SJointInfo { + const char* from; + const char* to; + float radius; + float separation; +}; struct SOBBJointInfo { const char* from; const char* to; diff --git a/Runtime/MP1/World/CFlaahgra.cpp b/Runtime/MP1/World/CFlaahgra.cpp index e69de29bb..0faaef1c9 100644 --- a/Runtime/MP1/World/CFlaahgra.cpp +++ b/Runtime/MP1/World/CFlaahgra.cpp @@ -0,0 +1,407 @@ +#include "CFlaahgra.hpp" +#include "CDependencyGroup.hpp" +#include "Character/CBoneTracking.hpp" +#include "Collision/CCollisionActor.hpp" +#include "Collision/CCollisionActorManager.hpp" +#include "MP1/World/CFlaahgraProjectile.hpp" +#include "World/CActorParameters.hpp" +#include "World/CGameArea.hpp" +#include "World/CPlayer.hpp" +#include "World/CScriptWaypoint.hpp" +#include "World/CWorld.hpp" +#include "World/ScriptLoader.hpp" +#include "GameGlobalObjects.hpp" +#include "CSimplePool.hpp" +#include "CStateManager.hpp" +#include "TCastTo.hpp" + +namespace urde::MP1 { + +const SJointInfo CFlaahgra::skLeftArmJointList[3]{ + {"L_elbow", "L_blade", 0.6f, 1.f}, {"L_blade", "L_claw", 0.6f, 1.f}, {"L_CLAW_LCTR", "L_CLAW_END_LCTR", 0.6f, 1.f}}; + +const SJointInfo CFlaahgra::skRightArmJointList[3]{ + {"R_elbow", "R_blade", 0.6f, 1.f}, {"R_blade", "R_claw", 0.6f, 1.f}, {"R_CLAW_LCTR", "R_CLAW_END_LCTR", 0.6f, 1.f}}; +const SSphereJointInfo CFlaahgra::skSphereJointList[5]{ + {"Head_1", 1.5f}, {"Spine_2", 1.5f}, {"Spine_4", 1.5f}, {"Spine_6", 1.5f}, {"Collar", 1.5f}}; + +CFlaahgraData::CFlaahgraData(CInputStream& in) +: x0_(in.readFloatBig()) +, x4_(in.readFloatBig()) +, x8_(in.readFloatBig()) +, xc_(in.readFloatBig()) +, x10_(in) +, x78_(in) +, x7c_(in) +, x98_(in) +, x9c_(in) +, xb8_(in) +, xbc_(in) +, xd8_(ScriptLoader::LoadActorParameters(in)) +, x140_(in.readFloatBig()) +, x144_(in.readFloatBig()) +, x148_(in.readFloatBig()) +, x14c_animationParameters(ScriptLoader::LoadAnimationParameters(in)) +, x158_(in) {} + +CFlaahgraRenderer::CFlaahgraRenderer(TUniqueId uid, TUniqueId owner, std::string_view name, const CEntityInfo& info, + const zeus::CTransform& xf) +: CActor(uid, true, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Character), + CActorParameters::None(), kInvalidUniqueId) +, xe8_owner(owner) {} + +void CFlaahgraRenderer::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + + if (const CActor* act = static_cast(mgr.GetObjectById(xe8_owner))) { + if (act->HasModelData() && (act->GetModelData()->HasAnimData() || act->GetModelData()->HasNormalModel())) + act->GetModelData()->RenderParticles(frustum); + } +} +void CFlaahgraRenderer::Accept(IVisitor& visitor) { visitor.Visit(this); } + +CFlaahgra::CFlaahgra(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + const CAnimRes& animRes, const CPatternedInfo& pInfo, const CActorParameters& actParms, + const CFlaahgraData& flaahgraData) +: CPatterned(ECharacter::Flaahgra, uid, name, EFlavorType::Zero, info, xf, CModelData::CModelDataNull(), pInfo, + EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Large) +, x56c_(flaahgraData) +, x6d4_(g_SimplePool->GetObj({SBIG('PART'), x56c_.xb8_})) +, x6dc_(x56c_.x78_, x56c_.x7c_) +, x704_(x56c_.x98_, x56c_.x9c_) +, x7dc_(GetContactDamage()) +, x820_(xf.origin) +, x8a0_(xf.frontVector()) +, x8ac_(animRes) { + x8e5_29_ = true; + x6dc_.Token().Lock(); + x704_.Token().Lock(); + x7dc_.SetDamage(0.5f * x7dc_.GetDamage()); + SetActorLights(actParms.GetLightParameters().MakeActorLights()); + x90_actorLights->SetCastShadows(false); + x90_actorLights->SetMaxAreaLights(2); + x90_actorLights->SetHasAreaLights(x90_actorLights->GetMaxAreaLights() > 0); + x90_actorLights->SetMaxDynamicLights(1); + x460_knockBackController.SetAutoResetImpulse(false); + x460_knockBackController.SetEnableLaggedBurnDeath(false); + x430_damageColor = skDamageColor; + LoadDependencies(x56c_.x158_); + /* TODO: Math that makes me go cross eyed */ +} + +void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + + switch (msg) { + case EScriptObjectMessage::InitializedInArea: { + if (!x8e4_25_loading && !x8e4_24_loaded) { + const_cast(mgr.WorldNC()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()) + ->x113c_playerActorsLoading++; + x8e4_25_loading = true; + } + + GetMirrorWaypoints(mgr); + break; + } + case EScriptObjectMessage::Activate: { + GatherAssets(mgr); + if (x8e5_25_) + break; + + SetupCollisionManagers(mgr); + x6d0_rendererId = mgr.AllocateUniqueId(); + mgr.AddObject(new CFlaahgraRenderer(x6d0_rendererId, GetUniqueId(), "Flaahgra Renderer"sv, + CEntityInfo(GetAreaIdAlways(), NullConnectionList), GetTransform())); + + //x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); + x450_bodyController->Activate(mgr); + x8e5_27_ = true; + break; + } + case EScriptObjectMessage::Deleted: { + if (!x8e5_27_) + break; + + x79c_leftArmCollision->Destroy(mgr); + x7a0_rightArmCollision->Destroy(mgr); + x7a4_sphereCollision->Destroy(mgr); + mgr.FreeScriptObject(x6d0_rendererId); + x6d0_rendererId = kInvalidUniqueId; + x8e5_27_ = false; + break; + } + case EScriptObjectMessage::Touched: { + break; + } + case EScriptObjectMessage::Damage: { + break; + } + case EScriptObjectMessage::Decrement: { + x780_ = 0; + break; + } + case EScriptObjectMessage::Close: { + sub801ae980(mgr); + break; + } + case EScriptObjectMessage::Start: { + x8e4_31_ = false; + break; + } + case EScriptObjectMessage::Stop: { + x8e4_31_ = true; + break; + } + case EScriptObjectMessage::Play: { + x7d0_ = 3.f; + x8e5_24_ = true; + break; + } + case EScriptObjectMessage::Action: { + if (TCastToConstPtr(mgr.GetObjectById(uid))) + x7f8_ = x788_; + break; + } + case EScriptObjectMessage::SetToMax: { + x7d4_ = 0.f; + break; + } + case EScriptObjectMessage::Reset: { + x8e5_28_ = true; + break; + } + default: + break; + } + CPatterned::AcceptScriptMsg(msg, uid, mgr); +} +void CFlaahgra::LoadDependencies(CAssetId dgrpId) { + if (!dgrpId.IsValid()) { + ResetModelDataAndBodyController(); + x8e4_24_loaded = true; + return; + } + + x8c8_depGroup = {g_SimplePool->GetObj({SBIG('DGRP'), dgrpId})}; + x8c8_depGroup->Lock(); +} + +void CFlaahgra::ResetModelDataAndBodyController() { + SetModelData(std::make_unique(x8ac_)); + _CreateShadow(); + CreateShadow(true); + x94_simpleShadow->SetAlwaysCalculateRadius(false); + BuildBodyController(EBodyType::Restricted); + x6cc_boneTracking.reset(new CBoneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), + zeus::degToRad(180.f), EBoneTrackingFlags::None)); +} +void CFlaahgra::GatherAssets(CStateManager& mgr) { + if (x8e4_24_loaded) + return; + + x8c8_depGroup->GetObj(); + LoadTokens(mgr); + + if (x8e4_24_loaded) + return; + + for (const CToken& tok : x8d4_tokens) + tok.GetObj(); + + FinalizeLoad(mgr); +} + +void CFlaahgra::LoadTokens(CStateManager& mgr) { + if (!x8d4_tokens.empty()) { + for (const CToken& tok : x8d4_tokens) { + if (!tok.IsLoaded()) + return; + } + + FinalizeLoad(mgr); + } + + if (!x8c8_depGroup) + return; + + TToken depGroup = *x8c8_depGroup; + if (depGroup->GetObjectTagVector().empty()) { + FinalizeLoad(mgr); + return; + } + + if (x8d4_tokens.empty()) { + x8d4_tokens.reserve(depGroup->GetObjectTagVector().size()); + + for (const auto& tag : depGroup->GetObjectTagVector()) { + CToken token = g_SimplePool->GetObj({tag.type, tag.id}); + token.Lock(); + x8d4_tokens.push_back(token); + } + } +} +void CFlaahgra::FinalizeLoad(CStateManager& mgr) { + x8e4_24_loaded = true; + if (x8e4_25_loading) { + const_cast(mgr.WorldNC()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()) + ->x113c_playerActorsLoading--; + x8e4_25_loading = false; + } + + ResetModelDataAndBodyController(); +} + +void CFlaahgra::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + CPatterned::Think(dt, mgr); + x6cc_boneTracking->Update(dt); + UpdateCollisionManagers(dt, mgr); + x6cc_boneTracking->PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), + *x450_bodyController); + UpdateSmallScaleReGrowth(dt); + UpdateHealthInfo(mgr); + UpdateAimPosition(mgr, dt); + x15c_force = {}; + x168_impulse = {}; +} + +void CFlaahgra::PreThink(float dt, CStateManager& mgr) { + if (!x8e4_24_loaded) + LoadTokens(mgr); + + CPatterned::PreThink(dt, mgr); +} + +void CFlaahgra::GetMirrorWaypoints(CStateManager& mgr) { + x770_mirrorWaypoints.clear(); + + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::Follow) + continue; + TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); + if (TCastToConstPtr wp = mgr.GetObjectById(uid)) + x770_mirrorWaypoints.push_back(uid); + } +} + +void CFlaahgra::AddCollisionList(const SJointInfo* joints, int count, + std::vector& outJoints) { + const CAnimData* animData = GetModelData()->GetAnimationData(); + for (u32 i = 0; i < count; ++i) { + CSegId from = animData->GetLocatorSegId(joints[i].from); + CSegId to = animData->GetLocatorSegId(joints[i].to); + + if (to != 0xFF && from != 0xFF) { + outJoints.push_back(CJointCollisionDescription::SphereSubdivideCollision( + to, from, joints[i].radius, joints[i].separation, CJointCollisionDescription::EOrientationType::One, + joints[i].from, 10.f)); + } + } +} + +void CFlaahgra::AddSphereCollisionList(const SSphereJointInfo* joints, int count, + std::vector& outJoints) { + const CAnimData* animData = GetModelData()->GetAnimationData(); + for (u32 i = 0; i < count; ++i) { + CSegId seg = animData->GetLocatorSegId(joints[i].name); + if (seg != 0xFF) { + outJoints.push_back(CJointCollisionDescription::SphereCollision(seg, joints[i].radius, joints[i].name, 10.f)); + } + } +} + +void CFlaahgra::SetupCollisionManagers(CStateManager& mgr) { + std::vector leftArmjointList; + leftArmjointList.reserve(3); + AddCollisionList(skLeftArmJointList, 3, leftArmjointList); + x79c_leftArmCollision.reset( + new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), leftArmjointList, true)); + SetMaterialProperties(x79c_leftArmCollision, mgr); + std::vector rightArmJointList; + rightArmJointList.reserve(3); + AddCollisionList(skRightArmJointList, 3, rightArmJointList); + x7a0_rightArmCollision.reset( + new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), rightArmJointList, true)); + SetMaterialProperties(x7a0_rightArmCollision, mgr); + std::vector sphereJointList; + sphereJointList.reserve(3); + AddSphereCollisionList(skSphereJointList, 5, sphereJointList); + x7a4_sphereCollision.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), sphereJointList, true)); + SetMaterialProperties(x7a4_sphereCollision, mgr); +} + +void CFlaahgra::sub801ae980(CStateManager& mgr) { + HealthInfo(mgr)->SetHP(HealthInfo(mgr)->GetHP() - x56c_.x8_); + x7d4_ = x56c_.xc_; + x8e4_29_ = true; + x430_damageColor = skUnkColor; + ++x788_; +} + +void CFlaahgra::FadeIn(CStateManager& mgr, EStateMsg msg, float) { + if (msg != EStateMsg::Activate) + return; + + if (HealthInfo(mgr)->GetHP() > 0.f) + SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); + + if (!x8e4_29_) + SendScriptMsgs(EScriptObjectState::CloseIn, mgr, EScriptObjectMessage::None); +} + +void CFlaahgra::FadeOut(CStateManager& mgr, EStateMsg msg, float) { + if (msg != EStateMsg::Activate) + return; + + x7a4_sphereCollision->SetActive(mgr, true); + x79c_leftArmCollision->SetActive(mgr, true); + x7a0_rightArmCollision->SetActive(mgr, true); +} +void CFlaahgra::UpdateCollisionManagers(float dt, CStateManager& mgr) { + x7a4_sphereCollision->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + x79c_leftArmCollision->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + x7a0_rightArmCollision->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); +} +void CFlaahgra::UpdateSmallScaleReGrowth(float) {} +void CFlaahgra::UpdateHealthInfo(CStateManager&) {} +void CFlaahgra::UpdateAimPosition(CStateManager&, float) {} +void CFlaahgra::SetMaterialProperties(const std::unique_ptr& actMgr, CStateManager& mgr) { + for (u32 i = 0; i < actMgr->GetNumCollisionActors(); ++i) { + TUniqueId uid = actMgr->GetCollisionDescFromIndex(i).GetCollisionActorId(); + if (CCollisionActor* colAct = static_cast(mgr.ObjectById(uid))) { + colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Player}, + {EMaterialTypes::Trigger, EMaterialTypes::CollisionActor, EMaterialTypes::Immovable})); + colAct->AddMaterial(EMaterialTypes::Trigger, EMaterialTypes::ScanPassthrough, mgr); + colAct->SetDamageVulnerability(*GetDamageVulnerability()); + } + } +} +bool CFlaahgra::ShouldTurn(CStateManager& mgr, float) { + zeus::CVector2f posDiff = mgr.GetPlayer().GetTranslation().toVec2f() - GetTranslation().toVec2f(); + zeus::CVector2f frontVec = x34_transform.frontVector().toVec2f(); + return zeus::CVector2f::getAngleDiff(frontVec, posDiff) > zeus::degToRad(15.f); +} + +void CFlaahgra::TurnAround(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x6cc_boneTracking->SetTarget(mgr.GetPlayer().GetUniqueId()); + x6cc_boneTracking->SetActive(true); + x8e5_29_ = false; + } else if (msg == EStateMsg::Update) { + if (!ShouldTurn(mgr, 0.f)) + return; + + float dt = 0.f; + if (GetModelData()->GetAnimationData()->GetSpeedScale() > 0.f) + dt = 1.5f / GetModelData()->GetAnimationData()->GetSpeedScale(); + + zeus::CVector3f offset = mgr.GetPlayer().GetAimPosition(mgr, dt) - GetTranslation(); + if (offset.canBeNormalized()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, offset.normalized(), 1.f)); + } + } else if (msg == EStateMsg::Deactivate) { + x6cc_boneTracking->SetActive(false); + } +} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlaahgra.hpp b/Runtime/MP1/World/CFlaahgra.hpp index 2dfc059a3..90154532b 100644 --- a/Runtime/MP1/World/CFlaahgra.hpp +++ b/Runtime/MP1/World/CFlaahgra.hpp @@ -1,15 +1,163 @@ #pragma once +#include "World/CActorParameters.hpp" +#include "World/CAnimationParameters.hpp" #include "World/CPatterned.hpp" +#include "Collision/CJointCollisionDescription.hpp" +#include "Weapon/CProjectileInfo.hpp" +namespace urde { +class CCollisionActorManager; +class CGenDescription; +class CBoneTracking; +class CDependencyGroup; +} namespace urde::MP1 { class CFlaahgraData { friend class CFlaahgra; + float x0_; + float x4_; + float x8_; + float xc_; + CDamageVulnerability x10_; + CAssetId x78_; + CDamageInfo x7c_; + CAssetId x98_; + CDamageInfo x9c_; + CAssetId xb8_; + CDamageInfo xbc_; + CActorParameters xd8_; + float x140_; + float x144_; + float x148_; + CAnimationParameters x14c_animationParameters; + CAssetId x158_; +public: + static constexpr u32 GetNumProperties() { return 23; } + CFlaahgraData(CInputStream&); + + const CAnimationParameters& GetAnimationParameters() const { return x14c_animationParameters; } +}; + +class CFlaahgraRenderer : public CActor { + TUniqueId xe8_owner; +public: + CFlaahgraRenderer(TUniqueId, TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&); + + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Accept(IVisitor&); + rstl::optional GetTouchBounds() const { return {}; } }; class CFlaahgra : public CPatterned { + + static const SJointInfo skLeftArmJointList[3]; + static const SJointInfo skRightArmJointList[3]; + static const SSphereJointInfo skSphereJointList[5]; + static constexpr zeus::CColor skDamageColor = zeus::CColor(0.5f, 0.5f, 0.f, 1.f); + static constexpr zeus::CColor skUnkColor = zeus::CColor(0.5f, 0.f, 0.f, 1.f); + s32 x568_ = -1; + CFlaahgraData x56c_; + std::unique_ptr x6cc_boneTracking; // Used to be an rstl::pair + TUniqueId x6d0_rendererId = kInvalidUniqueId; + TToken x6d4_; + CProjectileInfo x6dc_; + CProjectileInfo x704_; + s32 x72c_ = -1; + u32 x730_ = 0; + rstl::reserved_vector x770_mirrorWaypoints; + TUniqueId x77c_ = kInvalidUniqueId; + u32 x780_ = 1; + u32 x784_ = 1; + u32 x788_ = 0; + zeus::CVector3f x78c_; + s32 x798_ = -1; + std::unique_ptr x79c_leftArmCollision; + std::unique_ptr x7a0_rightArmCollision; + std::unique_ptr x7a4_sphereCollision; + s32 x7a8_ = -1; + u32 x7ac_ = 1; + u32 x7b0_ = 1; + s32 x7b4_ = -1; + float x7b8_ = 0.f; + float x7bc_ = 0.f; + float x7c0_ = 0.f; + float x7c4_ = 0.f; + float x7c8_ = -4.f; + float x7cc_ = 0.f; + float x7d0_ = 0.f; + float x7d4_ = 0.f; + float x7d8_ = 0.f; + CDamageInfo x7dc_; + u32 x7f8_ = 0; + u32 x7fc_ = 0; + TUniqueId x80c_ = kInvalidUniqueId; + float x810_ = 0.f; + float x814_ = 0.f; + float x818_ = 0.f; + zeus::CVector3f x820_; + u32 x82c_ = 0; + u32 x860_ = 0; + zeus::CVector3f x894_; + zeus::CVector3f x8a0_; + CAnimRes x8ac_; + rstl::optional> x8c8_depGroup; + bool x8d0_ = false; + std::vector x8d4_tokens; + union { + struct { + bool x8e4_24_loaded : 1; + bool x8e4_25_loading : 1; + bool x8e4_26_ : 1; + bool x8e4_27_ : 1; + bool x8e4_28_ : 1; + bool x8e4_29_ : 1; + bool x8e4_30_ : 1; + bool x8e4_31_ : 1; + bool x8e5_24_ : 1; + bool x8e5_25_ : 1; + bool x8e5_26_ : 1; + bool x8e5_27_ : 1; + bool x8e5_28_ : 1; + bool x8e5_29_ : 1; + bool x8e5_30_ : 1; + }; + u32 _dummy = 0; + }; + + + void LoadDependencies(CAssetId); + void ResetModelDataAndBodyController(); + void GatherAssets(CStateManager& mgr); + void LoadTokens(CStateManager& mgr); + void FinalizeLoad(CStateManager& mgr); + void GetMirrorWaypoints(CStateManager& mgr); + void AddCollisionList(const SJointInfo*, int, std::vector&); + void AddSphereCollisionList(const SSphereJointInfo*, int, std::vector&); + void SetupCollisionManagers(CStateManager&); + void sub801ae980(CStateManager&); + void UpdateCollisionManagers(float, CStateManager&); + void UpdateSmallScaleReGrowth(float); + void UpdateHealthInfo(CStateManager&); + void UpdateAimPosition(CStateManager&, float); + void SetMaterialProperties(const std::unique_ptr&, CStateManager&); + public: DEFINE_PATTERNED(Flaahgra); + CFlaahgra(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, const CAnimRes&, + const CPatternedInfo&, const CActorParameters&, const CFlaahgraData&); + void Think(float, CStateManager&); + void PreThink(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + bool CanRenderUnsorted(const CStateManager&) const { return true; } + zeus::CVector3f GetAimPosition(const CStateManager&, float) const { return x820_; } + + bool AnimOver(CStateManager&, float) { return x568_ == 4; } + bool ShouldTurn(CStateManager&, float); + + void FadeIn(CStateManager&, EStateMsg, float); + void FadeOut(CStateManager&, EStateMsg, float); + void TurnAround(CStateManager&, EStateMsg, float); }; } \ No newline at end of file diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index c3e873770..66eb4cbab 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -97,8 +97,10 @@ CPatterned::CPatterned(ECharacter character, TUniqueId uid, std::string_view nam x404_contactDamage.SetRadius(0.f); xe6_29_renderParticleDBInside = false; - x402_27_noXrayModel = !x64_modelData->HasModel(CModelData::EWhichModel::XRay); - BuildBodyController(bodyType); + if (x64_modelData) { + x402_27_noXrayModel = !x64_modelData->HasModel(CModelData::EWhichModel::XRay); + BuildBodyController(bodyType); + } } void CPatterned::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 2353e87ff..c6b8020c1 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -2182,7 +2182,32 @@ CEntity* ScriptLoader::LoadPlayerActor(CStateManager& mgr, CInputStream& in, int } CEntity* ScriptLoader::LoadFlaahgra(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { - return nullptr; + if (!EnsurePropertyCount(propCount, MP1::CFlaahgraData::GetNumProperties(), "Flaahgra")) + return nullptr; + + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); + + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + MP1::CFlaahgraData flaahgraData(in); + + CAnimRes animRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true); + + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) { + animRes = CAnimRes(flaahgraData.GetAnimationParameters().GetACSFile(), + flaahgraData.GetAnimationParameters().GetCharacter(), actHead.x40_scale, + flaahgraData.GetAnimationParameters().GetInitialAnimation(), true); + } + + if (!animRes.GetId().IsValid()) + return nullptr; + + return new MP1::CFlaahgra(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, animRes, pInfo, + actParms, flaahgraData); } CEntity* ScriptLoader::LoadAreaAttributes(CStateManager& mgr, CInputStream& in, int propCount,