Implement CScriptSound and bug fixes

This commit is contained in:
Jack Andersen 2017-11-26 19:06:53 -10:00
parent 11d17d0fe5
commit f60097b7e3
26 changed files with 369 additions and 143 deletions

View File

@ -30,7 +30,8 @@ struct Midi : IScriptObject
void gatherDependencies(std::vector<hecl::ProjectPath> &pathsOut) const
{
g_curSpec->flattenDependencies(song, pathsOut);
// Dedicated PAK for this
//g_curSpec->flattenDependencies(song, pathsOut);
}
};
}

View File

@ -16,22 +16,22 @@ struct Sound : IScriptObject
Value<atVec3f> location;
Value<atVec3f> orientation;
Value<atUint32> soundID;
Value<bool> unknown1;
Value<float> unknown2;
Value<float> unknown3;
Value<float> unknown4;
Value<atUint32> unknown5;
Value<atUint32> unknown6;
Value<atUint32> unknown7;
Value<atUint32> unknown8;
Value<bool> unknown9;
Value<bool> unknown10;
Value<bool> unknown11;
Value<bool> unknown12;
Value<bool> unknown13;
Value<bool> unknown14;
Value<bool> unknown15;
Value<atUint32> unknown16;
Value<bool> active;
Value<float> maxDist;
Value<float> distComp;
Value<float> startDelay;
Value<atUint32> minVol;
Value<atUint32> vol;
Value<atUint32> prio;
Value<atUint32> pan;
Value<bool> loop;
Value<bool> nonEmitter;
Value<bool> autoStart;
Value<bool> occlusionTest;
Value<bool> acoustics;
Value<bool> worldSfx;
Value<bool> allowDuplicates;
Value<atUint32> pitch;
};
}
}

View File

@ -289,6 +289,9 @@ struct SDSPStream : boo::IAudioVoiceCallback
stream.m_booVoice.reset();
stream.x0_active = false;
stream.xd4_ringBuffer.reset();
stream.m_readReqs[0].reset();
stream.m_readReqs[1].reset();
stream.m_file = std::experimental::nullopt;
}
}
@ -1196,6 +1199,15 @@ void CStreamAudioManager::Initialize()
CDSPStreamManager::Initialize();
}
void CStreamAudioManager::StopOneShot()
{
CStreamAudioManager::StopStreaming(true);
SDSPPlayer& p = s_Players[1];
p = SDSPPlayer();
SDSPPlayer& qp = s_QueuedPlayers[1];
qp = SDSPPlayer();
}
void CStreamAudioManager::Shutdown()
{
CDSPStreamManager::Shutdown();

View File

@ -32,6 +32,7 @@ public:
static void SetMusicVolume(u8 volume);
static void Initialize();
static void StopOneShot();
static void Shutdown();
};

View File

