Implement CAtomicAlpha

This commit is contained in:
Phillip Stephens 2018-12-17 20:42:17 -08:00
parent 6fe99a7ddf
commit d657a8ecf6
8 changed files with 215 additions and 10 deletions

View File

@ -215,7 +215,7 @@ EWeaponCollisionResponseTypes CCollisionResponseData::GetWorldCollisionResponseT
}
bool CCollisionResponseData::ResponseTypeIsEnemyNormal(EWeaponCollisionResponseTypes type) {
return (type >= EWeaponCollisionResponseTypes::Unknown19 && type <= EWeaponCollisionResponseTypes::Unknown43);
return (type >= EWeaponCollisionResponseTypes::Unknown19 && type <= EWeaponCollisionResponseTypes::AtomicAlpha);
}
bool CCollisionResponseData::ResponseTypeIsEnemySpecial(EWeaponCollisionResponseTypes type) {
@ -223,7 +223,7 @@ bool CCollisionResponseData::ResponseTypeIsEnemySpecial(EWeaponCollisionResponse
}
bool CCollisionResponseData::ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes type) {
return (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::Unknown93);
return (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect);
}
FourCC CCollisionResponseData::UncookedResType() { return SBIG('CRSM'); }

View File

@ -56,7 +56,7 @@ enum class EWeaponCollisionResponseTypes {
Unknown40,
Unknown41,
Unknown42,
Unknown43,
AtomicAlpha,
Unknown44,
Unknown45,
Unknown46,
@ -106,7 +106,7 @@ enum class EWeaponCollisionResponseTypes {
Unknown90,
Unknown91,
Unknown92,
Unknown93
AtomicAlphaReflect
};
class CCollisionResponseData {

View File

@ -1,10 +1,158 @@
#include "CAtomicAlpha.hpp"
#include "World/CWorld.hpp"
#include "World/CGameArea.hpp"
#include "World/CPlayer.hpp"
#include "World/CPatternedInfo.hpp"
#include "Weapon/CPlayerGun.hpp"
#include "CStateManager.hpp"
namespace urde::MP1 {
const std::string_view CAtomicAlpha::skBombLocators[4] = {
"bomb1_LCTR"sv,
"bomb2_LCTR"sv,
"bomb3_LCTR"sv,
"bomb4_LCTR"sv
};
CAtomicAlpha::CAtomicAlpha(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo,
CAssetId wpsc, const CDamageInfo& dInfo, float f1, float f2, float f3, CAssetId cmdl,
bool b1, bool b2)
CAssetId bombWeapon, const CDamageInfo& bombDamage, float bombDropDelay, float f2, float f3, CAssetId cmdl,
bool invisible, bool b2)
: CPatterned(ECharacter::AtomicAlpha, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium) {}
EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium)
, x568_24_inRange(false)
, x568_25_invisible(invisible)
, x568_26_applyBeamAttraction(b2)
, x56c_bomdDropDelay(bombDropDelay)
, x570_bombReappearDelay(f2)
, x574_bombRappearTime(f3)
, x580_pathFind(nullptr, 3, pInfo.GetPathfindingIndex(), 1.f, 1.f)
, x668_bombProjectile(bombWeapon, bombDamage)
, x690_bombModel(CStaticRes(cmdl, GetModelData()->GetScale())) {
const_cast<TToken<CWeaponDescription>*>(&x668_bombProjectile.Token())->Lock();
for (u32 i = 0; i < skBombCount; ++i) {
x6dc_bombLocators.push_back(
SBomb(skBombLocators[i], pas::ELocomotionType(u32(pas::ELocomotionType::Internal10) + i)));
}
}
void CAtomicAlpha::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::InitializedInArea) {
x580_pathFind.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
} else if (msg == EScriptObjectMessage::Registered) {
x450_bodyController->Activate(mgr);
} else if (msg == EScriptObjectMessage::AddSplashInhabitant) {
if (x400_25_alive)
x401_30_pendingDeath = true;
}
}
void CAtomicAlpha::Render(const CStateManager& mgr) const {
if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && x568_25_invisible)
return;
CPatterned::Render(mgr);
for (const SBomb& bomb : x6dc_bombLocators) {
zeus::CTransform locatorXf = GetTransform() * GetScaledLocatorTransform(bomb.x0_locatorName) *
zeus::CTransform::Scale(std::min(1.f, std::max(0.f, bomb.x14_scaleTime - x570_bombReappearDelay) / x570_bombReappearDelay));
CModelFlags flags;
flags.x2_flags = 1 | 2;
flags.x4_color = zeus::CColor::skWhite;
x690_bombModel.Render(mgr, locatorXf, x90_actorLights.get(), flags);
}
}
void CAtomicAlpha::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const {
if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && x568_25_invisible)
return;
CPatterned::AddToRenderer(frustum, mgr);
}
void CAtomicAlpha::Think(float dt, CStateManager& mgr) {
CPatterned::Think(dt, mgr);
if (!GetActive())
return;
x578_bombTime += dt;
for (SBomb& bomb : x6dc_bombLocators) {
bomb.x14_scaleTime += dt;
}
}
void CAtomicAlpha::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
if (type == EUserEventType::Projectile) {
zeus::CVector3f origin = GetLctrTransform(node.GetLocatorName()).origin;
zeus::CTransform xf = zeus::lookAt(origin, origin + zeus::CVector3f::skDown, zeus::CVector3f::skUp);
LaunchProjectile(xf, mgr, 4, EProjectileAttrib::None, false, {}, 0xFFFF, false, zeus::CVector3f(1.f));
x578_bombTime = 0.f;
x57c_curBomb = (x57c_curBomb + 1) & (x6dc_bombLocators.size() - 1);
} else
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
}
bool CAtomicAlpha::Leash(CStateManager& mgr, float) {
if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() <=
x3cc_playerLeashRadius * x3cc_playerLeashRadius)
return false;
return x3d4_curPlayerLeashTime > x3d0_playerLeashTime;
}
bool CAtomicAlpha::AggressionCheck(CStateManager& mgr, float) {
const CPlayerGun* playerGun = mgr.GetPlayer().GetPlayerGun();
float factor = 0.f;
if (x568_26_applyBeamAttraction && playerGun->IsCharging())
factor = playerGun->GetChargeBeamFactor();
return factor > 0.1f;
}
void CAtomicAlpha::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CStateManager& mgr) {
if (IsAlive()) {
if (TCastToConstPtr<CPlayer> pl = mgr.GetObjectById(uid)) {
if (x420_curDamageRemTime <= 0.f) {
mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), 0.5f, 0.25f);
for (SBomb& bomb : x6dc_bombLocators) {
bomb.x14_scaleTime = 0.f;
}
}
}
}
CPatterned::CollidedWith(uid, list, mgr);
}
void CAtomicAlpha::Patrol(CStateManager& mgr, EStateMsg msg, float arg) {
CPatterned::Patrol(mgr, msg, arg);
if (msg == EStateMsg::Activate) {
x578_bombTime = 0.f;
} else if (msg == EStateMsg::Update) {
if (x568_24_inRange) {
if (x578_bombTime >= x56c_bomdDropDelay &&
x6dc_bombLocators[0].x14_scaleTime > (x570_bombReappearDelay + x574_bombRappearTime)) {
x450_bodyController->SetLocomotionType(x6dc_bombLocators[x57c_curBomb].x10_locomotionType);
} else {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
}
if (Leash(mgr, arg))
x568_24_inRange = false;
} else {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
if (InMaxRange(mgr, arg))
x568_24_inRange = true;
}
} else if (msg == EStateMsg::Deactivate) {
x568_24_inRange = false;
}
}
void CAtomicAlpha::Attack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal8);
} else if (msg == EStateMsg::Update) {
zeus::CVector3f seekVec = x664_steeringBehaviors.Seek(*this, mgr.GetPlayer().GetEyePosition());
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(seekVec, {}, 1.f));
} else if (msg == EStateMsg::Deactivate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
}
}
} // namespace urde::MP1

