Add CScriptVisorGoo

Former-commit-id: 67416249b5
This commit is contained in:
Henrique Gemignani Passos Lima 2022-11-22 23:11:50 +02:00
parent 8f0b4b4770
commit cc64bb8b81
5 changed files with 189 additions and 7 deletions

View File

@ -3,8 +3,8 @@
.section .data
.balign 8
.global lbl_803E58C0
lbl_803E58C0:
.global __vt__15CScriptVisorGoo
__vt__15CScriptVisorGoo:
# ROM: 0x3E28C0
.4byte 0
.4byte 0
@ -482,9 +482,9 @@ __dt__15CScriptVisorGooFv:
/* 801D75B8 001D4518 93 C1 00 08 */ stw r30, 8(r1)
/* 801D75BC 001D451C 7C 7E 1B 79 */ or. r30, r3, r3
/* 801D75C0 001D4520 41 82 00 54 */ beq lbl_801D7614
/* 801D75C4 001D4524 3C 60 80 3E */ lis r3, lbl_803E58C0@ha
/* 801D75C4 001D4524 3C 60 80 3E */ lis r3, __vt__15CScriptVisorGoo@ha
/* 801D75C8 001D4528 34 1E 00 F0 */ addic. r0, r30, 0xf0
/* 801D75CC 001D452C 38 03 58 C0 */ addi r0, r3, lbl_803E58C0@l
/* 801D75CC 001D452C 38 03 58 C0 */ addi r0, r3, __vt__15CScriptVisorGoo@l
/* 801D75D0 001D4530 90 1E 00 00 */ stw r0, 0(r30)
/* 801D75D4 001D4534 41 82 00 10 */ beq lbl_801D75E4
/* 801D75D8 001D4538 38 7E 00 F0 */ addi r3, r30, 0xf0
@ -570,9 +570,9 @@ lbl_801D7614:
/* 801D7700 001D4660 38 61 00 D0 */ addi r3, r1, 0xd0
/* 801D7704 001D4664 38 80 FF FF */ li r4, -1
/* 801D7708 001D4668 4B F3 F3 45 */ bl __dt__10CModelDataFv
/* 801D770C 001D466C 3C 60 80 3E */ lis r3, lbl_803E58C0@ha
/* 801D770C 001D466C 3C 60 80 3E */ lis r3, __vt__15CScriptVisorGoo@ha
/* 801D7710 001D4670 3A BA 00 E8 */ addi r21, r26, 0xe8
/* 801D7714 001D4674 38 03 58 C0 */ addi r0, r3, lbl_803E58C0@l
/* 801D7714 001D4674 38 03 58 C0 */ addi r0, r3, __vt__15CScriptVisorGoo@l
/* 801D7718 001D4678 38 61 00 28 */ addi r3, r1, 0x28
/* 801D771C 001D467C 90 1A 00 00 */ stw r0, 0(r26)
/* 801D7720 001D4680 38 80 00 00 */ li r4, 0

View File

