mirror of https://github.com/PrimeDecomp/prime.git
232 lines
7.7 KiB
C++
232 lines
7.7 KiB
C++
#include "MetroidPrime/ScriptObjects/CScriptActor.hpp"
|
|
|
|
#include "MetroidPrime/CActorParameters.hpp"
|
|
#include "MetroidPrime/CAnimData.hpp"
|
|
#include "MetroidPrime/Cameras/CCameraManager.hpp"
|
|
#include "MetroidPrime/Cameras/CCinematicCamera.hpp"
|
|
#include "MetroidPrime/Player/CPlayerState.hpp"
|
|
#include "MetroidPrime/ScriptObjects/CScriptColorModulate.hpp"
|
|
#include "MetroidPrime/ScriptObjects/CScriptTrigger.hpp"
|
|
|
|
#include "Kyoto/Math/CloseEnough.hpp"
|
|
|
|
CScriptActor::CScriptActor(TUniqueId uid, const rstl::string& name, const CEntityInfo& info,
|
|
const CTransform4f& xf, const CModelData& mData, const CAABox& aabb,
|
|
const CMaterialList& matList, float mass, float zMomentum,
|
|
const CHealthInfo& hInfo, const CDamageVulnerability& dVuln,
|
|
const CActorParameters& actParms, bool looping, bool active,
|
|
uint shaderIdx, float xrayAlpha, bool noThermalHotZ, bool castsShadow,
|
|
bool scaleAdvancementDelta, bool materialFlag54)
|
|
: CPhysicsActor(uid, active, name, info, xf, mData, matList, aabb, SMoverData(mass), actParms, 0.3f,
|
|
0.1f)
|
|
, x258_initialHealth(hInfo)
|
|
, x260_currentHealth(hInfo)
|
|
, x268_damageVulnerability(dVuln)
|
|
, x2d0_fadeInTime(actParms.GetFadeInTime())
|
|
, x2d4_fadeOutTime(actParms.GetFadeOutTime())
|
|
, x2d8_shaderIdx(shaderIdx)
|
|
, x2dc_xrayAlpha(xrayAlpha)
|
|
, x2e0_triggerId(kInvalidUniqueId)
|
|
, x2e2_24_noThermalHotZ(noThermalHotZ)
|
|
, x2e2_25_dead(false)
|
|
, x2e2_26_animating(true)
|
|
, x2e2_27_xrayAlphaEnabled(!close_enough(xrayAlpha, 1.f))
|
|
, x2e2_28_inXrayAlpha(false)
|
|
, x2e2_29_processModelFlags(x2e2_27_xrayAlphaEnabled || x2e2_24_noThermalHotZ ||
|
|
x2d8_shaderIdx != 0)
|
|
, x2e2_30_scaleAdvancementDelta(scaleAdvancementDelta)
|
|
, x2e2_31_materialFlag54(materialFlag54)
|
|
, x2e3_24_isPlayerActor(false) {
|
|
if (HasModelData()) {
|
|
if (castsShadow) {
|
|
SetDrawShadow(true);
|
|
}
|
|
|
|
if (HasAnimation()) {
|
|
ModelData()->EnableLooping(looping);
|
|
}
|
|
}
|
|
|
|
SetMomentumWR(CVector3f(0.f, 0.f, -zMomentum));
|
|
}
|
|
|
|
CScriptActor::~CScriptActor() {}
|
|
|
|
CHealthInfo* CScriptActor::HealthInfo(CStateManager&) { return &x260_currentHealth; }
|
|
|
|
const CDamageVulnerability* CScriptActor::GetDamageVulnerability() const {
|
|
return &x268_damageVulnerability;
|
|
}
|
|
|
|
void CScriptActor::Touch(CActor&, CStateManager&) {}
|
|
|
|
rstl::optional_object< CAABox > CScriptActor::GetTouchBounds() const {
|
|
if (GetActive() && GetMaterialList().HasMaterial(kMT_Solid)) {
|
|
return CPhysicsActor::GetBoundingBox();
|
|
}
|
|
return rstl::optional_object_null();
|
|
}
|
|
|
|
void CScriptActor::Think(float dt, CStateManager& mgr) {
|
|
if (!GetActive()) {
|
|
return;
|
|
}
|
|
|
|
if (HasAnimation()) {
|
|
const bool timeRemaining =
|
|
GetAnimationData()->IsAnimTimeRemaining(dt - FLT_EPSILON, rstl::string_l("Whole Body"));
|
|
const bool loop = GetModelData()->GetIsLoop();
|
|
|
|
const CAdvancementDeltas deltas = CActor::UpdateAnimation(dt, mgr, true);
|
|
|
|
if (timeRemaining || loop) {
|
|
x2e2_26_animating = true;
|
|
|
|
if (x2e2_30_scaleAdvancementDelta) {
|
|
CVector3f rot = GetTransform().TransposeRotate(deltas.GetOffsetDelta());
|
|
CVector3f scale = GetModelData()->GetScale();
|
|
// CVector3f ret = GetTransform().Rotate(scale * rot);
|
|
CVector3f ret = GetTransform().Rotate(CVector3f(
|
|
scale.GetX() * rot.GetX(), scale.GetY() * rot.GetY(), scale.GetZ() * rot.GetZ()));
|
|
MoveToOR(ret, dt);
|
|
} else {
|
|
MoveToOR(deltas.GetOffsetDelta(), dt);
|
|
}
|
|
|
|
RotateToOR(deltas.GetOrientationDelta(), dt);
|
|
}
|
|
|
|
if (!timeRemaining && x2e2_26_animating && !loop) {
|
|
SendScriptMsgs(kSS_MaxReached, mgr, kSM_None);
|
|
x2e2_26_animating = false;
|
|
}
|
|
}
|
|
|
|
if (!x2e2_25_dead && HealthInfo(mgr)->GetHP() <= 0.f) {
|
|
x2e2_25_dead = true;
|
|
SendScriptMsgs(kSS_Dead, mgr, kSM_None);
|
|
}
|
|
}
|
|
|
|
void CScriptActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
|
|
switch (msg) {
|
|
case kSM_InitializedInArea: {
|
|
rstl::vector< SConnection >::const_iterator conn = GetConnectionList().begin();
|
|
for (; conn != GetConnectionList().end(); ++conn) {
|
|
if (conn->x0_state != kSS_InheritBounds || conn->x4_msg != kSM_Activate) {
|
|
continue;
|
|
}
|
|
|
|
CStateManager::TIdListResult search = mgr.GetIdListForScript(conn->x8_objId);
|
|
CStateManager::TIdList::const_iterator current = search.first;
|
|
CStateManager::TIdList::const_iterator end = search.second;
|
|
while (current != end) {
|
|
if (TCastToConstPtr< CScriptTrigger >(mgr.GetObjectById(current->second))) {
|
|
x2e0_triggerId = current->second;
|
|
}
|
|
current++;
|
|
}
|
|
}
|
|
|
|
if (x2e2_31_materialFlag54) {
|
|
CActor::AddMaterial(kMT_Unknown54, mgr);
|
|
}
|
|
break;
|
|
}
|
|
case kSM_Reset: {
|
|
x2e2_25_dead = false;
|
|
x260_currentHealth = x258_initialHealth;
|
|
break;
|
|
}
|
|
case kSM_Increment: {
|
|
if (!GetActive()) {
|
|
mgr.DeliverScriptMsg(this, GetUniqueId(), kSM_Activate);
|
|
CScriptColorModulate::FadeInHelper(mgr, GetUniqueId(), x2d0_fadeInTime);
|
|
}
|
|
break;
|
|
}
|
|
case kSM_Decrement: {
|
|
CScriptColorModulate::FadeOutHelper(mgr, GetUniqueId(), x2d4_fadeOutTime);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
CActor::AcceptScriptMsg(msg, uid, mgr);
|
|
}
|
|
|
|
void CScriptActor::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum) {
|
|
CActor::PreRender(mgr, frustum);
|
|
|
|
if (GetPreRenderClipped() &&
|
|
TCastToConstPtr< CCinematicCamera >(mgr.GetCameraManager()->GetCurrentCamera(mgr))) {
|
|
SetPreRenderClipped(false);
|
|
}
|
|
|
|
if (!GetPreRenderClipped() && x2e2_29_processModelFlags) {
|
|
if (x2e2_27_xrayAlphaEnabled) {
|
|
CModelFlags xrayFlags = CModelFlags::AlphaBlended(x2dc_xrayAlpha);
|
|
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::kPV_XRay) {
|
|
SetModelFlags(xrayFlags);
|
|
x2e2_28_inXrayAlpha = true;
|
|
} else if (x2e2_28_inXrayAlpha) {
|
|
x2e2_28_inXrayAlpha = false;
|
|
if (GetModelFlags() == xrayFlags) {
|
|
SetModelFlags(CModelFlags::Normal());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (x2e2_24_noThermalHotZ && GetThermalFlags() == kTF_Hot) {
|
|
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::kPV_Thermal) {
|
|
SetModelFlags(GetModelFlags().DepthCompareUpdate(false, false));
|
|
} else {
|
|
SetModelFlags(GetModelFlags().DepthCompareUpdate(true, true));
|
|
}
|
|
}
|
|
|
|
if (x2d8_shaderIdx != 0) {
|
|
SetModelFlags(GetModelFlags().UseShaderSet(x2d8_shaderIdx));
|
|
}
|
|
}
|
|
|
|
if (mgr.GetObjectById(x2e0_triggerId) == nullptr) {
|
|
x2e0_triggerId = kInvalidUniqueId;
|
|
}
|
|
}
|
|
|
|
void CScriptActor::Accept(IVisitor& visitor) { visitor.Visit(*this); }
|
|
|
|
EWeaponCollisionResponseTypes CScriptActor::GetCollisionResponseType(const CVector3f& v1,
|
|
const CVector3f& v2,
|
|
const CWeaponMode& wMode,
|
|
int w) const {
|
|
|
|
const CDamageVulnerability* dVuln = GetDamageVulnerability();
|
|
if (dVuln->GetVulnerability(wMode, false) == kVN_Deflect) {
|
|
const EDeflectionType deflectType = dVuln->GetDeflectionType(wMode);
|
|
switch (deflectType) {
|
|
case kDT_One:
|
|
case kDT_Two:
|
|
case kDT_Three:
|
|
return kWCR_Unknown15;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return CActor::GetCollisionResponseType(v1, v2, wMode, w);
|
|
}
|
|
|
|
CAABox CScriptActor::GetSortingBounds(const CStateManager& mgr) const {
|
|
if (x2e0_triggerId != kInvalidUniqueId) {
|
|
const CScriptTrigger* trigger =
|
|
static_cast< const CScriptTrigger* >(mgr.GetObjectById(x2e0_triggerId));
|
|
if (trigger) {
|
|
return trigger->GetTriggerBoundsWR();
|
|
}
|
|
}
|
|
|
|
return CActor::GetSortingBounds(mgr);
|
|
}
|