@ -1891,7 +1891,7 @@ void CStateManager::Update(float dt)
x884_actorModelParticles->Update(dt, *this);
if (x904_gameState == EGameState::Running || x904_gameState == EGameState::SoftPaused)
ThinkEffectsAndActors(dt);
Think(dt);
if (x904_gameState != EGameState::SoftPaused)
x870_cameraManager->Update(dt, *this);
@ -2039,17 +2039,17 @@ void CStateManager::MoveDoors(float dt)
if (doThink && ai->GetAreaIdAlways() != kInvalidAreaId)
{
const CGameArea* area = x850_world->GetAreaAlways(ai->GetAreaIdAlways());
float f1;
float occTime;
if (area->IsPostConstructed())
f1 = area->GetPostConstructed()->x10e4_;
occTime = area->GetPostConstructed()->x10e4_occludedTime;
else
f1 = 0.f;
if (f1 > 5.f)
occTime = 0.f;
if (occTime > 5.f)
doThink = false;
}
if (!doThink)
SendScriptMsgAlways(ai->GetUniqueId(), kInvalidUniqueId,
EScriptObjectMessage::InternalMessage26);
EScriptObjectMessage::SuspendedMove);
else if (x84c_player.get() != ent)
if (!GetPlatformAndDoorObjectList().IsPlatform(*ent))
CGameCollision::Move(*this, physActor, dt, nullptr);
@ -2102,7 +2102,7 @@ void CStateManager::CrossTouchActors()
}
}
void CStateManager::ThinkEffectsAndActors(float dt)
void CStateManager::Think(float dt)
{
if (x84c_player->x9f4_deathTime > 0.f)
{
@ -2119,26 +2119,27 @@ void CStateManager::ThinkEffectsAndActors(float dt)
else
{
for (CEntity* ent : GetAllObjectList())
{
if (TCastToPtr<CAi> ai = ent)
{
bool doThink = !xf94_29_cinematicPause;
if (doThink && ai->GetAreaIdAlways() != kInvalidAreaId)
{
const CGameArea* area = x850_world->GetAreaAlways(ai->GetAreaIdAlways());
float f1;
float occTime;
if (area->IsPostConstructed())
f1 = area->GetPostConstructed()->x10e4_;
occTime = area->GetPostConstructed()->x10e4_occludedTime;
else
f1 = 0.f;
if (f1 > 5.f)
occTime = 0.f;
if (occTime > 5.f)
doThink = false;
}
if (doThink)
{
CEntity* ent2 = GetAllObjectList().GetObjectById(ai->GetUniqueId());
ent2->Think(dt, *this);
}
if (!doThink)
continue;
}
if (!GetCameraObjectList().GetObjectById(ent->GetUniqueId()))
ent->Think(dt, *this);
}
}
}
@ -2207,7 +2208,7 @@ void CStateManager::InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaI
UpdateRoomAcoustics(x8cc_nextAreaId);
for (CEntity* ent : GetAllObjectList())
SendScriptMsg(ent, kInvalidUniqueId, EScriptObjectMessage::InternalMessage14);
SendScriptMsg(ent, kInvalidUniqueId, EScriptObjectMessage::WorldInitialized);
for (CEntity* ent : GetAllObjectList())
{

View File

@ -336,7 +336,7 @@ public:
void MovePlatforms(float dt);
void MoveDoors(float dt);
void CrossTouchActors();
void ThinkEffectsAndActors(float dt);
void Think(float dt);
void PostUpdatePlayer(float dt);
void ShowPausedHUDMemo(CAssetId strg, float time);
void ClearGraveyard();

View File

@ -827,7 +827,7 @@ SAdvancementDeltas CAnimData::DoAdvance(float dt, bool& suspendParticles, CRando
else
{
CCharAnimTime remTime = x1f8_animRoot->VGetTimeRemaining();
while (remTime.GreaterThanZero() && !remTime.EpsilonZero())
while (!remTime.EpsilonZero() && !time.EpsilonZero())
{
x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0);
x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0);

View File

@ -3,6 +3,7 @@
#include "CInt32POINode.hpp"
#include "CParticlePOINode.hpp"
#include "CSoundPOINode.hpp"
#include "CFBStreamedAnimReader.hpp"
namespace urde
{

View File

@ -1074,7 +1074,7 @@ void CBSJump::PlayJumpLoop(CStateManager& mgr, CBodyController& bc)
if (TCastToPtr<CPhysicsActor> act = bc.GetOwner())
{
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Falling);
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::InternalMessage18);
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped);
x30_24_bodyForceSet = false;
x18_velocity = act->GetVelocity();
}
@ -1195,7 +1195,7 @@ void CBSHurled::Start(CBodyController& bc, CStateManager& mgr)
const CPASAnimState* hurledState = bc.GetPASDatabase().GetAnimState(14);
xc_animSeries = hurledState->GetAnimParmData(best.second, 0).GetInt32Value();
mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Falling);
mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::InternalMessage18);
mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Jumped);
if (!zeus::close_enough(cmd->GetLaunchVelocity(), zeus::CVector3f::skZero, 0.0001f))
if (TCastToPtr<CPhysicsActor> act = bc.GetOwner())
act->SetConstantForce(act->GetMass() * cmd->GetLaunchVelocity());
@ -1729,7 +1729,7 @@ pas::EAnimationState CBSWallHang::UpdateBody(float dt, CBodyController& bc, CSta
}
if (TCastToPtr<CPhysicsActor> act = bc.GetOwner())
{
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::InternalMessage18);
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped);
if (TCastToPtr<CActor> wp = mgr.ObjectById(x8_wpId))
{
zeus::CVector3f toWp = wp->GetTranslation() - act->GetTranslation();
@ -1837,7 +1837,7 @@ pas::EAnimationState CBSWallHang::UpdateBody(float dt, CBodyController& bc, CSta
}
if (TCastToPtr<CPhysicsActor> act = bc.GetOwner())
{
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::InternalMessage18);
mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped);
x18_24_launched = false;
if (TCastToPtr<CActor> wp = mgr.ObjectById(x8_wpId))
{

View File

@ -23,7 +23,7 @@ bool CCharAnimTime::EqualsZero() const
bool CCharAnimTime::EpsilonZero() const
{
return (std::fabs(x0_time) < FLT_EPSILON);
return (std::fabs(x0_time) < 0.00001f);
}
bool CCharAnimTime::GreaterThanZero() const

View File

@ -498,7 +498,8 @@ SAdvancementResults CFBStreamedAnimReader::VAdvanceView(const CCharAnimTime& dt)
xc_curTime = nextTime;
x7c_totals.SetTime(x108_bitLoader, xc_curTime);
UpdatePOIStates();
if (x54_source->HasPOIData())
UpdatePOIStates();
zeus::CQuaternion nextQ = GetRotation(3);
zeus::CVector3f nextV = GetOffset(3);

View File

@ -70,14 +70,15 @@ u32 _getPOIList(const CCharAnimTime& time,
return ret;
CCharAnimTime nodeTime = stream[passedCount].GetTime();
while (nodeTime <= targetTime)
while (passedCount < stream.size() && nodeTime <= targetTime)
{
u32 idx = iterator + ret;
if (idx < capacity)
listOut[idx] = T::CopyNodeMinusStartTime(stream[passedCount], curTime);
++passedCount;
++ret;
nodeTime = stream[passedCount].GetTime();
if (passedCount < stream.size())
nodeTime = stream[passedCount].GetTime();
}
}
return ret;

View File

@ -166,7 +166,7 @@ void CCollisionActor::OnScanStateChanged(CActor::EScanState state, CStateManager
void CCollisionActor::Touch(CActor& actor, CStateManager& mgr)
{
x2fc_lastTouched = actor.GetUniqueId();
mgr.SendScriptMsgAlways(x25c_owner, GetUniqueId(), EScriptObjectMessage::InternalMessage08);
mgr.SendScriptMsgAlways(x25c_owner, GetUniqueId(), EScriptObjectMessage::Touched);
}
zeus::CVector3f CCollisionActor::GetOrbitPosition(const CStateManager&) const { return GetTouchBounds()->center(); }

View File

@ -41,6 +41,7 @@ public:
virtual bool Proc()=0;
virtual void Shutdown()=0;
virtual boo::IWindow* GetMainWindow() const= 0;
virtual EFlowState GetFlowState() const = 0;
virtual void SetFlowState(EFlowState) = 0;
virtual size_t GetExpectedIdSize() const = 0;
virtual void WarmupShaders() = 0;

View File

@ -730,9 +730,9 @@ void CGameArea::UpdateWeaponWorldLighting(float dt)
void CGameArea::AliveUpdate(float dt)
{
if (x12c_postConstructed->x10dc_occlusionState == EOcclusionState::Occluded)
x12c_postConstructed->x10e4_ += dt;
x12c_postConstructed->x10e4_occludedTime += dt;
else
x12c_postConstructed->x10e4_ = 0.f;
x12c_postConstructed->x10e4_occludedTime = 0.f;
UpdateFog(dt);
UpdateThermalVisor(dt);
UpdateWeaponWorldLighting(dt);

View File

@ -238,7 +238,7 @@ public:
const CScriptAreaAttributes* x10d8_areaAttributes = nullptr;
EOcclusionState x10dc_occlusionState = EOcclusionState::Occluded;
u32 x10e0_ = 0;
float x10e4_ = 5.f;
float x10e4_occludedTime = 5.f;
u32 x10e8_ = -1;
u32 x10ec_ = 0;
// std::vector<CAramToken> x10f0_tokens;

View File

@ -121,7 +121,7 @@ void CScriptCoverPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid,
{
CActor::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::InternalMessage14)
if (msg == EScriptObjectMessage::WorldInitialized)
{
for (const SConnection& con : x20_conns)
if (con.x0_state == EScriptObjectState::Retreat)

View File

@ -106,7 +106,7 @@ void CScriptDock::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat
case EScriptObjectMessage::InitializedInArea:
AreaLoaded(mgr);
break;
case EScriptObjectMessage::InternalMessage14:
case EScriptObjectMessage::WorldInitialized:
{
UpdateAreaActivateFlags(mgr);
CMaterialList exclude = GetMaterialFilter().GetExcludeList();

View File

@ -11,31 +11,32 @@ namespace urde
bool CScriptSound::sFirstInFrame = false;
CScriptSound::CScriptSound(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
s16 soundId, bool active, float f1, float f2, float f3, u32 w1, u32 w2, u32 w3, u32 w4,
u32 w5, u32 w6, bool b1, bool b2, bool autoStart, bool b4, bool b5, bool b6, bool b7, u32 w7)
u16 soundId, bool active, float maxDist, float distComp, float startDelay, u32 minVol,
u32 vol, u32 w3, u32 prio, u32 pan, u32 w6, bool looped, bool nonEmitter, bool autoStart,
bool occlusionTest, bool acoustics, bool worldSfx, bool allowDuplicates, s32 pitch)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Unknown),
CActorParameters::None(), kInvalidUniqueId)
, xfc_(f3)
, xfc_startDelay(startDelay)
, x100_soundId(CSfxManager::TranslateSFXID(soundId))
, x104_(f1)
, x108_(f2)
, x10c_(w1)
, x10e_(w2)
, x104_maxDist(maxDist)
, x108_distComp(distComp)
, x10c_minVol(minVol / 127.f)
, x10e_vol(vol / 127.f)
, x110_(w3)
, x112_(w4)
, x114_(w5)
, x112_prio(s16(prio))
, x114_pan(pan / 64.f - 1.f)
, x116_(w6)
, x118_(w7 + 8192)
, x118_pitch(pitch / 8192.f)
{
x11c_25_ = b1;
x11c_26_ = b2;
x11c_25_looped = looped;
x11c_26_nonEmitter = nonEmitter;
x11c_27_autoStart = autoStart;
x11c_28_ = b4;
x11c_29_ = b5;
x11c_30_ = b6;
x11d_24_ = b7;
if (x11c_30_ && (!x11c_26_ || !x11c_25_))
x11c_30_ = false;
x11c_28_occlusionTest = occlusionTest;
x11c_29_acoustics = acoustics;
x11c_30_worldSfx = worldSfx;
x11d_24_allowDuplicates = allowDuplicates;
if (x11c_30_worldSfx && (!x11c_26_nonEmitter || !x11c_25_looped))
x11c_30_worldSfx = false;
}
void CScriptSound::Accept(IVisitor& visitor) { visitor.Visit(this); }
@ -44,11 +45,120 @@ void CScriptSound::PreThink(float dt, CStateManager& mgr)
{
CEntity::PreThink(dt, mgr);
sFirstInFrame = true;
x11d_25_ = false;
x11d_25_processedThisFrame = false;
}
static const CMaterialFilter kSolidFilter =
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough});
float CScriptSound::GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr)
{
zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
zeus::CVector3f soundToCam = camXf.origin - pos;
float soundToCamMag = soundToCam.magnitude();
zeus::CVector3f soundToCamNorm = soundToCam * (1.f / soundToCamMag);
zeus::CVector3f thirdEdge = zeus::CVector3f::skUp - soundToCamNorm * soundToCamNorm.dot(zeus::CVector3f::skUp);
zeus::CVector3f cross = soundToCamNorm.cross(thirdEdge);
static float kInfluenceAmount = 3.f / soundToCamMag;
static float kInfluenceIncrement = kInfluenceAmount;
int totalCount = 0;
int invalCount = 0;
float f17 = -kInfluenceAmount;
while (f17 <= kInfluenceAmount)
{
zeus::CVector3f angledDir = thirdEdge * f17 + soundToCamNorm;
float f16 = -kInfluenceAmount;
while (f16 <= kInfluenceAmount)
{
if (mgr.RayStaticIntersection(pos, (cross * f16 + angledDir).normalized(),
soundToCamMag, kSolidFilter).IsInvalid())
++invalCount;
++totalCount;
f16 += kInfluenceIncrement;
}
f17 += kInfluenceIncrement;
}
return invalCount / float(totalCount) * 0.42f + 0.58f;
}
void CScriptSound::Think(float dt, CStateManager& mgr)
{
if (x11c_31_selfFree && (!GetActive() || x11c_25_looped || !x11c_27_autoStart))
{
mgr.FreeScriptObject(GetUniqueId());
}
else if (GetActive())
{
if (!x11c_25_looped && x11c_27_autoStart && !x11c_24_playRequested &&
xec_sfxHandle && !CSfxManager::IsPlaying(xec_sfxHandle))
mgr.FreeScriptObject(GetUniqueId());
if (!x11c_26_nonEmitter && xec_sfxHandle)
{
if (xf8_updateTimer <= 0.f)
{
xf8_updateTimer = 0.25f;
CSfxManager::UpdateEmitter(xec_sfxHandle, GetTranslation(), zeus::CVector3f::skZero, xf2_maxVolUpd);
}
else
{
xf8_updateTimer -= dt;
}
}
if (xec_sfxHandle && !x11c_26_nonEmitter && x11c_28_occlusionTest)
{
if (xe8_occUpdateTimer <= 0.f && sFirstInFrame)
{
sFirstInFrame = false;
float occVol = GetOccludedVolumeAmount(GetTranslation(), mgr);
float newMaxVol = std::max(occVol * x10e_vol, x10c_minVol);
if (newMaxVol != xf0_maxVol)
{
xf0_maxVol = newMaxVol;
float delta = xf0_maxVol - xf2_maxVolUpd;
xf4_maxVolUpdDelta = delta / 10.5f;
if (xf4_maxVolUpdDelta == 0.f)
{
if (xf2_maxVolUpd < xf0_maxVol)
xf4_maxVolUpdDelta = 1.f / 127.f;
else
xf4_maxVolUpdDelta = -1.f / 127.f;
}
}
xe8_occUpdateTimer = 0.5f;
}
else
{
xe8_occUpdateTimer -= dt;
}
if (xf2_maxVolUpd != xf0_maxVol)
{
xf2_maxVolUpd += xf4_maxVolUpdDelta;
if (xf4_maxVolUpdDelta > 0.f && xf2_maxVolUpd > xf0_maxVol)
xf2_maxVolUpd = xf0_maxVol;
if (xf4_maxVolUpdDelta < 0.f && xf2_maxVolUpd < xf0_maxVol)
xf2_maxVolUpd = xf0_maxVol;
CSfxManager::UpdateEmitter(xec_sfxHandle, GetTranslation(), zeus::CVector3f::skZero, xf2_maxVolUpd);
}
}
if (x11c_24_playRequested)
{
xfc_startDelay -= dt;
if (xfc_startDelay <= 0.f)
{
x11c_24_playRequested = false;
PlaySound(mgr);
}
}
if (x118_pitch != 0.f && xec_sfxHandle)
CSfxManager::PitchBend(xec_sfxHandle, x118_pitch);
}
}
void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
@ -60,8 +170,8 @@ void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
case EScriptObjectMessage::Registered:
{
if (GetActive() && x11c_27_autoStart)
x11c_24_ = true;
x11c_31_ = mgr.GetIsGeneratingObject();
x11c_24_playRequested = true;
x11c_31_selfFree = mgr.GetIsGeneratingObject();
}
break;
case EScriptObjectMessage::Play:
@ -85,12 +195,12 @@ void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
case EScriptObjectMessage::Activate:
{
if(GetActive())
x11c_24_ = true;
x11c_24_playRequested = true;
}
break;
case EScriptObjectMessage::Deleted:
{
if (!x11c_30_)
if (!x11c_30_worldSfx)
StopSound(mgr);
}
break;
@ -98,21 +208,52 @@ void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
}
}
void CScriptSound::PlaySound(CStateManager&)
void CScriptSound::PlaySound(CStateManager& mgr)
{
if ((x11d_24_allowDuplicates || !xec_sfxHandle) && !x11d_25_processedThisFrame)
{
x11d_25_processedThisFrame = true;
if (x11c_26_nonEmitter)
{
if (!x11c_30_worldSfx || !mgr.GetWorld()->HasGlobalSound(x100_soundId))
{
xec_sfxHandle = CSfxManager::SfxStart(x100_soundId, x10e_vol, x114_pan,
x11c_29_acoustics, x112_prio, x11c_25_looped,
x11c_30_worldSfx ? kInvalidAreaId : GetAreaIdAlways());
if (x11c_30_worldSfx)
mgr.WorldNC()->AddGlobalSound(xec_sfxHandle);
}
}
else
{
float occVol = x11c_28_occlusionTest ? GetOccludedVolumeAmount(GetTranslation(), mgr) : 1.f;
xf0_maxVol = xf2_maxVolUpd = x10e_vol * occVol;
CAudioSys::C3DEmitterParmData data = {};
data.x0_pos = GetTranslation();
data.x18_maxDist = x104_maxDist;
data.x1c_distComp = x108_distComp;
data.x20_flags = 1; // Continuous parameter update
data.x24_sfxId = x100_soundId;
data.x26_maxVol = xf0_maxVol;
data.x27_minVol = x10c_minVol;
data.x29_prio = 0x7f;
xec_sfxHandle = CSfxManager::AddEmitter(data, x11c_29_acoustics, x112_prio,
x11c_25_looped, GetAreaIdAlways());
}
}
}
void CScriptSound::StopSound(CStateManager& mgr)
{
x11c_24_ = false;
if (x11c_30_ && x11c_26_)
x11c_24_playRequested = false;
if (x11c_30_worldSfx && x11c_26_nonEmitter)
{
mgr.WorldNC()->StopSound(x100_soundId);
mgr.WorldNC()->StopGlobalSound(x100_soundId);
xec_sfxHandle.reset();
}
else if (xec_sfxHandle)
{
CSfxManager::RemoveEmitter(*xec_sfxHandle.get());
CSfxManager::RemoveEmitter(xec_sfxHandle);
xec_sfxHandle.reset();
}
}

