metaforce/Runtime/Collision/CCollisionActor.cpp

202 lines
8.3 KiB
C++
Raw Normal View History

#include "Runtime/Collision/CCollisionActor.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/Camera/CGameCamera.hpp"
#include "Runtime/Collision/CCollidableOBBTreeGroup.hpp"
#include "Runtime/Collision/CCollidableSphere.hpp"
#include "Runtime/World/CActorParameters.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
2021-04-10 08:42:06 +00:00
namespace metaforce {
constexpr CMaterialList skDefaultCollisionActorMaterials =
CMaterialList(EMaterialTypes::Solid, EMaterialTypes::CollisionActor, EMaterialTypes::ScanPassthrough,
EMaterialTypes::CameraPassthrough);
CCollisionActor::CCollisionActor(TUniqueId uid, TAreaId areaId, TUniqueId owner, const zeus::CVector3f& extent,
2019-01-05 03:28:02 +00:00
const zeus::CVector3f& center, bool active, float mass, std::string_view name)
2020-09-23 19:41:51 +00:00
: CPhysicsActor(uid, active, "CollisionActor", CEntityInfo(areaId, CEntity::NullConnectionList), zeus::CTransform(),
CModelData::CModelDataNull(), skDefaultCollisionActorMaterials, zeus::skNullBox, SMoverData(mass),
CActorParameters::None(), 0.3f, 0.1f)
2017-03-03 22:13:23 +00:00
, x258_primitiveType(EPrimitiveType::OBBTreeGroup)
, x25c_owner(owner)
2019-01-05 03:28:02 +00:00
, x260_boxSize(extent)
, x26c_center(center)
, x278_obbContainer(std::make_unique<CCollidableOBBTreeGroupContainer>(extent, center))
, x27c_obbTreeGroupPrimitive(std::make_unique<CCollidableOBBTreeGroup>(x278_obbContainer.get(), GetMaterialList())) {
2019-01-05 03:28:02 +00:00
x10_name += ' ';
x10_name += name;
2018-12-08 05:30:43 +00:00
SetCoefficientOfRestitutionModifier(0.5f);
SetCallTouch(false);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision}));
}
CCollisionActor::CCollisionActor(TUniqueId uid, TAreaId areaId, TUniqueId owner, const zeus::CVector3f& boxSize,
2019-01-05 03:28:02 +00:00
bool active, float mass, std::string_view name)
2020-09-23 19:41:51 +00:00
: CPhysicsActor(uid, active, "CollisionActor", CEntityInfo(areaId, CEntity::NullConnectionList), zeus::CTransform(),
CModelData::CModelDataNull(), skDefaultCollisionActorMaterials, zeus::skNullBox, SMoverData(mass),
CActorParameters::None(), 0.3f, 0.1f)
2017-03-03 22:13:23 +00:00
, x258_primitiveType(EPrimitiveType::AABox)
, x25c_owner(owner)
2017-03-03 22:13:23 +00:00
, x260_boxSize(boxSize)
, x280_aaboxPrimitive(
std::make_unique<CCollidableAABox>(zeus::CAABox(-0.5f * boxSize, 0.5f * boxSize),
CMaterialList(EMaterialTypes::Solid, EMaterialTypes::NoStaticCollision))) {
2019-01-05 03:28:02 +00:00
x10_name += ' ';
x10_name += name;
2018-12-08 05:30:43 +00:00
SetCoefficientOfRestitutionModifier(0.5f);
SetCallTouch(false);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision}));
}
CCollisionActor::CCollisionActor(TUniqueId uid, TAreaId areaId, TUniqueId owner, bool active, float radius, float mass,
2019-01-05 03:28:02 +00:00
std::string_view name)
2020-09-23 19:41:51 +00:00
: CPhysicsActor(uid, active, "CollisionActor", CEntityInfo(areaId, CEntity::NullConnectionList), zeus::CTransform(),
CModelData::CModelDataNull(), skDefaultCollisionActorMaterials, zeus::skNullBox, SMoverData(mass),
CActorParameters::None(), 0.3f, 0.1f)
2017-03-03 22:13:23 +00:00
, x258_primitiveType(EPrimitiveType::Sphere)
, x25c_owner(owner)
, x284_spherePrimitive(std::make_unique<CCollidableSphere>(
zeus::CSphere(zeus::skZero3f, radius), CMaterialList(EMaterialTypes::NoStaticCollision, EMaterialTypes::Solid)))
2018-12-08 05:30:43 +00:00
, x288_sphereRadius(radius) {
2019-01-05 03:28:02 +00:00
x10_name += ' ';
x10_name += name;
2018-12-08 05:30:43 +00:00
SetCoefficientOfRestitutionModifier(0.5f);
SetCallTouch(false);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision}));
}
2017-03-01 03:42:06 +00:00
2017-03-03 22:13:23 +00:00
void CCollisionActor::Accept(IVisitor& visitor) { visitor.Visit(this); }
void CCollisionActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
2018-12-08 05:30:43 +00:00
switch (msg) {
case EScriptObjectMessage::Falling:
case EScriptObjectMessage::Registered:
case EScriptObjectMessage::Deleted:
case EScriptObjectMessage::InitializedInArea:
break;
2018-12-08 05:30:43 +00:00
case EScriptObjectMessage::Touched:
case EScriptObjectMessage::Damage:
case EScriptObjectMessage::InvulnDamage: {
2019-01-05 03:28:02 +00:00
if (CEntity* ent = mgr.ObjectById(x25c_owner)) {
x2fc_lastTouched = sender;
2019-01-05 03:28:02 +00:00
mgr.SendScriptMsg(ent, GetUniqueId(), msg);
}
2018-12-08 05:30:43 +00:00
} break;
default:
2019-01-05 03:28:02 +00:00
mgr.SendScriptMsgAlways(x25c_owner, GetUniqueId(), msg);
break;
2018-12-08 05:30:43 +00:00
}
CActor::AcceptScriptMsg(msg, sender, mgr);
}
2017-03-01 03:42:06 +00:00
2017-08-20 05:23:22 +00:00
CHealthInfo* CCollisionActor::HealthInfo(CStateManager&) { return &x28c_healthInfo; }
2017-03-01 03:42:06 +00:00
const CDamageVulnerability* CCollisionActor::GetDamageVulnerability() const { return &x294_damageVuln; }
const CDamageVulnerability* CCollisionActor::GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&,
2018-12-08 05:30:43 +00:00
const CDamageInfo&) const {
return GetDamageVulnerability();
2017-03-01 03:42:06 +00:00
}
void CCollisionActor::SetDamageVulnerability(const CDamageVulnerability& vuln) { x294_damageVuln = vuln; }
2017-03-03 22:13:23 +00:00
2018-12-08 05:30:43 +00:00
zeus::CVector3f CCollisionActor::GetScanObjectIndicatorPosition(const CStateManager& mgr) const {
const auto* gameCamera = static_cast<const CGameCamera*>(mgr.GetCameraManager()->GetCurrentCamera(mgr));
2018-12-08 05:30:43 +00:00
float scanScale;
if (x258_primitiveType == EPrimitiveType::Sphere) {
2018-12-08 05:30:43 +00:00
scanScale = GetSphereRadius();
} else {
2018-12-08 05:30:43 +00:00
const zeus::CVector3f v = GetBoxSize();
2021-05-16 19:11:45 +00:00
float comp = v.x() >= v.y() ? v.z() : v.y();
if (comp < v.z()) {
comp = v.x();
}
2018-12-08 05:30:43 +00:00
scanScale = 0.5f * comp;
}
scanScale *= 3.0f;
zeus::CVector3f orbitPos = GetOrbitPosition(mgr);
2019-03-09 08:58:27 +00:00
return orbitPos - scanScale * (orbitPos - gameCamera->GetTranslation()).normalized();
2017-03-03 22:13:23 +00:00
}
2018-12-08 05:30:43 +00:00
const CCollisionPrimitive* CCollisionActor::GetCollisionPrimitive() const {
if (x258_primitiveType == EPrimitiveType::OBBTreeGroup) {
2018-12-08 05:30:43 +00:00
return x27c_obbTreeGroupPrimitive.get();
}
if (x258_primitiveType == EPrimitiveType::AABox) {
2018-12-08 05:30:43 +00:00
return x280_aaboxPrimitive.get();
}
2018-12-08 05:30:43 +00:00
return x284_spherePrimitive.get();
2017-03-03 22:13:23 +00:00
}
2018-11-19 01:19:44 +00:00
EWeaponCollisionResponseTypes CCollisionActor::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
2018-12-08 05:30:43 +00:00
const CWeaponMode&, EProjectileAttrib) const {
return x300_responseType;
2018-11-19 01:19:44 +00:00
}
2018-12-08 05:30:43 +00:00
zeus::CTransform CCollisionActor::GetPrimitiveTransform() const {
zeus::CTransform xf = x34_transform;
xf.origin = CPhysicsActor::GetPrimitiveTransform().origin;
return xf;
2017-03-03 22:13:23 +00:00
}
std::optional<zeus::CAABox> CCollisionActor::GetTouchBounds() const {
std::optional<zeus::CAABox> aabox;
2018-12-08 05:30:43 +00:00
if (x258_primitiveType == EPrimitiveType::OBBTreeGroup)
aabox = {x27c_obbTreeGroupPrimitive->CalculateAABox(x34_transform)};
else if (x258_primitiveType == EPrimitiveType::AABox)
aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)};
else if (x258_primitiveType == EPrimitiveType::Sphere)
aabox = {x284_spherePrimitive->CalculateAABox(x34_transform)};
2017-03-03 22:13:23 +00:00
2018-12-08 05:30:43 +00:00
aabox->accumulateBounds(aabox->max + x304_extendedTouchBounds);
aabox->accumulateBounds(aabox->min - x304_extendedTouchBounds);
2017-03-03 22:13:23 +00:00
2018-12-08 05:30:43 +00:00
return aabox;
2017-03-03 22:13:23 +00:00
}
void CCollisionActor::OnScanStateChanged(EScanState state, CStateManager& mgr) {
if (const TCastToPtr<CActor> actor = mgr.ObjectById(x25c_owner)) {
2018-12-08 05:30:43 +00:00
actor->OnScanStateChanged(state, mgr);
}
2017-03-03 22:13:23 +00:00
2018-12-08 05:30:43 +00:00
CActor::OnScanStateChanged(state, mgr);
2017-03-03 22:13:23 +00:00
}
2018-12-08 05:30:43 +00:00
void CCollisionActor::Touch(CActor& actor, CStateManager& mgr) {
x2fc_lastTouched = actor.GetUniqueId();
mgr.SendScriptMsgAlways(x25c_owner, GetUniqueId(), EScriptObjectMessage::Touched);
2017-03-03 22:13:23 +00:00
}
zeus::CVector3f CCollisionActor::GetOrbitPosition(const CStateManager&) const { return GetTouchBounds()->center(); }
2019-11-12 20:25:21 +00:00
void CCollisionActor::SetSphereRadius(float radius) {
if (x258_primitiveType != EPrimitiveType::Sphere) {
2019-11-12 20:25:21 +00:00
return;
}
2019-11-12 20:25:21 +00:00
x288_sphereRadius = radius;
x284_spherePrimitive->SetSphereRadius(radius);
}
2020-09-23 19:41:51 +00:00
void CCollisionActor::DebugDraw() {
zeus::CAABox aabox;
if (x258_primitiveType == EPrimitiveType::OBBTreeGroup)
aabox = x27c_obbTreeGroupPrimitive->CalculateAABox(x34_transform);
else if (x258_primitiveType == EPrimitiveType::AABox)
aabox = x280_aaboxPrimitive->CalculateAABox(x34_transform);
else if (x258_primitiveType == EPrimitiveType::Sphere)
aabox = x284_spherePrimitive->CalculateAABox(x34_transform);
m_aabox.setAABB(aabox);
zeus::CColor col = !GetActive() ? zeus::skRed : zeus::skGreen;
col.a() = 0.5f;
m_aabox.draw(col);
}
2021-04-10 08:42:06 +00:00
} // namespace metaforce