From fee4898ed31d7bc3394acc732f94301c14457ed6 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 22 Sep 2026 10:36:32 -0600 Subject: [PATCH] Improve CRidley PAL matching --- config/GM8P01_00/splits.txt | 9 +- config/GM8P01_00/symbols.txt | 198 +++--- configure.py | 6 +- include/MetroidPrime/Enemies/CRidley.hpp | 45 +- include/MetroidPrime/Player/CPlayer.hpp | 7 +- .../MetroidPrime/Weapons/CGameProjectile.hpp | 6 +- src/MetroidPrime/Enemies/CRidley.cpp | 606 +++++++++++++++++- src/MetroidPrime/Player/CPlayer.cpp | 6 + 8 files changed, 750 insertions(+), 133 deletions(-) diff --git a/config/GM8P01_00/splits.txt b/config/GM8P01_00/splits.txt index 9eb175a11..6baa71277 100644 --- a/config/GM8P01_00/splits.txt +++ b/config/GM8P01_00/splits.txt @@ -1695,9 +1695,14 @@ MetroidPrime/Weapons/CElectricBeamProjectile.cpp: .sdata2 start:0x8046F808 end:0x8046F820 MetroidPrime/Enemies/CRidley.cpp: - .text start:0x80241770 end:0x802497D4 + .text start:0x80240E10 end:0x8024AF94 + .ctors start:0x803B5078 end:0x803B507C + .rodata start:0x803BF608 end:0x803BFA50 + .data start:0x803D16C8 end:0x803D1B90 + .bss start:0x803F5300 end:0x803F5D38 .bss start:0x804344A4 end:0x804346B4 align:4 common - .sdata2 start:0x8046F83C end:0x8046F840 + .sdata start:0x8046A3C8 end:0x8046A458 + .sdata2 start:0x8046F820 end:0x8046F910 MetroidPrime/Enemies/CPuffer.cpp: .text start:0x8024AF94 end:0x8024BB54 diff --git a/config/GM8P01_00/symbols.txt b/config/GM8P01_00/symbols.txt index c107d622b..f2954a67a 100644 --- a/config/GM8P01_00/symbols.txt +++ b/config/GM8P01_00/symbols.txt @@ -319,7 +319,7 @@ UpdateElevation__18CFirstPersonCameraFR13CStateManager = .text:0x8000FCE4; // ty ProcessInput__18CFirstPersonCameraFRC11CFinalInputR13CStateManager = .text:0x8000FF78; // type:function size:0x4 __dt__18CFirstPersonCameraFv = .text:0x8000FF7C; // type:function size:0x60 __ct__18CFirstPersonCameraFRC9TUniqueIdRC12CTransform4f9TUniqueIdfffff = .text:0x8000FFDC; // type:function size:0x1B4 -fn_80010190 = .text:0x80010190; // type:function size:0x58 +__dt__11CEntityInfoFv = .text:0x80010190; // type:function size:0x58 __dt__Q24rstl48vector<11SConnection,Q24rstl17rmemory_allocator>Fv = .text:0x800101E8; // type:function size:0x8C GetObjectByIndex__11CObjectListCFi = .text:0x80010274; // type:function size:0x10 __vc__11CObjectListCFi = .text:0x80010284; // type:function size:0x38 @@ -2092,8 +2092,8 @@ __dt__10CPatternedFv = .text:0x80078044; // type:function size:0x1AC __dt__Q24rstl63vectorFv = .text:0x800781F0; // type:function size:0x8C GetTouchBounds__10CPatternedCFv = .text:0x8007827C; // type:function size:0x70 TakeDamage__10CPatternedFRC9CVector3ff = .text:0x800782EC; // type:function size:0xC -fn_800782F8 = .text:0x800782F8; // type:function size:0x8 -fn_80078300 = .text:0x80078300; // type:function size:0x8 +KnockbackWhenFrozen__10CPatternedCFv = .text:0x800782F8; // type:function size:0x8 scope:global +Default__10CPatternedFR13CStateManagerf = .text:0x80078300; // type:function size:0x8 scope:global GetSearchPath__10CPatternedFv = .text:0x80078308; // type:function size:0x8 GetModelAlphau8__10CPatternedCFRC13CStateManager = .text:0x80078310; // type:function size:0x8 IsOnGround__10CPatternedCFv = .text:0x80078318; // type:function size:0xC @@ -2576,46 +2576,46 @@ reserve__Q24rstl45vector<9CVector2f,Q24rstl17rmemory_allocator>Fi = .text:0x800A __sort3__4rstlFRQ29CMapWorld18CMapObjectSortInfoRQ29CMapWorld18CMapObjectSortInfoRQ29CMapWorld18CMapObjectSortInfo29CMapObjectSortInfoGreaterThan = .text:0x800A185C; // type:function size:0x1B4 swap__4rstlFRQ29CMapWorld18CMapObjectSortInfoRQ29CMapWorld18CMapObjectSortInfo = .text:0x800A1A10; // type:function size:0x54 __insertion_sort,Q24rstl17rmemory_allocator>,29CMapObjectSortInfoGreaterThan>__4rstlFQ24rstl154pointer_iterator,Q24rstl17rmemory_allocator>Q24rstl154pointer_iterator,Q24rstl17rmemory_allocator>f = .text:0x8019CA18; // type:function size:0x5C fn_8019CA74 = .text:0x8019CA74; // type:function size:0x60 fn_8019CAD4 = .text:0x8019CAD4; // type:function size:0x50 -fn_8019CB24 = .text:0x8019CB24; // type:function size:0x5C +SphereCollision__26CJointCollisionDescriptionF6CSegIdfRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>f = .text:0x8019CB24; // type:function size:0x5C SetSphereRadius__15CCollisionActorFf = .text:0x8019CB80; // type:function size:0x5C GetSphereRadius__15CCollisionActorCFv = .text:0x8019CBDC; // type:function size:0x8 GetBoxSize__15CCollisionActorCFv = .text:0x8019CBE4; // type:function size:0x8 @@ -6869,8 +6869,8 @@ __dt__Q24rstl69reserved_vector,Ui __ct__Q24rstl69reserved_vector,Ui>,8>FRCQ24rstl69reserved_vector,Ui>,8> = .text:0x801D6590; // type:function size:0x58 SetupHook__20CActorModelParticlesCF9TUniqueId = .text:0x801D65E8; // type:function size:0x60 GeneratePoints__Q220CActorModelParticles5CItemFPC9CVector3fPC9CVector3fi = .text:0x801D6648; // type:function size:0x4FC -fn_801D6B44 = .text:0x801D6B44; // type:function size:0x54 -fn_801D6B98 = .text:0x801D6B98; // type:function size:0x54 +SetOverrideFPos__17CParticleElectricFRC9CVector3f = .text:0x801D6B44; // type:function size:0x54 +SetOverrideIPos__17CParticleElectricFRC9CVector3f = .text:0x801D6B98; // type:function size:0x54 GetParticleEmission__17CParticleElectricCFv = .text:0x801D6BEC; // type:function size:0xC GetNextBestPt__FiPC9CVector3fiR9CRandom16 = .text:0x801D6BF8; // type:function size:0xD0 PointGenerator__20CActorModelParticlesFPvPC9CVector3fPC9CVector3fi = .text:0x801D6CC8; // type:function size:0x20 @@ -7051,7 +7051,7 @@ __ct__20CIceAttackProjectileF25TToken<15CGenDescription>25TToken<15CGenDescripti reserve__Q24rstl73vectorFi = .text:0x801E57AC; // type:function size:0xB4 destroy__4rstlFPQ220CIceAttackProjectile12CTrailObjectPQ220CIceAttackProjectile12CTrailObject = .text:0x801E5860; // type:function size:0xC0 uninitialized_copy,Q24rstl17rmemory_allocator>,PQ220CIceAttackProjectile12CTrailObject>__4rstlFQ24rstl166pointer_iterator,Q24rstl17rmemory_allocator>Q24rstl166pointer_iterator,Q24rstl17rmemory_allocator>PQ220CIceAttackProjectile12CTrailObject = .text:0x801E5920; // type:function size:0x68 scope:local -fn_801E5988 = .text:0x801E5988; // type:function size:0x18 +FixedRandom__10CPatternedFR13CStateManagerf = .text:0x801E5988; // type:function size:0x18 scope:global Random__10CPatternedFR13CStateManagerf = .text:0x801E59A0; // type:function size:0x14 UpdatePatternDestPos__10CPatternedFR13CStateManager = .text:0x801E59B4; // type:function size:0x2AC SetupPattern__10CPatternedFR13CStateManager = .text:0x801E5C60; // type:function size:0x424 @@ -7100,10 +7100,10 @@ OffLine__10CPatternedFR13CStateManagerf = .text:0x801E7DB0; // type:function siz PathFind__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E7F2C; // type:function size:0x2F8 Dead__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E8224; // type:function size:0x118 TargetPlayer__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E833C; // type:function size:0x8C -fn_801E83C8 = .text:0x801E83C8; // type:function size:0xCC -fn_801E8494 = .text:0x801E8494; // type:function size:0x208 +TargetPatrol__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E83C8; // type:function size:0xCC scope:global +FollowPattern__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E8494; // type:function size:0x208 scope:global Patrol__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E869C; // type:function size:0x218 -fn_801E88B4 = .text:0x801E88B4; // type:function size:0x4 +Start__10CPatternedFR13CStateManager9EStateMsgf = .text:0x801E88B4; // type:function size:0x4 scope:global fn_801E88B8 = .text:0x801E88B8; // type:function size:0xC0 fn_801E8978 = .text:0x801E8978; // type:function size:0x68 fn_801E89E0 = .text:0x801E89E0; // type:function size:0x228 @@ -7458,7 +7458,7 @@ __ct__Q24rstl52vector<15CVectorFixed8_8,Q24rstl17rmemory_allocator>FRCQ24rstl52v __ct__17CEnvFxManagerGridFRC9CVector2iRC9CVector2iRCQ24rstl52vector<15CVectorFixed8_8,Q24rstl17rmemory_allocator>i = .text:0x80204F04; // type:function size:0x90 reserve__Q24rstl52vector<15CVectorFixed8_8,Q24rstl17rmemory_allocator>Fi = .text:0x80204F94; // type:function size:0xC0 fn_80205054 = .text:0x80205054; // type:function size:0x44 -fn_80205098 = .text:0x80205098; // type:function size:0x40 +SetCameraShake__17CEnergyProjectileFRC16CCameraShakeData = .text:0x80205098; // type:function size:0x40 fn_802050D8 = .text:0x802050D8; // type:function size:0x194 PlayImpactSound__17CEnergyProjectileFRC9CVector3f29EWeaponCollisionResponseTypes = .text:0x8020526C; // type:function size:0x104 ChangeProjectileOwner__17CEnergyProjectileF9TUniqueIdR13CStateManager = .text:0x80205370; // type:function size:0x144 @@ -8304,45 +8304,45 @@ fn_80240B08 = .text:0x80240B08; // type:function size:0x54 fn_80240B5C = .text:0x80240B5C; // type:function size:0x54 Touch__23CElectricBeamProjectileFR6CActorR13CStateManager = .text:0x80240BB0; // type:function size:0x4 __ct__23CElectricBeamProjectileFRC28TToken<18CWeaponDescription>11EWeaponTypeRC17SElectricBeamInfoRC12CTransform4f14EMaterialTypesRC11CDamageInfo9TUniqueId7TAreaId9TUniqueIdQ27CWeapon17EProjectileAttrib = .text:0x80240BB4; // type:function size:0x25C -fn_80240E10 = .text:0x80240E10; // type:function size:0x21C -fn_8024102C = .text:0x8024102C; // type:function size:0x10C -fn_80241138 = .text:0x80241138; // type:function size:0x8 -fn_80241140 = .text:0x80241140; // type:function size:0x8 -fn_80241148 = .text:0x80241148; // type:function size:0x20 -fn_80241168 = .text:0x80241168; // type:function size:0x14 -fn_8024117C = .text:0x8024117C; // type:function size:0xEC -fn_80241268 = .text:0x80241268; // type:function size:0x1D0 -fn_80241438 = .text:0x80241438; // type:function size:0x14 -fn_8024144C = .text:0x8024144C; // type:function size:0x28 -fn_80241474 = .text:0x80241474; // type:function size:0x20 -fn_80241494 = .text:0x80241494; // type:function size:0xC -fn_802414A0 = .text:0x802414A0; // type:function size:0x14 -fn_802414B4 = .text:0x802414B4; // type:function size:0x14 -fn_802414C8 = .text:0x802414C8; // type:function size:0xE4 -fn_802415AC = .text:0x802415AC; // type:function size:0x10 -fn_802415BC = .text:0x802415BC; // type:function size:0x14 -fn_802415D0 = .text:0x802415D0; // type:function size:0x14 -fn_802415E4 = .text:0x802415E4; // type:function size:0xC -fn_802415F0 = .text:0x802415F0; // type:function size:0x14 -fn_80241604 = .text:0x80241604; // type:function size:0x70 -fn_80241674 = .text:0x80241674; // type:function size:0x2C -fn_802416A0 = .text:0x802416A0; // type:function size:0x58 -fn_802416F8 = .text:0x802416F8; // type:function size:0x2C -fn_80241724 = .text:0x80241724; // type:function size:0x4C +__dt__7CRidleyFv = .text:0x80240E10; // type:function size:0x21C +__dt__11CRidleyDataFv = .text:0x8024102C; // type:function size:0x10C +GetGravityConstant__7CRidleyCFv = .text:0x80241138; // type:function size:0x8 +GetCollisionResponseType__7CRidleyCFRC9CVector3fRC9CVector3fRC11CWeaponModei = .text:0x80241140; // type:function size:0x8 +SetAIStage__7CRidleyFR13CStateManagerf = .text:0x80241148; // type:function size:0x20 +AggressionCheck__7CRidleyFR13CStateManagerf = .text:0x80241168; // type:function size:0x14 +SpotPlayer__7CRidleyFR13CStateManagerf = .text:0x8024117C; // type:function size:0xEC +Bounce__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241268; // type:function size:0x1D0 +BounceFind__7CRidleyFR13CStateManagerf = .text:0x80241438; // type:function size:0x14 +HitSomething__7CRidleyFR13CStateManagerf = .text:0x8024144C; // type:function size:0x28 +Attacked__7CRidleyFR13CStateManagerf = .text:0x80241474; // type:function size:0x20 +ShotAt__7CRidleyFR13CStateManagerf = .text:0x80241494; // type:function size:0xC +IsDizzy__7CRidleyFR13CStateManagerf = .text:0x802414A0; // type:function size:0x14 +ShouldMove__7CRidleyFR13CStateManagerf = .text:0x802414B4; // type:function size:0x14 +TooClose__7CRidleyFR13CStateManagerf = .text:0x802414C8; // type:function size:0xE4 +AttackOver__7CRidleyFR13CStateManagerf = .text:0x802415AC; // type:function size:0x10 +ShouldTurn__7CRidleyFR13CStateManagerf = .text:0x802415BC; // type:function size:0x14 +ShouldDodge__7CRidleyFR13CStateManagerf = .text:0x802415D0; // type:function size:0x14 +ShouldRetreat__7CRidleyFR13CStateManagerf = .text:0x802415E4; // type:function size:0xC +ShouldCrouch__7CRidleyFR13CStateManagerf = .text:0x802415F0; // type:function size:0x14 +InRange__7CRidleyFR13CStateManagerf = .text:0x80241604; // type:function size:0x70 +AIStage__7CRidleyFR13CStateManagerf = .text:0x80241674; // type:function size:0x2C +ShouldAttack__7CRidleyFR13CStateManagerf = .text:0x802416A0; // type:function size:0x58 +ShouldFire__7CRidleyFR13CStateManagerf = .text:0x802416F8; // type:function size:0x2C +ShouldTaunt__7CRidleyFR13CStateManagerf = .text:0x80241724; // type:function size:0x4C Dead__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241770; // type:function size:0x48 CoverAttack__7CRidleyFR13CStateManager9EStateMsgf = .text:0x802417B8; // type:function size:0x15C Dodge__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241914; // type:function size:0x298 Hurled__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241BAC; // type:function size:0xCC Flinch__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241C78; // type:function size:0xF0 Jump__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241D68; // type:function size:0x250 -fn_80241FB8 = .text:0x80241FB8; // type:function size:0x1E0 +DoubleSnap__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80241FB8; // type:function size:0x1E0 ShouldDoubleSnap__7CRidleyFR13CStateManagerf = .text:0x80242198; // type:function size:0xC ShouldStrafe__7CRidleyFR13CStateManagerf = .text:0x802421A4; // type:function size:0xC ChooseStage3Attack__7CRidleyFR13CStateManager = .text:0x802421B0; // type:function size:0x2A8 CanJumpAttack__7CRidleyCFv = .text:0x80242458; // type:function size:0xB0 FadeOut__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80242508; // type:function size:0x14C ProjectileAttack__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80242654; // type:function size:0xF8 -fn_8024274C = .text:0x8024274C; // type:function size:0x114 +TurnAround__7CRidleyFR13CStateManager9EStateMsgf = .text:0x8024274C; // type:function size:0x114 Crouch__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80242860; // type:function size:0x198 JumpBack__7CRidleyFR13CStateManager9EStateMsgf = .text:0x802429F8; // type:function size:0x408 Land__7CRidleyFR13CStateManager9EStateMsgf = .text:0x80242E00; // type:function size:0x33C @@ -8390,7 +8390,7 @@ AcceptScriptMsg__7CRidleyF20EScriptObjectMessage9TUniqueIdR13CStateManager = .te Touch__7CRidleyFR6CActorR13CStateManager = .text:0x80248AB0; // type:function size:0x20 __ct__7CRidleyF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fRC10CModelDataRC14CPatternedInfoRC16CActorParametersR12CInputStreamUi = .text:0x80248AD0; // type:function size:0x9EC __ct__11CRidleyDataFR12CInputStreami = .text:0x802494BC; // type:function size:0x318 -fn_802497D4 = .text:0x802497D4; // type:function size:0x17C0 +__sinit_CRidley_cpp = .text:0x802497D4; // type:function size:0x17C0 scope:local UpdateJets__7CPufferFR13CStateManager = .text:0x8024AF94; // type:function size:0x298 Think__7CPufferFfR13CStateManager = .text:0x8024B22C; // type:function size:0x19C Death__7CPufferFR13CStateManagerRC9CVector3f18EScriptObjectState = .text:0x8024B3C8; // type:function size:0x208 @@ -15635,21 +15635,7 @@ lbl_803BF5D6 = .rodata:0x803BF5D6; // type:object size:0x12 skTailJoints = .rodata:0x803BF608; // type:object size:0x30 data:4byte skBodyJoints = .rodata:0x803BF638; // type:object size:0x50 data:4byte skStage2Settings = .rodata:0x803BF688; // type:object size:0x28 -@stringBase0 = .rodata:0x803BF6B0; // type:object size:0x7 scope:local data:string -lbl_803BF6B7 = .rodata:0x803BF6B7; // type:object size:0x7 data:string -lbl_803BF6BE = .rodata:0x803BF6BE; // type:object size:0x7 data:string -lbl_803BF6C5 = .rodata:0x803BF6C5; // type:object size:0x7 data:string -lbl_803BF6CC = .rodata:0x803BF6CC; // type:object size:0x7 data:string -lbl_803BF6D3 = .rodata:0x803BF6D3; // type:object size:0xE data:string -lbl_803BF6E1 = .rodata:0x803BF6E1; // type:object size:0x8 data:string -lbl_803BF6E9 = .rodata:0x803BF6E9; // type:object size:0x11 data:string -lbl_803BF6FA = .rodata:0x803BF6FA; // type:object size:0x7 data:string -lbl_803BF701 = .rodata:0x803BF701; // type:object size:0x8 data:string -lbl_803BF709 = .rodata:0x803BF709; // type:object size:0x8 data:string -lbl_803BF711 = .rodata:0x803BF711; // type:object size:0x8 data:string -lbl_803BF719 = .rodata:0x803BF719; // type:object size:0x8 data:string -lbl_803BF721 = .rodata:0x803BF721; // type:object size:0xA data:string -lbl_803BF72B = .rodata:0x803BF72B; // type:object size:0x325 +@stringBase0 = .rodata:0x803BF6B0; // type:object size:0x39E scope:local data:string_table lbl_803BFA50 = .rodata:0x803BFA50; // type:object size:0x9 data:string lbl_803BFA59 = .rodata:0x803BFA59; // type:object size:0x9 data:string lbl_803BFA62 = .rodata:0x803BFA62; // type:object size:0x9 data:string @@ -17235,10 +17221,10 @@ filter$1324 = .bss:0x803F52B8; // type:object size:0x18 data:4byte filter$1427 = .bss:0x803F52D0; // type:object size:0x18 data:4byte lbl_803F52E8 = .bss:0x803F52E8; // type:object size:0x18 data:4byte lbl_803F5300 = .bss:0x803F5300; // type:object size:0x150 -skWingEffects = .bss:0x803F5450; // type:object size:0x2E8 -lbl_803F5738 = .bss:0x803F5738; // type:object size:0x1E0 +skWingEffects = .bss:0x803F5450; // type:object size:0x180 scope:local +skWingBones = .bss:0x803F5738; // type:object size:0x1E0 scope:local skStage2Attacks = .bss:0x803F5918; // type:object size:0x2D0 data:4byte -lbl_803F5BE8 = .bss:0x803F5BE8; // type:object size:0x150 data:4byte +skStage3Attacks = .bss:0x803F5BE8; // type:object size:0x150 scope:local data:4byte kSolidFilter$934 = .bss:0x803F5D38; // type:object size:0x18 data:4byte skExcludeProjectilePassthrough = .bss:0x803F5D50; // type:object size:0x30 scope:local data:4byte sGlobalSineWave = .bss:0x803F5D80; // type:object size:0x400 scope:local align:4 data:float @@ -19035,11 +19021,11 @@ lbl_8046A420 = .sdata:0x8046A420; // type:object size:0x4 lbl_8046A424 = .sdata:0x8046A424; // type:object size:0x4 lbl_8046A428 = .sdata:0x8046A428; // type:object size:0x4 lbl_8046A42C = .sdata:0x8046A42C; // type:object size:0x4 -lbl_8046A430 = .sdata:0x8046A430; // type:object size:0x2 data:string +lbl_8046A430 = .sdata:0x8046A430; // type:object size:0x4 data:float lbl_8046A434 = .sdata:0x8046A434; // type:object size:0x4 lbl_8046A438 = .sdata:0x8046A438; // type:object size:0x4 lbl_8046A43C = .sdata:0x8046A43C; // type:object size:0x4 -lbl_8046A440 = .sdata:0x8046A440; // type:object size:0x3 data:string +lbl_8046A440 = .sdata:0x8046A440; // type:object size:0x4 data:float lbl_8046A444 = .sdata:0x8046A444; // type:object size:0x4 data:4byte lbl_8046A448 = .sdata:0x8046A448; // type:object size:0x4 data:4byte lbl_8046A44C = .sdata:0x8046A44C; // type:object size:0x4 @@ -23780,7 +23766,7 @@ skGenericMenu = .sdata2:0x8046F7E0; // type:object size:0x8 data:4byte skNumProperties__7CRidley = .sdata2:0x8046F820; // type:object size:0x4 data:4byte lbl_8046F824 = .sdata2:0x8046F824; // type:object size:0x4 align:4 data:float skMinFlightScale = .sdata2:0x8046F828; // type:object size:0x4 -maxSpeed$1963 = .sdata2:0x8046F82C; // type:object size:0x2 data:string +maxSpeed$1963 = .sdata2:0x8046F82C; // type:object size:0x4 scope:local data:float lbl_8046F830 = .sdata2:0x8046F830; // type:object size:0x4 align:4 data:float lbl_8046F834 = .sdata2:0x8046F834; // type:object size:0x4 align:4 data:float lbl_8046F838 = .sdata2:0x8046F838; // type:object size:0x4 align:4 data:float @@ -23797,7 +23783,7 @@ lbl_8046F860 = .sdata2:0x8046F860; // type:object size:0x4 align:4 data:float lbl_8046F864 = .sdata2:0x8046F864; // type:object size:0x4 align:4 data:float lbl_8046F868 = .sdata2:0x8046F868; // type:object size:0x4 align:4 data:float lbl_8046F86C = .sdata2:0x8046F86C; // type:object size:0x4 align:4 data:float -skFlightScaleDistance = .sdata2:0x8046F870; // type:object size:0x3 data:string +skFlightScaleDistance = .sdata2:0x8046F870; // type:object size:0x4 scope:local data:float lbl_8046F874 = .sdata2:0x8046F874; // type:object size:0x4 align:4 data:float lbl_8046F878 = .sdata2:0x8046F878; // type:object size:0x4 align:4 data:float lbl_8046F87C = .sdata2:0x8046F87C; // type:object size:0x4 align:4 data:float diff --git a/configure.py b/configure.py index 9795ceba2..de20cd871 100755 --- a/configure.py +++ b/configure.py @@ -1392,7 +1392,11 @@ def EquivalentFor(*versions): Object(EquivalentFor("GM8E01_00"), "MetroidPrime/CSaveGameScreen.cpp"), Object(MatchingFor("GM8E01_00", "GM8E01_01"), "MetroidPrime/Enemies/CAtomicBeta.cpp"), Object(MatchingFor("GM8E01_00", "GM8E01_01"), "MetroidPrime/Weapons/CElectricBeamProjectile.cpp"), - Object(NonMatching, "MetroidPrime/Enemies/CRidley.cpp"), + Object( + NonMatching, + "MetroidPrime/Enemies/CRidley.cpp", + extra_cflags=['-pragma "inline_max_total_size(10000)"'], + ), Object(NonMatching, "MetroidPrime/Enemies/CPuffer.cpp"), Object( MatchingFor("GM8E01_00", "GM8E01_01"), diff --git a/include/MetroidPrime/Enemies/CRidley.hpp b/include/MetroidPrime/Enemies/CRidley.hpp index 3542ea818..4195c204d 100644 --- a/include/MetroidPrime/Enemies/CRidley.hpp +++ b/include/MetroidPrime/Enemies/CRidley.hpp @@ -19,6 +19,7 @@ class CProjectedShadow; class CRidleyData { friend class CRidley; +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 CAssetId x0_; CAssetId x4_; CAssetId x8_; @@ -29,6 +30,7 @@ class CRidleyData { CAssetId x1c_; CAssetId x20_; CAssetId x24_; +#endif CAssetId x28_; CAssetId x2c_; CAssetId x30_; @@ -41,6 +43,9 @@ class CRidleyData { CBeamInfo x64_; ushort xa8_; CAssetId xac_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + CAssetId x88_; +#endif CDamageInfo xb0_; CCameraShakeData xcc_; CAssetId x1a0_; @@ -61,12 +66,16 @@ class CRidleyData { float x3f4_; ushort x3f8_; CDamageInfo x3fc_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + CDamageInfo x3f4_bounceDamage; +#endif public: CRidleyData(CInputStream& in, int propCount); }; -CHECK_SIZEOF(CRidleyData, 0x418) +CHECK_SIZEOF(CRidleyData, + (VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 ? 0x410 : 0x418)) class CRidley : public CPatterned { public: @@ -130,6 +139,13 @@ class CRidley : public CPatterned { bool AIStage(CStateManager& mgr, float arg) override; bool ShouldStrafe(CStateManager& mgr, float arg) override; bool IsDizzy(CStateManager& mgr, float arg) override; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + void TurnAround(CStateManager& mgr, EStateMsg msg, float arg) override; + void Bounce(CStateManager& mgr, EStateMsg msg, float arg) override; + bool BounceFind(CStateManager& mgr, float arg) override; + bool SpotPlayer(CStateManager& mgr, float arg) override; + bool AggressionCheck(CStateManager& mgr, float arg) override; +#endif CRidley(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, const CTransform4f& xf, const CModelData& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, @@ -195,7 +211,17 @@ class CRidley : public CPatterned { bool xa34_24_ : 1; bool xa34_25_ : 1; bool xa34_26_ : 1; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + bool xa34_27_ : 1; + bool xa34_28_ : 1; + bool xa34_29_ : 1; + bool xa34_30_jumpCanBeInterrupted : 1; + bool xa34_31_canBreakLockOn : 1; + bool xa35_24_hasPreviousBeamPos : 1; + bool xa35_25_inFlinch : 1; +#else CModelData xa38_; +#endif CTransform4f xa84_; float xab4_; float xab8_; @@ -236,6 +262,9 @@ class CRidley : public CPatterned { float xc08_; float xc0c_; float xc10_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + CProjectileInfo xbd0_projectileInfo; +#endif CProjectileInfo xc14_; CProjectileInfo xc3c_; int xc64_aiStage; @@ -246,10 +275,17 @@ class CRidley : public CPatterned { float xc80_; uint xc84_; uint xc88_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + int xc70_meleeAttack; +#endif CDamageInfo xc8c_; CSfxHandle xca8_; CSfxHandle xcac_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + int xcb0_; +#else uint xcb0_; +#endif uint xcb4_; float xcb8_; float xcbc_; @@ -263,7 +299,11 @@ class CRidley : public CPatterned { float xd08_; CSfxHandle xd0c_; rstl::single_ptr< CProjectedShadow > xd10_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + CVector3f xcfc_previousBeamPos; +#else uint xd14_; +#endif static const CDamageVulnerability skDirectNormal; static const CDamageVulnerability skIceWeakness; @@ -273,6 +313,7 @@ class CRidley : public CPatterned { static const rstl::string skHead; static const rstl::string skRoot; }; -CHECK_SIZEOF(CRidley, (VERSION >= VERSION_GM8P_00 ? 0xd28 : 0xD18)) +CHECK_SIZEOF(CRidley, + (VERSION < VERSION_GM8P_00 ? 0xd18 : (VERSION == VERSION_GM8E_02 ? 0xd28 : 0xd08))) #endif // _CRIDLEY diff --git a/include/MetroidPrime/Player/CPlayer.hpp b/include/MetroidPrime/Player/CPlayer.hpp index 3ee35bf28..4d5e73064 100644 --- a/include/MetroidPrime/Player/CPlayer.hpp +++ b/include/MetroidPrime/Player/CPlayer.hpp @@ -714,6 +714,10 @@ class CPlayer : public CPhysicsActor, public TOneStatic< CPlayer > { float xa14_envDmgCameraShakeTimer; float xa18_phazonDamageLag; float xa1c_threatOverride; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + int xa30_phazonCollisionDelay[7]; + int xa4c_phazonCollisionIndex; +#endif float xa20_radarXYRadiusOverride; float xa24_radarZRadiusOverride; float xa28_attachedActorStruggle; @@ -721,7 +725,8 @@ class CPlayer : public CPhysicsActor, public TOneStatic< CPlayer > { float xa30_samusExhaustedVoiceTimer; }; NESTED_CHECK_SIZEOF(CPlayer, CPlayerStuckTracker, 0x2e0); -CHECK_SIZEOF(CPlayer, (VERSION >= VERSION_GM8P_00 ? 0xa48 : 0xa38)) +CHECK_SIZEOF(CPlayer, + (VERSION < VERSION_GM8P_00 ? 0xa38 : (VERSION == VERSION_GM8E_02 ? 0xa48 : 0xa68))) extern const bool gkAutoAim; extern const bool gkAutoAimAtOrbitedObject; diff --git a/include/MetroidPrime/Weapons/CGameProjectile.hpp b/include/MetroidPrime/Weapons/CGameProjectile.hpp index 8c8eb82a9..ed3f24cc8 100644 --- a/include/MetroidPrime/Weapons/CGameProjectile.hpp +++ b/include/MetroidPrime/Weapons/CGameProjectile.hpp @@ -71,7 +71,11 @@ class CGameProjectile : public CWeapon { bool GetWeaponActive() const { return x2e4_24_active; } void DeleteProjectileLight(CStateManager&); - + +#if VERSION >= VERSION_GM8P_00 + bool GetUnkPalFlag() const { return x2e4_29_unkPalFlag; } +#endif + void SetUnkPalFlag(bool active) { #if VERSION >= VERSION_GM8P_00 x2e4_29_unkPalFlag = active; diff --git a/src/MetroidPrime/Enemies/CRidley.cpp b/src/MetroidPrime/Enemies/CRidley.cpp index b0bb6227e..c7b661d19 100644 --- a/src/MetroidPrime/Enemies/CRidley.cpp +++ b/src/MetroidPrime/Enemies/CRidley.cpp @@ -1,4 +1,5 @@ #include "MetroidPrime/Enemies/CRidley.hpp" +#include "Collision/CollisionUtil.hpp" #include "Kyoto/Animation/CPASAnimParmData.hpp" #include "Kyoto/Audio/CSfxManager.hpp" #include "Kyoto/CSimplePool.hpp" @@ -24,7 +25,11 @@ #include "rstl/math.hpp" #include +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +const int CRidley::skNumProperties = 39; +#else const int CRidley::skNumProperties = 47; +#endif static const float skMinFlightScale = 0.3f; static const float skFlightScaleDistance = 250.f; @@ -127,6 +132,44 @@ static const SStage2Attack skStage2Attacks[5][12] = { }, }; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +static const SStage2Attack skStage3Attacks[4][7] = { + { + SStage2Attack(2, 100.f, -1), + SStage2Attack(1, 100.f, -1), + SStage2Attack(2, 100.f, -1), + SStage2Attack(5, 100.f, 7), + SStage2Attack(1, 100.f, -1), + SStage2Attack(-1, 100.f, -1), + }, + { + SStage2Attack(5, 100.f, 2), + SStage2Attack(6, 100.f, -1), + SStage2Attack(5, 100.f, 2), + SStage2Attack(2, 100.f, -1), + SStage2Attack(1, 100.f, -1), + SStage2Attack(-1, 100.f, -1), + }, + { + SStage2Attack(5, 100.f, -1), + SStage2Attack(2, 50.f, 7), + SStage2Attack(6, 100.f, -1), + SStage2Attack(5, 100.f, 6), + SStage2Attack(1, 100.f, -1), + SStage2Attack(-1, 100.f, -1), + }, + { + SStage2Attack(2, 30.f, 7), + SStage2Attack(5, 100.f, 5), + SStage2Attack(5, 100.f, 5), + SStage2Attack(5, 100.f, 5), + SStage2Attack(1, 100.f, -1), + SStage2Attack(6, 50.f, 7), + SStage2Attack(-1, 100.f, -1), + }, +}; +#endif + const CDamageVulnerability CRidley::skDirectNormal = CDamageVulnerability(kVN_DirectNormal, kVN_DirectNormal, kVN_DirectNormal, kVN_DirectNormal, kVN_DirectNormal, kVN_DirectNormal, kVN_DirectNormal, kVN_DirectNormal, @@ -143,22 +186,40 @@ struct STailJoint { const char* x4_to; float x8_radius; }; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +static const STailJoint skTailJoints[4] = { + {"Tail_1", "Tail_3", 1.48f}, + {"Tail_3", "Tail_5", 1.48f}, + {"Tail_5", "Tail_7", 1.48f}, + {"Tail_7", "Tail_9", 1.48f}, +}; +#else static const STailJoint skTailJoints[4] = { {"Tail_1", "Tail_3", 0.66f}, {"Tail_3", "Tail_5", 0.66f}, {"Tail_5", "Tail_7", 0.66f}, {"Tail_7", "Tail_9", 0.66f}, }; +#endif struct SBodyJoint { const char* x0_name; float x4_radius; }; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +static const SBodyJoint skBodyJoints[10] = { + {"Skeleton_Root", 1.35f}, {"Spine_2", 1.35f}, {"breastPlate_LCTR", 1.f}, {"Head_1", 1.35f}, + {"L_wrist", 1.1f}, {"R_wrist", 1.1f}, {"L_ankle", 1.35f}, {"R_ankle", 1.35f}, + {"L_pinky_1", 0.9f}, {"R_pinky_1", 0.9f}, +}; +#else static const SBodyJoint skBodyJoints[10] = { {"Skeleton_Root", 0.6f}, {"Spine_2", 0.6f}, {"breastPlate_LCTR", 0.3f}, {"Head_1", 0.6f}, {"L_wrist", 0.5f}, {"R_wrist", 0.5f}, {"L_ankle", 0.6f}, {"R_ankle", 0.6f}, {"L_pinky_1", 0.4f}, {"R_pinky_1", 0.4f}, }; +#endif struct SStage2Settings { +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 uint x0_; uint x4_; float x8_; @@ -166,6 +227,7 @@ struct SStage2Settings { float x10_; float x14_; float x18_; +#endif uint x1c_; uchar x20_; uchar x21_; @@ -173,19 +235,26 @@ struct SStage2Settings { uchar x23_; }; static const SStage2Settings skStage2Settings[5] = { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + {1, 0, 0, 0, 0}, {2, 0, 0, 0, 0}, {2, 1, 0, 0, 0}, {2, 0, 0, 0, 0}, {2, 1, 0, 0, 0}, +#else {4, 6, 50.f, 50.f, 0.f, 33.f, 0.f, 1, 0, 0, 0, 0}, {4, 6, 20.f, 20.f, 60.f, 50.f, 0.f, 2, 0, 0, 0, 0}, {4, 6, 40.f, 40.f, 20.f, 50.f, 50.f, 2, 1, 0, 0, 0}, {3, 5, 10.f, 15.f, 75.f, 100.f, 25.f, 2, 0, 0, 0, 0}, {3, 5, 30.f, 30.f, 40.f, 50.f, 50.f, 2, 1, 0, 0, 0}, +#endif }; +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 static const float skStage3AttackWeights[6][6] = { {0.f, 20.f, 40.f, 0.f, 0.f, 40.f}, {0.f, 0.f, 70.f, 0.f, 0.f, 30.f}, {0.f, 60.f, 0.f, 0.f, 0.f, 40.f}, {0.f, 40.f, 30.f, 0.f, 0.f, 30.f}, {0.f, 0.f, 50.f, 0.f, 0.f, 50.f}, {0.f, 40.f, 60.f, 0.f, 0.f, 0.f}, }; +#endif CRidleyData::CRidleyData(CInputStream& in, int propCount) +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 : x0_(in.ReadLong()) , x4_(in.ReadLong()) , x8_(in.ReadLong()) @@ -197,6 +266,9 @@ CRidleyData::CRidleyData(CInputStream& in, int propCount) , x20_(in.ReadLong()) , x24_(in.ReadLong()) , x28_(in.ReadLong()) +#else +: x28_(in.ReadLong()) +#endif , x2c_(in.ReadLong()) , x30_(in.ReadLong()) , x34_(in.ReadFloat()) @@ -208,6 +280,9 @@ CRidleyData::CRidleyData(CInputStream& in, int propCount) , x64_(in) , xa8_(CSfxManager::TranslateSFXID(in.ReadLong())) , xac_(in.ReadLong()) +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +, x88_(in.ReadLong()) +#endif , xb0_(in) , xcc_(CCameraShakeData::EatOldCameraShakerData(in)) , x1a0_(in.ReadLong()) @@ -227,7 +302,14 @@ CRidleyData::CRidleyData(CInputStream& in, int propCount) , x3f0_(in.ReadLong()) , x3f4_(in.ReadFloat()) , x3f8_(CSfxManager::TranslateSFXID(in.ReadLong())) -, x3fc_(propCount > 47 ? CDamageInfo(in) : x48_) {} +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +, x3fc_(in) +, x3f4_bounceDamage(propCount > 39 ? CDamageInfo(in) : x298_) +#else +, x3fc_(propCount > 47 ? CDamageInfo(in) : x48_) +#endif +{ +} CRidley::CRidley(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, const CTransform4f& xf, const CModelData& mData, const CPatternedInfo& pInfo, @@ -267,8 +349,17 @@ CRidley::CRidley(TUniqueId uid, const rstl::string& name, const CEntityInfo& inf , xa33_31_(false) , xa34_24_(false) , xa34_25_(false) +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +, xa34_27_(true) +, xa34_29_(false) +, xa34_30_jumpCanBeInterrupted(false) +, xa34_31_canBreakLockOn(true) +, xa35_24_hasPreviousBeamPos(false) +, xa35_25_inFlinch(false) +#else , xa34_26_(false) , xa38_(CStaticRes(x568_data.x24_, 4.f * mData.ScaleCopy())) +#endif , xa84_(CTransform4f::Identity()) , xab4_(20.f) , xab8_(12.f) @@ -305,7 +396,12 @@ CRidley::CRidley(TUniqueId uid, const rstl::string& name, const CEntityInfo& inf , xc08_(0.f) , xc0c_(0.f) , xc10_(120.f) +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +, xbd0_projectileInfo(x568_data.xac_, x568_data.xb0_) +, xc14_(x568_data.x88_, x568_data.xb0_) +#else , xc14_(x568_data.xac_, x568_data.xb0_) +#endif , xc3c_(x568_data.x1a0_, x568_data.x1a4_) , xc64_aiStage(2) , xc68_(CVector3f::Zero()) @@ -314,6 +410,9 @@ CRidley::CRidley(TUniqueId uid, const rstl::string& name, const CEntityInfo& inf , xc7c_(0.f) , xc80_(0.f) , xc88_(4) +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +, xc70_meleeAttack(2) +#endif , xc8c_(GetContactDamage()) , xca8_() , xcac_() @@ -328,9 +427,16 @@ CRidley::CRidley(TUniqueId uid, const rstl::string& name, const CEntityInfo& inf , xcdc_electric(rs_new CParticleElectric(xcd0_)) , xd08_(0.f) , xd0c_() -, xd10_(rs_new CProjectedShadow(128, 128, true)) { +, xd10_(rs_new CProjectedShadow(128, 128, true)) +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +, xcfc_previousBeamPos(CVector3f::Zero()) +#endif +{ SetDoTargetDistanceTest(false); xb68_.Token().Lock(); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xbd0_projectileInfo.Token().Lock(); +#endif xc14_.Token().Lock(); xc3c_.Token().Lock(); if (!xcdc_electric.null()) { @@ -366,14 +472,23 @@ void CRidley::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan xcbc_ = 0.8f * xcb8_; break; case kSM_Reset: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_25_ = true; +#else xa34_26_ = true; +#endif if (GetActive()) { break; } CPatterned::AcceptScriptMsg(kSM_Activate, uid, mgr); // Fall through. case kSM_Activate: { - mgr.SetBossParams(GetUniqueId(), xb1c_ + (xcb8_ + xb18_), 90); + mgr.SetBossParams(GetUniqueId(), xb1c_ + (xcb8_ + xb18_), +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + 84); +#else + 90); +#endif HealthInfo(mgr)->SetHP(xb1c_ + (xb10_ + xb18_)); CPlayer& player = *mgr.Player(); player.SetIsOverrideRadarRadius(true); @@ -421,6 +536,9 @@ void CRidley::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan if (CCollisionActor* actor = TCastToPtr< CCollisionActor >(mgr.ObjectById(uid))) { const float damage = 1000.f - actor->HealthInfo(mgr)->GetHP(); actor->HealthInfo(mgr)->SetHP(1000.f); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + bool interruptAttack = false; +#endif bool suppressKnockback = false; switch (xc64_aiStage) { case 2: @@ -473,6 +591,19 @@ void CRidley::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan TakeDamage(CVector3f::Forward(), 1.f); xb20_ = skDamageHitTime; if (xa32_29_) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (xa34_30_jumpCanBeInterrupted && damage >= 40.f) { + interruptAttack = true; + if (const CEntity* entity = mgr.GetObjectById(actor->GetLastTouchedObject())) { + if (const CGameProjectile* projectile = TCastToConstPtr< CGameProjectile >(entity)) { + if (projectile->GetCurrentDamageInfo().GetWeaponMode().IsCharged() && + !projectile->GetUnkPalFlag()) { + interruptAttack = false; + } + } + } + } +#else if (const CEntity* entity = mgr.GetObjectById(actor->GetLastTouchedObject())) { if (const CGameProjectile* projectile = TCastToConstPtr< CGameProjectile >(entity)) { const CWeaponMode& mode = projectile->GetCurrentDamageInfo().GetWeaponMode(); @@ -481,11 +612,15 @@ void CRidley::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan } } } +#endif xb14_ -= damage; x430_damageColor = skFrozenDamageColor; if (xb14_ <= 0.f) { xa32_29_ = false; suppressKnockback = true; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + interruptAttack = false; +#endif xa32_28_shotAt = true; xb14_ = x568_data.x38_; } @@ -498,6 +633,9 @@ void CRidley::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan suppressKnockback = true; xb18_ = 0.f; xcbc_ = 0.6667f * x568_data.x40_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xcb0_ = 3; +#endif } else if (xb18_ < xcbc_) { suppressKnockback = true; x450_bodyController->CommandMgr().DeliverCmd( @@ -521,14 +659,27 @@ void CRidley::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMan break; } HealthInfo(mgr)->SetHP(xb1c_ + (xb10_ + xb18_)); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (interruptAttack) { + x450_bodyController->CommandMgr().DeliverCmd(CBCGenerateCmd(pas::kGType_Five, -1)); + xa34_30_jumpCanBeInterrupted = false; + SendScriptMsgs(kSS_Retreat, mgr, kSM_None); + } else if (!suppressKnockback) { +#else if (!suppressKnockback) { +#endif const TUniqueId touchedId = actor->GetLastTouchedObject(); if (const CGameProjectile* projectile = TCastToConstPtr< CGameProjectile >(mgr.GetObjectById(touchedId))) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + KnockBack(projectile->GetVelocity(), mgr, projectile->GetCurrentDamageInfo(), + projectile->GetCurrentDamageInfo().GetKnockBackPower(), true, false); +#else const float power = projectile->GetCurrentDamageInfo().GetKnockBackPower(); const CVector3f projectilePos = projectile->GetTranslation(); const CVector3f& direction = projectilePos - projectile->GetPreviousPos(); KnockBack(direction, mgr, projectile->GetCurrentDamageInfo(), power, true, false); +#endif } } } @@ -598,6 +749,9 @@ void CRidley::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUs case kUE_BeginAction: if (xa32_25_ && !xa31_29_) { ActivateBeam(mgr); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa35_24_hasPreviousBeamPos = false; +#endif } if (xa31_31_ && xa32_25_) { xbf0_ = xa84_.GetRight(); @@ -633,16 +787,37 @@ void CRidley::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUs case kUE_Projectile: switch (xc64_aiStage) { case 2: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (mgr.CanCreateProjectile(GetUniqueId(), kWT_AI, 9)) { +#else if (xc14_.Token().TryCache() && mgr.CanCreateProjectile(GetUniqueId(), kWT_AI, 9)) { +#endif const float x = mgr.Random()->Range(-1.f, 1.f); const float angle = atan2f(mgr.Random()->Range(-1.f, 1.f), x); CTransform4f xf = GetLctrTransform(xa30_breastPlateSegId) * CTransform4f::RotateX(CRelAngle::FromDegrees(-90.f)); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (!xa34_27_) { + xf = xf * CTransform4f::RotateY(CRelAngle(angle)); + } +#else xf = xf * CTransform4f::RotateY(CRelAngle(angle)); +#endif const CVector3f offset(0.f, 1.f, 1.f); xf.SetTranslation(xf * offset); CEnergyProjectile* projectile = rs_new CEnergyProjectile( - true, xc14_.Token(), kWT_AI, xf, kMT_Character, xc14_.GetDamage(), + true, +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_27_ ? xc14_.Token() : xbd0_projectileInfo.Token(), +#else + xc14_.Token(), +#endif + kWT_AI, xf, kMT_Character, +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xbd0_projectileInfo.GetDamage(), +#else + xc14_.GetDamage(), +#endif mgr.AllocateUniqueId(), GetCurrentAreaId(), GetUniqueId(), mgr.GetPlayer()->GetUniqueId(), CWeapon::kPA_None, false, CVector3f(1.f, 1.f, 1.f), rstl::optional_object< TLockedToken< CGenDescription > >(), @@ -651,6 +826,9 @@ void CRidley::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUs mgr.AddObject(projectile); projectile->SetCameraShake(x568_data.xcc_); projectile->SetMinHomingDistance(20.f); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_27_ = false; +#endif } } break; @@ -681,13 +859,25 @@ void CRidley::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUs } else if (xc64_aiStage == 3) { xa31_24_ = false; } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + handled = true; +#endif break; case kUE_BreakLockOn: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (IsAlive() && xa34_31_canBreakLockOn) { +#else if (IsAlive()) { +#endif RemoveMaterial(kMT_Target, kMT_Orbit, mgr); mgr.Player()->TryToBreakOrbit(GetUniqueId(), CPlayer::kOB_ActivateOrbitSource, mgr); +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 handled = true; +#endif } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + handled = true; +#endif break; case kUE_Landing: SetVelocityWR(CVector3f::Down()); @@ -696,9 +886,19 @@ void CRidley::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUs break; case kUE_ScreenShake: x328_25_verticalMovement = false; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (mgr.GetPlayer()->GetTranslation().GetZ() - xa84_.GetTranslation().GetZ() < 1.f && + (mgr.GetPlayer()->GetTranslation() - GetTranslation()).Magnitude() < x568_data.x388_) { +#else if ((mgr.GetPlayer()->GetTranslation() - GetTranslation()).Magnitude() < x568_data.x388_) { +#endif mgr.ApplyDamage( - GetUniqueId(), mgr.GetPlayer()->GetUniqueId(), GetUniqueId(), x568_data.x298_, + GetUniqueId(), mgr.GetPlayer()->GetUniqueId(), GetUniqueId(), +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xc64_aiStage == 2 ? x568_data.x298_ : x568_data.x3f4_bounceDamage, +#else + x568_data.x298_, +#endif CMaterialFilter::MakeIncludeExclude(CMaterialList(kMT_Solid), CMaterialList()), CVector3f::Zero()); } @@ -731,6 +931,24 @@ void CRidley::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUs break; } break; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + case kUE_EventStart: { + const float duration = x568_data.x3cc_; + x402_28_isMakingBigStrike = duration > 0.f; + x504_damageDur = duration; + xc8c_ = x568_data.x3b0_; + CCollisionActorManager& collision = *x984_bodyCollision; + uint index = 9; + if (node.GetLocatorName()[0] == 'L') { + index = 8; + } + const TUniqueId id = collision.GetCollisionDescFromIndex(index).GetCollisionActorId(); + if (CCollisionActor* actor = TCastToPtr< CCollisionActor >(mgr.ObjectById(id))) { + actor->SetExtendedTouchBounds(CVector3f(7.f, 7.f, 7.f)); + } + break; + } +#endif } if (!handled) { CPatterned::DoUserAnimEvent(mgr, node, type, dt); @@ -789,6 +1007,7 @@ void CRidley::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum) { void CRidley::Render(const CStateManager& mgr) const { float damageDuration; +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 CColor damageColor = CColor::Black(); const float damageTime0 = xb20_; if (damageTime0 > 0.f) { @@ -796,21 +1015,22 @@ void CRidley::Render(const CStateManager& mgr) const { damageColor = CColor::Lerp(CColor::Black(), x430_damageColor, damageTime0 / damageDuration); } const CModelFlags damageFlags(CModelFlags::kT_Two, damageColor); +#endif CColor multiplyColor = CColor::White(); const float damageTime1 = xb24_; if (damageTime1 > 0.f) { - const float duration = skDamageHitTime; - multiplyColor = CColor::Lerp(CColor::White(), x430_damageColor, damageTime1 / duration); + damageDuration = skDamageHitTime; + multiplyColor = CColor::Lerp(CColor::White(), x430_damageColor, damageTime1 / damageDuration); } gpRender->SetGXRegister1Color(multiplyColor); if (xa31_25_) { const CTransform4f xf = GetLctrTransform(xa30_breastPlateSegId); const float damageTime1 = xb24_; if (damageTime1 > 0.f) { - const float duration = skDamageHitTime; + damageDuration = skDamageHitTime; x9e4_.Render(mgr, xf, GetActorLights(), CModelFlags(CModelFlags::kT_Two, CColor::Lerp(CColor::Black(), x430_damageColor, - damageTime1 / duration))); + damageTime1 / damageDuration))); } else { x9e4_.Render(mgr, xf, GetActorLights(), CModelFlags::Normal()); } @@ -818,6 +1038,15 @@ void CRidley::Render(const CStateManager& mgr) const { const CTransform4f xf = GetLctrTransform(xa30_breastPlateSegId); const float damageTime0 = xb20_; if (damageTime0 > 0.f) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + CColor damageColor = CColor::Black(); + const float damageTime0 = xb20_; + if (damageTime0 > 0.f) { + damageDuration = skDamageHitTime; + damageColor = CColor::Lerp(CColor::Black(), x430_damageColor, damageTime0 / damageDuration); + } + const CModelFlags damageFlags(CModelFlags::kT_Two, damageColor); +#endif x998_.Render(mgr, xf, GetActorLights(), damageFlags); } else { x998_.Render(mgr, xf, GetActorLights(), CModelFlags::Normal()); @@ -827,7 +1056,8 @@ void CRidley::Render(const CStateManager& mgr) const { } void CRidley::SetStage2Vulnerability(CStateManager& mgr) { - for (uint i = 0; i < x980_tailCollision->GetNumCollisionActors(); ++i) { + uint i; + for (i = 0; i < x980_tailCollision->GetNumCollisionActors(); ++i) { const CJointCollisionDescription& desc = x980_tailCollision->GetCollisionDescFromIndex(i); const TUniqueId id = desc.GetCollisionActorId(); if (CCollisionActor* actor = TCastToPtr< CCollisionActor >(mgr.ObjectById(id))) { @@ -840,7 +1070,7 @@ void CRidley::SetStage2Vulnerability(CStateManager& mgr) { } const CMaterialList& tailMaterials = CMaterialList(kMT_AIJoint); x980_tailCollision->AddMaterial(mgr, tailMaterials); - for (uint i = 0; i < x984_bodyCollision->GetNumCollisionActors(); ++i) { + for (i = 0; i < x984_bodyCollision->GetNumCollisionActors(); ++i) { const CJointCollisionDescription& desc = x984_bodyCollision->GetCollisionDescFromIndex(i); const TUniqueId id = desc.GetCollisionActorId(); if (CCollisionActor* actor = TCastToPtr< CCollisionActor >(mgr.ObjectById(id))) { @@ -863,7 +1093,9 @@ void CRidley::SetStage3ThroatVulnerability(CStateManager& mgr) { actor->SetDamageVulnerability(i == 3 ? skIceWeakness : CDamageVulnerability::ImmuneVulnerability()); actor->HealthInfo(mgr)->SetHP(1000.f); +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 actor->SetDrawShadow(true); +#endif } } xa32_29_ = true; @@ -878,7 +1110,9 @@ void CRidley::SetStage3BreastVulnerability(CStateManager& mgr) { actor->SetDamageVulnerability(i == 2 ? skDirectNormal : CDamageVulnerability::ImmuneVulnerability()); actor->HealthInfo(mgr)->SetHP(1000.f); +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 actor->SetDrawShadow(true); +#endif } } xa32_29_ = false; @@ -886,13 +1120,20 @@ void CRidley::SetStage3BreastVulnerability(CStateManager& mgr) { } void CRidley::SetStage3Immunity(CStateManager& mgr) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (xa35_25_inFlinch) { + return; + } +#endif for (uint i = 0; i < x984_bodyCollision->GetNumCollisionActors(); ++i) { const CJointCollisionDescription& desc = x984_bodyCollision->GetCollisionDescFromIndex(i); const TUniqueId id = desc.GetCollisionActorId(); if (CCollisionActor* actor = TCastToPtr< CCollisionActor >(mgr.ObjectById(id))) { actor->SetDamageVulnerability(CDamageVulnerability::ImmuneVulnerability()); actor->HealthInfo(mgr)->SetHP(1000.f); +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 actor->SetDrawShadow(true); +#endif } } xa32_29_ = false; @@ -917,7 +1158,11 @@ void CRidley::SetupCollisionManagers(CStateManager& mgr) { uint i; for (i = 0; i < 4; ++i) { const STailJoint& joint = skTailJoints[i]; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + const float radius = joint.x8_radius; +#else const float radius = joint.x8_radius * GetModelData()->ScaleCopy().GetZ(); +#endif joints.push_back(CJointCollisionDescription::OBBAutoSizeCollision( animData.GetLocatorSegId(rstl::string_l(joint.x0_from)), animData.GetLocatorSegId(rstl::string_l(joint.x4_to)), CVector3f(radius, radius, radius), @@ -930,9 +1175,16 @@ void CRidley::SetupCollisionManagers(CStateManager& mgr) { joints.clear(); for (i = 0; i < 10; ++i) { const SBodyJoint& joint = skBodyJoints[i]; +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 const float radius = joint.x4_radius * GetModelData()->ScaleCopy().GetZ(); +#endif joints.push_back(CJointCollisionDescription::SphereCollision( - animData.GetLocatorSegId(rstl::string_l(joint.x0_name)), radius, + animData.GetLocatorSegId(rstl::string_l(joint.x0_name)), +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + joint.x4_radius, +#else + radius, +#endif GetDebugName() + rstl::string_l(" - Collision Actor ") + rstl::string_l(joint.x0_name), 10.f)); } @@ -989,7 +1241,12 @@ void CRidley::ActivateBeam(CStateManager& mgr) { if (xb64_plasmaProjectile == kInvalidUniqueId) { CPlasmaProjectile* projectile = rs_new CPlasmaProjectile( xb68_.Token(), rstl::string_l(""), kWT_AI, x568_data.x64_, CTransform4f::Identity(), - kMT_Character, xb68_.GetDamage(), mgr.AllocateUniqueId(), GetCurrentAreaId(), GetUniqueId(), +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + kMT_Player, +#else + kMT_Character, +#endif + xb68_.GetDamage(), mgr.AllocateUniqueId(), GetCurrentAreaId(), GetUniqueId(), CWeaponAssetInfo(), false, CWeapon::kPA_KeepInCinematic); if (projectile) { mgr.AddObject(*projectile); @@ -1010,6 +1267,51 @@ void CRidley::ActivateBeam(CStateManager& mgr) { } } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +void CRidley::UpdateBeam(CStateManager& mgr, float dt) { + if (CPlasmaProjectile* projectile = + static_cast< CPlasmaProjectile* >(mgr.ObjectById(xb64_plasmaProjectile))) { + if (projectile->GetActive()) { + CTransform4f beamXf = GetLctrTransform(xb91_mouthSegId); + if (xc64_aiStage == 3) { + beamXf.SetColumn(kDY, CVector3f(beamXf.GetForward().ToVec2f().AsNormalized(), 0.f)); + beamXf.SetColumn(kDZ, + CVector3f::Cross(beamXf.GetRight(), beamXf.GetForward()).AsNormalized()); + beamXf.SetColumn(kDX, CVector3f::Cross(beamXf.GetForward(), beamXf.GetUp())); + } else { + beamXf = CTransform4f::LookAt(beamXf.GetTranslation(), xbe4_, CVector3f::Up()); + const CVector3f side = CVector3f::Cross(xbf0_, CVector3f::Up()); + const CVector3f target = mgr.GetPlayer()->GetTranslation() + CVector3f::Up() - xbe4_; + const float speed = CVector3f::Dot(side, target) > 0.f ? -xc10_ : xc10_; + const CQuaternion rotation = CQuaternion::ZRotation(CRelAngle::FromDegrees(dt * speed)); + const CVector3f direction = rotation.Transform(xbf0_); + const float dot = CVector3f::Dot(xbfc_, direction); + if (dot > 0.5f || dot > CVector3f::Dot(xbfc_, xbf0_)) { + xbf0_ = direction; + } + } + projectile->UpdateFx(beamXf, dt, mgr); + + const CVector3f currentPos = projectile->GetCurrentPos(); + const CAABox playerBounds = mgr.GetPlayer()->GetBoundingBox(); + if (xa35_24_hasPreviousBeamPos && CollisionUtil::TriBoxOverlap( + playerBounds.GetCenterPoint(), + 0.5f * (playerBounds.GetMaxPoint() - playerBounds.GetMinPoint()), + beamXf.GetTranslation(), xcfc_previousBeamPos, currentPos)) { + mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer()->GetUniqueId(), GetUniqueId(), + xb68_.GetDamage().MakeScaledForTime(dt), CMaterialFilter::skPassEverything, + beamXf.GetForward()); + } + + xcfc_previousBeamPos = currentPos; + xa35_24_hasPreviousBeamPos = true; + } + } + if (xca8_) { + CSfxManager::UpdateEmitter(xca8_, GetTranslation(), CVector3f::Zero(), 127); + } +} +#else void CRidley::UpdateBeam(CStateManager& mgr, float dt) { if (CPlasmaProjectile* projectile = static_cast< CPlasmaProjectile* >(mgr.ObjectById(xb64_plasmaProjectile))) { @@ -1037,6 +1339,7 @@ void CRidley::UpdateBeam(CStateManager& mgr, float dt) { CSfxManager::UpdateEmitter(xca8_, GetTranslation(), CVector3f::Zero(), 127); } } +#endif void CRidley::DeactivateBeam(CStateManager& mgr, bool reset) { if (CPlasmaProjectile* projectile = @@ -1080,8 +1383,9 @@ void CRidley::UpdateWingElectricity(CStateManager& mgr, float dt) { } } else { CAnimData& animData = *ModelData()->AnimationData(); - xcdc_electric->SetOverrideIPos( - animData.GetLocatorTransform(xa30_breastPlateSegId, nullptr).GetTranslation()); + const CVector3f initial = + animData.GetLocatorTransform(xa30_breastPlateSegId, nullptr).GetTranslation(); + xcdc_electric->SetOverrideIPos(initial); int min = 0; int max = xce4_wingBoneIds.size() - 1; if (!xa32_30_) { @@ -1089,9 +1393,10 @@ void CRidley::UpdateWingElectricity(CStateManager& mgr, float dt) { } else { min = max - 12; } - xcdc_electric->SetOverrideFPos( + const CVector3f finalPos = animData.GetLocatorTransform(xce4_wingBoneIds[mgr.Random()->Range(min, max)], nullptr) - .GetTranslation()); + .GetTranslation(); + xcdc_electric->SetOverrideFPos(finalPos); xcdc_electric->ForceParticleCreation(1); } } @@ -1144,16 +1449,37 @@ void CRidley::UpdateFlight(float dt) { void CRidley::Fly(const CVector3f& direction, float speed, float dt) { xaf8_ = (speed * (0.2f * speed)) * direction; xaec_ += dt * xaf8_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + if (xaec_.IsMagnitudeSafe() && xaec_.Magnitude() > speed) { +#else if (xaec_.Magnitude() > speed) { +#endif xaec_ = speed * xaec_.AsNormalized(); } } void CRidley::FacePlayer(CStateManager& mgr, float dt) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + const CVector3f delta = mgr.GetPlayer()->GetTranslation() - GetTranslation(); + if (delta.IsMagnitudeSafe()) { + x450_bodyController->FaceDirection(delta.AsNormalized(), dt); + } +#else x450_bodyController->FaceDirection( (mgr.GetPlayer()->GetTranslation() - GetTranslation()).AsNormalized(), dt); +#endif } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +void CRidley::PushPlayer(CStateManager& mgr) const { + const CVector3f delta = mgr.GetPlayer()->GetTranslation() - GetTranslation(); + const CVector3f planarDelta(delta.ToVec2f(), 0.f); + if (planarDelta.IsMagnitudeSafe() && delta.Magnitude() < 8.f) { + const float impulse = mgr.GetPlayer()->GetMass() * (8.f - delta.Magnitude()); + mgr.Player()->ApplyImpulseWR(impulse * planarDelta.AsNormalized(), CAxisAngle::Identity()); + } +} +#else void CRidley::PushPlayer(CStateManager& mgr) const { const CVector3f delta = mgr.GetPlayer()->GetTranslation() - GetTranslation(); if (delta.Magnitude() < 8.f) { @@ -1162,6 +1488,7 @@ void CRidley::PushPlayer(CStateManager& mgr) const { CAxisAngle::Identity()); } } +#endif void CRidley::ChooseStage2Attack(CStateManager& mgr) { const SStage2Attack& attack = skStage2Attacks[xcb0_][xcb4_]; @@ -1208,9 +1535,16 @@ void CRidley::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { void CRidley::Generate(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { case kStateMsg_Activate: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_25_ = false; +#else xa34_26_ = false; +#endif SetTranslation(xa84_ * CVector3f(0.f, xabc_, xac0_ - xadc_)); x450_bodyController->CommandMgr().DeliverCmd(CBodyStateCmd(kBSC_NextState)); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa32_31_ = false; +#endif break; case kStateMsg_Update: case kStateMsg_Deactivate: @@ -1275,7 +1609,12 @@ void CRidley::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float arg) { break; case kStateMsg_Update: TryCommand(mgr, pas::kAS_ProjectileAttack, - static_cast< FTryCommandCallback >(&CRidley::TryProjectileAttack), 0); + static_cast< FTryCommandCallback >(&CRidley::TryProjectileAttack), +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_29_ ? 1 : 0); +#else + 0); +#endif break; case kStateMsg_Deactivate: x32c_animState = kAS_NotReady; @@ -1283,6 +1622,9 @@ void CRidley::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float arg) { SetStage3Immunity(mgr); xa32_25_ = false; RandomSlowDown(); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_29_ = true; +#endif break; } } @@ -1298,9 +1640,18 @@ void CRidley::Flee(CStateManager& mgr, EStateMsg msg, float arg) { break; } case kStateMsg_Update: { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + CVector3f direction = x2e0_destPos - GetTranslation(); + if (direction.IsMagnitudeSafe()) { + direction.Normalize(); + Fly(direction, 50.f, arg); + x450_bodyController->FaceDirection(direction, arg); + } +#else const CVector3f direction = (x2e0_destPos - GetTranslation()).AsNormalized(); Fly(direction, 50.f, arg); x450_bodyController->FaceDirection(direction, arg); +#endif break; } case kStateMsg_Deactivate: @@ -1352,11 +1703,22 @@ void CRidley::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { const CVector3f right = CVector3f::Cross(forward, CVector3f::Up()); SetTransform(CTransform4f::FromColumns(right, forward, CVector3f::Up(), GetTranslation())); xa33_27_ = false; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_25_ = false; +#else xa34_26_ = false; +#endif break; } case kStateMsg_Update: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + const CVector3f delta = x2e0_destPos - GetTranslation(); + if (delta.IsMagnitudeSafe()) { + Fly(delta.AsNormalized(), 50.f, arg); + } +#else Fly((x2e0_destPos - GetTranslation()).AsNormalized(), 50.f, arg); +#endif FacePlayer(mgr, 10.f * arg); break; case kStateMsg_Deactivate: @@ -1402,6 +1764,9 @@ void CRidley::LoopedAttack(CStateManager& mgr, EStateMsg msg, float arg) { xa33_24_ = false; xbc4_ = GetTranslation(); xbd0_ = GetTransform().GetForward(); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + x2ec_reflectedDestPos = GetTranslation(); +#endif } else { xa33_24_ = CVector3f::Dot(xa84_.GetRight(), GetTranslation() - xa84_.GetTranslation()) < 0.f; const rstl::vector< SConnection >& connections = GetConnectionList(); @@ -1462,7 +1827,12 @@ void CRidley::LoopedAttack(CStateManager& mgr, EStateMsg msg, float arg) { if (!xa31_30_) { CVector3f direction = xbc4_ - GetTranslation(); const float distance = direction.Magnitude(); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + const float dot = CVector3f::Dot(direction, xbc4_ - x2ec_reflectedDestPos); + if (distance > 2.f && dot > 0.f) { +#else if (distance > 2.f && CVector3f::Dot(direction, xbc4_ - x2ec_reflectedDestPos) > 0.f) { +#endif direction *= 1.f / distance; xbdc_ += CMath::Clamp(-100.f * arg, xbe0_ - xbdc_, 100.f * arg); Fly(direction, xbdc_, arg); @@ -1541,7 +1911,14 @@ void CRidley::Approach(CStateManager& mgr, EStateMsg msg, float arg) { break; } case kStateMsg_Update: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + const CVector3f delta = x2e0_destPos - GetTranslation(); + if (delta.IsMagnitudeSafe()) { + Fly(delta.AsNormalized(), 50.f, arg); + } +#else Fly((x2e0_destPos - GetTranslation()).AsNormalized(), 50.f, arg); +#endif FacePlayer(mgr, arg); break; case kStateMsg_Deactivate: @@ -1645,6 +2022,27 @@ void CRidley::JumpBack(CStateManager& mgr, EStateMsg msg, float arg) { } } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +void CRidley::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { + switch (msg) { + case kStateMsg_Activate: + break; + case kStateMsg_Update: + if (x450_bodyController->GetCurrentStateId() != pas::kAS_Turn) { + const CVector3f direction = + (mgr.GetPlayer()->GetTranslation() - GetTranslation()).AsNormalized(); + if (CVector3f::Dot(direction, GetTransform().GetForward()) < 0.9f) { + x450_bodyController->CommandMgr().DeliverCmd( + CBCLocomotionCmd(CVector3f::Zero(), direction, 1.f)); + } + } + break; + case kStateMsg_Deactivate: + break; + } +} +#endif + void CRidley::Crouch(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { case kStateMsg_Activate: @@ -1664,6 +2062,9 @@ void CRidley::Crouch(CStateManager& mgr, EStateMsg msg, float arg) { } break; case kStateMsg_Deactivate: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_29_ = false; +#endif break; } } @@ -1674,6 +2075,9 @@ void CRidley::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float arg) { x32c_animState = kAS_Ready; --xcc4_; xa33_31_ = true; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_27_ = true; +#endif break; case kStateMsg_Update: TryCommand(mgr, pas::kAS_ProjectileAttack, @@ -1696,6 +2100,60 @@ bool CRidley::CanJumpAttack() const { return ret; } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +void CRidley::ChooseStage3Attack(CStateManager& mgr) { + const SStage2Attack& attack = skStage3Attacks[xcb0_][xcb4_]; + xb0c_ = mgr.Random()->Range(0.f, 100.f) <= attack.x4_probability ? attack.x0_primary + : attack.x8_alternate; + if (xb0c_ == -1) { + xcb4_ = 0; + const SStage2Attack& attack = skStage3Attacks[xcb0_][xcb4_]; + xb0c_ = mgr.Random()->Range(0.f, 100.f) <= attack.x4_probability ? attack.x0_primary + : attack.x8_alternate; + } + CVector3f delta = mgr.GetPlayer()->GetTranslation() - GetTranslation(); + const float distance = delta.Magnitude(); + delta *= 1.f / distance; + const float dot = CVector3f::Dot(delta, GetTransform().GetForward()); + bool adjusted = false; + if (dot < 0.f && distance < x300_maxAttackRange) { + adjusted = true; + xb0c_ = 3; + } + if (dot > 0.f && distance < x2fc_minAttackRange && xb08_ != 4) { + adjusted = true; + xb0c_ = 4; + } + switch (xb0c_) { + case 2: + case 7: + if (dot < 0.5f) { + adjusted = true; + xb0c_ = 0; + } + break; + case 5: + if (dot < 0.5f) { + adjusted = true; + xb0c_ = 0; + } else if (!CanJumpAttack()) { + const SStage2Attack& fallback = skStage3Attacks[xcb0_][xcb4_]; + xb0c_ = fallback.x8_alternate; + } + break; + case 6: + if (dot < 0.f) { + adjusted = true; + xb0c_ = 0; + } + break; + } + if (!adjusted) { + ++xcb4_; + } + xb08_ = xb0c_; +} +#else void CRidley::ChooseStage3Attack(CStateManager& mgr) { xb08_ = xb0c_; const float roll = 100.f * mgr.Random()->Float(); @@ -1727,6 +2185,7 @@ void CRidley::ChooseStage3Attack(CStateManager& mgr) { xb0c_ = 4; } } +#endif void CRidley::FadeOut(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { @@ -1747,6 +2206,10 @@ void CRidley::FadeOut(CStateManager& mgr, EStateMsg msg, float arg) { case kStateMsg_Deactivate: x32c_animState = kAS_NotReady; xcbc_ = 0.6667f * x568_data.x3c_; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xcb0_ = 0; + xcb4_ = 0; +#endif break; } } @@ -1759,21 +2222,39 @@ void CRidley::DoubleSnap(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { case kStateMsg_Activate: { x32c_animState = kAS_Ready; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + const float distance = (mgr.GetPlayer()->GetTranslation() - GetTranslation()).Magnitude(); + xc70_meleeAttack = distance < 0.66f * x2fc_minAttackRange ? 2 : 7; +#else const float duration = x568_data.x3cc_; x402_28_isMakingBigStrike = duration > 0.f; x504_damageDur = duration; xc8c_ = x568_data.x3b0_; +#endif break; } case kStateMsg_Update: TryCommand(mgr, pas::kAS_MeleeAttack, - static_cast< FTryCommandCallback >(&CRidley::TryMeleeAttack), 2); + static_cast< FTryCommandCallback >(&CRidley::TryMeleeAttack), +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xc70_meleeAttack); +#else + 2); +#endif break; case kStateMsg_Deactivate: x32c_animState = kAS_NotReady; x402_28_isMakingBigStrike = false; x504_damageDur = 0.f; xc8c_ = GetContactDamage(); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + for (int i = 8; i <= 9; ++i) { + const TUniqueId id = x984_bodyCollision->GetCollisionDescFromIndex(i).GetCollisionActorId(); + if (CCollisionActor* actor = TCastToPtr< CCollisionActor >(mgr.ObjectById(id))) { + actor->SetExtendedTouchBounds(CVector3f::Zero()); + } + } +#endif break; } } @@ -1793,6 +2274,10 @@ void CRidley::Jump(CStateManager& mgr, EStateMsg msg, float arg) { x504_damageDur = duration; xc8c_ = x568_data.x390_; RandomSpeedUp(mgr); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_30_jumpCanBeInterrupted = true; + xa34_31_canBreakLockOn = true; +#endif break; } case kStateMsg_Update: @@ -1804,12 +2289,20 @@ void CRidley::Jump(CStateManager& mgr, EStateMsg msg, float arg) { break; case kStateMsg_Deactivate: AddMaterial(kMT_Orbit, kMT_Target, mgr); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_31_canBreakLockOn = false; +#endif x402_28_isMakingBigStrike = false; x504_damageDur = 0.f; xc8c_ = GetContactDamage(); x32c_animState = kAS_NotReady; +#if VERSION < VERSION_GM8P_00 || VERSION == VERSION_GM8E_02 xa34_25_ = false; +#endif RandomSlowDown(); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa34_30_jumpCanBeInterrupted = false; +#endif break; } } @@ -1819,6 +2312,9 @@ void CRidley::Flinch(CStateManager& mgr, EStateMsg msg, float arg) { case kStateMsg_Activate: SetStage3BreastVulnerability(mgr); x32c_animState = kAS_Ready; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa35_25_inFlinch = true; +#endif break; case kStateMsg_Update: TryCommand(mgr, pas::kAS_KnockBack, static_cast< FTryCommandCallback >(&CRidley::TryKnockBack), @@ -1826,8 +2322,20 @@ void CRidley::Flinch(CStateManager& mgr, EStateMsg msg, float arg) { break; case kStateMsg_Deactivate: x32c_animState = kAS_NotReady; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa35_25_inFlinch = false; +#endif SetStage3Immunity(mgr); xa32_28_shotAt = false; +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xcb4_ = 0; + if (xcb0_ < 3) { + ++xcb0_; + if (xcb0_ == 3) { + xcb0_ = 1; + } + } +#endif break; } } @@ -1948,7 +2456,11 @@ bool CRidley::ShouldAttack(CStateManager& mgr, float arg) { ret = xb04_ == 0; break; case 3: +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + ret = xb0c_ == 2 || xb0c_ == 7; +#else ret = xb0c_ == 2; +#endif break; } return ret; @@ -1966,7 +2478,13 @@ bool CRidley::InRange(CStateManager& mgr, float arg) { bool CRidley::ShouldCrouch(CStateManager& mgr, float arg) { return xb04_ == 1; } -bool CRidley::ShouldRetreat(CStateManager& mgr, float arg) { return xa34_26_; } +bool CRidley::ShouldRetreat(CStateManager& mgr, float arg) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + return xa34_25_; +#else + return xa34_26_; +#endif +} bool CRidley::ShouldDodge(CStateManager& mgr, float arg) { return xb04_ == 3; } @@ -1991,6 +2509,9 @@ bool CRidley::TooClose(CStateManager& mgr, float arg) { } bool CRidley::ShouldMove(CStateManager& mgr, float arg) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + return xb0c_ == 5; +#else if (xb0c_ == 5) { xa34_25_ = true; return true; @@ -2006,9 +2527,13 @@ bool CRidley::ShouldMove(CStateManager& mgr, float arg) { } } return false; +#endif } bool CRidley::IsDizzy(CStateManager& mgr, float arg) { +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + return xb0c_ == 3; +#else if (xb0c_ == 3) { return true; } @@ -2021,6 +2546,7 @@ bool CRidley::IsDizzy(CStateManager& mgr, float arg) { } } return false; +#endif } bool CRidley::ShotAt(CStateManager& mgr, float arg) { return xa32_28_shotAt; } @@ -2029,6 +2555,46 @@ bool CRidley::Attacked(CStateManager& mgr, float arg) { return xa31_24_ && xa31_ bool CRidley::HitSomething(CStateManager& mgr, float arg) { return xa32_27_ || xc64_aiStage == 3; } +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 +bool CRidley::BounceFind(CStateManager& mgr, float arg) { return xb0c_ == 6; } + +void CRidley::Bounce(CStateManager& mgr, EStateMsg msg, float arg) { + switch (msg) { + case kStateMsg_Activate: { + CVector3f delta = mgr.GetPlayer()->GetTranslation() - xa84_.GetTranslation(); + delta.SetZ(0.f); + const float distance = CMath::Min(15.f + xab4_, delta.Magnitude()); + SetDestPos(xa84_.GetTranslation() + distance * delta.Normalize()); + x32c_animState = kAS_Ready; + const float duration = x568_data.x38c_; + x402_28_isMakingBigStrike = duration > 0.f; + x504_damageDur = duration; + break; + } + case kStateMsg_Update: + if (x330_stateMachineState.GetTime() < 1.f) { + FacePlayer(mgr, arg); + } + TryCommand(mgr, pas::kAS_MeleeAttack, + static_cast< FTryCommandCallback >(&CRidley::TryMeleeAttack_TargetPos), 8); + break; + case kStateMsg_Deactivate: + x402_28_isMakingBigStrike = false; + x504_damageDur = 0.f; + x32c_animState = kAS_NotReady; + break; + } +} + +bool CRidley::SpotPlayer(CStateManager& mgr, float arg) { + const float dot = CMath::FastCosR(CMath::Deg2Rad(0.5f * arg)); + const CVector3f delta = mgr.GetPlayer()->GetTranslation() - GetTranslation(); + return CVector3f::Dot(delta.AsNormalized(), GetTransform().GetForward()) > dot; +} + +bool CRidley::AggressionCheck(CStateManager& mgr, float arg) { return xb0c_ == 7; } +#endif + bool CRidley::SetAIStage(CStateManager& mgr, float arg) { xc64_aiStage = arg; return true; diff --git a/src/MetroidPrime/Player/CPlayer.cpp b/src/MetroidPrime/Player/CPlayer.cpp index a0e759362..e340a83c6 100644 --- a/src/MetroidPrime/Player/CPlayer.cpp +++ b/src/MetroidPrime/Player/CPlayer.cpp @@ -452,6 +452,12 @@ CPlayer::CPlayer(TUniqueId uid, const CTransform4f& xf, const CAABox& aabb, CAss x2b4_accelerationTable.push_back(80.f); x2b4_accelerationTable.push_back(270.f); SetMaxVelocityAfterCollision(25.f); +#if VERSION >= VERSION_GM8P_00 && VERSION != VERSION_GM8E_02 + xa4c_phazonCollisionIndex = 0; + for (int i = 0; i < 7; ++i) { + xa30_phazonCollisionDelay[i] = 0; + } +#endif x354_onScreenOrbitObjects.reserve(64); x344_nearbyOrbitObjects.reserve(64); x364_offScreenOrbitObjects.reserve(64);