View File

@ -10,50 +10,54 @@ class CScriptSound : public CActor
{
static bool sFirstInFrame;
float xe8_ = 0.f;
std::unique_ptr<CSfxHandle> xec_sfxHandle;
s16 xf0_ = 0;
s16 xf4_ = 0;
float xf8_ = 0.f;
float xfc_;
s16 x100_soundId;
float x104_;
float x108_;
s16 x10c_;
s16 x10e_;
float xe8_occUpdateTimer = 0.f;
CSfxHandle xec_sfxHandle;
float xf0_maxVol = 0.f;
float xf2_maxVolUpd = 0.f;
float xf4_maxVolUpdDelta = 0.f;
float xf8_updateTimer = 0.f;
float xfc_startDelay;
u16 x100_soundId;
float x104_maxDist;
float x108_distComp;
float x10c_minVol;
float x10e_vol;
s16 x110_;
s16 x112_;
s16 x114_;
s16 x112_prio;
float x114_pan;
bool x116_;
u32 x118_;
float x118_pitch;
union
{
struct
{
bool x11c_24_ : 1;
bool x11c_25_ : 1;
bool x11c_26_ : 1;
bool x11c_24_playRequested : 1;
bool x11c_25_looped : 1;
bool x11c_26_nonEmitter : 1;
bool x11c_27_autoStart : 1;
bool x11c_28_ : 1;
bool x11c_29_ : 1;
bool x11c_30_ : 1;
bool x11c_31_ : 1;
bool x11d_24_ : 1;
bool x11d_25_ : 1;
bool x11c_28_occlusionTest : 1;
bool x11c_29_acoustics : 1;
bool x11c_30_worldSfx : 1;
bool x11c_31_selfFree : 1;
bool x11d_24_allowDuplicates : 1;
bool x11d_25_processedThisFrame : 1;
};
u32 x11c_dummy = 0;
};
static float GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr);
public:
CScriptSound(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, s16 soundId,
bool, float, float, float, u32, u32, u32, u32, u32, u32, bool, bool, bool, bool, bool, bool, bool, u32);
CScriptSound(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
u16 soundId, bool active, float maxDist, float distComp, float startDelay, u32 minVol,
u32 vol, u32 w3, u32 prio, u32 pan, u32 w6, bool looped, bool nonEmitter, bool autoStart,
bool occlusionTest, bool acoustics, bool worldSfx, bool allowDuplicates, s32 pitch);
void Accept(IVisitor& visitor);
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {}
void PreThink(float, CStateManager&);
void Think(float, CStateManager&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void GetOccludedVolumeAmount(const zeus::CVector3f&, const CStateManager&);
void PlaySound(CStateManager&);
void StopSound(CStateManager&);
};

