CFlaahgraTentacle implementations (needs testing)

This commit is contained in:
Phillip Stephens 2019-06-09 17:09:07 -07:00
parent 77d0ef942d
commit b251bc541f
8 changed files with 324 additions and 3 deletions

View File

View File

@ -0,0 +1,15 @@
#pragma once
#include "World/CPatterned.hpp"
namespace urde::MP1 {
class CFlaahgraData {
friend class CFlaahgra;
};
class CFlaahgra : public CPatterned {
public:
DEFINE_PATTERNED(Flaahgra);
};
}

View File

@ -0,0 +1,234 @@
#include "CFlaahgraTentacle.hpp"
#include "Collision/CCollisionActor.hpp"
#include "World/CPlayer.hpp"
#include "World/CScriptTrigger.hpp"
#include "CStateManager.hpp"
#include "TCastTo.hpp"
namespace urde::MP1 {
CFlaahgraTentacle::CFlaahgraTentacle(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
const CActorParameters& actParms)
: CPatterned(ECharacter::FlaahgraTentacle, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Large) {
x58e_24_ = false;
ActorLights()->SetCastShadows(false);
x460_knockBackController.SetAutoResetImpulse(false);
CreateShadow(true);
}
void CFlaahgraTentacle::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
switch (msg) {
case EScriptObjectMessage::Registered: {
x450_bodyController->Activate(mgr);
SetupCollisionManager(mgr);
break;
}
case EScriptObjectMessage::Deleted: {
x56c_collisionManager->Destroy(mgr);
if (TCastToPtr<CScriptTrigger> trigger = mgr.ObjectById(x58c_triggerId)) {
trigger->SetForceVector(x580_forceVector);
}
break;
}
case EScriptObjectMessage::Touched: {
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(uid)) {
if (colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId() && x420_curDamageRemTime <= 0.f) {
mgr.ApplyDamage(mgr.GetPlayer().GetUniqueId(), GetUniqueId(), GetUniqueId(), GetContactDamage(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
x420_curDamageRemTime = x424_damageWaitTime;
}
}
break;
}
case EScriptObjectMessage::Play: {
x578_ = 0.039999999f;
break;
}
case EScriptObjectMessage::Deactivate: {
DeathDelete(mgr);
break;
}
case EScriptObjectMessage::Open: {
ExtractTentacle(mgr);
break;
}
case EScriptObjectMessage::Close: {
RetractTentacle(mgr);
break;
}
case EScriptObjectMessage::InitializedInArea: {
SaveBombSlotInfo(mgr);
break;
}
default:
break;
}
CPatterned::AcceptScriptMsg(msg, uid, mgr);
}
void CFlaahgraTentacle::Think(float dt, CStateManager& mgr) {
if (!GetActive())
return;
CPatterned::Think(dt, mgr);
x56c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
if (x574_ > 0.f)
x574_ -= dt;
if (x578_ > 0.f)
x578_ -= dt;
}
void CFlaahgraTentacle::AddSphereCollisionList(const SSphereJointInfo* sphereJoints, s32 jointCount,
std::vector<CJointCollisionDescription>& outJoints) {
const CAnimData* animData = GetModelData()->GetAnimationData();
for (u32 i = 0; i < jointCount; ++i) {
CSegId segId = animData->GetLocatorSegId(sphereJoints[i].name);
if (segId == 0xFF)
continue;
outJoints.push_back(
CJointCollisionDescription::SphereCollision(segId, sphereJoints->radius, sphereJoints->name, 10.f));
}
}
const SSphereJointInfo CFlaahgraTentacle::skJointList[3] = {{"Arm_8", 2.f}, {"Arm_10", 1.2f}, {"Arm_12", 1.2f}};
void CFlaahgraTentacle::SetupCollisionManager(CStateManager& mgr) {
std::vector<CJointCollisionDescription> jointList;
AddSphereCollisionList(skJointList, 3, jointList);
x56c_collisionManager.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), jointList, true));
for (u32 i = 0; i < x56c_collisionManager->GetNumCollisionActors(); ++i) {
const CJointCollisionDescription& desc = x56c_collisionManager->GetCollisionDescFromIndex(i);
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(desc.GetCollisionActorId())) {
colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Player},
{EMaterialTypes::Character,
EMaterialTypes::CollisionActor,
EMaterialTypes::NoStaticCollision,
EMaterialTypes::NoPlatformCollision}));
colAct->AddMaterial(EMaterialTypes::ScanPassthrough);
colAct->SetDamageVulnerability(*GetDamageVulnerability());
if (x57c_tentacleTipAct == kInvalidUniqueId && desc.GetName() == skpTentacleTip)
x57c_tentacleTipAct = desc.GetCollisionActorId();
}
}
RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
AddMaterial(EMaterialTypes::Scannable, mgr);
}
zeus::CVector3f CFlaahgraTentacle::GetAimPosition(const CStateManager& mgr, float dt) const {
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(x57c_tentacleTipAct))
return colAct->GetTranslation();
return CPatterned::GetAimPosition(mgr, dt);
}
void CFlaahgraTentacle::ExtractTentacle(CStateManager& mgr) {
if (!Inside(mgr, 0.f))
return;
x58e_24_ = true;
if (TCastToPtr<CScriptTrigger> trigger = mgr.ObjectById(x58c_triggerId)) {
trigger->SetForceVector(x580_forceVector);
}
}
void CFlaahgraTentacle::RetractTentacle(CStateManager& mgr) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
if (TCastToPtr<CScriptTrigger> trigger = mgr.ObjectById(x58c_triggerId)) {
trigger->SetForceVector({});
}
}
void CFlaahgraTentacle::SaveBombSlotInfo(CStateManager& mgr) {
for (const SConnection& conn : GetConnectionList()) {
if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::ToggleActive)
continue;
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
if (TCastToConstPtr<CScriptTrigger> trigger = mgr.GetObjectById(uid)) {
x58c_triggerId = uid;
x580_forceVector = trigger->GetForceVector();
return;
}
}
}
bool CFlaahgraTentacle::ShouldAttack(CStateManager& mgr, float) {
if (x578_ > 0.f)
return true;
/* FIXME: Double check this */
if (x574_ > 0.f || mgr.GetPlayer().IsInWaterMovement())
return false;
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(x57c_tentacleTipAct)) {
float mag = (colAct->GetTranslation().toVec2f() - mgr.GetPlayer().GetTranslation().toVec2f()).magSquared();
return mag >= (x2fc_minAttackRange * x2fc_minAttackRange) && mag <= (x300_maxAttackRange * x300_maxAttackRange);
}
return false;
}
void CFlaahgraTentacle::Attack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack)
x568_ = 2;
else
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCMeleeAttackCmd((x578_ > 0.f ? pas::ESeverity::Zero : pas::ESeverity::One), {}));
} else if (x568_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) {
x568_ = 3;
}
} else if (msg == EStateMsg::Deactivate) {
x574_ = (x308_attackTimeVariation * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime;
x578_ = 0.f;
}
}
void CFlaahgraTentacle::Retreat(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Update) {
if (!x58e_24_)
return;
if (x330_stateMachineState.GetTime() <= 1.f)
return;
if (TCastToPtr<CScriptTrigger> trigger = mgr.ObjectById(x58c_triggerId)) {
if (trigger->IsPlayerTriggerProc())
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
}
} else if (msg == EStateMsg::Deactivate) {
x58e_24_ = false;
}
}
void CFlaahgraTentacle::InActive(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x570_ = 0.f;
} else if (msg == EStateMsg::Update) {
if (Inside(mgr, 0.f))
return;
if (TCastToPtr<CScriptTrigger> trigger = mgr.ObjectById(x58c_triggerId)) {
if (trigger->IsPlayerTriggerProc()) {
if (x570_ > 1.f) {
RetractTentacle(mgr);
ExtractTentacle(mgr);
} else
x570_ += arg;
}
}
}
}
}