View File

@ -1,13 +1,61 @@
#pragma once
#include "World/CPatterned.hpp"
#include "World/CPathFindSearch.hpp"
#include "Weapon/CProjectileInfo.hpp"
namespace urde::MP1 {
class CAtomicAlpha : public CPatterned {
static const std::string_view skBombLocators[4];
static constexpr u32 skBombCount = 4;
struct SBomb {
std::string x0_locatorName;
pas::ELocomotionType x10_locomotionType;
float x14_scaleTime = FLT_MAX;
SBomb(const std::string_view locator, pas::ELocomotionType locomotionType)
: x0_locatorName(locator.data())
, x10_locomotionType(locomotionType) {}
};
bool x568_24_inRange : 1;
bool x568_25_invisible : 1;
bool x568_26_applyBeamAttraction : 1;
float x56c_bomdDropDelay;
float x570_bombReappearDelay;
float x574_bombRappearTime;
float x578_bombTime = 0.f;
u32 x57c_curBomb = 0;
CPathFindSearch x580_pathFind;
CSteeringBehaviors x664_steeringBehaviors;
CProjectileInfo x668_bombProjectile;
CModelData x690_bombModel;
rstl::reserved_vector<SBomb, skBombCount> x6dc_bombLocators;
public:
DEFINE_PATTERNED(AtomicAlpha)
CAtomicAlpha(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
const CActorParameters&, const CPatternedInfo&, CAssetId, const CDamageInfo&, float, float, float,
CAssetId, bool, bool);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void Render(const CStateManager&) const;
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const;
void Think(float, CStateManager&);
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt);
CPathFindSearch* GetSearchPath() { return &x580_pathFind; }
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
const CWeaponMode& wMode, EProjectileAttrib) const {
return GetDamageVulnerability()->WeaponHits(wMode, false) ? EWeaponCollisionResponseTypes::AtomicAlpha
: EWeaponCollisionResponseTypes::AtomicAlphaReflect;
}
bool Leash(CStateManager& mgr, float);
bool AggressionCheck(CStateManager&, float);
void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&);
void Patrol(CStateManager&, EStateMsg, float);
void Attack(CStateManager&, EStateMsg, float);
CProjectileInfo* GetProjectileInfo() { return &x668_bombProjectile; }
};
} // namespace urde::MP1

View File

@ -34,4 +34,11 @@ CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& in
const CBabygothData& babyData)
: CPatterned(ECharacter::Babygoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) {}
void CBabygoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::Registered) {
x450_bodyController->Activate(mgr);
}
}
} // namespace urde::MP1

View File

@ -50,6 +50,7 @@ public:
DEFINE_PATTERNED(Babygoth)
CBabygoth(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
const CPatternedInfo&, const CActorParameters&, const CBabygothData&);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr);
};
} // namespace urde::MP1

View File

@ -269,7 +269,7 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
if (vulnType != EVulnerability::Immune && !deflect) {
deflect =
(type == EWeaponCollisionResponseTypes::Unknown15 || type == EWeaponCollisionResponseTypes::EnemyShielded ||
(type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::Unknown93));
(type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect));
}
SetTranslation(offsetPos);

View File

@ -1789,10 +1789,11 @@ CEntity* ScriptLoader::LoadActorRotate(CStateManager& mgr, CInputStream& in, int
zeus::CVector3f rotation = zeus::CVector3f::ReadBig(in);
float scale = in.readFloatBig();
bool updateActors = in.readBool();
bool b2 = in.readBool();
bool updateOnCreation = in.readBool();
bool active = in.readBool();
return new CScriptActorRotate(mgr.AllocateUniqueId(), name, info, rotation, scale, updateActors, b2, active);
return new CScriptActorRotate(mgr.AllocateUniqueId(), name, info, rotation, scale, updateActors, updateOnCreation,
active);
}
CEntity* ScriptLoader::LoadSpecialFunction(CStateManager& mgr, CInputStream& in, int propCount,