View File

@ -6,6 +6,9 @@
#include "CGameState.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "World/CScriptAreaAttributes.hpp"
#include "IMain.hpp"
#include "Audio/CStreamAudioManager.hpp"
#include "CScriptRoomAcoustics.hpp"
namespace urde
{
@ -175,8 +178,6 @@ bool CDummyWorld::ICheckWorldComplete()
default:
return false;
}
return false;
}
std::string CDummyWorld::IGetDefaultAudioTrack() const { return {}; }
@ -192,6 +193,18 @@ CWorld::CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId)
resFactory.LoadResourceAsync(tag, x40_loadBuf.get());
}
CWorld::~CWorld()
{
StopSounds();
if (g_GameState->GetWorldTransitionManager()->IsTransitionEnabled() &&
g_Main->GetFlowState() == EFlowState::None)
CStreamAudioManager::StopOneShot();
else
CStreamAudioManager::StopAll();
UnloadSoundGroups();
CScriptRoomAcoustics::DisableAuxCallbacks();
}
CAssetId CWorld::IGetWorldAssetId() const { return x8_mlvlId; }
CAssetId CWorld::IGetStringTableAssetId() const { return xc_strgId; }
@ -242,10 +255,35 @@ void CWorld::MoveAreaToAliveChain(TAreaId aid)
MoveToChain(x18_areas[aid].get(), EChain::Alive);
}
void CWorld::LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data) {}
void CWorld::LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data)
{
if (!CAudioSys::SysLoadGroupSet(g_SimplePool, agscId))
{
auto name = CAudioSys::SysGetGroupSetName(agscId);
CAudioSys::SysAddGroupIntoAmuse(name);
data.xc_name = name;
++x6c_loadedAudioGrpCount;
}
}
void CWorld::LoadSoundGroups() {}
void CWorld::UnloadSoundGroups()
{
for (CSoundGroupData& data : x74_soundGroupData)
{
CAudioSys::SysRemoveGroupFromAmuse(data.xc_name);
CAudioSys::SysUnloadAudioGroupSet(data.xc_name);
}
}
void CWorld::StopSounds()
{
for (CSfxHandle& hnd : xc8_globalSfxHandles)
CSfxManager::RemoveEmitter(hnd);
xc8_globalSfxHandles.clear();
}
bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId)
{
if (mreaId.IsValid())
@ -654,12 +692,10 @@ void CWorld::PreRender()
void CWorld::TouchSky()
{
#if 0
if (xa4_skyboxB.IsLoaded())
xa4_skyboxB->Touch();
if (xb4_skyboxC.IsLoaded())
xb4_skyboxC->Touch();
#endif
if (xa4_skyboxWorldLoaded.IsLoaded())
xa4_skyboxWorldLoaded->Touch(0);
if (xb4_skyboxOverride.IsLoaded())
xb4_skyboxOverride->Touch(0);
}
void CWorld::DrawSky(const zeus::CTransform& xf) const
@ -686,7 +722,28 @@ void CWorld::DrawSky(const zeus::CTransform& xf) const
CGraphics::SetDepthRange(0.125f, 1.f);
}
void CWorld::StopSound(s16)
void CWorld::StopGlobalSound(u16 id)
{
auto search = std::find_if(xc8_globalSfxHandles.begin(), xc8_globalSfxHandles.end(),
[id](CSfxHandle& hnd) { return hnd->GetSfxId() == id; });
if (search != xc8_globalSfxHandles.end())
{
CSfxManager::RemoveEmitter(*search);
xc8_globalSfxHandles.erase(search);
}
}
bool CWorld::HasGlobalSound(u16 id) const
{
auto search = std::find_if(xc8_globalSfxHandles.begin(), xc8_globalSfxHandles.end(),
[id](const CSfxHandle& hnd) { return hnd->GetSfxId() == id; });
return search != xc8_globalSfxHandles.end();
}
void CWorld::AddGlobalSound(const CSfxHandle& hnd)
{
if (xc8_globalSfxHandles.size() >= xc8_globalSfxHandles.capacity())
return;
xc8_globalSfxHandles.push_back(hnd);
}
}

