mirror of https://github.com/PrimeDecomp/prime.git
205 lines
6.8 KiB
C++
205 lines
6.8 KiB
C++
#include "MetroidPrime/Weapons/WeaponTypes.hpp"
|
|
#include "MetroidPrime/Weapons/WeaponCommon.hpp"
|
|
|
|
#include "MetroidPrime/CAnimData.hpp"
|
|
#include "MetroidPrime/CAnimPlaybackParms.hpp"
|
|
#include "MetroidPrime/CStateManager.hpp"
|
|
#include "MetroidPrime/Player/CPlayerState.hpp"
|
|
#include "MetroidPrime/Player/CGameState.hpp"
|
|
#include "MetroidPrime/Weapons/CGunWeapon.hpp"
|
|
#include "MetroidPrime/Tweaks/CTweakPlayerGun.hpp"
|
|
|
|
#include "Kyoto/Animation/CPrimitive.hpp"
|
|
#include "Kyoto/Audio/CSfxManager.hpp"
|
|
#include "Kyoto/CResFactory.hpp"
|
|
#include "Kyoto/CToken.hpp"
|
|
|
|
#include "rstl/set.hpp"
|
|
|
|
namespace NWeaponTypes {
|
|
|
|
CAssetId get_asset_id_from_name(const char* name) {
|
|
const SObjectTag* tag = gpResourceFactory->GetResourceIdByName(name);
|
|
if (!tag) {
|
|
return kInvalidAssetId;
|
|
}
|
|
return tag->mId;
|
|
}
|
|
|
|
void get_token_vector(CAnimData& animData, int animIdx, rstl::vector< CToken >& tokensOut,
|
|
bool preLock) {
|
|
rstl::set< CPrimitive > prims;
|
|
CAnimPlaybackParms parms(animIdx, -1, 1.f, true);
|
|
animData.GetAnimationPrimitives(parms, prims);
|
|
primitive_set_to_token_vector(animData, prims, tokensOut, preLock);
|
|
}
|
|
|
|
void get_token_vector(const CAnimData& animData, int begin, int end,
|
|
rstl::vector< CToken >& tokensOut, bool preLock) {
|
|
rstl::set< CPrimitive > prims;
|
|
for (int i = begin; i < end; ++i) {
|
|
CAnimPlaybackParms parms(i, -1, 1.f, true);
|
|
animData.GetAnimationPrimitives(parms, prims);
|
|
}
|
|
primitive_set_to_token_vector(animData, prims, tokensOut, preLock);
|
|
}
|
|
|
|
bool are_tokens_ready(const rstl::vector< CToken >& anims) {
|
|
for (rstl::vector< CToken >::const_iterator it = anims.begin(); it != anims.end(); ++it)
|
|
if (!it->IsLoaded())
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void lock_tokens(rstl::vector< CToken >& anims) {
|
|
for (rstl::vector< CToken >::iterator it = anims.begin(); it != anims.end(); ++it)
|
|
it->Lock();
|
|
}
|
|
|
|
void unlock_tokens(rstl::vector< CToken >& anims) {
|
|
for (rstl::vector< CToken >::iterator it = anims.begin(); it != anims.end(); ++it)
|
|
it->Unlock();
|
|
}
|
|
|
|
void primitive_set_to_token_vector(const CAnimData& animData,
|
|
const rstl::set< CPrimitive >& primSet,
|
|
rstl::vector< CToken >& tokensOut, bool preLock) {
|
|
|
|
int eventCount = 0;
|
|
|
|
rstl::set< CPrimitive >::const_iterator it = primSet.begin();
|
|
for (; it != primSet.end(); ++it) {
|
|
if (animData.GetEventResourceIdForAnimResourceId(it->GetAnimResId()) != -1)
|
|
++eventCount;
|
|
}
|
|
|
|
tokensOut = rstl::vector< CToken >();
|
|
tokensOut.reserve(primSet.size() + eventCount);
|
|
|
|
for (it = primSet.begin(); it != primSet.end(); ++it) {
|
|
int aId = it->GetAnimResId();
|
|
int eId = animData.GetEventResourceIdForAnimResourceId(aId);
|
|
|
|
if (eId != -1) {
|
|
CToken token = gpSimplePool->GetObj(SObjectTag('EVNT', eId));
|
|
if (preLock)
|
|
token.Lock();
|
|
tokensOut.push_back(token);
|
|
}
|
|
|
|
CToken token = gpSimplePool->GetObj(SObjectTag('ANIM', aId));
|
|
if (preLock)
|
|
token.Lock();
|
|
tokensOut.push_back(token);
|
|
}
|
|
}
|
|
|
|
void do_sound_event(rstl::pair< u16, CSfxHandle >& sfxHandle, int& pitch, bool doPitchBend,
|
|
uint soundId, float weight, uint flags, float falloff, float maxDist,
|
|
uchar minVol, uchar maxVol, const CVector3f& posToCam, const CVector3f& pos,
|
|
TAreaId aid, CStateManager& mgr) {
|
|
if (posToCam.MagSquared() >= maxDist * maxDist)
|
|
return;
|
|
|
|
u16 useSfxId = CSfxManager::TranslateSFXID(u16(soundId));
|
|
uint useFlags = 0x1; // Continuous parameter update
|
|
if ((flags & 0x8) != 0)
|
|
useFlags |= 0x8; // Doppler effect
|
|
bool useAcoustics = (flags & 0x80) == 0;
|
|
|
|
// TODO ctor?
|
|
CAudioSys::C3DEmitterParmData parms(maxDist, falloff, useFlags, maxVol, minVol);
|
|
parms.x0_pos = pos;
|
|
parms.xc_dir = CVector3f::Up();
|
|
parms.x24_sfxId = useSfxId;
|
|
|
|
if (mgr.Random()->Float() <= weight) {
|
|
if ((soundId & 0x80000000) != 0) {
|
|
if (!sfxHandle.second) {
|
|
CSfxHandle hnd;
|
|
if ((soundId & 0x40000000) != 0)
|
|
hnd = CSfxManager::SfxStart(useSfxId, 0x7f, 0x40, true, CSfxManager::kMedPriority, true,
|
|
aid.Value());
|
|
else
|
|
hnd = CSfxManager::AddEmitter(parms, useAcoustics, CSfxManager::kMedPriority, true,
|
|
aid.Value());
|
|
if (hnd) {
|
|
sfxHandle.first = useSfxId;
|
|
sfxHandle.second = hnd;
|
|
if (doPitchBend)
|
|
CSfxManager::PitchBend(hnd, pitch);
|
|
}
|
|
} else {
|
|
if (sfxHandle.first == useSfxId) {
|
|
CSfxManager::UpdateEmitter(sfxHandle.second, parms.x0_pos, parms.xc_dir, maxVol);
|
|
} else if ((flags & 0x4) != 0) // Pausable
|
|
{
|
|
CSfxManager::RemoveEmitter(sfxHandle.second);
|
|
CSfxHandle hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid.Value());
|
|
if (hnd) {
|
|
sfxHandle.first = useSfxId;
|
|
sfxHandle.second = hnd;
|
|
if (doPitchBend && hnd)
|
|
CSfxManager::PitchBend(hnd, pitch);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
CSfxHandle hnd;
|
|
if ((soundId & 0x40000000) != 0)
|
|
hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, false, aid.Value());
|
|
else
|
|
hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, false, aid.Value());
|
|
if (doPitchBend)
|
|
CSfxManager::PitchBend(hnd, pitch);
|
|
}
|
|
}
|
|
}
|
|
|
|
CSfxHandle play_sfx(u16 sfx, bool underwater, bool looped, short pan) {
|
|
CSfxHandle hnd = CSfxManager::SfxStart(sfx, 0x7f, pan, true, CSfxManager::kMaxPriority, looped);
|
|
CSfxManager::SfxSpan(hnd, 0);
|
|
if (underwater)
|
|
CSfxManager::PitchBend(hnd, 0);
|
|
return hnd;
|
|
}
|
|
|
|
} // namespace NWeaponTypes
|
|
|
|
CDamageInfo CGunWeapon::GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) const {
|
|
// CWeaponMode mode(shotParam.x0_weaponType, 0);
|
|
// float damage = shotParam.x8_damage;
|
|
// float radiusDamage = shotParam.xc_radiusDamage;
|
|
// float radius = shotParam.x10_radius;
|
|
// float knockback = shotParam.x14_knockback;
|
|
// bool noImmunity = shotParam.x18_24_noImmunity;
|
|
|
|
CDamageInfo result(
|
|
CWeaponMode(shotParam.x0_weaponType, 0),
|
|
shotParam.x8_damage,
|
|
shotParam.xc_radiusDamage,
|
|
shotParam.x10_radius,
|
|
shotParam.x14_knockback,
|
|
shotParam.x18_24_noImmunity);
|
|
|
|
if (gpGameState->GetHardMode()) {
|
|
result.MultiplyDamage(gpGameState->GetHardModeWeaponMultiplier());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
namespace NWeaponTypes {
|
|
|
|
int get_current_suit(const CStateManager& mgr) {
|
|
const CPlayerState* state = mgr.GetPlayerState();
|
|
CPlayerState::EPlayerSuit suit = state->GetCurrentSuit();
|
|
if (suit < CPlayerState::kPS_Power || suit > CPlayerState::kPS_FusionGravity)
|
|
suit = CPlayerState::kPS_Power;
|
|
if (suit == CPlayerState::kPS_FusionPower)
|
|
suit = CPlayerState::EPlayerSuit(int(suit) + int(state->GetCurrentSuitRaw()));
|
|
return suit;
|
|
}
|
|
|
|
} // namespace NWeaponTypes
|