mirror of https://github.com/AxioDL/metaforce.git
Merge branch 'master' of ssh://git.axiodl.com:6431/AxioDL/urde
This commit is contained in:
commit
41ae32be31
|
@ -93,6 +93,8 @@ public:
|
||||||
s32 GetShadowLightIndex() const { return x2a0_shadowLightIdx; }
|
s32 GetShadowLightIndex() const { return x2a0_shadowLightIdx; }
|
||||||
u32 GetAreaUpdateFramePeriod() const { return x2a8_areaUpdateFramePeriod; }
|
u32 GetAreaUpdateFramePeriod() const { return x2a8_areaUpdateFramePeriod; }
|
||||||
void SetAreaUpdateFramePeriod(u32 p) { x2a8_areaUpdateFramePeriod = p; }
|
void SetAreaUpdateFramePeriod(u32 p) { x2a8_areaUpdateFramePeriod = p; }
|
||||||
|
zeus::CVector3f GetActorPositionBias() const { return x2ac_actorPosBias; }
|
||||||
|
void SetActorPositionBias(const zeus::CVector3f& bias) { x2ac_actorPosBias = bias; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,9 +91,9 @@ public:
|
||||||
CBCGenerateCmd(pas::EGenerateType type, s32 animId = -1)
|
CBCGenerateCmd(pas::EGenerateType type, s32 animId = -1)
|
||||||
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId)
|
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId)
|
||||||
{ x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
|
{ x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
|
||||||
CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec)
|
CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec, bool targetTransform = false, bool overrideAnim = false)
|
||||||
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), xc_targetPos(vec)
|
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), xc_targetPos(vec)
|
||||||
{ x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
|
{ x1c_24_targetTransform = targetTransform; x1c_25_overrideAnim = overrideAnim; }
|
||||||
pas::EGenerateType GetGenerateType() const { return x8_type; }
|
pas::EGenerateType GetGenerateType() const { return x8_type; }
|
||||||
const zeus::CVector3f& GetExitTargetPos() const { return xc_targetPos; }
|
const zeus::CVector3f& GetExitTargetPos() const { return xc_targetPos; }
|
||||||
bool HasExitTargetPos() const { return x1c_24_targetTransform; }
|
bool HasExitTargetPos() const { return x1c_24_targetTransform; }
|
||||||
|
|
|
@ -7,21 +7,21 @@ namespace pas
|
||||||
enum class ELocomotionType
|
enum class ELocomotionType
|
||||||
{
|
{
|
||||||
Invalid = -1,
|
Invalid = -1,
|
||||||
Crouch,
|
Crouch = 0,
|
||||||
Relaxed,
|
Relaxed = 1,
|
||||||
Lurk,
|
Lurk = 2,
|
||||||
Combat,
|
Combat = 3,
|
||||||
Internal4,
|
Internal4 = 4,
|
||||||
Internal5,
|
Internal5 = 5,
|
||||||
Internal6,
|
Internal6 = 6,
|
||||||
Internal7,
|
Internal7 = 7,
|
||||||
Internal8,
|
Internal8 = 8,
|
||||||
Internal9,
|
Internal9 = 9,
|
||||||
Internal10,
|
Internal10 = 10,
|
||||||
Internal11,
|
Internal11 = 11,
|
||||||
Internal12,
|
Internal12 = 12,
|
||||||
Internal13,
|
Internal13 = 13,
|
||||||
Internal14
|
Internal14 = 14
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ELocomotionAnim
|
enum class ELocomotionAnim
|
||||||
|
|
|
@ -5,6 +5,19 @@
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
struct SOBBJointDescription
|
||||||
|
{
|
||||||
|
const char* from;
|
||||||
|
const char* to;
|
||||||
|
zeus::CVector3f bounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SSphereJointDescription
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
class CJointCollisionDescription
|
class CJointCollisionDescription
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -111,7 +111,7 @@ public:
|
||||||
|
|
||||||
void Add(EMaterialTypes type)
|
void Add(EMaterialTypes type)
|
||||||
{
|
{
|
||||||
x0_list |= (1ull << u32(type));
|
x0_list |= (1ull << u64(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Add(const CMaterialList& l)
|
void Add(const CMaterialList& l)
|
||||||
|
@ -121,7 +121,7 @@ public:
|
||||||
|
|
||||||
void Remove(EMaterialTypes type)
|
void Remove(EMaterialTypes type)
|
||||||
{
|
{
|
||||||
x0_list &= ~(1ull << u32(type));
|
x0_list &= ~(1ull << u64(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Remove(const CMaterialList& other)
|
void Remove(const CMaterialList& other)
|
||||||
|
@ -131,7 +131,7 @@ public:
|
||||||
|
|
||||||
bool HasMaterial(EMaterialTypes type) const
|
bool HasMaterial(EMaterialTypes type) const
|
||||||
{
|
{
|
||||||
return (x0_list & (1ull << u32(type))) != 0;
|
return (x0_list & (1ull << u64(type))) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharesMaterials(const CMaterialList& other)
|
bool SharesMaterials(const CMaterialList& other)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "Weapon/CGameProjectile.hpp"
|
#include "Weapon/CGameProjectile.hpp"
|
||||||
#include "Weapon/CPlasmaProjectile.hpp"
|
#include "Weapon/CPlasmaProjectile.hpp"
|
||||||
#include "World/CPlayer.hpp"
|
#include "World/CPlayer.hpp"
|
||||||
|
#include "World/CWorld.hpp"
|
||||||
|
#include "World/CGameArea.hpp"
|
||||||
#include "CStateManager.hpp"
|
#include "CStateManager.hpp"
|
||||||
#include "TCastTo.hpp"
|
#include "TCastTo.hpp"
|
||||||
namespace urde::MP1
|
namespace urde::MP1
|
||||||
|
@ -13,13 +15,18 @@ CEyeball::CEyeball(TUniqueId uid, std::string_view name, CPatterned::EFlavorType
|
||||||
u32 w1, u32 w2, u32 w3, u32 w4, u32 w5,
|
u32 w1, u32 w2, u32 w3, u32 w4, u32 w5,
|
||||||
bool b1, const CActorParameters& actParms)
|
bool b1, const CActorParameters& actParms)
|
||||||
: CPatterned(ECharacter::EyeBall, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
|
: CPatterned(ECharacter::EyeBall, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
|
||||||
EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::Medium), x568_(f1), x56c_(f2),
|
EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::Medium), x568_attackDelay(f1), x56c_maxAttackDelay(f2),
|
||||||
x570_boneTracking(*GetModelData()->GetAnimationData(), "Eye"sv, zeus::degToRad(45.f),
|
x570_boneTracking(*GetModelData()->GetAnimationData(), "Eye"sv, zeus::degToRad(45.f),
|
||||||
zeus::degToRad(180.f), true), x5b4_projectileInfo(aId1, dInfo), x5dc_(aId2), x5e0_(aId3),
|
zeus::degToRad(180.f), true), x5b4_projectileInfo(aId1, dInfo), x5dc_(aId2), x5e0_(aId3),
|
||||||
x5e4_(aId4),
|
x5e4_(aId4),
|
||||||
x5e8_(aId5), x5f4_(w1), x5f8_(w2), x5fc_(w3), x600_(w4), x604_(CSfxManager::TranslateSFXID(w5)), x60c_24_(false),
|
x5e8_(aId5), x604_beamSfxId(CSfxManager::TranslateSFXID(w5)), x60c_24_canAttack(false),
|
||||||
x60c_25_(false), x60c_26_alert(false), x60c_27_(b1), x60c_28_(false)
|
x60c_25_playerInRange(false), x60c_26_alert(false), x60c_27_attackDisabled(b1), x60c_28_firingBeam(false)
|
||||||
{
|
{
|
||||||
|
x5f4_animIdxs[0] = w1;
|
||||||
|
x5f4_animIdxs[1] = w2;
|
||||||
|
x5f4_animIdxs[2] = w3;
|
||||||
|
x5f4_animIdxs[3] = w4;
|
||||||
|
|
||||||
x460_knockBackController.SetAutoResetImpulse(false);
|
x460_knockBackController.SetAutoResetImpulse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,10 +68,10 @@ void CEyeball::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMa
|
||||||
if (x5ec_projectileId != kInvalidUniqueId)
|
if (x5ec_projectileId != kInvalidUniqueId)
|
||||||
{
|
{
|
||||||
mgr.FreeScriptObject(x5ec_projectileId);
|
mgr.FreeScriptObject(x5ec_projectileId);
|
||||||
if (x608_)
|
if (x608_beamSfx)
|
||||||
{
|
{
|
||||||
CSfxManager::RemoveEmitter(x608_);
|
CSfxManager::RemoveEmitter(x608_beamSfx);
|
||||||
x608_.reset();
|
x608_beamSfx.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x5ec_projectileId = kInvalidUniqueId;
|
x5ec_projectileId = kInvalidUniqueId;
|
||||||
|
@ -76,6 +83,47 @@ void CEyeball::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMa
|
||||||
CPatterned::AcceptScriptMsg(msg, uid, mgr);
|
CPatterned::AcceptScriptMsg(msg, uid, mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float kMinAngle = std::cos(zeus::degToRad(45.f));
|
||||||
|
void CEyeball::Think(float dt, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
CPatterned::Think(dt, mgr);
|
||||||
|
if (!GetActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
CPlayer& player = mgr.GetPlayer();
|
||||||
|
zeus::CVector3f direction = (player.GetTranslation() - GetTranslation()).normalized();
|
||||||
|
|
||||||
|
x60c_25_playerInRange = (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed &&
|
||||||
|
direction.dot(GetTransform().frontVector()) > kMinAngle);
|
||||||
|
|
||||||
|
if (x60c_25_playerInRange)
|
||||||
|
{
|
||||||
|
x570_boneTracking.SetActive(true);
|
||||||
|
x5a8_targetPosition = player.GetTranslation() - (0.5f * player.GetVelocity());
|
||||||
|
x570_boneTracking.SetTargetPosition(x5a8_targetPosition);
|
||||||
|
x570_boneTracking.Update(dt);
|
||||||
|
ModelData()->AnimationData()->PreRender();
|
||||||
|
x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(),
|
||||||
|
*x450_bodyController.get());
|
||||||
|
} else
|
||||||
|
x570_boneTracking.SetActive(false);
|
||||||
|
|
||||||
|
if (GetActive())
|
||||||
|
{
|
||||||
|
CPlasmaProjectile* projectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId));
|
||||||
|
if (projectile && projectile->GetActive())
|
||||||
|
projectile->UpdateFX(GetLctrTransform(skEyeLocator), dt, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x60c_28_firingBeam)
|
||||||
|
{
|
||||||
|
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways());
|
||||||
|
if (area->GetActive() && area->IsPostConstructed() &&
|
||||||
|
area->GetPostConstructed()->x10dc_occlusionState == CGameArea::EOcclusionState::Occluded)
|
||||||
|
ResetBeamState(mgr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CEyeball::CreateBeam(CStateManager& mgr)
|
void CEyeball::CreateBeam(CStateManager& mgr)
|
||||||
{
|
{
|
||||||
if (x5ec_projectileId != kInvalidUniqueId)
|
if (x5ec_projectileId != kInvalidUniqueId)
|
||||||
|
@ -102,8 +150,8 @@ void CEyeball::Cover(CStateManager&, EStateMsg msg, float)
|
||||||
if (msg == EStateMsg::Activate)
|
if (msg == EStateMsg::Activate)
|
||||||
{
|
{
|
||||||
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
|
||||||
x60c_24_ = false;
|
x60c_24_canAttack = false;
|
||||||
x330_stateMachineState.SetDelay(x568_);
|
x330_stateMachineState.SetDelay(x568_attackDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +160,7 @@ void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg)
|
||||||
if (msg == EStateMsg::Activate)
|
if (msg == EStateMsg::Activate)
|
||||||
{
|
{
|
||||||
x32c_animState = EAnimState::One;
|
x32c_animState = EAnimState::One;
|
||||||
x330_stateMachineState.SetDelay(x568_);
|
x330_stateMachineState.SetDelay(x568_attackDelay);
|
||||||
}
|
}
|
||||||
else if (msg == EStateMsg::Update)
|
else if (msg == EStateMsg::Update)
|
||||||
TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0);
|
TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0);
|
||||||
|
@ -131,31 +179,99 @@ void CEyeball::Active(CStateManager& mgr, EStateMsg msg, float)
|
||||||
{
|
{
|
||||||
x400_24_hitByPlayerProjectile = 0;
|
x400_24_hitByPlayerProjectile = 0;
|
||||||
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat);
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat);
|
||||||
x60c_24_ = false;
|
x60c_24_canAttack = false;
|
||||||
}
|
}
|
||||||
else if (msg == EStateMsg::Update)
|
else if (msg == EStateMsg::Update)
|
||||||
{
|
{
|
||||||
if (x330_stateMachineState.GetDelay() > x56c_)
|
if (x330_stateMachineState.GetDelay() > x56c_maxAttackDelay)
|
||||||
x60c_24_ = true;
|
x60c_24_canAttack = true;
|
||||||
|
|
||||||
sub802249c8();
|
UpdateAnimation();
|
||||||
}
|
}
|
||||||
else if (msg == EStateMsg::Deactivate)
|
else if (msg == EStateMsg::Deactivate)
|
||||||
{
|
{
|
||||||
x330_stateMachineState.SetDelay(x568_);
|
x330_stateMachineState.SetDelay(x568_attackDelay);
|
||||||
if (CPlasmaProjectile* proj = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId)))
|
if (CPlasmaProjectile* proj = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId)))
|
||||||
proj->ResetBeam(mgr, true);
|
proj->ResetBeam(mgr, true);
|
||||||
|
|
||||||
x60c_24_ = false;
|
x60c_24_canAttack = false;
|
||||||
|
|
||||||
CSfxManager::RemoveEmitter(x608_);
|
CSfxManager::RemoveEmitter(x608_beamSfx);
|
||||||
x608_.reset();
|
x608_beamSfx.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEyeball::sub802249c8()
|
void CEyeball::UpdateAnimation()
|
||||||
{
|
{
|
||||||
|
if (std::fabs(GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) - 0.f) >= 0.00001f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
x5f0_currentAnim = (x5f0_currentAnim + 1) & 3;
|
||||||
|
for (u32 i=0 ; i<4 ; ++i)
|
||||||
|
{
|
||||||
|
if (x5f4_animIdxs[x5f0_currentAnim] != -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
x5f0_currentAnim = (x5f0_currentAnim + 1) & 3;
|
||||||
|
}
|
||||||
|
s32 animIdx = x5f4_animIdxs[x5f0_currentAnim];
|
||||||
|
if (animIdx != -1)
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCScriptedCmd(animIdx, false, false, 0.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CEyeball::ResetBeamState(CStateManager& mgr)
|
||||||
|
{
|
||||||
|
if (CPlasmaProjectile* projectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId)))
|
||||||
|
projectile->ResetBeam(mgr, true);
|
||||||
|
|
||||||
|
x60c_28_firingBeam = false;
|
||||||
|
if (x608_beamSfx)
|
||||||
|
{
|
||||||
|
CSfxManager::RemoveEmitter(x608_beamSfx);
|
||||||
|
x608_beamSfx.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEyeball::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt)
|
||||||
|
{
|
||||||
|
if (type == EUserEventType::DamageOff)
|
||||||
|
ResetBeamState(mgr);
|
||||||
|
else if (type == EUserEventType::DamageOn && x60c_24_canAttack)
|
||||||
|
FireBeam(mgr, GetLctrTransform(node.GetLocatorName()));
|
||||||
|
else
|
||||||
|
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEyeball::FireBeam(CStateManager& mgr, const zeus::CTransform& xf)
|
||||||
|
{
|
||||||
|
if (CPlasmaProjectile* projectile = static_cast<CPlasmaProjectile*>(mgr.ObjectById(x5ec_projectileId)))
|
||||||
|
{
|
||||||
|
if (!projectile->GetActive())
|
||||||
|
{
|
||||||
|
projectile->Fire(xf, mgr, false);
|
||||||
|
x60c_28_firingBeam = true;
|
||||||
|
if (!x608_beamSfx)
|
||||||
|
{
|
||||||
|
CAudioSys::C3DEmitterParmData
|
||||||
|
parmData{GetTranslation(), {}, 50.f, 0.1f, 0x1, x604_beamSfxId, 1.f /* 127 */, 0.15f /* 20 / 127 */,
|
||||||
|
false, 127};
|
||||||
|
x608_beamSfx = CSfxManager::AddEmitter(parmData, true, 127, true, GetAreaIdAlways());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEyeball::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum)
|
||||||
|
{
|
||||||
|
CPatterned::PreRender(mgr, frustum);
|
||||||
|
x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(),
|
||||||
|
*x450_bodyController);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEyeball::Death(CStateManager& mgr, const zeus::CVector3f& pos, EScriptObjectState state)
|
||||||
|
{
|
||||||
|
zeus::CTransform oldXf = GetTransform();
|
||||||
|
CPatterned::Death(mgr, pos, state);
|
||||||
|
SetTransform(oldXf);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,33 +8,32 @@ namespace urde::MP1
|
||||||
{
|
{
|
||||||
class CEyeball : public CPatterned
|
class CEyeball : public CPatterned
|
||||||
{
|
{
|
||||||
float x568_;
|
static constexpr std::string_view skEyeLocator="Laser_LCTR"sv;
|
||||||
float x56c_;
|
float x568_attackDelay;
|
||||||
|
float x56c_maxAttackDelay;
|
||||||
CBoneTracking x570_boneTracking;
|
CBoneTracking x570_boneTracking;
|
||||||
zeus::CVector3f x5a8_;
|
zeus::CVector3f x5a8_targetPosition;
|
||||||
CProjectileInfo x5b4_projectileInfo;
|
CProjectileInfo x5b4_projectileInfo;
|
||||||
CAssetId x5dc_;
|
CAssetId x5dc_;
|
||||||
CAssetId x5e0_;
|
CAssetId x5e0_;
|
||||||
CAssetId x5e4_;
|
CAssetId x5e4_;
|
||||||
CAssetId x5e8_;
|
CAssetId x5e8_;
|
||||||
TUniqueId x5ec_projectileId = kInvalidUniqueId;
|
TUniqueId x5ec_projectileId = kInvalidUniqueId;
|
||||||
u32 x5f0_ = 0;
|
u32 x5f0_currentAnim = 0;
|
||||||
u32 x5f4_;
|
s32 x5f4_animIdxs[4];
|
||||||
u32 x5f8_;
|
u16 x604_beamSfxId;
|
||||||
u32 x5fc_;
|
CSfxHandle x608_beamSfx = 0;
|
||||||
u32 x600_;
|
bool x60c_24_canAttack : 1;
|
||||||
s16 x604_;
|
bool x60c_25_playerInRange : 1;
|
||||||
CSfxHandle x608_ = 0;
|
|
||||||
bool x60c_24_ : 1;
|
|
||||||
bool x60c_25_ : 1;
|
|
||||||
bool x60c_26_alert : 1;
|
bool x60c_26_alert : 1;
|
||||||
bool x60c_27_ : 1;
|
bool x60c_27_attackDisabled : 1;
|
||||||
bool x60c_28_ : 1;
|
bool x60c_28_firingBeam : 1;
|
||||||
|
|
||||||
void CreateBeam(CStateManager&);
|
void CreateBeam(CStateManager&);
|
||||||
|
void FireBeam(CStateManager&, const zeus::CTransform&);
|
||||||
void TryFlinch(CStateManager&, int);
|
void TryFlinch(CStateManager&, int);
|
||||||
void sub802249c8();
|
void UpdateAnimation();
|
||||||
|
void ResetBeamState(CStateManager&);
|
||||||
public:
|
public:
|
||||||
DEFINE_PATTERNED(EyeBall)
|
DEFINE_PATTERNED(EyeBall)
|
||||||
|
|
||||||
|
@ -43,8 +42,13 @@ public:
|
||||||
CAssetId, CAssetId, u32, u32, u32, u32, u32, bool, const CActorParameters&);
|
CAssetId, CAssetId, u32, u32, u32, u32, u32, bool, const CActorParameters&);
|
||||||
|
|
||||||
void Accept(IVisitor& visitor);
|
void Accept(IVisitor& visitor);
|
||||||
|
void PreRender(CStateManager&, const zeus::CFrustum&);
|
||||||
|
void Touch(CActor&, CStateManager&) {};
|
||||||
|
void Death(CStateManager&, const zeus::CVector3f&, EScriptObjectState);
|
||||||
|
|
||||||
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr);
|
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr);
|
||||||
|
void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float);
|
||||||
|
void Think(float, CStateManager&);
|
||||||
void Flinch(CStateManager&, EStateMsg, float);
|
void Flinch(CStateManager&, EStateMsg, float);
|
||||||
void Active(CStateManager&, EStateMsg, float);
|
void Active(CStateManager&, EStateMsg, float);
|
||||||
void InActive(CStateManager&, EStateMsg, float);
|
void InActive(CStateManager&, EStateMsg, float);
|
||||||
|
@ -52,6 +56,6 @@ public:
|
||||||
void Cover(CStateManager&, EStateMsg, float);
|
void Cover(CStateManager&, EStateMsg, float);
|
||||||
|
|
||||||
bool ShouldAttack(CStateManager&, float) { return x60c_26_alert; }
|
bool ShouldAttack(CStateManager&, float) { return x60c_26_alert; }
|
||||||
bool ShouldFire(CStateManager&, float) { return !x60c_27_; }
|
bool ShouldFire(CStateManager&, float) { return !x60c_27_attackDisabled; }
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -28,6 +28,7 @@ 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
|
||||||
CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp)
|
CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp
|
||||||
|
CSpankWeed.hpp CSpankWeed.cpp)
|
||||||
|
|
||||||
runtime_add_list(World MP1_WORLD_SOURCES)
|
runtime_add_list(World MP1_WORLD_SOURCES)
|
||||||
|
|
|
@ -37,24 +37,11 @@ void CNewIntroBoss::Accept(IVisitor &visitor)
|
||||||
visitor.Visit(this);
|
visitor.Visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SSphereJointDescription
|
|
||||||
{
|
|
||||||
const char* name;
|
|
||||||
float radius;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const SSphereJointDescription skSphereJoints[] ={
|
static const SSphereJointDescription skSphereJoints[] ={
|
||||||
{"Head_1", 1.5f},
|
{"Head_1", 1.5f},
|
||||||
{"Tail_1", 1.5f}
|
{"Tail_1", 1.5f}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SOBBJointDescription
|
|
||||||
{
|
|
||||||
const char* from;
|
|
||||||
const char* to;
|
|
||||||
zeus::CVector3f bounds;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const SOBBJointDescription skOBBJoints[] = {
|
static const SOBBJointDescription skOBBJoints[] = {
|
||||||
{"Pelvis", "Spine_3", {4.f, 1.f, 4.f}},
|
{"Pelvis", "Spine_3", {4.f, 1.f, 4.f}},
|
||||||
{"Spine_3", "Tail_1", {2.f, 1.f, 2.f}},
|
{"Spine_3", "Tail_1", {2.f, 1.f, 2.f}},
|
||||||
|
|
|
@ -1,17 +1,363 @@
|
||||||
#include "CPuddleToadGamma.hpp"
|
#include "CPuddleToadGamma.hpp"
|
||||||
|
#include "GameGlobalObjects.hpp"
|
||||||
|
#include "CSimplePool.hpp"
|
||||||
|
#include "CStateManager.hpp"
|
||||||
|
#include "World/CPlayer.hpp"
|
||||||
|
#include "Collision/CGameCollision.hpp"
|
||||||
|
#include "TCastTo.hpp"
|
||||||
|
|
||||||
namespace urde::MP1
|
namespace urde::MP1
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const zeus::CVector3f CPuddleToadGamma::skBellyOffset(0.f, 0.1f, -.3f);
|
||||||
|
|
||||||
CPuddleToadGamma::CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
|
CPuddleToadGamma::CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
|
||||||
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
|
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
|
||||||
const CActorParameters& aParms, float f1, float f2, float f3,
|
const CActorParameters& aParms, float f1, float f2, float f3,
|
||||||
const zeus::CVector3f& v1,
|
const zeus::CVector3f& v1, float f4, float f5, float f6, const CDamageInfo& dInfo1,
|
||||||
float f4, float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2)
|
const CDamageInfo& dInfo2, CAssetId dcln)
|
||||||
: CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
|
: CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
|
||||||
EColliderType::Zero, EBodyType::Restricted, aParms, EKnockBackVariant::Large)
|
EColliderType::Zero, EBodyType::Restricted, aParms, EKnockBackVariant::Large), x570_(dInfo1),
|
||||||
|
x58c_(dInfo2), x5a8_(f1), x5ac_(std::cos(zeus::degToRad(f2 * 0.5f))), x5b0_(f3), x5b4_(v1), x5c0_(f4), x5c4_(f5),
|
||||||
|
x5c8_(f6), x5e8_24_(false), x5e8_25_(false), x5e8_26_(false)
|
||||||
|
{
|
||||||
|
x401_26_disableMove = true;
|
||||||
|
x460_knockBackController.SetEnableBurn(false);
|
||||||
|
x460_knockBackController.SetEnableLaggedBurnDeath(false);
|
||||||
|
x460_knockBackController.SetEnableShock(false);
|
||||||
|
x460_knockBackController.SetX81_31(false);
|
||||||
|
SetMovable(false);
|
||||||
|
if (dcln.IsValid() && g_ResFactory->GetResourceTypeById(dcln) != 0)
|
||||||
|
{
|
||||||
|
TLockedToken<CCollidableOBBTreeGroupContainer> container = g_SimplePool->GetObj({FOURCC('DCLN'), dcln});
|
||||||
|
x5e4_collisionTreePrim.reset(new CCollidableOBBTreeGroup(container.GetObj(), GetMaterialList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::SetSolid(CStateManager& mgr, bool solid)
|
||||||
|
{
|
||||||
|
if (solid)
|
||||||
|
{
|
||||||
|
AddMaterial(EMaterialTypes::Solid, mgr);
|
||||||
|
RemoveMaterial(EMaterialTypes::NonSolidDamageable, mgr);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
RemoveMaterial(EMaterialTypes::Solid, mgr);
|
||||||
|
AddMaterial(EMaterialTypes::NonSolidDamageable, mgr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CCollisionPrimitive* CPuddleToadGamma::GetCollisionPrimitive() const
|
||||||
|
{
|
||||||
|
if (!x5e4_collisionTreePrim)
|
||||||
|
return CPhysicsActor::GetCollisionPrimitive();
|
||||||
|
return x5e4_collisionTreePrim.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CTransform CPuddleToadGamma::GetPrimitiveTransform() const
|
||||||
|
{
|
||||||
|
zeus::CTransform xf = GetTransform();
|
||||||
|
xf.origin += GetPrimitiveOffset();
|
||||||
|
return xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
CPatterned::AcceptScriptMsg(msg, uid, mgr);
|
||||||
|
|
||||||
|
if (msg == EScriptObjectMessage::Registered)
|
||||||
|
{
|
||||||
|
x450_bodyController->Activate(mgr);
|
||||||
|
zeus::CTransform bellyXf = GetLctrTransform(mBellyLocatorName);
|
||||||
|
zeus::CVector3f bellyOffset = GetTransform().rotate(skBellyOffset);
|
||||||
|
x5d8_ = x5cc_ = bellyXf.origin + bellyOffset;
|
||||||
|
RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
|
||||||
|
AddMaterial(EMaterialTypes::Immovable, mgr);
|
||||||
|
AddMaterial(EMaterialTypes::SolidCharacter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::Think(float dt, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
CPatterned::Think(dt, mgr);
|
||||||
|
if (x5e8_25_)
|
||||||
|
x56c_ += dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::experimental::optional<zeus::CAABox> CPuddleToadGamma::GetTouchBounds() const
|
||||||
|
{
|
||||||
|
if (!GetActive())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return (x5e4_collisionTreePrim ? x5e4_collisionTreePrim->CalculateAABox(GetTransform()) : GetBoundingBox());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::CenterPlayer(CStateManager& mgr, const zeus::CVector3f& pos, float dt)
|
||||||
|
{
|
||||||
|
zeus::CVector3f dir = (mgr.GetPlayer().GetTranslation() - pos).normalized();
|
||||||
|
mgr.GetPlayer().SetVelocityWR((1.f / (2.f * dt)) * dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CDamageVulnerability* CPuddleToadGamma::GetDamageVulnerability(const zeus::CVector3f& pos,
|
||||||
|
const zeus::CVector3f& dir,
|
||||||
|
const CDamageInfo& dInfo) const
|
||||||
|
{
|
||||||
|
if (x5e8_24_ && (x5d8_ - pos).magSquared() < 4.f)
|
||||||
|
return CAi::GetDamageVulnerability();
|
||||||
|
|
||||||
|
return &CDamageVulnerability::ImmuneVulnerabilty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt)
|
||||||
|
{
|
||||||
|
if (type == EUserEventType::Projectile)
|
||||||
|
{
|
||||||
|
ShootPlayer(mgr, x5c0_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPuddleToadGamma::SpotPlayer(CStateManager&, float arg)
|
||||||
|
{
|
||||||
|
return x56c_ >= x5c8_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPuddleToadGamma::ShouldAttack(CStateManager&, float)
|
||||||
|
{
|
||||||
|
return x56c_ >= x5c4_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPuddleToadGamma::LostInterest(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
zeus::CAABox box = *GetTouchBounds();
|
||||||
|
zeus::CAABox plBox = mgr.GetPlayer().GetBoundingBox();
|
||||||
|
return !box.intersects(plBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::ShootPlayer(CStateManager&, float)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPuddleToadGamma::InAttackPosition(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
return mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed &&
|
||||||
|
PlayerInVortexArea(mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CMaterialFilter kSolidFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid},
|
||||||
|
{EMaterialTypes::Character,
|
||||||
|
EMaterialTypes::Player,
|
||||||
|
EMaterialTypes::ProjectilePassthrough});
|
||||||
|
|
||||||
|
bool CPuddleToadGamma::PlayerInVortexArea(const CStateManager& mgr)
|
||||||
|
{
|
||||||
|
CPlayer& player = mgr.GetPlayer();
|
||||||
|
zeus::CTransform xf = GetLctrTransform(mMouthLocatorName);
|
||||||
|
|
||||||
|
zeus::CVector3f playerOffset =
|
||||||
|
player.GetTranslation() + zeus::CVector3f{0.f, 0.f, player.GetMorphBall()->GetBallRadius()};
|
||||||
|
zeus::CVector3f rotatedOffset = GetTransform().rotate(zeus::CVector3f::skForward);
|
||||||
|
|
||||||
|
zeus::CVector3f vec1 = (playerOffset - (xf.origin - (1.f * rotatedOffset)));
|
||||||
|
float f31 = vec1.normalized().dot(rotatedOffset);
|
||||||
|
float f28 = vec1.magnitude();
|
||||||
|
float f26 = (player.GetTranslation() - (xf.origin - (4.f * rotatedOffset))).normalized().dot(rotatedOffset);
|
||||||
|
if (f28 > 2.f)
|
||||||
|
{
|
||||||
|
CRayCastResult result = mgr.RayStaticIntersection(vec1, 1.f / f28 * vec1,
|
||||||
|
f28 - player.GetMorphBall()->GetBallRadius(), kSolidFilter);
|
||||||
|
if (result.IsValid())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (f28 < x5b0_ && f31 > 0.f && f26 > x5ac_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::InActive(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
||||||
|
SetSolid(mgr, true);
|
||||||
|
mgr.GetPlayer().Set_X590(true);
|
||||||
|
x330_stateMachineState.SetDelay(2.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::Active(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
|
||||||
|
zeus::CTransform xf = GetLctrTransform(mBellyLocatorName);
|
||||||
|
x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset);
|
||||||
|
x56c_ = 0.f;
|
||||||
|
x5e8_25_ = true;
|
||||||
|
SetSolid(mgr, true);
|
||||||
|
mgr.GetPlayer().Set_X590(true);
|
||||||
|
} else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5e8_25_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::Suck(CStateManager& mgr, EStateMsg msg, float arg)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
SetSolid(mgr, false);
|
||||||
|
mgr.GetPlayer().Set_X590(false);
|
||||||
|
mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus();
|
||||||
|
} else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
if (x568_ == 0)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LoopReaction)
|
||||||
|
{
|
||||||
|
x568_ = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero));
|
||||||
|
} else if (x568_ == 1)
|
||||||
|
SuckPlayer(mgr, arg);
|
||||||
|
} else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::SuckPlayer(CStateManager& mgr, float arg)
|
||||||
|
{
|
||||||
|
CPlayer& player = mgr.GetPlayer();
|
||||||
|
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zeus::CVector3f posDiff = player.GetTranslation() - x5cc_;
|
||||||
|
if (posDiff.magnitude() < 3.f)
|
||||||
|
{
|
||||||
|
player.Stop();
|
||||||
|
CenterPlayer(mgr, x5cc_, arg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d = x5a8_ * (x5b0_ / (posDiff.magnitude() * posDiff.magnitude()));
|
||||||
|
zeus::CVector3f force = d * (player.GetMass() * -posDiff);
|
||||||
|
player.ApplyForceWR(force, zeus::CAxisAngle::sIdentity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::Attack(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
mgr.GetPlayer().Stop();
|
||||||
|
mgr.GetPlayer().SetVelocityWR({});
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One));
|
||||||
|
x5e8_26_ = false;
|
||||||
|
mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpDisabled);
|
||||||
|
} else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
if (!x5e8_26_)
|
||||||
|
{
|
||||||
|
zeus::CTransform xf = GetLctrTransform(mBellyLocatorName);
|
||||||
|
x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset);
|
||||||
|
SetPlayerPosition(mgr, x5cc_);
|
||||||
|
} else if (LostInterest(mgr, 0.f))
|
||||||
|
SetSolid(mgr, true);
|
||||||
|
} else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
SetSolid(mgr, true);
|
||||||
|
mgr.GetPlayer().Set_X590(true);
|
||||||
|
mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpAvailable);
|
||||||
|
x5e8_24_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::SetPlayerPosition(CStateManager& mgr, const zeus::CVector3f& targetPos)
|
||||||
|
{
|
||||||
|
float preThinkDt = x500_preThinkDt;
|
||||||
|
CPlayer& player = mgr.GetPlayer();
|
||||||
|
player.Stop();
|
||||||
|
player.SetVelocityWR({});
|
||||||
|
bool hadPlayerMaterial = player.GetMaterialList().HasMaterial(EMaterialTypes::Player);
|
||||||
|
|
||||||
|
if (hadPlayerMaterial)
|
||||||
|
player.RemoveMaterial(EMaterialTypes::GroundCollider, mgr);
|
||||||
|
player.RemoveMaterial(EMaterialTypes::Player, mgr);
|
||||||
|
|
||||||
|
bool hadSolidMaterial = GetMaterialList().HasMaterial(EMaterialTypes::Solid);
|
||||||
|
if (hadSolidMaterial)
|
||||||
|
RemoveMaterial(EMaterialTypes::Solid, mgr);
|
||||||
|
|
||||||
|
CPhysicsState physState = player.GetPhysicsState();
|
||||||
|
player.Stop();
|
||||||
|
player.MoveToWR(targetPos, preThinkDt);
|
||||||
|
CGameCollision::Move(mgr, player, preThinkDt, nullptr);
|
||||||
|
physState.SetTranslation(player.GetTranslation());
|
||||||
|
player.SetPhysicsState(physState);
|
||||||
|
if (hadPlayerMaterial)
|
||||||
|
player.AddMaterial(EMaterialTypes::GroundCollider, mgr);
|
||||||
|
player.AddMaterial(EMaterialTypes::Player, mgr);
|
||||||
|
if (hadSolidMaterial)
|
||||||
|
AddMaterial(EMaterialTypes::Solid, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPuddleToadGamma::Inside(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - x5cc_;
|
||||||
|
return posDiff.dot(GetTransform().frontVector()) <= 0.f &&
|
||||||
|
posDiff.magSquared() < 2.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPuddleToadGamma::Crouch(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x568_ = 0;
|
||||||
|
x56c_ = 0.f;
|
||||||
|
x5e8_25_ = true;
|
||||||
|
x5e8_24_ = true;
|
||||||
|
mgr.GetPlayer().Stop();
|
||||||
|
mgr.GetPlayer().SetVelocityWR({});
|
||||||
|
SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None);
|
||||||
|
if (!mgr.GetPlayer().AttachActorToPlayer(GetUniqueId(), false))
|
||||||
|
x56c_ = 100.f;
|
||||||
|
|
||||||
|
SetSolid(mgr, false);
|
||||||
|
mgr.GetPlayer().Set_X590(false);
|
||||||
|
mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus();
|
||||||
|
SetSolid(mgr, false);
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
zeus::CTransform xf = GetLctrTransform(mBellyLocatorName);
|
||||||
|
x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset);
|
||||||
|
SetPlayerPosition(mgr, x5cc_);
|
||||||
|
if (x568_ == 0)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Locomotion)
|
||||||
|
x568_ = 1;
|
||||||
|
else
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
if (mgr.GetPlayer().GetAttachedActor() == GetUniqueId())
|
||||||
|
mgr.GetPlayer().DetachActorFromPlayer();
|
||||||
|
mgr.GetPlayer().Set_X590(true);
|
||||||
|
x5e8_25_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,74 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "World/CPatterned.hpp"
|
#include "World/CPatterned.hpp"
|
||||||
|
#include "Collision/CCollidableOBBTreeGroup.hpp"
|
||||||
|
|
||||||
namespace urde::MP1
|
namespace urde::MP1
|
||||||
{
|
{
|
||||||
|
|
||||||
class CPuddleToadGamma : public CPatterned
|
class CPuddleToadGamma final : public CPatterned
|
||||||
{
|
{
|
||||||
|
static constexpr std::string_view mMouthLocatorName = "MOUTH_LCTR_SDK"sv;
|
||||||
|
static constexpr std::string_view mBellyLocatorName = "SAMUS_POS_LCTR_SDK"sv;
|
||||||
|
static const zeus::CVector3f skBellyOffset;
|
||||||
|
u32 x568_ = 0;
|
||||||
|
float x56c_ = 0.f;
|
||||||
|
CDamageInfo x570_;
|
||||||
|
CDamageInfo x58c_;
|
||||||
|
float x5a8_;
|
||||||
|
float x5ac_;
|
||||||
|
float x5b0_;
|
||||||
|
zeus::CVector3f x5b4_;
|
||||||
|
float x5c0_;
|
||||||
|
float x5c4_;
|
||||||
|
float x5c8_;
|
||||||
|
zeus::CVector3f x5cc_;
|
||||||
|
zeus::CVector3f x5d8_;
|
||||||
|
std::unique_ptr<CCollidableOBBTreeGroup> x5e4_collisionTreePrim;
|
||||||
|
bool x5e8_24_ : 1;
|
||||||
|
bool x5e8_25_ : 1;
|
||||||
|
bool x5e8_26_ : 1;
|
||||||
|
|
||||||
|
void SetSolid(CStateManager&, bool);
|
||||||
|
|
||||||
|
static void CenterPlayer(CStateManager&, const zeus::CVector3f&, float);
|
||||||
|
void ShootPlayer(CStateManager&, float);
|
||||||
|
void SuckPlayer(CStateManager&, float);
|
||||||
|
bool PlayerInVortexArea(const CStateManager&);
|
||||||
|
void SetPlayerPosition(CStateManager&, const zeus::CVector3f&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_PATTERNED(PuddleToad)
|
DEFINE_PATTERNED(PuddleToad)
|
||||||
|
|
||||||
CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
|
CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
|
||||||
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
|
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
|
||||||
const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1,
|
const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1,
|
||||||
float f4, float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2);
|
float f4, float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, CAssetId dcln);
|
||||||
|
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
|
||||||
|
void Think(float dt, CStateManager& mgr);
|
||||||
|
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt);
|
||||||
|
std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
|
||||||
|
|
||||||
|
const CDamageVulnerability*
|
||||||
|
GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, const CDamageInfo&) const;
|
||||||
|
|
||||||
|
const CDamageVulnerability* GetDamageVulnerability() const { return &CDamageVulnerability::ImmuneVulnerabilty(); }
|
||||||
|
|
||||||
|
const CCollisionPrimitive* GetCollisionPrimitive() const;
|
||||||
|
|
||||||
|
zeus::CTransform GetPrimitiveTransform() const;
|
||||||
|
|
||||||
|
void InActive(CStateManager&, EStateMsg, float);
|
||||||
|
void Active(CStateManager&, EStateMsg, float);
|
||||||
|
void Suck(CStateManager&, EStateMsg, float);
|
||||||
|
void Attack(CStateManager&, EStateMsg, float);
|
||||||
|
void Crouch(CStateManager&, EStateMsg, float);
|
||||||
|
bool InAttackPosition(CStateManager&, float);
|
||||||
|
bool SpotPlayer(CStateManager&, float);
|
||||||
|
bool ShouldAttack(CStateManager&, float);
|
||||||
|
bool LostInterest(CStateManager&, float);
|
||||||
|
bool Inside(CStateManager&, float);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
#include "MP1/World/CSeedling.hpp"
|
#include "MP1/World/CSeedling.hpp"
|
||||||
|
#include "World/CPatternedInfo.hpp"
|
||||||
|
#include "World/CWorld.hpp"
|
||||||
|
#include "World/CGameArea.hpp"
|
||||||
|
#include "World/CPlayer.hpp"
|
||||||
|
#include "CStateManager.hpp"
|
||||||
#include "TCastTo.hpp"
|
#include "TCastTo.hpp"
|
||||||
|
#include "CSeedling.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -8,12 +15,21 @@ namespace MP1
|
||||||
|
|
||||||
CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
|
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
|
||||||
CAssetId, CAssetId, const CDamageInfo&, const CDamageInfo&, float f1, float f2, float f3, float f4)
|
CAssetId needleId, CAssetId weaponId, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2,
|
||||||
|
float f1, float f2, float f3, float f4)
|
||||||
: CWallWalker(ECharacter::Seedling, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
|
: CWallWalker(ECharacter::Seedling, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
|
||||||
EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, f1, f2,
|
EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, f1, f2,
|
||||||
EKnockBackVariant::Small, f3, EWalkerType::Seedling, f4, false)
|
EKnockBackVariant::Small, f3, EWalkerType::Seedling, f4, false)
|
||||||
|
, x5d8_searchPath(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f)
|
||||||
|
, x6bc_spikeData(new CModelData(CStaticRes(needleId, GetModelData()->GetScale())))
|
||||||
|
, x6c0_projectileInfo(weaponId, dInfo1)
|
||||||
|
, x6e8_deathDamage(dInfo2)
|
||||||
|
, x722_24_renderOnlyClusterA(true)
|
||||||
|
, x722_25_curNeedleCluster(false)
|
||||||
{
|
{
|
||||||
|
const_cast<TToken<CWeaponDescription>*>(&x6c0_projectileInfo.Token())->Lock();
|
||||||
|
CreateShadow(false);
|
||||||
|
SetKeepInThermalVisor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeedling::Accept(IVisitor& visitor)
|
void CSeedling::Accept(IVisitor& visitor)
|
||||||
|
@ -21,5 +37,228 @@ void CSeedling::Accept(IVisitor& visitor)
|
||||||
visitor.Visit(this);
|
visitor.Visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string CSeedling::skNeedleLocators[2][6] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"A_spike1_LCTR_SDK",
|
||||||
|
"A_spike2_LCTR_SDK",
|
||||||
|
"A_spike3_LCTR_SDK",
|
||||||
|
"A_spike4_LCTR_SDK",
|
||||||
|
"A_spike5_LCTR_SDK",
|
||||||
|
"A_spike6_LCTR_SDK",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"B_spike1_LCTR_SDK",
|
||||||
|
"B_spike2_LCTR_SDK",
|
||||||
|
"B_spike3_LCTR_SDK",
|
||||||
|
"B_spike4_LCTR_SDK",
|
||||||
|
"B_spike5_LCTR_SDK",
|
||||||
|
"B_spike6_LCTR_SDK",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void CSeedling::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
CPatterned::AcceptScriptMsg(msg, uid, mgr);
|
||||||
|
|
||||||
|
if (msg == EScriptObjectMessage::Activate)
|
||||||
|
{
|
||||||
|
x5d6_27_disableMove = false;
|
||||||
|
TUniqueId id = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow);
|
||||||
|
if (id != kInvalidUniqueId)
|
||||||
|
x2dc_destObj = id;
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::Registered)
|
||||||
|
{
|
||||||
|
x450_bodyController->Activate(mgr);
|
||||||
|
x704_modelBounds = GetModelData()->GetBounds();
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::InitializedInArea)
|
||||||
|
{
|
||||||
|
x5d8_searchPath.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::Think(float dt, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
if (!GetActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
++x5d4_thinkCounter;
|
||||||
|
x5d6_26_playerObstructed = false;
|
||||||
|
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways());
|
||||||
|
CGameArea::EOcclusionState occlusionState = CGameArea::EOcclusionState::Occluded;
|
||||||
|
if (area && area->IsPostConstructed())
|
||||||
|
occlusionState = area->GetPostConstructed()->x10dc_occlusionState;
|
||||||
|
|
||||||
|
if (occlusionState == CGameArea::EOcclusionState::Occluded)
|
||||||
|
x5d6_26_playerObstructed = true;
|
||||||
|
|
||||||
|
if (!x5d6_26_playerObstructed)
|
||||||
|
{
|
||||||
|
zeus::CVector3f playerPos = mgr.GetPlayer().GetTranslation();
|
||||||
|
float distance = (playerPos - GetTranslation()).magnitude();
|
||||||
|
if (distance > x5c4_playerObstructionMinDist)
|
||||||
|
{
|
||||||
|
zeus::CVector3f direction = (playerPos - GetTranslation()).normalized();
|
||||||
|
CRayCastResult result = mgr.RayStaticIntersection(playerPos, direction, distance,
|
||||||
|
CMaterialFilter::skPassEverything);
|
||||||
|
if (result.IsValid())
|
||||||
|
x5d6_26_playerObstructed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x5d6_26_playerObstructed)
|
||||||
|
xf8_24_movable = false;
|
||||||
|
|
||||||
|
xf8_24_movable = !x5d6_24_alignToFloor;
|
||||||
|
CWallWalker::Think(dt, mgr);
|
||||||
|
|
||||||
|
if (!x5d6_25_hasAlignSurface && x450_bodyController->GetPercentageFrozen() < 0.00001f && x5d6_24_alignToFloor)
|
||||||
|
AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + (2.f * (dt * GetVelocity())), dt);
|
||||||
|
|
||||||
|
if (x71c_attackCoolOff > 0.f)
|
||||||
|
x71c_attackCoolOff -= dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::Render(const CStateManager& mgr) const
|
||||||
|
{
|
||||||
|
if (x400_25_alive && x6bc_spikeData)
|
||||||
|
{
|
||||||
|
u32 index = x722_24_renderOnlyClusterA ? 0 : u32(x722_25_curNeedleCluster);
|
||||||
|
CModelFlags flags;
|
||||||
|
flags.x2_flags = 3;
|
||||||
|
flags.x4_color = zeus::CColor::skWhite;
|
||||||
|
|
||||||
|
for (const std::string& sv : skNeedleLocators[index])
|
||||||
|
x6bc_spikeData->Render(mgr, GetLctrTransform(sv), x90_actorLights.get(), flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
CWallWalker::Render(mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt)
|
||||||
|
{
|
||||||
|
if (type == EUserEventType::Projectile)
|
||||||
|
LaunchNeedles(mgr);
|
||||||
|
else if (type == EUserEventType::BeginAction)
|
||||||
|
x722_24_renderOnlyClusterA = true;
|
||||||
|
else
|
||||||
|
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::experimental::optional<zeus::CAABox> CSeedling::GetTouchBounds() const
|
||||||
|
{
|
||||||
|
return x704_modelBounds.getTransformedAABox(GetTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::Touch(CActor& act, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
if (x400_25_alive)
|
||||||
|
{
|
||||||
|
if (TCastToPtr<CPlayer> pl = act)
|
||||||
|
MassiveDeath(mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPatterned::Touch(act, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::Patrol(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
||||||
|
x5d6_24_alignToFloor = true;
|
||||||
|
x150_momentum.zeroOut();
|
||||||
|
x5d6_25_hasAlignSurface = false;
|
||||||
|
xf8_24_movable = false;
|
||||||
|
|
||||||
|
TUniqueId id = (x720_prevObj != kInvalidUniqueId ? x720_prevObj :
|
||||||
|
GetWaypointForState(mgr, EScriptObjectState::Patrol,
|
||||||
|
EScriptObjectMessage::Follow));
|
||||||
|
|
||||||
|
if (id != kInvalidUniqueId)
|
||||||
|
x2dc_destObj = id;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
UpdateWPDestination(mgr);
|
||||||
|
zeus::CVector3f upVec = GetTransform().upVector();
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(
|
||||||
|
CBCLocomotionCmd(ProjectVectorToPlane((x2e0_destPos - GetTranslation()).normalized(), upVec), {}, 0.f));
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(
|
||||||
|
ProjectVectorToPlane(ProjectVectorToPlane(x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec), upVec),
|
||||||
|
{}, 1.f));
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(1.f * GetTransform().frontVector(), {}, 0.f));
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x720_prevObj = x2dc_destObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::Active(CStateManager& mgr, EStateMsg msg, float arg)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
|
||||||
|
CPatterned::Patrol(mgr, msg, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::Enraged(CStateManager&, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
x32c_animState = EAnimState::One;
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0);
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x32c_animState = EAnimState::Zero;
|
||||||
|
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;
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSeedling::ShouldAttack(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
if (x71c_attackCoolOff > 0.f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::LaunchNeedles(CStateManager& mgr)
|
||||||
|
{
|
||||||
|
for (const std::string& needle : skNeedleLocators[u32(x722_25_curNeedleCluster)])
|
||||||
|
LaunchProjectile(GetLctrTransform(needle), mgr, 6, EProjectileAttrib::None, true, {}, 0xFFFF, false,
|
||||||
|
GetModelData()->GetScale());
|
||||||
|
|
||||||
|
x722_25_curNeedleCluster = !x722_25_curNeedleCluster;
|
||||||
|
x722_24_renderOnlyClusterA = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSeedling::MassiveDeath(CStateManager& mgr)
|
||||||
|
{
|
||||||
|
if (x400_25_alive)
|
||||||
|
{
|
||||||
|
mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x6e8_deathDamage,
|
||||||
|
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}));
|
||||||
|
LaunchNeedles(mgr);
|
||||||
|
}
|
||||||
|
CPatterned::MassiveDeath(mgr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "World/CWallWalker.hpp"
|
#include "World/CWallWalker.hpp"
|
||||||
|
#include "World/CPathFindSearch.hpp"
|
||||||
|
#include "Weapon/CProjectileInfo.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -8,6 +10,17 @@ namespace MP1
|
||||||
{
|
{
|
||||||
class CSeedling : public CWallWalker
|
class CSeedling : public CWallWalker
|
||||||
{
|
{
|
||||||
|
static const std::string skNeedleLocators[2][6];
|
||||||
|
CPathFindSearch x5d8_searchPath;
|
||||||
|
std::unique_ptr<CModelData> x6bc_spikeData;
|
||||||
|
CProjectileInfo x6c0_projectileInfo;
|
||||||
|
CDamageInfo x6e8_deathDamage;
|
||||||
|
zeus::CAABox x704_modelBounds = zeus::CAABox::skNullBox;
|
||||||
|
float x71c_attackCoolOff = 0.f;
|
||||||
|
TUniqueId x720_prevObj = kInvalidUniqueId;
|
||||||
|
bool x722_24_renderOnlyClusterA : 1;
|
||||||
|
bool x722_25_curNeedleCluster : 1;
|
||||||
|
void LaunchNeedles(CStateManager&);
|
||||||
public:
|
public:
|
||||||
DEFINE_PATTERNED(Seedling)
|
DEFINE_PATTERNED(Seedling)
|
||||||
CSeedling(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&,
|
CSeedling(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&,
|
||||||
|
@ -16,6 +29,21 @@ public:
|
||||||
float, float, float, float);
|
float, float, float, float);
|
||||||
|
|
||||||
void Accept(IVisitor&);
|
void Accept(IVisitor&);
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
|
||||||
|
void Think(float, CStateManager&);
|
||||||
|
void Render(const CStateManager&) const;
|
||||||
|
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt);
|
||||||
|
CProjectileInfo* GetProjectileInfo() { return &x6c0_projectileInfo; }
|
||||||
|
std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
|
||||||
|
void Touch(CActor&, CStateManager&);
|
||||||
|
CPathFindSearch* GetSearchPath() { return &x5d8_searchPath; }
|
||||||
|
void Patrol(CStateManager&, EStateMsg, float);
|
||||||
|
void Active(CStateManager&, EStateMsg, float);
|
||||||
|
void Enraged(CStateManager&, EStateMsg, float);
|
||||||
|
void ProjectileAttack(CStateManager&, EStateMsg, float);
|
||||||
|
void Generate(CStateManager&, EStateMsg, float);
|
||||||
|
bool ShouldAttack(CStateManager&, float);
|
||||||
|
void MassiveDeath(CStateManager&);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,415 @@
|
||||||
|
#include "CSpankWeed.hpp"
|
||||||
|
#include "World/CPatternedInfo.hpp"
|
||||||
|
#include "World/CPlayer.hpp"
|
||||||
|
#include "Collision/CCollisionActor.hpp"
|
||||||
|
#include "CStateManager.hpp"
|
||||||
|
#include <logvisor/logvisor.hpp>
|
||||||
|
|
||||||
|
namespace urde::MP1
|
||||||
|
{
|
||||||
|
logvisor::Module SpankLog("urde::MP1::SpankWeed");
|
||||||
|
CSpankWeed::CSpankWeed(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float maxDetectionRange,
|
||||||
|
float maxHearingRange, float maxSightRange, float hideTime)
|
||||||
|
: CPatterned(ECharacter::SpankWeed, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
|
||||||
|
EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium)
|
||||||
|
, x568_maxDetectionRange(maxDetectionRange)
|
||||||
|
, x56c_detectionHeightRange(pInfo.GetDetectionHeightRange())
|
||||||
|
, x570_maxHearingRange(maxHearingRange)
|
||||||
|
, x574_maxSightRange(maxSightRange)
|
||||||
|
, x578_hideTime(hideTime)
|
||||||
|
, x584_retreatOrigin(xf.origin)
|
||||||
|
{
|
||||||
|
SetCallTouch(false);
|
||||||
|
CreateShadow(false);
|
||||||
|
|
||||||
|
zeus::CVector3f modelScale = GetModelData()->GetScale();
|
||||||
|
if (modelScale.x != modelScale.y || modelScale.x != modelScale.z)
|
||||||
|
{
|
||||||
|
float scale = modelScale.magnitude() / std::sqrt(3.f);
|
||||||
|
|
||||||
|
ModelData()->SetScale(zeus::CVector3f(scale));
|
||||||
|
SpankLog.report(logvisor::Level::Warning, "WARNING: Non-uniform scale (%.2f, %.2f, %.2f) applied to Spank Weed"
|
||||||
|
"...changing scale to (%.2f, %.2f, %.2f)\n",
|
||||||
|
modelScale.x, modelScale.y, modelScale.z,
|
||||||
|
scale, scale, scale);
|
||||||
|
}
|
||||||
|
CMaterialList list = GetMaterialFilter().GetExcludeList();
|
||||||
|
list.Add(EMaterialTypes::Character);
|
||||||
|
list.Add(EMaterialTypes::Player);
|
||||||
|
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(GetMaterialFilter().GetIncludeList(), list));
|
||||||
|
|
||||||
|
CSegId segId = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv);
|
||||||
|
if (segId != 0xFF)
|
||||||
|
{
|
||||||
|
zeus::CTransform locatorXf = GetTransform() * zeus::CTransform::Scale(GetModelData()->GetScale()) *
|
||||||
|
GetModelData()->GetAnimationData()->GetLocatorTransform(segId, nullptr);
|
||||||
|
x5a8_lockonTarget = locatorXf.origin;
|
||||||
|
x59c_lockonOffset = locatorXf.origin - GetTranslation();
|
||||||
|
}
|
||||||
|
x460_knockBackController.SetAutoResetImpulse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const SSphereJointDescription kArmCollision[]=
|
||||||
|
{
|
||||||
|
{"Arm_4", 1.5f},
|
||||||
|
{"Arm_6", 1.f},
|
||||||
|
{"Arm_7", 1.f},
|
||||||
|
{"Arm_8", 1.f},
|
||||||
|
{"Arm_9", 1.f},
|
||||||
|
{"Arm_11", 1.f},
|
||||||
|
{"Swoosh_LCTR", 1.5f}
|
||||||
|
};
|
||||||
|
|
||||||
|
void CSpankWeed::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
bool oldActive = GetActive();
|
||||||
|
if (msg == EScriptObjectMessage::Activate)
|
||||||
|
{
|
||||||
|
if (x90_actorLights)
|
||||||
|
x90_actorLights->SetDirty();
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::Decrement)
|
||||||
|
{
|
||||||
|
if (x5b4_ != 0 && x5b4_ != 5 && x5b4_ != 6 && x5b4_ != 4)
|
||||||
|
{
|
||||||
|
x400_24_hitByPlayerProjectile = true;
|
||||||
|
x428_damageCooldownTimer = x424_damageWaitTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::Registered)
|
||||||
|
{
|
||||||
|
if (!x450_bodyController->GetActive())
|
||||||
|
{
|
||||||
|
x450_bodyController->Activate(mgr);
|
||||||
|
zeus::CVector3f extents = GetBoundingBox().extents();
|
||||||
|
|
||||||
|
SetBoundingBox({-extents, extents});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CJointCollisionDescription> joints;
|
||||||
|
joints.reserve(12);
|
||||||
|
|
||||||
|
for (const SSphereJointDescription& joint : kArmCollision)
|
||||||
|
{
|
||||||
|
CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId(joint.name);
|
||||||
|
if (id != 0xFF)
|
||||||
|
joints.push_back(CJointCollisionDescription::SphereCollision(id, joint.radius, joint.name, 0.001f));
|
||||||
|
}
|
||||||
|
|
||||||
|
x594_collisionMgr.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), joints, GetActive()));
|
||||||
|
CMaterialList list;
|
||||||
|
list.Add(EMaterialTypes::CameraPassthrough);
|
||||||
|
list.Add(EMaterialTypes::Immovable);
|
||||||
|
x594_collisionMgr->AddMaterial(mgr, list);
|
||||||
|
if (x90_actorLights)
|
||||||
|
{
|
||||||
|
x90_actorLights->SetDirty();
|
||||||
|
zeus::CVector3f swooshOrigin = GetScaledLocatorTransform("swoosh_LCTR"sv).origin;
|
||||||
|
x90_actorLights->SetActorPositionBias(GetTransform().buildMatrix3f() * swooshOrigin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::Touched)
|
||||||
|
{
|
||||||
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid))
|
||||||
|
{
|
||||||
|
if (TCastToPtr<CPlayer> player = mgr.ObjectById(colAct->GetLastTouchedObject()))
|
||||||
|
{
|
||||||
|
if (x420_curDamageRemTime <= 0.f && x5b4_ != 4 && x5b4_ != 6)
|
||||||
|
{
|
||||||
|
mgr.ApplyDamage(GetUniqueId(), player->GetUniqueId(), GetUniqueId(), GetContactDamage(),
|
||||||
|
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
|
||||||
|
x420_curDamageRemTime = x424_damageWaitTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::Deleted)
|
||||||
|
{
|
||||||
|
mgr.FreeScriptObject(x590_);
|
||||||
|
x594_collisionMgr->Destroy(mgr);
|
||||||
|
}
|
||||||
|
else if (msg == EScriptObjectMessage::SuspendedMove)
|
||||||
|
{
|
||||||
|
x594_collisionMgr->SetMovable(mgr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPatterned::AcceptScriptMsg(msg, uid, mgr);
|
||||||
|
|
||||||
|
if (GetActive() != oldActive)
|
||||||
|
x594_collisionMgr.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::Think(float dt, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
if (!GetActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
HealthInfo(mgr)->SetHP(1000000.0f);
|
||||||
|
|
||||||
|
if (!x598_isHiding)
|
||||||
|
{
|
||||||
|
zeus::CVector3f eyeOrigin = GetLocatorTransform("Eye"sv).origin;
|
||||||
|
MoveCollisionPrimitive(GetModelData()->GetScale() * eyeOrigin);
|
||||||
|
x594_collisionMgr->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
|
||||||
|
xe4_27_notInSortedLists = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPatterned::Think(dt, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector3f CSpankWeed::GetOrbitPosition(const CStateManager& mgr) const
|
||||||
|
{
|
||||||
|
zeus::CVector3f ret = CPatterned::GetOrbitPosition(mgr);
|
||||||
|
float delay = std::max(1.f, x330_stateMachineState.GetDelay());
|
||||||
|
if (x5b4_ == 3 && x5b8_ == 2)
|
||||||
|
{
|
||||||
|
return (ret * (1.f - delay) + ((GetTranslation() + x59c_lockonOffset) * delay));
|
||||||
|
}
|
||||||
|
else if (x5b4_ == 2 && x5b8_ == 3)
|
||||||
|
{
|
||||||
|
return (GetTranslation() + x59c_lockonOffset) * (1.f - delay) + (ret * delay);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector3f CSpankWeed::GetAimPosition(const CStateManager&, float dt) const
|
||||||
|
{
|
||||||
|
zeus::CVector3f pos = (dt > 0.f ? PredictMotion(dt).x0_translation : zeus::CVector3f::skZero);
|
||||||
|
|
||||||
|
CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv);
|
||||||
|
if (id != 0xFF)
|
||||||
|
{
|
||||||
|
zeus::CVector3f lockonOff = GetModelData()->GetAnimationData()->GetLocatorTransform(id, nullptr).origin;
|
||||||
|
return pos + (GetTransform() * (GetModelData()->GetScale() * lockonOff));
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos + GetBoundingBox().center();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::Flinch(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x5bc_ = 0;
|
||||||
|
x5b4_ = 0;
|
||||||
|
RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
if (x5bc_ == 0)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::KnockBack)
|
||||||
|
x5bc_ = 2;
|
||||||
|
else
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockBackCmd({}, pas::ESeverity::Zero));
|
||||||
|
}
|
||||||
|
else if (x5bc_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack)
|
||||||
|
x5bc_ = 3;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5b8_ = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSpankWeed::Delay(CStateManager&, float)
|
||||||
|
{
|
||||||
|
if (x400_24_hitByPlayerProjectile)
|
||||||
|
{
|
||||||
|
if (x330_stateMachineState.GetTime() > x578_hideTime)
|
||||||
|
{
|
||||||
|
x400_24_hitByPlayerProjectile = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSpankWeed::InRange(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
float playerDist = GetPlayerDistance(mgr);
|
||||||
|
if (x56c_detectionHeightRange > 0.f)
|
||||||
|
{
|
||||||
|
return std::fabs(mgr.GetPlayer().GetTranslation().z - GetTranslation().z) < x56c_detectionHeightRange &&
|
||||||
|
playerDist < (x574_maxSightRange * x574_maxSightRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
return playerDist < (x574_maxSightRange * x574_maxSightRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSpankWeed::HearPlayer(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
float playerDist = GetPlayerDistance(mgr);
|
||||||
|
if (x56c_detectionHeightRange > 0.f)
|
||||||
|
{
|
||||||
|
return std::fabs(mgr.GetPlayer().GetTranslation().z - GetTranslation().z) < x56c_detectionHeightRange &&
|
||||||
|
playerDist < (x570_maxHearingRange * x570_maxHearingRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
return playerDist < (x570_maxHearingRange * x570_maxHearingRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSpankWeed::InDetectionRange(CStateManager& mgr, float)
|
||||||
|
{
|
||||||
|
float playerDist = GetPlayerDistance(mgr);
|
||||||
|
if (x56c_detectionHeightRange > 0.f)
|
||||||
|
{
|
||||||
|
return std::fabs(mgr.GetPlayer().GetTranslation().z - GetTranslation().z) < x56c_detectionHeightRange &&
|
||||||
|
playerDist < (x568_maxDetectionRange * x568_maxDetectionRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
return playerDist < (x568_maxDetectionRange * x568_maxDetectionRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::Attack(CStateManager&, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero));
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero));
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5b8_ = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::TargetPatrol(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat);
|
||||||
|
RemoveMaterial(EMaterialTypes::Solid, mgr);
|
||||||
|
x5b4_ = 2;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5b8_ = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::Lurk(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x460_knockBackController.SetEnableFreeze(true);
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
|
||||||
|
RemoveMaterial(EMaterialTypes::Solid, mgr);
|
||||||
|
x5b4_ = 1;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5b8_ = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::FadeOut(CStateManager&, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x5bc_ = 0;
|
||||||
|
x57c_canKnockBack = false;
|
||||||
|
x5b4_ = 6;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
if (x5bc_ == 0)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step)
|
||||||
|
x5bc_ = 2;
|
||||||
|
else
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(
|
||||||
|
CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (x5bc_ == 2)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step)
|
||||||
|
x5bc_ = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5b8_ = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::FadeIn(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x5bc_ = 0;
|
||||||
|
x57c_canKnockBack = true;
|
||||||
|
x5b4_ = 5;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Update)
|
||||||
|
{
|
||||||
|
if (x5bc_ == 0)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step)
|
||||||
|
x5bc_ = 2;
|
||||||
|
else
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(
|
||||||
|
CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Normal));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (x5bc_ == 2)
|
||||||
|
{
|
||||||
|
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step)
|
||||||
|
x5bc_ = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
x5b8_ = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
xe7_28_worldLightingDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::Patrol(CStateManager& mgr, EStateMsg msg, float)
|
||||||
|
{
|
||||||
|
if (msg == EStateMsg::Activate)
|
||||||
|
{
|
||||||
|
x460_knockBackController.SetEnableFreeze(false);
|
||||||
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
||||||
|
RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Scannable, mgr);
|
||||||
|
RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
|
||||||
|
x594_collisionMgr->SetActive(mgr, false);
|
||||||
|
x598_isHiding = true;
|
||||||
|
x5b4_ = 0;
|
||||||
|
}
|
||||||
|
else if (msg == EStateMsg::Deactivate)
|
||||||
|
{
|
||||||
|
AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, EMaterialTypes::Scannable, mgr);
|
||||||
|
SetTranslation(x584_retreatOrigin);
|
||||||
|
x594_collisionMgr->SetActive(mgr, true);
|
||||||
|
x598_isHiding = false;
|
||||||
|
x460_knockBackController.SetEnableFreeze(true);
|
||||||
|
x5b8_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpankWeed::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, const CDamageInfo& info,
|
||||||
|
EKnockBackType type, bool inDeferred, float magnitude)
|
||||||
|
{
|
||||||
|
if (!x57c_canKnockBack)
|
||||||
|
return;
|
||||||
|
CPatterned::KnockBack(backVec, mgr, info, type, inDeferred, magnitude);
|
||||||
|
x57c_canKnockBack = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CSpankWeed::GetPlayerDistance(CStateManager& mgr) const
|
||||||
|
{
|
||||||
|
return (mgr.GetPlayer().GetTranslation() - x5a8_lockonTarget).magSquared();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "World/CPatterned.hpp"
|
||||||
|
#include "Collision/CCollisionActorManager.hpp"
|
||||||
|
|
||||||
|
namespace urde::MP1
|
||||||
|
{
|
||||||
|
class CSpankWeed : public CPatterned
|
||||||
|
{
|
||||||
|
float x568_maxDetectionRange;
|
||||||
|
float x56c_detectionHeightRange;
|
||||||
|
float x570_maxHearingRange;
|
||||||
|
float x574_maxSightRange;
|
||||||
|
float x578_hideTime;
|
||||||
|
bool x57c_canKnockBack = false;
|
||||||
|
/* float x580_ = 0.f; unused */
|
||||||
|
zeus::CVector3f x584_retreatOrigin;
|
||||||
|
TUniqueId x590_ = kInvalidUniqueId;
|
||||||
|
std::unique_ptr<CCollisionActorManager> x594_collisionMgr;
|
||||||
|
bool x598_isHiding = true;
|
||||||
|
zeus::CVector3f x59c_lockonOffset;
|
||||||
|
zeus::CVector3f x5a8_lockonTarget;
|
||||||
|
s32 x5b4_ = -1;
|
||||||
|
s32 x5b8_ = -1;
|
||||||
|
s32 x5bc_ = -1;
|
||||||
|
|
||||||
|
float GetPlayerDistance(CStateManager&) const;
|
||||||
|
public:
|
||||||
|
DEFINE_PATTERNED(SpankWeed)
|
||||||
|
|
||||||
|
CSpankWeed(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
|
||||||
|
const CActorParameters&, const CPatternedInfo&, float, float, float, float);
|
||||||
|
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
|
||||||
|
void Think(float, CStateManager&);
|
||||||
|
zeus::CVector3f GetOrbitPosition(const CStateManager&) const;
|
||||||
|
zeus::CVector3f GetAimPosition(const CStateManager&, float) const;
|
||||||
|
bool AnimOver(CStateManager&, float) { return x5bc_ == 3; }
|
||||||
|
void Flinch(CStateManager&, EStateMsg, float);
|
||||||
|
bool Delay(CStateManager&, float);
|
||||||
|
bool InRange(CStateManager&, float);
|
||||||
|
bool HearPlayer(CStateManager&, float);
|
||||||
|
bool InDetectionRange(CStateManager&, float);
|
||||||
|
void Attack(CStateManager&, EStateMsg, float);
|
||||||
|
void TargetPatrol(CStateManager&, EStateMsg, float);
|
||||||
|
void Lurk(CStateManager&, EStateMsg, float);
|
||||||
|
void FadeOut(CStateManager&, EStateMsg, float);
|
||||||
|
void FadeIn(CStateManager&, EStateMsg, float);
|
||||||
|
void Patrol(CStateManager&, EStateMsg, float);
|
||||||
|
void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info,
|
||||||
|
EKnockBackType type, bool inDeferred, float magnitude);
|
||||||
|
};
|
||||||
|
}
|
|
@ -18,4 +18,9 @@ void CPlasmaProjectile::Accept(IVisitor& visitor)
|
||||||
visitor.Visit(this);
|
visitor.Visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPlasmaProjectile::Fire(const zeus::CTransform&, CStateManager&, bool)
|
||||||
|
{
|
||||||
|
SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
void Accept(IVisitor& visitor);
|
void Accept(IVisitor& visitor);
|
||||||
|
|
||||||
void UpdateFx(const zeus::CTransform&, float, CStateManager&) {}
|
void UpdateFx(const zeus::CTransform&, float, CStateManager&) {}
|
||||||
void Fire(const zeus::CTransform&, CStateManager&, bool) {}
|
void Fire(const zeus::CTransform&, CStateManager&, bool);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ CAi::CAi(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& i
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x90_actorLights)
|
if (x90_actorLights)
|
||||||
x260_damageVulnerability.SetX38_25(true);
|
x90_actorLights->SetCastShadows(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
|
void CAi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
|
||||||
|
|
|
@ -34,9 +34,7 @@ class CDamageVulnerability
|
||||||
EVulnerability x2c_enemyWp3Lava;
|
EVulnerability x2c_enemyWp3Lava;
|
||||||
EVulnerability x30_enemyWp4;
|
EVulnerability x30_enemyWp4;
|
||||||
EVulnerability x34_unk1;
|
EVulnerability x34_unk1;
|
||||||
/* FIXME: What's going on here? */
|
|
||||||
EVulnerability x38_unk2;
|
EVulnerability x38_unk2;
|
||||||
bool x38_25 : 1;
|
|
||||||
|
|
||||||
EVulnerability x3c_chargedPower;
|
EVulnerability x3c_chargedPower;
|
||||||
EVulnerability x40_chargedIce;
|
EVulnerability x40_chargedIce;
|
||||||
|
@ -80,7 +78,6 @@ public:
|
||||||
static const CDamageVulnerability& ImmuneVulnerabilty() { return sImmuneVulnerability; }
|
static const CDamageVulnerability& ImmuneVulnerabilty() { return sImmuneVulnerability; }
|
||||||
static const CDamageVulnerability& ReflectVulnerabilty() { return sReflectVulnerability; }
|
static const CDamageVulnerability& ReflectVulnerabilty() { return sReflectVulnerability; }
|
||||||
static const CDamageVulnerability& PasshThroughVulnerabilty() { return sPassThroughVulnerability; }
|
static const CDamageVulnerability& PasshThroughVulnerabilty() { return sPassThroughVulnerability; }
|
||||||
void SetX38_25(bool) { x38_25 = true; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ public:
|
||||||
void SetEnableBurnDeath(bool b) { x81_28_enableBurnDeath = b; }
|
void SetEnableBurnDeath(bool b) { x81_28_enableBurnDeath = b; }
|
||||||
void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; }
|
void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; }
|
||||||
void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; }
|
void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; }
|
||||||
|
void SetX81_31(bool b) { x81_31_ = b; }
|
||||||
void SetX82_24(bool b) { x82_24_ = b; }
|
void SetX82_24(bool b) { x82_24_ = b; }
|
||||||
void SetLocomotionDuringElectrocution(bool b) { x82_26_locomotionDuringElectrocution = b; }
|
void SetLocomotionDuringElectrocution(bool b) { x82_26_locomotionDuringElectrocution = b; }
|
||||||
const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
|
const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
|
||||||
|
|
|
@ -1026,6 +1026,16 @@ void CPatterned::TryLoopReaction(CStateManager& mgr, int arg)
|
||||||
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType(arg)));
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType(arg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPatterned::TryProjectileAttack(CStateManager&, int arg)
|
||||||
|
{
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity(arg), x2e0_destPos, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPatterned::TryGenerate(CStateManager& mgr, int arg)
|
||||||
|
{
|
||||||
|
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType(arg), x2e0_destPos, true));
|
||||||
|
}
|
||||||
|
|
||||||
void CPatterned::BuildBodyController(EBodyType bodyType)
|
void CPatterned::BuildBodyController(EBodyType bodyType)
|
||||||
{
|
{
|
||||||
if (x450_bodyController)
|
if (x450_bodyController)
|
||||||
|
|
|
@ -381,6 +381,8 @@ public:
|
||||||
|
|
||||||
void TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg);
|
void TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg);
|
||||||
void TryLoopReaction(CStateManager& mgr, int arg);
|
void TryLoopReaction(CStateManager& mgr, int arg);
|
||||||
|
void TryProjectileAttack(CStateManager& mgr, int arg);
|
||||||
|
void TryGenerate(CStateManager& mgr, int arg);
|
||||||
|
|
||||||
virtual bool KnockbackWhenFrozen() const { return true; }
|
virtual bool KnockbackWhenFrozen() const { return true; }
|
||||||
virtual void MassiveDeath(CStateManager& mgr);
|
virtual void MassiveDeath(CStateManager& mgr);
|
||||||
|
@ -422,6 +424,12 @@ public:
|
||||||
bool CanLongJump() const { return x328_26_longJump; }
|
bool CanLongJump() const { return x328_26_longJump; }
|
||||||
bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; }
|
bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; }
|
||||||
|
|
||||||
|
void SetKeepInThermalVisor()
|
||||||
|
{
|
||||||
|
x403_24_keepThermalVisorState = true;
|
||||||
|
xe6_27_thermalVisorFlags = 1 | 2;
|
||||||
|
}
|
||||||
|
|
||||||
//region Casting Functions
|
//region Casting Functions
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -59,13 +59,13 @@ public:
|
||||||
CPatternedInfo(CInputStream& in, u32 pcount);
|
CPatternedInfo(CInputStream& in, u32 pcount);
|
||||||
static std::pair<bool, u32> HasCorrectParameterCount(CInputStream& in);
|
static std::pair<bool, u32> HasCorrectParameterCount(CInputStream& in);
|
||||||
|
|
||||||
CAnimationParameters& GetAnimationParameters() { return xec_animParams; }
|
float GetDetectionHeightRange() const { return x10_detectionHeightRange; }
|
||||||
const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; }
|
|
||||||
|
|
||||||
float GetHalfExtent() const { return xc4_halfExtent; }
|
float GetHalfExtent() const { return xc4_halfExtent; }
|
||||||
float GetHeight() const { return xc8_height; }
|
float GetHeight() const { return xc8_height; }
|
||||||
u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; }
|
|
||||||
const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; }
|
const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; }
|
||||||
|
CAnimationParameters& GetAnimationParameters() { return xec_animParams; }
|
||||||
|
const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; }
|
||||||
|
u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -689,6 +689,7 @@ public:
|
||||||
EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; }
|
EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; }
|
||||||
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
|
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
|
||||||
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
|
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
|
||||||
|
void Set_X590(bool b) { x590_ = b; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
#include "CScriptSound.hpp"
|
#include "CScriptSound.hpp"
|
||||||
#include "CScriptSpawnPoint.hpp"
|
#include "CScriptSpawnPoint.hpp"
|
||||||
#include "CScriptSpecialFunction.hpp"
|
#include "CScriptSpecialFunction.hpp"
|
||||||
|
#include "MP1/World/CSpankWeed.hpp"
|
||||||
#include "MP1/World/CBabygoth.hpp"
|
#include "MP1/World/CBabygoth.hpp"
|
||||||
#include "MP1/World/CEyeball.hpp"
|
#include "MP1/World/CEyeball.hpp"
|
||||||
#include "CScriptSteam.hpp"
|
#include "CScriptSteam.hpp"
|
||||||
|
@ -86,6 +87,7 @@
|
||||||
#include "CScriptWorldTeleporter.hpp"
|
#include "CScriptWorldTeleporter.hpp"
|
||||||
#include "CScriptDebugCameraWaypoint.hpp"
|
#include "CScriptDebugCameraWaypoint.hpp"
|
||||||
#include "CScriptSpiderBallAttractionSurface.hpp"
|
#include "CScriptSpiderBallAttractionSurface.hpp"
|
||||||
|
#include "MP1/World/CPuddleToadGamma.hpp"
|
||||||
#include "CScriptSpindleCamera.hpp"
|
#include "CScriptSpindleCamera.hpp"
|
||||||
#include "MP1/World/CAtomicAlpha.hpp"
|
#include "MP1/World/CAtomicAlpha.hpp"
|
||||||
#include "CSimplePool.hpp"
|
#include "CSimplePool.hpp"
|
||||||
|
@ -1723,7 +1725,34 @@ CEntity* ScriptLoader::LoadSpiderBallAttractionSurface(CStateManager& mgr, CInpu
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||||
{
|
{
|
||||||
|
if (!EnsurePropertyCount(propCount, 17, "PuddleToadGamma"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
std::string name = mgr.HashInstanceName(in);
|
||||||
|
CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big());
|
||||||
|
zeus::CTransform xf = LoadEditorTransform(in);
|
||||||
|
zeus::CVector3f scale = zeus::CVector3f::ReadBig(in);
|
||||||
|
auto pair = CPatternedInfo::HasCorrectParameterCount(in);
|
||||||
|
if (!pair.first)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
CPatternedInfo pInfo(in, pair.second);
|
||||||
|
CActorParameters actParms = LoadActorParameters(in);
|
||||||
|
float f1 = in.readFloatBig();
|
||||||
|
float f2 = in.readFloatBig();
|
||||||
|
float f3 = in.readFloatBig();
|
||||||
|
zeus::CVector3f vec = zeus::CVector3f::ReadBig(in);
|
||||||
|
float f4 = in.readFloatBig();
|
||||||
|
float f5 = in.readFloatBig();
|
||||||
|
float f6 = in.readFloatBig();
|
||||||
|
CDamageInfo dInfo1(in);
|
||||||
|
CDamageInfo dInfo2(in);
|
||||||
|
CAssetId collisionData(in);
|
||||||
|
const CAnimationParameters& animParms = pInfo.GetAnimationParameters();
|
||||||
|
CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale,
|
||||||
|
animParms.GetInitialAnimation(), true));
|
||||||
|
return new MP1::CPuddleToadGamma(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, actParms,
|
||||||
|
f1, f2, f3, vec, f4, f5, f6, dInfo1, dInfo2, collisionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
CEntity* ScriptLoader::LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||||
|
@ -1879,7 +1908,29 @@ CEntity* ScriptLoader::LoadSpecialFunction(CStateManager& mgr, CInputStream& in,
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadSpankWeed(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
CEntity* ScriptLoader::LoadSpankWeed(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||||
{
|
{
|
||||||
|
if (!EnsurePropertyCount(propCount, 11, "SpankWeed"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
SScaledActorHead aHead = LoadScaledActorHead(in, mgr);
|
||||||
|
auto pair = CPatternedInfo::HasCorrectParameterCount(in);
|
||||||
|
if (!pair.first)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
CPatternedInfo pInfo(in, pair.second);
|
||||||
|
CActorParameters actParms = LoadActorParameters(in);
|
||||||
|
in.readBool();
|
||||||
|
float f1 = in.readFloatBig();
|
||||||
|
float f2 = in.readFloatBig();
|
||||||
|
float f3 = in.readFloatBig();
|
||||||
|
float f4 = in.readFloatBig();
|
||||||
|
|
||||||
|
const CAnimationParameters& animParms = pInfo.GetAnimationParameters();
|
||||||
|
if (!animParms.GetACSFile().IsValid())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), aHead.x40_scale,
|
||||||
|
animParms.GetInitialAnimation(), true));
|
||||||
|
return new MP1::CSpankWeed(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData),
|
||||||
|
actParms, pInfo, f1, f2, f3, f4);
|
||||||
}
|
}
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||||
|
|
|
@ -231,7 +231,7 @@ vertex VertToFrag vmain(constant VertData* va [[ buffer(1) ]],
|
||||||
vtf.color = v.colorIn * particle.moduColor;
|
vtf.color = v.colorIn * particle.moduColor;
|
||||||
vtf.uvFlake = v.uvsIn[vertId].xy;
|
vtf.uvFlake = v.uvsIn[vertId].xy;
|
||||||
float4 pos = float4(v.posIn[vertId].xyz, 1.0);
|
float4 pos = float4(v.posIn[vertId].xyz, 1.0);
|
||||||
vtf.uvEnv = (envMtx * pos).xy;
|
vtf.uvEnv = (particle.envMtx * pos).xy;
|
||||||
vtf.mvPos = particle.mv * pos;
|
vtf.mvPos = particle.mv * pos;
|
||||||
vtf.position = particle.proj * vtf.mvPos;
|
vtf.position = particle.proj * vtf.mvPos;
|
||||||
return vtf;
|
return vtf;
|
||||||
|
@ -258,7 +258,7 @@ struct FogUniform
|
||||||
float4 MainPostFunc(thread VertToFrag& vtf, constant FogUniform& fu, float4 colorIn)
|
float4 MainPostFunc(thread VertToFrag& vtf, constant FogUniform& fu, float4 colorIn)
|
||||||
{
|
{
|
||||||
float fogZ, temp;
|
float fogZ, temp;
|
||||||
switch (lu.mode)
|
switch (fu.mode)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
fogZ = (-vtf.mvPos.z - fu.start) * fu.rangeScale;
|
fogZ = (-vtf.mvPos.z - fu.start) * fu.rangeScale;
|
||||||
|
|
Loading…
Reference in New Issue