View File

@ -129,7 +129,7 @@ private:
IObjectStore& x60_objectStore;
IFactory& x64_resFactory;
TAreaId x68_curAreaId = kInvalidAreaId;
u32 x6c_ = 0;
u32 x6c_loadedAudioGrpCount = 0;
union
{
@ -148,10 +148,12 @@ private:
TLockedToken<CModel> xa4_skyboxWorldLoaded;
TLockedToken<CModel> xb4_skyboxOverride;
EEnvFxType xc4_neededFx = EEnvFxType::None;
std::vector<CSfxHandle> xc8_sfxHandles;
rstl::reserved_vector<CSfxHandle, 10> xc8_globalSfxHandles;
void LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data);
void LoadSoundGroups();
void UnloadSoundGroups();
void StopSounds();
public:
@ -169,6 +171,7 @@ public:
void SetPauseState(bool paused);
CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId);
~CWorld();
bool DoesAreaExist(TAreaId area) const;
const std::vector<std::unique_ptr<CGameArea>>& GetGameAreas() const { return x18_areas; }
@ -200,7 +203,9 @@ public:
void PreRender();
void TouchSky();
void DrawSky(const zeus::CTransform& xf) const;
void StopSound(s16);
void StopGlobalSound(u16 id);
bool HasGlobalSound(u16 id) const;
void AddGlobalSound(const CSfxHandle& hnd);
EEnvFxType GetNeededEnvFx() const { return xc4_neededFx; }
};

