Merge branch 'master' of ssh://git.axiodl.com:6431/AxioDL/urde

This commit is contained in:
Jack Andersen 2018-12-07 18:36:12 -10:00
commit 41ae32be31
27 changed files with 1424 additions and 91 deletions

View File

@ -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; }
}; };
} }

View File

@ -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; }

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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);
}
} }

View File

@ -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; }
}; };
} }

View File

@ -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)

View File

@ -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}},

View File

@ -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;
}
}
} }

View File

@ -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);
}; };
} }

View File

@ -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);
}
} }
} }

View File

@ -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&);
}; };
} }
} }

View File

@ -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();
}
}

View File

@ -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);
};
}

View File

@ -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);
}
} }

View File

@ -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);
}; };
} }

View File

@ -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)

View File

@ -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; }
}; };
} }

View File

@ -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; }

View File

@ -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)

View File

@ -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>

View File

@ -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; }
}; };
} }

View File

@ -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; }
}; };
} }

View File

@ -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)

View File

@ -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;