View File

@ -0,0 +1,44 @@
#pragma once
#include "World/CPatterned.hpp"
#include "Collision/CCollisionActorManager.hpp"
namespace urde::MP1 {
class CFlaahgraTentacle : public CPatterned {
static const SSphereJointInfo skJointList[3];
static constexpr std::string_view skpTentacleTip = "Arm_12"sv;
s32 x568_ = -1;
std::unique_ptr<CCollisionActorManager> x56c_collisionManager;
float x570_ = 0.f;
float x574_ = 0.f;
float x578_ = 0.f;
TUniqueId x57c_tentacleTipAct = kInvalidUniqueId;
zeus::CVector3f x580_forceVector;
TUniqueId x58c_triggerId = kInvalidUniqueId;
bool x58e_24_ : 1;
void AddSphereCollisionList(const SSphereJointInfo*, s32, std::vector<CJointCollisionDescription>&);
void SetupCollisionManager(CStateManager&);
void ExtractTentacle(CStateManager&);
void RetractTentacle(CStateManager&);
void SaveBombSlotInfo(CStateManager&);
public:
DEFINE_PATTERNED(FlaahgraTentacle);
CFlaahgraTentacle(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
const CPatternedInfo&, const CActorParameters&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void Think(float, CStateManager&);
zeus::CVector3f GetAimPosition(const CStateManager&, float) const;
bool Inside(CStateManager&, float) { return x450_bodyController->GetLocomotionType() == pas::ELocomotionType::Crouch; }
bool AnimOver(CStateManager&, float) { return x568_ == 3; }
bool ShouldAttack(CStateManager&, float);
void Dead(CStateManager&, EStateMsg, float) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); }
void Attack(CStateManager&, EStateMsg, float);
void Retreat(CStateManager&, EStateMsg, float);
void InActive(CStateManager&, EStateMsg, float);
};
}