View File

@ -667,28 +667,28 @@ CEntity* ScriptLoader::LoadSound(CStateManager& mgr, CInputStream& in, int propC
SActorHead head = LoadActorHead(in, mgr);
s32 soundId = in.readInt32Big();
bool active = in.readBool();
float maxDistance = in.readFloatBig();
float minDistance = in.readFloatBig();
float f3 = in.readFloatBig();
u32 priority = in.readUint32Big();
u32 maxVolume = in.readUint32Big();
u32 minVolume = in.readUint32Big();
u32 panning = in.readUint32Big();
float maxDist = in.readFloatBig();
float distComp = in.readFloatBig();
float startDelay = in.readFloatBig();
u32 minVol = in.readUint32Big();
u32 vol = in.readUint32Big();
u32 prio = in.readUint32Big();
u32 pan = in.readUint32Big();
bool loop = in.readBool();
bool persistent = in.readBool();
bool triggered = in.readBool();
bool b4 = in.readBool();
bool roomAcoustic = in.readBool();
bool b6 = in.readBool();
bool b7 = in.readBool();
u32 w5 = in.readUint32Big();
bool nonEmitter = in.readBool();
bool autoStart = in.readBool();
bool occlusionTest = in.readBool();
bool acoustics = in.readBool();
bool worldSfx = in.readBool();
bool allowDuplicates = in.readBool();
u32 pitch = in.readUint32Big();
if (soundId < 0)
return nullptr;
return new CScriptSound(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, soundId, active,
maxDistance, minDistance, f3, priority, maxVolume, 0, minVolume, panning, 0, loop,
persistent, triggered, b4, roomAcoustic, b6, b7, w5);
return new CScriptSound(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, u16(soundId), active,
maxDist, distComp, startDelay, minVol, vol, 0, prio, pan, 0, loop,
nonEmitter, autoStart, occlusionTest, acoustics, worldSfx, allowDuplicates, pitch);
}
CEntity* ScriptLoader::LoadGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)