@ -286,7 +286,7 @@ LIBS = [
"MetroidPrime/Player/CGameState",
["MetroidPrime/ScriptObjects/CScriptVisorFlare", False],
["MetroidPrime/ScriptObjects/CScriptWorldTeleporter", False],
"MetroidPrime/ScriptObjects/CScriptVisorGoo",
["MetroidPrime/ScriptObjects/CScriptVisorGoo", False],
"MetroidPrime/Enemies/CJellyZap",
["MetroidPrime/ScriptObjects/CScriptControllerAction", False],
["MetroidPrime/Weapons/GunController/CGunMotion", False],

View File

@ -12,6 +12,7 @@ class CMath {
public:
static float FastCosR(float v);
static float FastSinR(float v);
static float FastArcCosR(float v);
static inline float FastFmod(float x, float y) {
int v = static_cast< int >(x * (1.f / y));
return x - v * y;

View File

@ -0,0 +1,39 @@
#ifndef _CSCRIPTVISORGOO
#define _CSCRIPTVISORGOO
#include "MetroidPrime/CActor.hpp"
class CGenDescription;
class CElectricDescription;
class CScriptVisorGoo : public CActor {
public:
CScriptVisorGoo(TUniqueId uid, const rstl::string& name, const CEntityInfo& info,
const CTransform4f& xf, CAssetId particle, CAssetId electric, float minDist,
float maxDist, float nearProb, float farProb, const CColor& color, int sfx,
bool forceShow, bool active);
~CScriptVisorGoo();
void Accept(IVisitor& visitor) override;
void Think(float, CStateManager& stateMgr) override;
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) override;
void AddToRenderer(const CFrustumPlanes&, const CStateManager&) const override;
void Render(const CStateManager&) const override;
rstl::optional_object< CAABox > GetTouchBounds() const override;
void Touch(CActor&, CStateManager&) override;
private:
TToken< CGenDescription > xe8_particleDesc;
TToken< CElectricDescription > xf0_electricDesc;
ushort xf8_sfx;
CAssetId xfc_particleId;
CAssetId x100_electricId;
float x104_minDist;
float x108_maxDist;
float x10c_nearProb;
float x110_farProb;
CColor x114_color;
bool x118_24_angleTest : 1;
};
#endif // _CSCRIPTVISORGOO

View File

@ -0,0 +1,142 @@
#include "MetroidPrime/ScriptObjects/CScriptVisorGoo.hpp"
#include "MetroidPrime/CActorParameters.hpp"
#include "MetroidPrime/CStateManager.hpp"
#include "MetroidPrime/Cameras/CCameraManager.hpp"
#include "MetroidPrime/Player/CPlayer.hpp"
#include "MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp"
#include "Kyoto/Audio/CSfxManager.hpp"
#include "rstl/math.hpp"
CScriptVisorGoo::CScriptVisorGoo(TUniqueId uid, const rstl::string& name, const CEntityInfo& info,
const CTransform4f& xf, CAssetId particle, CAssetId electric,
float minDist, float maxDist, float nearProb, float farProb,
const CColor& color, int sfx, bool forceShow, bool active)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(),
CActorParameters::None(), kInvalidUniqueId)
, xe8_particleDesc(nullptr)
, xf0_electricDesc(nullptr)
, xf8_sfx(CSfxManager::TranslateSFXID(sfx))
, xfc_particleId(particle)
, x100_electricId(electric)
, x104_minDist(minDist)
, x108_maxDist(rstl::max_val(maxDist, minDist + 0.01f))
, x10c_nearProb(nearProb)
, x110_farProb(farProb)
, x114_color(color) {
x118_24_angleTest = !forceShow;
if (particle != kInvalidAssetId) {
xe8_particleDesc = gpSimplePool->GetObj(SObjectTag('PART', particle));
}
if (electric != kInvalidAssetId) {
xf0_electricDesc = gpSimplePool->GetObj(SObjectTag('ELSC', electric));
}
}
CScriptVisorGoo::~CScriptVisorGoo() {}
void CScriptVisorGoo::Think(float, CStateManager& mgr) {
if (GetActive()) {
bool loaded = false;
if (xfc_particleId != kInvalidAssetId) {
if (xe8_particleDesc.IsLoaded()) {
if (x100_electricId != kInvalidAssetId) {
if (xf0_electricDesc.IsLoaded()) {
loaded = true;
}
} else {
loaded = true;
}
}
} else {
if (xf0_electricDesc.IsLoaded()) {
loaded = true;
}
}
if (loaded) {
bool showGoo = false;
if (mgr.GetPlayer()->GetCameraState() == CPlayer::kCS_FirstPerson) {
const CVector3f eyeToGoo = GetTranslation() - mgr.GetPlayer()->GetEyePosition();
const float eyeToGooDist = eyeToGoo.Magnitude();
if (eyeToGooDist >= x104_minDist && eyeToGooDist <= x108_maxDist) {
if (x118_24_angleTest) {
CVector3f colNorm = mgr.GetCameraManager()
->GetCurrentCameraTransform(mgr)
.GetColumn(kDY)
.AsNormalized();
float angleThresh = 45.f;
float angle = CMath::Rad2Deg(CMath::FastArcCosR(
CVector3f::Dot(eyeToGoo.AsNormalized(), colNorm))) *
360.f;
if (eyeToGooDist < 4.f) {
angleThresh *= 4.f / eyeToGooDist;
angleThresh = rstl::min_val(angleThresh, 90.f);
}
if (angle <= angleThresh) {
showGoo = true;
}
} else {
showGoo = true;
}
if (showGoo) {
const float t = (x108_maxDist - eyeToGooDist) / (x108_maxDist - x104_minDist);
float prob = t * x10c_nearProb + (1.0f - t) * x110_farProb;
if (mgr.Random()->Float() * 100.f <= prob) {
mgr.AddObject(new CHUDBillboardEffect(
xfc_particleId != kInvalidAssetId
? rstl::optional_object< TToken< CGenDescription > >(xe8_particleDesc)
: rstl::optional_object_null(),
x100_electricId != kInvalidAssetId
? rstl::optional_object< TToken< CElectricDescription > >(xf0_electricDesc)
: rstl::optional_object_null(),
mgr.AllocateUniqueId(), true, rstl::string_l("VisorGoo"),
CHUDBillboardEffect::GetNearClipDistance(mgr),
CHUDBillboardEffect::GetScaleForPOV(mgr), x114_color, CVector3f(1.f, 1.f, 1.f),
CVector3f(0.f, 0.f, 0.f)));
CSfxManager::SfxStart(xf8_sfx, 0x7f, 0x40, false, CSfxManager::kMedPriority);
}
}
}
}
mgr.FreeScriptObject(GetUniqueId());
}
}
}
void CScriptVisorGoo::Touch(CActor& other, CStateManager& mgr) {
// Empty
}
rstl::optional_object< CAABox > CScriptVisorGoo::GetTouchBounds() const {
return rstl::optional_object_null();
}
void CScriptVisorGoo::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId,
CStateManager& mgr) {
switch (msg) {
case kSM_Activate:
if (xfc_particleId != kInvalidAssetId) {
xe8_particleDesc.Lock();
}
if (x100_electricId != kInvalidAssetId) {
xf0_electricDesc.Lock();
}
break;
default:
break;
}
CActor::AcceptScriptMsg(msg, objId, mgr);
}
void CScriptVisorGoo::Render(const CStateManager& mgr) const {
// Empty
}
void CScriptVisorGoo::AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const {
// Empty
}
void CScriptVisorGoo::Accept(IVisitor& visitor) { visitor.Visit(*this); }