diff --git a/asm/MetroidPrime/CCollisionActor.s b/asm/MetroidPrime/CCollisionActor.s index dad85525..08814535 100644 --- a/asm/MetroidPrime/CCollisionActor.s +++ b/asm/MetroidPrime/CCollisionActor.s @@ -1616,8 +1616,8 @@ lbl_801A9BEC: /* 801A9DA0 001A6D00 38 21 01 D0 */ addi r1, r1, 0x1d0 /* 801A9DA4 001A6D04 4E 80 00 20 */ blr -.global __ct__15CCollisionActorF9TUniqueIdCRi9TUniqueIdRC9CVector3fRC9CVector3fbf -__ct__15CCollisionActorF9TUniqueIdCRi9TUniqueIdRC9CVector3fRC9CVector3fbf: +.global __ct__15CCollisionActorF9TUniqueId7TAreaId9TUniqueIdRC9CVector3fRC9CVector3fbf +__ct__15CCollisionActorF9TUniqueId7TAreaId9TUniqueIdRC9CVector3fRC9CVector3fbf: /* 801A9DA8 001A6D08 94 21 FE 70 */ stwu r1, -0x190(r1) /* 801A9DAC 001A6D0C 7C 08 02 A6 */ mflr r0 /* 801A9DB0 001A6D10 90 01 01 94 */ stw r0, 0x194(r1) diff --git a/asm/MetroidPrime/CCollisionActorManager.s b/asm/MetroidPrime/CCollisionActorManager.s index 3e34e99f..854dce92 100644 --- a/asm/MetroidPrime/CCollisionActorManager.s +++ b/asm/MetroidPrime/CCollisionActorManager.s @@ -927,7 +927,7 @@ lbl_801A7B98: /* 801A7C24 001A4B84 B1 61 00 78 */ sth r11, 0x78(r1) /* 801A7C28 001A4B88 91 41 00 A8 */ stw r10, 0xa8(r1) /* 801A7C2C 001A4B8C B0 01 00 74 */ sth r0, 0x74(r1) -/* 801A7C30 001A4B90 48 00 21 79 */ bl __ct__15CCollisionActorF9TUniqueIdCRi9TUniqueIdRC9CVector3fRC9CVector3fbf +/* 801A7C30 001A4B90 48 00 21 79 */ bl __ct__15CCollisionActorF9TUniqueId7TAreaId9TUniqueIdRC9CVector3fRC9CVector3fbf /* 801A7C34 001A4B94 7C 73 1B 78 */ mr r19, r3 lbl_801A7C38: /* 801A7C38 001A4B98 80 01 04 F4 */ lwz r0, 0x4f4(r1) @@ -1406,7 +1406,7 @@ lbl_801A8310: /* 801A835C 001A52BC 90 C1 00 98 */ stw r6, 0x98(r1) /* 801A8360 001A52C0 38 C1 00 40 */ addi r6, r1, 0x40 /* 801A8364 001A52C4 B0 01 00 3C */ sth r0, 0x3c(r1) -/* 801A8368 001A52C8 48 00 1A 41 */ bl __ct__15CCollisionActorF9TUniqueIdCRi9TUniqueIdRC9CVector3fRC9CVector3fbf +/* 801A8368 001A52C8 48 00 1A 41 */ bl __ct__15CCollisionActorF9TUniqueId7TAreaId9TUniqueIdRC9CVector3fRC9CVector3fbf /* 801A836C 001A52CC 7C 60 1B 78 */ mr r0, r3 lbl_801A8370: /* 801A8370 001A52D0 7C 13 03 78 */ mr r19, r0 diff --git a/asm/MetroidPrime/Enemies/CFlaahgra.s b/asm/MetroidPrime/Enemies/CFlaahgra.s index 4975339f..bd354b7d 100644 --- a/asm/MetroidPrime/Enemies/CFlaahgra.s +++ b/asm/MetroidPrime/Enemies/CFlaahgra.s @@ -6405,7 +6405,7 @@ lbl_801B28EC: /* 801B2A7C 001AF9DC D0 21 00 64 */ stfs f1, 0x64(r1) /* 801B2A80 001AF9E0 B1 61 00 18 */ sth r11, 0x18(r1) /* 801B2A84 001AF9E4 90 01 00 08 */ stw r0, 8(r1) -/* 801B2A88 001AF9E8 48 05 60 4D */ bl "__ct__15CFlaahgraPlantsF25TToken<15CGenDescription>9TUniqueId9TUniqueIdRC12CTransform4fRC11CDamageInfoRC9CVector3f" +/* 801B2A88 001AF9E8 48 05 60 4D */ bl "__ct__15CFlaahgraPlantsFRC25TToken<15CGenDescription>RC16CActorParameters9TUniqueId7TAreaId9TUniqueIdRC12CTransform4fRC11CDamageInfoRC9CVector3f" /* 801B2A8C 001AF9EC 7C 7A 1B 78 */ mr r26, r3 lbl_801B2A90: /* 801B2A90 001AF9F0 7F 20 07 75 */ extsb. r0, r25 diff --git a/asm/MetroidPrime/Enemies/CFlaahgraPlants.s b/asm/MetroidPrime/Enemies/CFlaahgraPlants.s index 0c6948e0..3dad1476 100644 --- a/asm/MetroidPrime/Enemies/CFlaahgraPlants.s +++ b/asm/MetroidPrime/Enemies/CFlaahgraPlants.s @@ -152,7 +152,7 @@ lbl_80208454: /* 80208528 00205488 A0 1D 01 6C */ lhz r0, 0x16c(r29) /* 8020852C 0020548C 91 41 00 28 */ stw r10, 0x28(r1) /* 80208530 00205490 B0 01 00 0C */ sth r0, 0xc(r1) -/* 80208534 00205494 4B FA 18 75 */ bl __ct__15CCollisionActorF9TUniqueIdCRi9TUniqueIdRC9CVector3fRC9CVector3fbf +/* 80208534 00205494 4B FA 18 75 */ bl __ct__15CCollisionActorF9TUniqueId7TAreaId9TUniqueIdRC9CVector3fRC9CVector3fbf /* 80208538 00205498 7C 7F 1B 78 */ mr r31, r3 lbl_8020853C: /* 8020853C 0020549C 28 1F 00 00 */ cmplwi r31, 0 @@ -543,8 +543,8 @@ lbl_80208AB8: /* 80208ACC 00205A2C 38 21 00 10 */ addi r1, r1, 0x10 /* 80208AD0 00205A30 4E 80 00 20 */ blr -.global "__ct__15CFlaahgraPlantsF25TToken<15CGenDescription>9TUniqueId9TUniqueIdRC12CTransform4fRC11CDamageInfoRC9CVector3f" -"__ct__15CFlaahgraPlantsF25TToken<15CGenDescription>9TUniqueId9TUniqueIdRC12CTransform4fRC11CDamageInfoRC9CVector3f": +.global "__ct__15CFlaahgraPlantsFRC25TToken<15CGenDescription>RC16CActorParameters9TUniqueId7TAreaId9TUniqueIdRC12CTransform4fRC11CDamageInfoRC9CVector3f" +"__ct__15CFlaahgraPlantsFRC25TToken<15CGenDescription>RC16CActorParameters9TUniqueId7TAreaId9TUniqueIdRC12CTransform4fRC11CDamageInfoRC9CVector3f": /* 80208AD4 00205A34 94 21 FE C0 */ stwu r1, -0x140(r1) /* 80208AD8 00205A38 7C 08 02 A6 */ mflr r0 /* 80208ADC 00205A3C 3D 60 80 3D */ lis r11, lbl_803D2738@ha @@ -740,7 +740,6 @@ lbl_80208C98: /* 80208DC0 00205D20 D0 03 00 14 */ stfs f0, 0x14(r3) lbl_80208DC4: /* 80208DC4 00205D24 38 00 00 01 */ li r0, 1 -.global lbl_80208DC8 lbl_80208DC8: /* 80208DC8 00205D28 98 18 01 28 */ stb r0, 0x128(r24) /* 80208DCC 00205D2C 48 00 00 34 */ b lbl_80208E00 diff --git a/configure.py b/configure.py index a0b50307..e1379151 100755 --- a/configure.py +++ b/configure.py @@ -310,7 +310,7 @@ LIBS = [ "MetroidPrime/Enemies/CThardusRockProjectile", "MetroidPrime/CInventoryScreen", ["MetroidPrime/CVisorFlare", False], - "MetroidPrime/Enemies/CFlaahgraPlants", + ["MetroidPrime/Enemies/CFlaahgraPlants", True], "MetroidPrime/CWorldTransManager", ["MetroidPrime/ScriptObjects/CScriptMidi", False], "MetroidPrime/ScriptObjects/CScriptStreamedAudio", diff --git a/include/Collision/COBBox.hpp b/include/Collision/COBBox.hpp index 868113dc..80ae3c5c 100644 --- a/include/Collision/COBBox.hpp +++ b/include/Collision/COBBox.hpp @@ -20,6 +20,9 @@ public: bool AABoxIntersectsBox(const CAABox& box) const; bool OBBIntersectsBox(const COBBox& box) const; + const CTransform4f& GetTransform() const { return mTransform; } + const CVector3f& GetSize() const { return mExtents; } + private: CTransform4f mTransform; CVector3f mExtents; diff --git a/include/Kyoto/Particles/CElementGen.hpp b/include/Kyoto/Particles/CElementGen.hpp index ee6d6333..1d61ad90 100644 --- a/include/Kyoto/Particles/CElementGen.hpp +++ b/include/Kyoto/Particles/CElementGen.hpp @@ -83,6 +83,8 @@ public: static void ShutDown(); void SetGlobalOrientAndTrans(const CTransform4f& xf); + void SetLeaveLightsEnabledForModelRender(bool b) { x26d_26_modelsUseLights = b; } + static void SetSubtractBlend(bool subtract) { sSubtractBlend = subtract; } public: diff --git a/include/MetroidPrime/CCollisionActor.hpp b/include/MetroidPrime/CCollisionActor.hpp index 9c3d3b04..c212c14f 100644 --- a/include/MetroidPrime/CCollisionActor.hpp +++ b/include/MetroidPrime/CCollisionActor.hpp @@ -3,14 +3,69 @@ #include "types.h" +#include "MetroidPrime/CDamageVulnerability.hpp" +#include "MetroidPrime/CHealthInfo.hpp" #include "MetroidPrime/CPhysicsActor.hpp" +#include "rstl/single_ptr.hpp" + +class CCollidableOBBTreeGroupContainer; +class CCollidableOBBTreeGroup; +class CCollidableAABox; +class CCollidableSphere; + class CCollisionActor : public CPhysicsActor { public: - // TODO + enum EPrimitiveType { + kPT_OBBTreeGroup, + kPT_AABox, + kPT_Sphere, + }; + + CCollisionActor(TUniqueId uid, TAreaId areaId, TUniqueId owner, const CVector3f& extent, + const CVector3f& center, bool active, float mass); + CCollisionActor(TUniqueId uid, TAreaId areaId, TUniqueId owner, const CVector3f& boxSize, + bool active, float mass); + CCollisionActor(TUniqueId uid, TAreaId areaId, TUniqueId owner, bool active, float radius, + float mass); + + // CEntity + ~CCollisionActor() override; + void Accept(IVisitor& visitor) override; + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; + + // CActor + CHealthInfo* HealthInfo(CStateManager&) override; + const CDamageVulnerability* GetDamageVulnerability() const override; + const CDamageVulnerability* GetDamageVulnerability(const CVector3f&, const CVector3f&, + const CDamageInfo&) const override; + rstl::optional_object< CAABox > GetTouchBounds() const override; + void Touch(CActor&, CStateManager&) override; + CVector3f GetOrbitPosition(const CStateManager&) const override; + CVector3f GetScanObjectIndicatorPosition(const CStateManager&) const override; + EWeaponCollisionResponseTypes GetCollisionResponseType(const CVector3f&, const CVector3f&, + const CWeaponMode&, + int /*EProjectileAttrib?*/) const override; + void OnScanStateChange(EScanState, CStateManager&) override; + + // CPhysicsActor + CTransform4f GetPrimitiveTransform() const override; private: - // TODO + EPrimitiveType x258_primitiveType; + TUniqueId x25c_owner; + CVector3f x260_boxSize; + CVector3f x26c_center; + rstl::single_ptr< CCollidableOBBTreeGroupContainer > x278_obbContainer; + rstl::single_ptr< CCollidableOBBTreeGroup > x27c_obbTreeGroupPrimitive; + rstl::single_ptr< CCollidableAABox > x280_aaboxPrimitive; + rstl::single_ptr< CCollidableSphere > x284_spherePrimitive; + float x288_sphereRadius; + CHealthInfo x28c_healthInfo; + CDamageVulnerability x294_damageVuln; + TUniqueId x2fc_lastTouched; + EWeaponCollisionResponseTypes x300_responseType; + CVector3f x304_extendedTouchBounds; }; #endif // _CCOLLISIONACTOR diff --git a/include/MetroidPrime/Enemies/CFlaahgraPlants.hpp b/include/MetroidPrime/Enemies/CFlaahgraPlants.hpp new file mode 100644 index 00000000..64b1091e --- /dev/null +++ b/include/MetroidPrime/Enemies/CFlaahgraPlants.hpp @@ -0,0 +1,39 @@ +#ifndef _CFLAAHGRAPLANTS +#define _CFLAAHGRAPLANTS +#include "types.h" + +#include "Collision/COBBox.hpp" +#include "Kyoto/Particles/CElementGen.hpp" +#include "MetroidPrime/CDamageInfo.hpp" +#include "MetroidPrime/Enemies/CPatterned.hpp" + +class CPatternedInfo; +class CGenDescription; + +class CFlaahgraPlants : public CActor { +public: + CFlaahgraPlants(const TToken< CGenDescription >&, const CActorParameters&, TUniqueId, TAreaId, + TUniqueId, const CTransform4f&, const CDamageInfo&, const CVector3f&); + + // CEntity + ~CFlaahgraPlants() override; + void Accept(IVisitor& visitor) override; + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) override; + void Think(float dt, CStateManager& mgr) override; + + // CActor + void AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const override; + rstl::optional_object< CAABox > GetTouchBounds() const override; + void Touch(CActor& actor, CStateManager& mgr) override; + +private: + rstl::auto_ptr< CElementGen > xe8_elementGen; + TUniqueId xf0_ownerId; + CDamageInfo xf4_damageInfo; + rstl::optional_object< CAABox > x110_aabox; + float x12c_lastDt; + COBBox x130_obbox; + TUniqueId x16c_colAct; +}; + +#endif // _CFLAAHGRAPLANTS diff --git a/include/MetroidPrime/TGameTypes.hpp b/include/MetroidPrime/TGameTypes.hpp index 08aead19..44b2e4e3 100644 --- a/include/MetroidPrime/TGameTypes.hpp +++ b/include/MetroidPrime/TGameTypes.hpp @@ -46,7 +46,6 @@ CHECK_SIZEOF(TEditorId, 0x4) struct TUniqueId { ushort value; - //TUniqueId(const TUniqueId& other) : value(other.value) {} TUniqueId(ushort version, ushort id) : value(((version & 0x3F) << 10) | (id & 0x3FF)) {} ushort Value() const { return value & 0x3FF; } diff --git a/src/MetroidPrime/Enemies/CFlaahgraPlants.cpp b/src/MetroidPrime/Enemies/CFlaahgraPlants.cpp new file mode 100644 index 00000000..af577fb6 --- /dev/null +++ b/src/MetroidPrime/Enemies/CFlaahgraPlants.cpp @@ -0,0 +1,106 @@ +#include "MetroidPrime/Enemies/CFlaahgraPlants.hpp" + +#include "MetroidPrime/BodyState/CBodyController.hpp" +#include "MetroidPrime/CCollisionActor.hpp" +#include "MetroidPrime/Player/CPlayer.hpp" + +#include "MetaRender/CCubeRenderer.hpp" + +CFlaahgraPlants::CFlaahgraPlants(const TToken< CGenDescription >& genDesc, + const CActorParameters& actParms, TUniqueId uid, TAreaId aId, + TUniqueId owner, const CTransform4f& xf, const CDamageInfo& dInfo, + const CVector3f& extents) +: CActor(uid, true, "Flaahgra Plants", CEntityInfo(aId, NullConnectionList), xf, + CModelData::CModelDataNull(), CMaterialList(kMT_Projectile), actParms, kInvalidUniqueId) +, xe8_elementGen(new CElementGen(genDesc)) +, xf0_ownerId(owner) +, xf4_damageInfo(dInfo) +, x12c_lastDt(0.f) +, x130_obbox(xf, extents) +, x16c_colAct(kInvalidUniqueId) { + xe8_elementGen->SetOrientation(xf.GetRotation()); + xe8_elementGen->SetTranslation(xf.GetTranslation()); + xe8_elementGen->SetLeaveLightsEnabledForModelRender(true); + x110_aabox = x130_obbox.CalculateAABox(CTransform4f::Identity()); +} + +CFlaahgraPlants::~CFlaahgraPlants() {} + +void CFlaahgraPlants::Touch(CActor& act, CStateManager& mgr) { + if (act.GetUniqueId() == mgr.GetPlayer()->GetUniqueId() && x110_aabox) { + COBBox plObb = COBBox::FromAABox(mgr.GetPlayer()->GetBoundingBox(), CTransform4f::Identity()); + + if (!x130_obbox.OBBIntersectsBox(plObb)) { + return; + } + + CDamageInfo dInfo(xf4_damageInfo.GetWeaponMode(), x12c_lastDt * xf4_damageInfo.GetDamage(), + xf4_damageInfo.GetRadius(), xf4_damageInfo.GetKnockBackPower(), true); + CMaterialFilter filter = + CMaterialFilter::MakeIncludeExclude(CMaterialList(kMT_Solid), CMaterialList()); + CVector3f diffVec = mgr.GetPlayer()->GetTranslation() - GetTranslation(); + CVector3f right = GetTransform().GetColumn(kDX); + CVector3f knockbackVec = CVector3f::Dot(diffVec, right) > 0.f ? right : -right; + mgr.ApplyDamage(GetUniqueId(), act.GetUniqueId(), GetUniqueId(), dInfo, filter, knockbackVec); + } +} + +rstl::optional_object< CAABox > CFlaahgraPlants::GetTouchBounds() const { + if (GetActive()) { + return x110_aabox; + } else { + return rstl::optional_object_null(); + } +} + +void CFlaahgraPlants::AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const { + gpRender->AddParticleGen(*xe8_elementGen); + CActor::AddToRenderer(frustum, mgr); +} + +void CFlaahgraPlants::Accept(IVisitor& visitor) { visitor.Visit(*this); } + +void CFlaahgraPlants::Think(float dt, CStateManager& mgr) { + if (GetActive()) { + xe8_elementGen->Update(dt); + x12c_lastDt = dt; + } + + if (xe8_elementGen->IsSystemDeletable()) { + mgr.FreeScriptObject(GetUniqueId()); + } +} + +void CFlaahgraPlants::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + + switch (msg) { + case kSM_Registered: { + xe8_elementGen->SetParticleEmission(true); + SetActive(true); + if (x16c_colAct == kInvalidUniqueId) { + x16c_colAct = mgr.AllocateUniqueId(); + CVector3f extent = x130_obbox.GetSize() + CVector3f(0.f, 5.f, 10.f); + CCollisionActor* colAct = new CCollisionActor(x16c_colAct, GetCurrentAreaId(), GetUniqueId(), + extent, CVector3f::Zero(), true, 0.001f); + if (colAct != nullptr) { + colAct->SetTransform(GetTransform()); + colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + CMaterialList(kMT_Player), + CMaterialList(kMT_Trigger, kMT_CollisionActor, kMT_NoStaticCollision, kMT_Character))); + colAct->MaterialList().Add(kMT_Immovable); + colAct->MaterialList().Add(kMT_ProjectilePassthrough); + mgr.AddObject(colAct); + mgr.SetActorAreaId(*colAct, GetCurrentAreaId()); + } + } + break; + } + case kSM_Deleted: { + if (x16c_colAct != kInvalidUniqueId) { + mgr.FreeScriptObject(x16c_colAct); + } + break; + } + } +}