View File

@ -216,17 +216,17 @@ std::string_view ScriptObjectMessageToStr(EScriptObjectMessage message)
case EScriptObjectMessage::OnIceSurface: return "OnIceSurface"sv;
case EScriptObjectMessage::OnMudSlowSurface: return "OnMudSlowSurface"sv;
case EScriptObjectMessage::OnNormalSurface: return "OnNormalSurface"sv;
case EScriptObjectMessage::InternalMessage08: return "InternalMessage08"sv;
case EScriptObjectMessage::Touched: return "Touched"sv;
case EScriptObjectMessage::AddPlatformRider: return "AddPlatformRider"sv;
case EScriptObjectMessage::LandOnNotFloor: return "LandOnNotFloor"sv;
case EScriptObjectMessage::Registered: return "Registered"sv;
case EScriptObjectMessage::Deleted: return "Deleted"sv;
case EScriptObjectMessage::InitializedInArea: return "InitializedInArea"sv;
case EScriptObjectMessage::InternalMessage14: return "InternalMessage14"sv;
case EScriptObjectMessage::WorldInitialized: return "WorldInitialized"sv;
case EScriptObjectMessage::AddSplashInhabitant: return "AddSplashInhabitant"sv;
case EScriptObjectMessage::UpdateSplashInhabitant: return "UpdateSplashInhabitant"sv;
case EScriptObjectMessage::RemoveSplashInhabitant: return "RemoveSplashInhabitant"sv;
case EScriptObjectMessage::InternalMessage18: return "InternalMessage18"sv;
case EScriptObjectMessage::Jumped: return "Jumped"sv;
case EScriptObjectMessage::Damage: return "Damage"sv;
case EScriptObjectMessage::InvulnDamage: return "InvulnDamage"sv;
case EScriptObjectMessage::ProjectileCollide: return "ProjectileCollide"sv;
@ -234,7 +234,7 @@ std::string_view ScriptObjectMessageToStr(EScriptObjectMessage message)
case EScriptObjectMessage::AddPhazonPoolInhabitant: return "AddPhazonPoolInhabitant"sv;
case EScriptObjectMessage::UpdatePhazonPoolInhabitant: return "UpdatePhazonPoolInhabitant"sv;
case EScriptObjectMessage::RemovePhazonPoolInhabitant: return "RemovePhazonPoolInhabitant"sv;
case EScriptObjectMessage::InternalMessage26: return "InternalMessage26"sv;
case EScriptObjectMessage::SuspendedMove: return "SuspendedMove"sv;
default: return "..."sv;
}
}

View File

@ -209,17 +209,17 @@ enum class EScriptObjectMessage
OnIceSurface = 27,
OnMudSlowSurface = 28,
OnNormalSurface = 29,
InternalMessage08 = 30,
Touched = 30,
AddPlatformRider = 31,
LandOnNotFloor = 32,
Registered = 33,
Deleted = 34,
InitializedInArea = 35,
InternalMessage14 = 36,
WorldInitialized = 36,
AddSplashInhabitant = 37,
UpdateSplashInhabitant = 38,
RemoveSplashInhabitant = 39,
InternalMessage18 = 40,
Jumped = 40,
Damage = 41,
InvulnDamage = 42,
ProjectileCollide = 43,
@ -227,7 +227,7 @@ enum class EScriptObjectMessage
AddPhazonPoolInhabitant = 45,
UpdatePhazonPoolInhabitant = 46,
RemovePhazonPoolInhabitant = 47,
InternalMessage26 = 48
SuspendedMove = 48
};
#ifndef NDEBUG

2
amuse

@ -1 +1 @@
Subproject commit cab740210479ae8f5090ec847dfc4dd76c816dac
Subproject commit ebe6f18898411aa8fa6aa6f5556333e463bbfff9