View File

@ -30,6 +30,8 @@ set(MP1_WORLD_SOURCES
CSeedling.hpp CSeedling.cpp CSeedling.hpp CSeedling.cpp
CRidley.hpp CRidley.cpp CRidley.hpp CRidley.cpp
CPuddleToadGamma.hpp CPuddleToadGamma.cpp CPuddleToadGamma.hpp CPuddleToadGamma.cpp
CFlaahgra.hpp CFlaahgra.cpp
CFlaahgraTentacle.hpp CFlaahgraTentacle.cpp
CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp
CSpankWeed.hpp CSpankWeed.cpp CSpankWeed.hpp CSpankWeed.cpp
CPuddleSpore.hpp CPuddleSpore.cpp) CPuddleSpore.hpp CPuddleSpore.cpp)

View File

@ -242,12 +242,12 @@ void CScriptEffect::Render(const CStateManager& mgr) const {
*/ */
if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) { if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) {
g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll(); g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll();
x104_particleSystem->Render(GetActorLights()); x104_particleSystem->Render(x138_actorLights.get());
} }
if (xf4_electric && xf4_electric->GetParticleCount() > 0) { if (xf4_electric && xf4_electric->GetParticleCount() > 0) {
g_NumParticlesRendered += xf4_electric->GetParticleCount(); g_NumParticlesRendered += xf4_electric->GetParticleCount();
xf4_electric->Render(GetActorLights()); xf4_electric->Render(x138_actorLights.get());
} }
} }

View File

@ -84,5 +84,10 @@ public:
ETriggerFlags GetTriggerFlags() const { return x12c_flags; } ETriggerFlags GetTriggerFlags() const { return x12c_flags; }
float GetForceMagnitude() const { return x128_forceMagnitude; } float GetForceMagnitude() const { return x128_forceMagnitude; }
const zeus::CVector3f& GetForceVector() const { return x11c_forceField; } const zeus::CVector3f& GetForceVector() const { return x11c_forceField; }
void SetForceVector(const zeus::CVector3f& force) {
x11c_forceField = force;
x128_forceMagnitude = x11c_forceField.magnitude();
}
bool IsPlayerTriggerProc() const { return x148_28_playerTriggerProc; }
}; };
} // namespace urde } // namespace urde

View File

@ -10,6 +10,8 @@
#include "CScriptActorKeyframe.hpp" #include "CScriptActorKeyframe.hpp"
#include "CScriptActorRotate.hpp" #include "CScriptActorRotate.hpp"
#include "CScriptAiJumpPoint.hpp" #include "CScriptAiJumpPoint.hpp"
#include "MP1/World/CFlaahgra.hpp"
#include "MP1/World/CFlaahgraTentacle.hpp"
#include "CScriptAreaAttributes.hpp" #include "CScriptAreaAttributes.hpp"
#include "MP1/World/CSeedling.hpp" #include "MP1/World/CSeedling.hpp"
#include "MP1/World/CBurrower.hpp" #include "MP1/World/CBurrower.hpp"
@ -2522,7 +2524,26 @@ CEntity* ScriptLoader::LoadAiJumpPoint(CStateManager& mgr, CInputStream& in, int
CEntity* ScriptLoader::LoadFlaahgraTentacle(CStateManager& mgr, CInputStream& in, int propCount, CEntity* ScriptLoader::LoadFlaahgraTentacle(CStateManager& mgr, CInputStream& in, int propCount,
const CEntityInfo& info) { const CEntityInfo& info) {
if (!EnsurePropertyCount(propCount, 6, "FlaahgraTentacle"))
return nullptr; 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);
if (!pInfo.GetAnimationParameters().GetACSFile().IsValid())
return nullptr;
const CAnimationParameters& animParms = pInfo.GetAnimationParameters();
CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), actHead.x40_scale,
animParms.GetInitialAnimation(), true));
return new MP1::CFlaahgraTentacle(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform,
std::move(mData), pInfo, actParms);
} }
CEntity* ScriptLoader::LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { CEntity* ScriptLoader::LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {