Work on projectiles

This commit is contained in:
Jack Andersen 2018-02-10 19:27:00 -10:00
parent 137c7424bb
commit 547471c6ba
24 changed files with 601 additions and 76 deletions

View File

@ -202,16 +202,16 @@ struct MetroidPrimeStage1 : IScriptObject
DamageInfo damageInfo3;
CameraShakeData primeStruct2_5;
struct PrimeStruct5B : BigYAML
struct PrimeProjectileInfo : BigYAML
{
DECL_YAML
Value<atUint32> propertyCount;
UniqueID32 particle5;
UniqueID32 particle;
DamageInfo damageInfo4;
Value<float> unknown9;
Value<float> unknown10;
Value<float> unknown11;
UniqueID32 texture2;
UniqueID32 texture;
Value<bool> unknown12;
Value<bool> unknown13;
Value<bool> unknown14;
@ -219,24 +219,24 @@ struct MetroidPrimeStage1 : IScriptObject
void nameIDs(PAKRouter<PAKBridge>& pakRouter, const std::string& name) const
{
if (particle5)
if (particle)
{
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5);
ent->name = name + "_part5";
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle);
ent->name = name + "_part";
}
if (texture2)
if (texture)
{
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2);
ent->name = name + "_tex2";
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture);
ent->name = name + "_tex";
}
}
void depIDs(std::vector<hecl::ProjectPath>& pathsOut) const
{
g_curSpec->flattenDependencies(particle5, pathsOut);
g_curSpec->flattenDependencies(texture2, pathsOut);
g_curSpec->flattenDependencies(particle, pathsOut);
g_curSpec->flattenDependencies(texture, pathsOut);
}
} primeStruct5b;
} projectileInfo;
DamageInfo damageInfo5;
CameraShakeData primeStruct2_6;
@ -299,7 +299,7 @@ struct MetroidPrimeStage1 : IScriptObject
primeStruct4s[1].nameIDs(pakRouter, name + "_prime42");
primeStruct4s[2].nameIDs(pakRouter, name + "_prime43");
primeStruct4s[3].nameIDs(pakRouter, name + "_prime44");
primeStruct5b.nameIDs(pakRouter, name + "_prime5");
projectileInfo.nameIDs(pakRouter, name + "_projectileInfo");
}
void depIDs(std::vector<hecl::ProjectPath>& pathsOut) const
@ -318,7 +318,7 @@ struct MetroidPrimeStage1 : IScriptObject
primeStruct4s[1].depIDs(pathsOut);
primeStruct4s[2].depIDs(pathsOut);
primeStruct4s[3].depIDs(pathsOut);
primeStruct5b.depIDs(pathsOut);
projectileInfo.depIDs(pathsOut);
}
void scanIDs(std::vector<Scan>& scansOut) const

View File

@ -62,7 +62,7 @@ public:
const rstl::optional_object<TLockedToken<CGenDescription>>& GetParticleDescription(EWeaponCollisionResponseTypes) const;
const rstl::optional_object<TLockedToken<CDecalDescription>>& GetDecalDescription(EWeaponCollisionResponseTypes type) const;
s32 GetSoundEffectId(EWeaponCollisionResponseTypes) const;
EWeaponCollisionResponseTypes GetWorldCollisionResponseType(s32);
static EWeaponCollisionResponseTypes GetWorldCollisionResponseType(s32);
static bool ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes);
static bool ResponseTypeIsEnemyNormal(EWeaponCollisionResponseTypes);
static bool ResponseTypeIsEnemySpecial(EWeaponCollisionResponseTypes);

View File

@ -19,7 +19,7 @@ private:
zeus::CVector3f x4_point;
zeus::CPlane x10_plane;
EInvalid x20_invalid = EInvalid::Invalid;
CMaterialList x24_material;
CMaterialList x28_material;
public:
CRayCastResult() = default;
CRayCastResult(const CRayCastResult& other, EInvalid invalid)
@ -27,14 +27,14 @@ public:
x4_point(other.x4_point),
x10_plane(other.x10_plane),
x20_invalid(invalid),
x24_material(other.x24_material)
x28_material(other.x28_material)
{
}
CRayCastResult(float t, const zeus::CVector3f& point,
const zeus::CPlane& plane, const CMaterialList& matList)
: x0_t(t), x4_point(point), x10_plane(plane),
x20_invalid(EInvalid::Valid), x24_material(matList)
x20_invalid(EInvalid::Valid), x28_material(matList)
{}
void MakeInvalid();
@ -44,7 +44,7 @@ public:
float GetT() const { return x0_t; }
const zeus::CVector3f& GetPoint() const { return x4_point; }
const zeus::CPlane& GetPlane() const { return x10_plane; }
const CMaterialList& GetMaterial() const { return x24_material; }
const CMaterialList& GetMaterial() const { return x28_material; }
void Transform(const zeus::CTransform&);
};

View File

@ -0,0 +1,24 @@
//
// Created by Jack Andersen on 2/10/18.
//
#include "CFlaahgraProjectile.hpp"
namespace urde::MP1
{
CFlaahgraProjectile::CFlaahgraProjectile(bool bigStrike, const TToken<CWeaponDescription>& desc,
const zeus::CTransform& xf, const CDamageInfo& damage, TUniqueId uid,
TAreaId aid, TUniqueId owner)
: CEnergyProjectile(true, desc, EWeaponType::AI, xf, EMaterialTypes::Character, damage, uid, aid, owner,
kInvalidUniqueId, EProjectileAttrib::BigProjectile, false, zeus::CVector3f::skOne,
{}, 0xffff, false), x3d8_bigStrike(bigStrike)
{
if (x3d8_bigStrike)
{
xe8_projectileAttribs |= EProjectileAttrib::BigStrike;
x150_damageDuration = 2.f;
}
}
}

View File

@ -0,0 +1,19 @@
#ifndef URDE_CFLAAHGRAPROJECTILE_HPP
#define URDE_CFLAAHGRAPROJECTILE_HPP
#include "Weapon/CEnergyProjectile.hpp"
namespace urde::MP1
{
class CFlaahgraProjectile : public CEnergyProjectile
{
bool x3d8_bigStrike;
public:
CFlaahgraProjectile(bool bigStrike, const TToken<CWeaponDescription>& desc, const zeus::CTransform& xf,
const CDamageInfo& damage, TUniqueId uid, TAreaId aid, TUniqueId owner);
};
}
#endif // URDE_CFLAAHGRAPROJECTILE_HPP

View File

@ -7,10 +7,13 @@ set(MP1_WORLD_SOURCES
CBabygoth.hpp CBabygoth.cpp
CMetroidPrimeRelay.hpp CMetroidPrimeRelay.cpp
CMetroidPrimeExo.hpp CMetroidPrimeExo.cpp
CMetroidPrimeProjectile.hpp CMetroidPrimeProjectile.cpp
CActorContraption.hpp CActorContraption.cpp
CThardusRockProjectile.hpp CThardusRockProjectile.cpp
CMetroidBeta.hpp CMetroidBeta.cpp
CMetroid.hpp CMetroid.cpp
CMetaree.hpp CMetaree.cpp)
CMetaree.hpp CMetaree.cpp
CPuddleToadGamma.hpp CPuddleToadGamma.cpp
CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp)
runtime_add_list(World MP1_WORLD_SOURCES)

View File

@ -41,21 +41,6 @@ SPrimeStruct4::SPrimeStruct4(CInputStream& in)
x8c_dInfo2(in)
{}
SPrimeStruct5B::SPrimeStruct5B(CInputStream& in)
: x0_propertyCount(in.readUint32Big()),
x4_particle(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), in.readUint32Big()})),
xc_dInfo(in),
x28_(in.readFloatBig()),
x2c_(in.readFloatBig()),
x30_(in.readFloatBig()),
x34_texture(in.readUint32Big())
{
x38_24_ = in.readBool();
x38_25_ = in.readBool();
x38_26_ = in.readBool();
x38_27_ = in.readBool();
}
SPrimeStruct6::SPrimeStruct6(CInputStream& in)
: x0_propertyCount(in.readUint32Big()),
x4_damageVulnerability(in),
@ -152,7 +137,7 @@ CMetroidPrimeExo::CMetroidPrimeExo(TUniqueId uid, std::string_view name, const C
const rstl::reserved_vector<SPrimeStruct4, 4>& struct4s, CAssetId wpsc1,
const CDamageInfo& dInfo1, const CCameraShakeData& shakeData4, CAssetId wpsc2,
const CDamageInfo& dInfo2, const CCameraShakeData& shakeData5,
const SPrimeStruct5B& struct5b, const CDamageInfo& dInfo3,
const SPrimeProjectileInfo& projectileInfo, const CDamageInfo& dInfo3,
const CCameraShakeData& shakeData6, CAssetId particle2, CAssetId swoosh,
CAssetId particle3, CAssetId particle4,
const rstl::reserved_vector<SPrimeStruct6, 4>& struct6s)

View File

@ -6,6 +6,7 @@
#include "World/CActorParameters.hpp"
#include "Camera/CCameraShakeData.hpp"
#include "Weapon/CBeamInfo.hpp"
#include "CMetroidPrimeProjectile.hpp"
namespace urde
{
@ -54,22 +55,6 @@ struct SPrimeStruct4
explicit SPrimeStruct4(CInputStream& in);
};
struct SPrimeStruct5B
{
u32 x0_propertyCount;
TToken<CGenDescription> x4_particle;
CDamageInfo xc_dInfo;
float x28_;
float x2c_;
float x30_;
CAssetId x34_texture;
bool x38_24_ : 1;
bool x38_25_ : 1;
bool x38_26_ : 1;
bool x38_27_ : 1;
explicit SPrimeStruct5B(CInputStream& in);
};
struct SPrimeStruct6
{
u32 x0_propertyCount;
@ -98,7 +83,7 @@ struct SPrimeExoParameters
CAssetId x7fc_wpsc2;
CDamageInfo x800_dInfo2;
CCameraShakeData x81c_shakeData2;
SPrimeStruct5B x8f0_;
SPrimeProjectileInfo x8f0_;
CDamageInfo x92c_;
CCameraShakeData x948_;
CAssetId xa1c_particle2;
@ -125,9 +110,10 @@ public:
const CCameraShakeData& shakeData3, const SPrimeStruct2B& struct2b, CAssetId particle1,
const rstl::reserved_vector<SPrimeStruct4, 4>& struct4s, CAssetId wpsc1, const CDamageInfo& dInfo1,
const CCameraShakeData& shakeData4, CAssetId wpsc2, const CDamageInfo& dInfo2,
const CCameraShakeData& shakeData5, const SPrimeStruct5B& struct5b, const CDamageInfo& dInfo3,
const CCameraShakeData& shakeData6, CAssetId particle2, CAssetId swoosh, CAssetId particle3,
CAssetId particle4, const rstl::reserved_vector<SPrimeStruct6, 4>& struct6s);
const CCameraShakeData& shakeData5, const SPrimeProjectileInfo& projectileInfo,
const CDamageInfo& dInfo3, const CCameraShakeData& shakeData6, CAssetId particle2,
CAssetId swoosh, CAssetId particle3, CAssetId particle4,
const rstl::reserved_vector<SPrimeStruct6, 4>& struct6s);
};
}

View File

@ -0,0 +1,36 @@
#include "CMetroidPrimeProjectile.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
namespace urde::MP1
{
SPrimeProjectileInfo::SPrimeProjectileInfo(CInputStream& in)
: x0_propertyCount(in.readUint32Big()),
x4_particle(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), in.readUint32Big()})),
xc_dInfo(in),
x28_(in.readFloatBig()),
x2c_(in.readFloatBig()),
x30_(in.readFloatBig()),
x34_texture(in.readUint32Big())
{
x38_24_ = in.readBool();
x38_25_ = in.readBool();
x38_26_ = in.readBool();
x38_27_ = in.readBool();
}
CMetroidPrimeProjectile::CMetroidPrimeProjectile(
bool active, const TToken<CWeaponDescription>& desc, EWeaponType type,
const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage,
TUniqueId uid, TAreaId aid, TUniqueId owner, const SPrimeProjectileInfo& auxData,
TUniqueId homingTarget, EProjectileAttrib attribs, const zeus::CVector3f& scale,
const rstl::optional_object<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg)
: CEnergyProjectile(active, desc, type, xf, materials, damage, uid, aid, owner, homingTarget, attribs, false,
scale, visorParticle, visorSfx, sendCollideMsg), x3d8_auxData(auxData)
{
}
}

View File

@ -0,0 +1,39 @@
#ifndef URDE_CMETROIDPRIMEPROJECTILE_HPP
#define URDE_CMETROIDPRIMEPROJECTILE_HPP
#include "Weapon/CEnergyProjectile.hpp"
namespace urde::MP1
{
struct SPrimeProjectileInfo
{
u32 x0_propertyCount;
TToken<CGenDescription> x4_particle;
CDamageInfo xc_dInfo;
float x28_;
float x2c_;
float x30_;
CAssetId x34_texture;
bool x38_24_ : 1;
bool x38_25_ : 1;
bool x38_26_ : 1;
bool x38_27_ : 1;
explicit SPrimeProjectileInfo(CInputStream& in);
};
class CMetroidPrimeProjectile : public CEnergyProjectile
{
SPrimeProjectileInfo x3d8_auxData;
public:
CMetroidPrimeProjectile(bool active, const TToken<CWeaponDescription>& desc, EWeaponType type,
const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage,
TUniqueId uid, TAreaId aid, TUniqueId owner, const SPrimeProjectileInfo& auxData,
TUniqueId homingTarget, EProjectileAttrib attribs, const zeus::CVector3f& scale,
const rstl::optional_object<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg);
};
}
#endif // URDE_CMETROIDPRIMEPROJECTILE_HPP

View File

@ -0,0 +1,21 @@
//
// Created by Jack Andersen on 2/10/18.
//
#include "CPuddleToadGamma.hpp"
namespace urde::MP1
{
CPuddleToadGamma::CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
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)
: CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
EColliderType::Zero, EBodyType::Restricted, aParms, 2)
{
}
}

View File

@ -0,0 +1,21 @@
#ifndef __URDE_MP1_CPUDDLETOADGAMMA_HPP__
#define __URDE_MP1_CPUDDLETOADGAMMA_HPP__
#include "World/CPatterned.hpp"
namespace urde::MP1
{
class CPuddleToadGamma : public CPatterned
{
public:
static constexpr ECharacter CharacterType = ECharacter::PuddleToad;
CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
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);
};
}
#endif // __URDE_MP1_CPUDDLETOADGAMMA_HPP__

View File

@ -53,7 +53,7 @@ public:
bool xa4_EWTR = true;
bool xa5_LWTR = true;
bool xa6_SWTR = true;
u32 xa8_PJFX;
s32 xa8_PJFX;
std::unique_ptr<CRealElement> xac_RNGE;
std::unique_ptr<CRealElement> xb0_FOFF;
};

View File

@ -1,4 +1,7 @@
#include <Runtime/GameGlobalObjects.hpp>
#include "CEnergyProjectile.hpp"
#include "CStateManager.hpp"
#include "TCastTo.hpp"
namespace urde
{
@ -7,14 +10,160 @@ CEnergyProjectile::CEnergyProjectile(bool active, const TToken<CWeaponDescriptio
const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage,
TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget,
EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale,
const rstl::optional_object<TLockedToken<CGenDescription>>& particle,
s16 w2, bool b2)
const rstl::optional_object<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg)
: CGameProjectile(active, desc, "GameProjectile", type, xf, materials, damage, uid, aid,
owner, homingTarget, attribs, underwater, scale, particle, w2, b2),
owner, homingTarget, attribs, underwater, scale, visorParticle, visorSfx, sendCollideMsg),
x2ec_dir(xf.basis[1]), x2f8_mag(x2ec_dir.magnitude()),
x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f))
{
xe6_27_thermalVisorFlags = 2;
}
void CEnergyProjectile::PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type)
{
u16 sfxId = x170_projectile.GetSoundIdForCollision(type);
if (sfxId >= 0.f)
{
CAudioSys::C3DEmitterParmData parmData = {};
parmData.x18_maxDist = x170_projectile.GetAudibleRange();
parmData.x1c_distComp = x170_projectile.GetAudibleFallOff();
parmData.x20_flags = 0x1; // Continuous parameter update
parmData.x24_sfxId = CSfxManager::TranslateSFXID(sfxId);
parmData.x26_maxVol = 1.f;
parmData.x27_minVol = 0.16f;
parmData.x29_prio = 0x7f;
CSfxHandle hnd = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId);
if (x2e4_26_waterUpdate)
CSfxManager::PitchBend(hnd, -1.f);
}
}
void CEnergyProjectile::ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr)
{
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(owner))
{
float rDam = g_tweakPlayerGun->GetRichochetDamage(u32(x110_origDamageInfo.GetWeaponMode().GetType()));
x110_origDamageInfo.MultiplyDamageAndRadius(rDam);
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
xec_ownerId = owner;
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
/* Can now damage Player */
xf8_filter.ExcludeList().Add(EMaterialTypes::Character);
xf8_filter.ExcludeList().Remove(EMaterialTypes::Player);
xf8_filter = CMaterialFilter::MakeIncludeExclude(xf8_filter.GetIncludeList(), xf8_filter.GetExcludeList());
}
}
void CEnergyProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr)
{
switch (msg)
{
case EScriptObjectMessage::Deleted:
if (x2e4_24_)
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
if (x2e8_sfx)
{
CSfxManager::RemoveEmitter(x2e8_sfx);
x2e8_sfx.reset();
}
break;
case EScriptObjectMessage::Registered:
{
if (CElementGen* ps1 = x170_projectile.GetAttachedPS1())
if (ps1->SystemHasLight())
CreateProjectileLight("ProjectileLight_GameProjectile", ps1->GetLight(), mgr);
TLockedToken<CWeaponDescription> desc = x170_projectile.GetWeaponDescription();
s32 sfx = desc->xa8_PJFX;
if (sfx != -1)
{
float range = 50.f;
float falloff = 0.2f;
if (CRealElement* rnge = desc->xac_RNGE.get())
rnge->GetValue(0, range);
if (CRealElement* foff = desc->xb0_FOFF.get())
foff->GetValue(0, falloff);
CAudioSys::C3DEmitterParmData parmData = {};
parmData.x0_pos = x170_projectile.GetTranslation();
parmData.xc_dir = x170_projectile.GetVelocity();
parmData.x18_maxDist = range;
parmData.x1c_distComp = falloff;
parmData.x20_flags = 0x9; // Continuous parameter update, doppler
parmData.x24_sfxId = CSfxManager::TranslateSFXID(sfx);
parmData.x26_maxVol = 1.f;
parmData.x27_minVol = 0.16f;
parmData.x29_prio = 0x7f;
x2e8_sfx = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId);
}
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
break;
}
default:
break;
}
CGameProjectile::AcceptScriptMsg(msg, sender, mgr);
}
void CEnergyProjectile::Accept(IVisitor& visitor)
{
visitor.Visit(this);
}
/* Material surface types only (not meta flags) */
static constexpr u64 kCheckMaterial = 0xE3FFFE;
void CEnergyProjectile::ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr)
{
EWeaponCollisionResponseTypes crType = CCollisionResponseData::GetWorldCollisionResponseType(
CMaterialList::BitPosition(res.GetMaterial().GetValue() & 0xffffffff & kCheckMaterial));
if ((xe8_projectileAttribs & (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) !=
(EProjectileAttrib::Wave | EProjectileAttrib::ComboShot))
{
/* Not wavebuster */
if (Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr,
CDamageVulnerability::NormalVulnerabilty(), kInvalidUniqueId))
mgr.ApplyDamageToWorld(xec_ownerId, *this, res.GetPoint(), x12c_curDamageInfo, xf8_filter);
x2c2_ = kInvalidUniqueId;
}
}
void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr)
{
}
void CEnergyProjectile::Think(float dt, CStateManager& mgr)
{
}
void CEnergyProjectile::Render(const CStateManager& mgr) const
{
}
void CEnergyProjectile::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const
{
}
void CEnergyProjectile::Touch(CActor& act, CStateManager& mgr)
{
}
bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
EWeaponCollisionResponseTypes type, CStateManager& mgr,
const CDamageVulnerability& dVuln, TUniqueId exploder)
{
return false;
}
void CEnergyProjectile::StopProjectile(CStateManager& mgr)
{
}
}

View File

@ -9,7 +9,7 @@ namespace urde
class CEnergyProjectile : public CGameProjectile
{
u32 x2e8_ = 0;
CSfxHandle x2e8_sfx;
zeus::CVector3f x2ec_dir;
float x2f8_mag;
CCameraShakeData x2fc_camShake;
@ -25,14 +25,27 @@ class CEnergyProjectile : public CGameProjectile
u32 _dummy = 0;
};
float x3d4_ = 0.f;
void StopProjectile(CStateManager& mgr);
public:
CEnergyProjectile(bool active, const TToken<CWeaponDescription>& desc, EWeaponType type,
const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage,
TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget,
EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale,
const rstl::optional_object<TLockedToken<CGenDescription>>& particle,
s16 w2, bool b2);
const rstl::optional_object<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg);
void SetCameraShake(const CCameraShakeData& data) { x2fc_camShake = data; x3d0_27_camShakeDirty = true; }
void PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type);
void ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr);
void Accept(IVisitor& visitor);
void ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr);
void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr);
void Think(float dt, CStateManager& mgr);
void Render(const CStateManager& mgr) const;
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const;
void Touch(CActor& act, CStateManager& mgr);
virtual bool Explode(const zeus::CVector3f& pos, const zeus::CVector3f& dir, EWeaponCollisionResponseTypes type,
CStateManager& mgr, const CDamageVulnerability& dVuln, TUniqueId exploder);
};
}

View File

@ -7,6 +7,9 @@
#include "World/CWallCrawlerSwarm.hpp"
#include "World/CScriptDoor.hpp"
#include "Collision/CInternalRayCastStructure.hpp"
#include "MP1/World/CPuddleToadGamma.hpp"
#include "World/CScriptPlatform.hpp"
#include "Collision/CCollisionActor.hpp"
namespace urde
{
@ -23,12 +26,13 @@ CGameProjectile::CGameProjectile(bool active, const TToken<CWeaponDescription>&
{EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, matType, EMaterialTypes::Solid}),
CMaterialList(), dInfo, attribs | GetBeamAttribType(wType), CModelData::CModelDataNull()),
x158_visorParticle(visorParticle), x168_visorSfx(visorSfx), x170_projectile(wDesc, xf.origin, xf.basis, scale,
(attribs & EProjectileAttrib::Sixteen) == EProjectileAttrib::Sixteen), x298_(xf.origin),
x2a4_((xe8_projectileAttribs & EProjectileAttrib::Ten) == EProjectileAttrib::Ten ? 0.25f : 0.1f),
(attribs & EProjectileAttrib::ParticleOPTS) == EProjectileAttrib::ParticleOPTS), x298_lastOrigin(xf.origin),
x2a4_projExtent((xe8_projectileAttribs & EProjectileAttrib::BigProjectile) ==
EProjectileAttrib::BigProjectile ? 0.25f : 0.1f),
x2c0_homingTargetId(homingTarget), x2cc_wpscId(wDesc.GetObjectTag()->id)
{
x2e4_24_ = true;
x2e4_25_ = underwater;
x2e4_25_startedUnderwater = underwater;
x2e4_26_waterUpdate = underwater;
x2e4_27_inWater = underwater;
x2e4_28_sendProjectileCollideMsg = sendCollideMsg;
@ -214,7 +218,7 @@ void CGameProjectile::UpdateProjectileMovement(float dt, CStateManager& mgr)
if (x2e4_26_waterUpdate)
useDt = 37.5f * dt * dt;
x298_ = x34_transform.origin;
x298_lastOrigin = x34_transform.origin;
x170_projectile.Update(useDt);
SetTransform(x170_projectile.GetTransform());
SetTranslation(x170_projectile.GetTranslation());
@ -227,12 +231,12 @@ CGameProjectile::DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr)
CRayCastResult res;
if (x2e4_24_)
{
zeus::CVector3f posDelta = x34_transform.origin - x298_;
zeus::CVector3f posDelta = x34_transform.origin - x298_lastOrigin;
rstl::reserved_vector<TUniqueId, 1024> nearList;
mgr.BuildNearList(nearList, GetProjectileBounds(),
CMaterialFilter::MakeExclude(EMaterialTypes::ProjectilePassthrough), this);
res = RayCollisionCheckWithWorld(idOut, x298_, x34_transform.origin,
res = RayCollisionCheckWithWorld(idOut, x298_lastOrigin, x34_transform.origin,
posDelta.magnitude(), nearList, mgr);
}
@ -361,12 +365,174 @@ CGameProjectile::RayCollisionCheckWithWorld(TUniqueId& idOut, const zeus::CVecto
CProjectileTouchResult CGameProjectile::CanCollideWith(CActor& act, CStateManager& mgr)
{
return {{}, {}};
if (act.GetDamageVulnerability()->GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false) ==
EVulnerability::PassThrough)
{
return {kInvalidUniqueId, {}};
}
else
{
if (TCastToPtr<CScriptTrigger>(act))
{
return CanCollideWithTrigger(act, mgr);
}
else if (TCastToPtr<CScriptPlatform>(act) || TCastToPtr<CCollisionActor>(act) ||
CPatterned::CastTo<MP1::CPuddleToadGamma>(&act))
{
return CanCollideWithComplexCollision(act, mgr);
}
else
{
return CanCollideWithGameObject(act, mgr);
}
}
}
CProjectileTouchResult CGameProjectile::CanCollideWithComplexCollision(CActor& act, CStateManager& mgr)
{
CPhysicsActor* useAct = nullptr;
if (TCastToPtr<CScriptPlatform> plat = act)
{
if (plat->HasComplexCollision())
useAct = plat.GetPtr();
}
else if (MP1::CPuddleToadGamma* toad = CPatterned::CastTo<MP1::CPuddleToadGamma>(&act))
{
useAct = toad;
}
else if (TCastToPtr<CCollisionActor> cact = act)
{
if (cact->GetOwnerId() == xec_ownerId)
return {kInvalidUniqueId, {}};
useAct = cact.GetPtr();
}
if (useAct)
{
const CCollisionPrimitive* prim = useAct->GetCollisionPrimitive();
zeus::CTransform xf = useAct->GetPrimitiveTransform();
zeus::CVector3f deltaPos = GetTranslation() - x298_lastOrigin;
if (deltaPos.canBeNormalized())
{
zeus::CVector3f dir = deltaPos.normalized();
float mag = deltaPos.magnitude();
CRayCastResult res =
prim->CastRayInternal({x298_lastOrigin, dir, mag, xf,
CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid},
{EMaterialTypes::ProjectilePassthrough})});
if (!res.IsValid())
{
if (prim->GetPrimType() == FOURCC('SPHR'))
{
mag *= 2.f;
CRayCastResult res2 =
prim->CastRayInternal({x298_lastOrigin - dir * mag, dir, deltaPos.magnitude(), xf,
CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid},
{EMaterialTypes::ProjectilePassthrough})});
if (res2.IsValid())
return {act.GetUniqueId(), {res2}};
}
else if (TCastToPtr<CCollisionActor> cAct = act)
{
float rad = cAct->GetSphereRadius();
if ((x298_lastOrigin - GetTranslation()).magSquared() < rad * rad)
{
zeus::CVector3f point = x298_lastOrigin - dir * rad * 1.125f;
zeus::CUnitVector3f revDir(-dir);
return {act.GetUniqueId(), {{0.f, point, {revDir, point.dot(revDir)}, act.GetMaterialList()}}};
}
}
return {kInvalidUniqueId, {}};
}
else
{
return {act.GetUniqueId(), {res}};
}
}
else
{
return {kInvalidUniqueId, {}};
}
}
else
{
return {act.GetUniqueId(), {}};
}
}
CProjectileTouchResult CGameProjectile::CanCollideWithGameObject(CActor& act, CStateManager& mgr)
{
TCastToPtr<CGameProjectile> proj = act;
if (!proj)
{
if (!act.GetMaterialList().HasMaterial(EMaterialTypes::Solid) && !act.HealthInfo(mgr))
{
return {kInvalidUniqueId, {}};
}
else if (act.GetUniqueId() == xec_ownerId)
{
return {kInvalidUniqueId, {}};
}
else if (act.GetUniqueId() == x2c2_)
{
return {kInvalidUniqueId, {}};
}
else if (xf8_filter.GetExcludeList().Intersection(act.GetMaterialList()))
{
return {kInvalidUniqueId, {}};
}
else if (TCastToPtr<CAi> ai = act)
{
if (!ai->CanBeShot(mgr, int(xe8_projectileAttribs)))
return {kInvalidUniqueId, {}};
}
}
else if ((xe8_projectileAttribs & EProjectileAttrib::PartialCharge) == EProjectileAttrib::PartialCharge ||
(proj->xe8_projectileAttribs & EProjectileAttrib::PartialCharge) == EProjectileAttrib::PartialCharge)
{
return {act.GetUniqueId(), {}};
}
else if ((xe8_projectileAttribs & EProjectileAttrib::PartialCharge) != EProjectileAttrib::PartialCharge &&
(proj->xe8_projectileAttribs & EProjectileAttrib::PartialCharge) != EProjectileAttrib::PartialCharge)
{
return {kInvalidUniqueId, {}};
}
return {act.GetUniqueId(), {}};
}
CProjectileTouchResult CGameProjectile::CanCollideWithTrigger(CActor& act, CStateManager& mgr)
{
bool isWater = TCastToPtr<CScriptWater>(act).operator bool();
if (isWater)
{
bool enteredWater = false;
if (isWater && !x2e4_25_startedUnderwater)
{
if (!x170_projectile.GetWeaponDescription()->xa4_EWTR)
enteredWater = true;
}
/* This case is logically unreachable */
bool leftWater = false;
if (!isWater && x2e4_25_startedUnderwater)
{
if (!x170_projectile.GetWeaponDescription()->xa5_LWTR)
leftWater = true;
}
return {(enteredWater || leftWater) ? act.GetUniqueId() : kInvalidUniqueId, {}};
}
return {kInvalidUniqueId, {}};
}
zeus::CAABox CGameProjectile::GetProjectileBounds() const
{
return {};
return {{std::min(x298_lastOrigin.x, GetTranslation().x) - x2a4_projExtent,
std::min(x298_lastOrigin.y, GetTranslation().y) - x2a4_projExtent,
std::min(x298_lastOrigin.z, GetTranslation().z) - x2a4_projExtent},
{std::max(x298_lastOrigin.x, GetTranslation().x) + x2a4_projExtent,
std::max(x298_lastOrigin.y, GetTranslation().y) + x2a4_projExtent,
std::max(x298_lastOrigin.z, GetTranslation().z) + x2a4_projExtent}};
}
}

View File

@ -29,11 +29,12 @@ public:
class CGameProjectile : public CWeapon
{
protected:
rstl::optional_object<TLockedToken<CGenDescription>> x158_visorParticle;
u16 x168_visorSfx;
CProjectileWeapon x170_projectile;
zeus::CVector3f x298_;
float x2a4_;
zeus::CVector3f x298_lastOrigin;
float x2a4_projExtent;
float x2a8_homingDt = 0.03f;
double x2b0_targetHomingTime = 0.0;
double x2b8_curHomingTime = x2a8_homingDt;
@ -50,7 +51,7 @@ class CGameProjectile : public CWeapon
struct
{
bool x2e4_24_ : 1;
bool x2e4_25_ : 1;
bool x2e4_25_startedUnderwater : 1;
bool x2e4_26_waterUpdate : 1;
bool x2e4_27_inWater : 1;
bool x2e4_28_sendProjectileCollideMsg : 1;
@ -81,6 +82,9 @@ public:
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
CStateManager& mgr);
CProjectileTouchResult CanCollideWith(CActor& act, CStateManager& mgr);
CProjectileTouchResult CanCollideWithComplexCollision(CActor& act, CStateManager& mgr);
CProjectileTouchResult CanCollideWithGameObject(CActor& act, CStateManager& mgr);
CProjectileTouchResult CanCollideWithTrigger(CActor& act, CStateManager& mgr);
zeus::CAABox GetProjectileBounds() const;
TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; }
};

View File

@ -20,6 +20,7 @@ set(WEAPON_SOURCES
CWeapon.hpp CWeapon.cpp
CGameProjectile.hpp CGameProjectile.cpp
CBeamProjectile.hpp CBeamProjectile.cpp
CTargetableProjectile.hpp CTargetableProjectile.cpp
CBeamInfo.hpp CBeamInfo.cpp
CPlasmaProjectile.hpp CPlasmaProjectile.cpp
CEnergyProjectile.cpp CEnergyProjectile.cpp

View File

@ -96,6 +96,7 @@ public:
virtual void Update(float dt);
void SetGravity(const zeus::CVector3f& grav) { xbc_gravity = grav; }
static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; }
CElementGen* GetAttachedPS1() const { return xfc_APSMGen.get(); }
};
}

View File

@ -0,0 +1,26 @@
//
// Created by Jack Andersen on 2/10/18.
//
#include "CTargetableProjectile.hpp"
namespace urde
{
CTargetableProjectile::CTargetableProjectile(
const TToken<CWeaponDescription>& desc, EWeaponType type,
const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage,
const CDamageInfo& damage2, TUniqueId uid, TAreaId aid, TUniqueId owner,
TUniqueId homingTarget, EProjectileAttrib attribs,
const rstl::optional_object<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg)
: CEnergyProjectile(true, desc, type, xf, materials, damage, uid, aid, owner, homingTarget,
attribs | EProjectileAttrib::BigProjectile | EProjectileAttrib::PartialCharge |
EProjectileAttrib::PlasmaProjectile, false, zeus::CVector3f::skOne, visorParticle,
visorSfx, sendCollideMsg), x3e0_dInfo2(damage2)
{
x68_material.Add(EMaterialTypes::Target);
x68_material.Add(EMaterialTypes::Orbit);
}
}

View File

@ -0,0 +1,23 @@
#ifndef URDE_CTARGETABLEPROJECTILE_HPP
#define URDE_CTARGETABLEPROJECTILE_HPP
#include "CEnergyProjectile.hpp"
namespace urde
{
class CTargetableProjectile : public CEnergyProjectile
{
CDamageInfo x3e0_dInfo2;
public:
CTargetableProjectile(const TToken<CWeaponDescription>& desc, EWeaponType type,
const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage,
const CDamageInfo& damage2, TUniqueId uid, TAreaId aid, TUniqueId owner,
TUniqueId homingTarget, EProjectileAttrib attribs,
const rstl::optional_object<TLockedToken<CGenDescription>>& visorParticle,
u16 visorSfx, bool sendCollideMsg);
};
}
#endif // URDE_CTARGETABLEPROJECTILE_HPP

View File

@ -24,13 +24,13 @@ public:
ComboShot = (1 << 7),
Bombs = (1 << 8),
PowerBombs = (1 << 9),
Ten = (1 << 10),
BigProjectile = (1 << 10),
ArmCannon = (1 << 11),
BigStrike = (1 << 12),
DamageFalloff = (1 << 13),
StaticInterference = (1 << 14),
PlayerUnFreeze = (1 << 15),
Sixteen = (1 << 16),
ParticleOPTS = (1 << 16),
KeepInCinematic = (1 << 17),
};

View File

@ -61,6 +61,13 @@ public:
xc_radiusDamage *= m;
x14_knockback *= m;
}
void MultiplyDamageAndRadius(float m)
{
x8_damage *= m;
xc_radiusDamage *= m;
x10_radius *= m;
x14_knockback *= m;
}
};
}

View File

@ -73,6 +73,7 @@ public:
std::vector<SRiders>& GetX338() { return x338_; }
const std::vector<SRiders>& GetX338() const { return x338_; }
void AddSlave(TUniqueId, CStateManager&) {}
bool HasComplexCollision() const { return x314_treeGroup.operator bool(); }
};
}