From 81ea6f0258895e9087e0cb89cbd8bd30346974e2 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 13 May 2020 11:38:05 +0300 Subject: [PATCH 001/148] ped attractor: start --- src/core/FileLoader.cpp | 14 +- src/math/Matrix.h | 3 +- src/peds/Ped.cpp | 6 +- src/peds/Ped.h | 48 +++- src/peds/PedAttactor.cpp | 559 +++++++++++++++++++++++++++++++++++++++ src/peds/PedAttractor.h | 188 +++++++++++++ src/render/2dEffect.h | 9 +- 7 files changed, 813 insertions(+), 14 deletions(-) create mode 100644 src/peds/PedAttactor.cpp create mode 100644 src/peds/PedAttractor.h diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 09c62c35..aaa13c56 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -956,7 +956,7 @@ CFileLoader::LoadCarPathNode(const char *line, int id, int node, bool waterPath) void CFileLoader::Load2dEffect(const char *line) { - int id, r, g, b, a, type; + int id, r, g, b, a, type, ptype; float x, y, z; char corona[32], shadow[32]; int shadowIntens, lightType, roadReflection, flare, flags, probability; @@ -1029,6 +1029,18 @@ CFileLoader::Load2dEffect(const char *line) effect->attractor.flags = flags; effect->attractor.probability = probability; break; + case EFFECT_PED_ATTRACTOR: + sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f", + &id, &x, &y, &z, &r, &g, &b, &a, &type, + &ptype, + &effect->pedattr.useDir.x, + &effect->pedattr.useDir.y, + &effect->pedattr.useDir.z, + &effect->pedattr.queueDir.x, + &effect->pedattr.queueDir.y, + &effect->pedattr.queueDir.z); + effect->pedattr.type = ptype; + break; } CTxdStore::PopCurrentTxd(); diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 35972e7f..f2d228a4 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -78,7 +78,8 @@ public: return *this; } - CVector &GetPosition(void){ return *(CVector*)&m_matrix.pos; } + const CVector &GetPosition(void) const { return *(CVector*)&m_matrix.pos; } + CVector& GetPosition(void) { return *(CVector*)&m_matrix.pos; } CVector &GetRight(void) { return *(CVector*)&m_matrix.right; } CVector &GetForward(void) { return *(CVector*)&m_matrix.up; } CVector &GetUp(void) { return *(CVector*)&m_matrix.at; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 65bd168e..a73c4bba 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -459,6 +459,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_vecOffsetSeek.x = 0.0f; m_vecOffsetSeek.y = 0.0f; m_vecOffsetSeek.z = 0.0f; + m_attractor = nil; + m_positionInQueue = -1; m_pedFormation = FORMATION_UNDEFINED; m_collidingThingTimer = 0; m_nPedStateTimer = 0; @@ -12658,8 +12660,8 @@ CPed::ProcessObjective(void) case OBJECTIVE_FOLLOW_CAR_IN_CAR: case OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE: case OBJECTIVE_DESTROY_OBJ: - case OBJECTIVE_23: - case OBJECTIVE_24: + case OBJECTIVE_26: + case OBJECTIVE_27: case OBJECTIVE_SET_LEADER: break; case OBJECTIVE_IDLE: diff --git a/src/peds/Ped.h b/src/peds/Ped.h index ccffc3cb..d8df1f49 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -19,6 +19,7 @@ class CObject; class CFire; struct AnimBlendFrameData; class CAnimBlendAssociation; +class CPedAttractor; struct PedAudioData { @@ -154,6 +155,7 @@ enum eWaitState { enum eObjective : uint32 { OBJECTIVE_NONE, OBJECTIVE_IDLE, + OBJ_2, OBJECTIVE_FLEE_TILL_SAFE, OBJECTIVE_GUARD_SPOT, OBJECTIVE_GUARD_AREA, // not implemented @@ -165,6 +167,8 @@ enum eObjective : uint32 { OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, OBJECTIVE_GOTO_CHAR_ON_FOOT, OBJECTIVE_FOLLOW_PED_IN_FORMATION, + OBJ_14, + OBJ_15, OBJECTIVE_LEAVE_VEHICLE, OBJECTIVE_ENTER_CAR_AS_PASSENGER, OBJECTIVE_ENTER_CAR_AS_DRIVER, @@ -175,8 +179,8 @@ enum eObjective : uint32 { OBJECTIVE_GOTO_AREA_ANY_MEANS, OBJECTIVE_GOTO_AREA_ON_FOOT, OBJECTIVE_RUN_TO_AREA, - OBJECTIVE_23, // not implemented - OBJECTIVE_24, // not implemented + OBJECTIVE_26, // not implemented + OBJECTIVE_27, // not implemented OBJECTIVE_FIGHT_CHAR, OBJECTIVE_SET_LEADER, OBJECTIVE_FOLLOW_ROUTE, @@ -185,11 +189,32 @@ enum eObjective : uint32 { OBJECTIVE_CATCH_TRAIN, OBJECTIVE_BUY_ICE_CREAM, OBJECTIVE_STEAL_ANY_CAR, + OBJ_36, OBJECTIVE_MUG_CHAR, - OBJECTIVE_FLEE_CAR, -#ifdef VC_PED_PORTS - OBJECTIVE_LEAVE_CAR_AND_DIE -#endif + OBJECTIVE_LEAVE_CAR_AND_DIE, + OBJECTIVE_USE_SEAT_ATTRACTOR, + OBJECTIVE_USE_ATM_ATTRACTOR, + OBJECTIVE_FLEE_CAR, // is it 41? + OBJ_42, + OBJECTIVE_USE_STOP_ATTRACTOR, + OBJECTIVE_USE_PIZZA_ATTRACTOR, + OBJECTIVE_USE_SHELTER_ATTRACTOR, + OBJ_46, + OBJ_47, + OBJ_48, + OBJ_49, + OBJ_50, + OBJ_51, + OBJ_52, + OBJECTIVE_USE_ICECREAM_ATTRACTOR, + OBJ_53, + OBJ_54, + OBJ_55, + OBJ_56, + OBJ_57, + OBJ_58, + OBJ_59 + }; enum { @@ -389,9 +414,10 @@ public: uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle - uint32 bCarPassenger : 1; - uint32 bMiamiViceCop : 1; // - uint32 bDeadPedInFrontOfCar : 1; + uint32 bHasAlreadyUsedAttractor : 1; // 0x155 0x1 + uint32 bCarPassenger : 1; // 0x155 0x4 + uint32 bMiamiViceCop : 1; // 0x155 0x20 + uint32 bDeadPedInFrontOfCar : 1; // 0x156 0x40 uint8 CharCreatedBy; eObjective m_objective; @@ -457,6 +483,8 @@ public: bool bInVehicle; float m_distanceToCountSeekDone; + CPedAttractor* m_attractor; + int32 m_positionInQueue; CVehicle* m_vehicleInAccident; bool bRunningToPhone; @@ -793,6 +821,8 @@ public: bool CanPedJumpThis(CEntity*); #endif + void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int); + bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp new file mode 100644 index 00000000..9e3e6ae4 --- /dev/null +++ b/src/peds/PedAttactor.cpp @@ -0,0 +1,559 @@ +#include "common.h" +#include "PedAttractor.h" + +#include "General.h" +#include "Vehicle.h" + +const int gcMaxSizeOfAtmQueue = 1; +const int gcMaxSizeOfShelterQueue = 5; + +CPedAttractorManager* GetPedAttractorManager() +{ + static CPedAttractorManager manager; + return &manager; +} + +CVehicleToEffect::CVehicleToEffect(CVehicle* pVehicle) : m_pVehicle(pVehicle) +{ + m_effects[1].col = CRGBA(0, 0, 0, 0); + m_effects[1].type = EFFECT_PED_ATTRACTOR; + m_effects[1].pos = CVector(2.0f, 1.0f, 0.0f); + m_effects[1].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f); + m_effects[1].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f); + m_effects[1].pedattr.type = ATTRACTOR_ICECREAM; + + m_effects[3].col = CRGBA(0, 0, 0, 0); + m_effects[3].type = EFFECT_PED_ATTRACTOR; + m_effects[3].pos = CVector(2.0f, -0.5f, 0.0f); + m_effects[3].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f); + m_effects[3].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f); + m_effects[3].pedattr.type = ATTRACTOR_ICECREAM; + + m_effects[0].col = CRGBA(0, 0, 0, 0); + m_effects[0].type = EFFECT_PED_ATTRACTOR; + m_effects[0].pos = CVector(-2.0f, 1.0f, 0.0f); + m_effects[0].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f); + m_effects[0].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f); + m_effects[0].pedattr.type = ATTRACTOR_ICECREAM; + + m_effects[2].col = CRGBA(0, 0, 0, 0); + m_effects[2].type = EFFECT_PED_ATTRACTOR; + m_effects[2].pos = CVector(-2.0f, -0.5f, 0.0f); + m_effects[2].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f); + m_effects[2].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f); + m_effects[2].pedattr.type = ATTRACTOR_ICECREAM; +} + +CVehicleToEffect& CVehicleToEffect::From(const CVehicleToEffect& other) +{ + m_pVehicle = other.m_pVehicle; + for (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) { + m_effects[i].col = other.m_effects[i].col; + m_effects[i].type = other.m_effects[i].type; + m_effects[i].pos = other.m_effects[i].pos; + m_effects[i].pedattr = other.m_effects[i].pedattr; + } + return *this; +} + +const C2dEffect* CVehicleToEffect::ChooseEffect(const CVector& pos) const +{ + if (!m_pVehicle) + return nil; + if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetRight()) > 0.0f) { + if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f) + return &m_effects[0]; + else + return &m_effects[2]; + } + else { + if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f) + return &m_effects[1]; + else + return &m_effects[3]; + } +} + +bool CVehicleToEffect::HasThisEffect(C2dEffect* pEffect) const +{ + for (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) { + if (pEffect == &m_effects[i]) + return true; + } + return false; +} + +const C2dEffect* CPedAttractorManager::GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos) +{ + if (!vVehicleToEffect.empty()) { + for (std::vector::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) { + if (assoc->GetVehicle() == pVehicle) + return assoc->ChooseEffect(pos); + } + } + CVehicleToEffect effect(pVehicle); + vVehicleToEffect.push_back(effect); + return effect.ChooseEffect(pos); +} + +CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect) +{ + if (vVehicleToEffect.empty()) + return false; + for (std::vector::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) { + if (assoc->HasThisEffect(pEffect)) + return assoc->GetVehicle(); + } + return nil; +} + +const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector vecAttractors) +{ + if (vecAttractors.empty()) + return nil; + for (std::vector::const_iterator attractor = vecAttractors.cbegin(); attractor != vecAttractors.cend(); ++attractor) { + if ((*attractor)->GetEffect() == pEffect) + return *attractor; + } + return nil; +} + +void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect) +{ + CVehicle* pVehicle = GetIceCreamVanForEffect(pEffect); + if (!pVehicle) + return; + if (vVehicleToEffect.empty()) + return; + for (std::vector::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend();) { + if (assoc->GetVehicle() != pVehicle) + return; + size_t total = 0; + for (size_t j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) { + if (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors)) + total++; + } + if (total > 0) + assoc++; + else + assoc = vVehicleToEffect.erase(assoc); + } +} + +CPedAttractor::CPedAttractor(C2dEffect* pEffect, CMatrix const& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + p2dEffect(p2dEffect), + m_nMaxPedsInAttractor(maxpeds), + m_fQueueDistance(qdist), + m_fTimeInWaitQueue(waitTime), + m_fTimeInApproachingQueue(approachTime), + field_30(unk8), + field_34(unk9), + m_fMaxPositionDisplacement(posdisp), + m_fMaxHeadingDisplacement(headdisp), + vecEffectPos(Multiply3x3(matrix, pEffect->pos)), + vecQueueDir(Multiply3x3(matrix, pEffect->pedattr.queueDir)), + vecUseDir(Multiply3x3(matrix, pEffect->pedattr.useDir)) +{} + +float CPedAttractor::ComputeDeltaHeading() const +{ + return CGeneral::GetRandomNumberInRange(-m_fMaxHeadingDisplacement, m_fMaxHeadingDisplacement); +} + +float CPedAttractor::ComputeDeltaPos() const +{ + return CGeneral::GetRandomNumberInRange(-m_fMaxPositionDisplacement, m_fMaxPositionDisplacement); +} + +void CPedAttractor::ComputeAttractTime(int32 id, bool approacher, float& time) const +{ + if (approacher) + time = m_fTimeInApproachingQueue; + else + time = m_fTimeInWaitQueue; +} + +void CPedAttractor::ComputeAttractPos(int32 qid, CVector& pos) const +{ + if (!p2dEffect) + return; + pos = vecEffectPos - qid * vecQueueDir * m_fQueueDistance; + if (qid != 0) { + pos.x += ComputeDeltaPos(); + pos.y += ComputeDeltaPos(); + } +} + +CVector CPedShelterAttractor::GetDisplacement(int32 qid) +{ + if (ms_displacements.empty()) { + int i = 0; + while (i < gcMaxSizeOfShelterQueue) { + float fRandomAngle = CGeneral::GetRandomNumberInRange(0.0f, TWOPI); + float fRandomOffset = CGeneral::GetRandomNumberInRange(0.0f, 2.0f); + CVector vecDisplacement(fRandomOffset * Sin(fRandomAngle), fRandomOffset * Cos(fRandomAngle), 0.0f); + bool close = false; + for (std::vector::const_iterator v = ms_displacements.cbegin(); v != ms_displacements.cend(); ++v) { + if ((*v - vecDisplacement).Magnitude() < 1.0f) { + close = true; + break; + } + } + if (!close) { + ms_displacements.push_back(vecDisplacement); + i++; + } + } + } + return ms_displacements[qid]; +} + +void CPedAttractor::ComputeAttractHeading(int32 qid, float& heading) const +{ + heading = CGeneral::GetRadianAngleBetweenPoints(qid != 0 ? vecQueueDir.x : vecUseDir.x, qid != 0 ? vecQueueDir.y : vecUseDir.y, 0.0f, 0.0f); + if (qid != 0) + heading += ComputeDeltaHeading(); +} + +void CPedShelterAttractor::ComputeAttractHeading(int32 qid, float& heading) const +{ + heading = CGeneral::GetRandomNumberInRange(0.0f, TWOPI); +} + +bool CPedAttractor::RegisterPed(CPed* pPed) +{ + for (std::vector::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) { + if (*pPedIt == pPed) { + vApproachingQueue.erase(pPedIt); + return false; + } + } + if (GetNoOfRegisteredPeds() >= m_nMaxPedsInAttractor) + return 0; + vApproachingQueue.push_back(pPed); + CVector pos; + float heading; + float time; + int32 slot = ComputeFreeSlot(); + ComputeAttractPos(slot, pos); + ComputeAttractHeading(slot, heading); + ComputeAttractTime(slot, false, time); + pPed->SetNewAttraction(this, pos, heading, time, slot); + return true; +} + +static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed) +{ + switch (type) { + case ATTRACTOR_ATM: + if (pPed->m_objective == OBJECTIVE_USE_ATM_ATTRACTOR) + return true; + break; + case ATTRACTOR_SEAT: + if (pPed->m_objective == OBJECTIVE_USE_SEAT_ATTRACTOR) + return true; + break; + case ATTRACTOR_STOP: + if (pPed->m_objective == OBJECTIVE_USE_STOP_ATTRACTOR || pPed->m_objective == OBJ_52 || pPed->m_objective == OBJECTIVE_IDLE) + return true; + break; + case ATTRACTOR_PIZZA: + if (pPed->m_objective == OBJECTIVE_USE_PIZZA_ATTRACTOR || pPed->m_objective == OBJECTIVE_IDLE) + return true; + break; + case ATTRACTOR_SHELTER: + if (pPed->m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR || pPed->m_objective == OBJ_48) + return true; + break; + case ATTRACTOR_ICECREAM: + if (pPed->m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR || pPed->m_objective == OBJ_54) + return true; + break; + } + return false; +} + +bool CPedAttractor::DeRegisterPed(CPed* pPed) +{ + for (std::vector::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) { + if (*pPedIt != pPed) + continue; + pPed->m_attractor = nil; + pPed->m_positionInQueue = -1; + pPed->bHasAlreadyUsedAttractor = true; + + if (IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) + pPed->SetObjective(OBJECTIVE_NONE); + else if (pPed->GetPedState() != PED_IDLE && pPed->GetPedState() != PED_NONE) { + vApproachingQueue.erase(pPedIt); + return true; + } + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y)); + return true; + } + return BroadcastDeparture(pPed); +} + +bool CPedAttractor::BroadcastArrival(CPed* pPed) +{ + for (std::vector::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) { + if (*pPedIt == pPed) + return false; + } + vWaitingQueue.push_back(pPed); + for (std::vector::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) { + if (*pPedIt == pPed) { + vApproachingQueue.erase(pPedIt); + break; + } + } + for (std::vector::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) { + CPed* pPed = *pPedIt; + CVector pos; + float heading; + float time; + int32 slot = ComputeFreeSlot(); + ComputeAttractPos(slot, pos); + ComputeAttractHeading(slot, heading); + ComputeAttractTime(slot, false, time); + pPed->SetNewAttraction(this, pos, heading, time, slot); + } + return true; +} + +bool CPedAttractor::BroadcastDeparture(CPed* pPed) +{ + int qid = -1; + for (size_t i = 0; i < vWaitingQueue.size(); i++){ + if (vWaitingQueue[i] == pPed) + qid = i; + } + if (qid < 0) + return false; + for (size_t i = qid + 1; i < vWaitingQueue.size(); i++) { + CVector pos; + float heading; + float time; + ComputeAttractPos(i - 1, pos); + ComputeAttractHeading(i - 1, heading); + ComputeAttractTime(i - 1, true, time); + pPed->SetNewAttraction(this, pos, heading, time, i - 1); + } + pPed->m_attractor = nil; + pPed->m_positionInQueue = -1; + pPed->bHasAlreadyUsedAttractor = true; + if (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) { + if (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE) + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y)); + } + else if (qid == 0) + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y)); + else if (qid == vWaitingQueue.size() - 1) + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y)); + else + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.z)); + vWaitingQueue.erase(vWaitingQueue.cbegin() + qid); + for (std::vector::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) { + CPed* pPed = *pPedIt; + CVector pos; + float heading; + float time; + int32 slot = ComputeFreeSlot(); + ComputeAttractPos(slot, pos); + ComputeAttractHeading(slot, heading); + ComputeAttractTime(slot, false, time); + pPed->SetNewAttraction(this, pos, heading, time, slot); + } + return true; +} + +bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed) +{ + int qid = -1; + for (size_t i = 0; i < vWaitingQueue.size(); i++) { + if (vWaitingQueue[i] == pPed) + qid = i; + } + if (qid < 0) + return false; + pPed->m_attractor = nil; + pPed->m_positionInQueue = -1; + pPed->bHasAlreadyUsedAttractor = true; + if (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) { + if (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE) + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y)); + } + else if (qid == 0) + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y)); + else if (qid == vWaitingQueue.size() - 1) + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y)); + else + pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.z)); + vWaitingQueue.erase(vWaitingQueue.cbegin() + qid); + for (std::vector::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) { + CPed* pPed = *pPedIt; + CVector pos; + float heading; + float time; + int32 slot = ComputeFreeSlot(); + ComputeAttractPos(slot, pos); + ComputeAttractHeading(slot, heading); + ComputeAttractTime(slot, false, time); + pPed->SetNewAttraction(this, pos, heading, time, slot); + } + return true; +} + +CPedAttractor* CPedAttractorManager::RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix) +{ + if (pEffect->type != EFFECT_PED_ATTRACTOR) + return nil; + if (IsPedRegisteredWithEffect(pPed)) + return nil; + switch (pEffect->pedattr.type) { + case ATTRACTOR_ATM: return RegisterPed(pPed, pEffect, matrix, vAtmAttractors); + case ATTRACTOR_SEAT: return RegisterPed(pPed, pEffect, matrix, vSeatAttractors); + case ATTRACTOR_STOP: return RegisterPed(pPed, pEffect, matrix, vStopAttractors); + case ATTRACTOR_PIZZA: return RegisterPed(pPed, pEffect, matrix, vPizzaAttractors); + case ATTRACTOR_SHELTER: return RegisterPed(pPed, pEffect, matrix, vShelterAttractors); + case ATTRACTOR_ICECREAM: return RegisterPed(pPed, pEffect, matrix, vIceCreamAttractors); + } + return nil; +} + +bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor) +{ + if (!pAttractor) + return false; + if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) + return nil; + if (IsPedRegisteredWithEffect(pPed)) + return nil; + switch (pAttractor->GetEffect()->pedattr.type) { + case ATTRACTOR_ATM: return DeRegisterPed(pPed, pAttractor, vAtmAttractors); + case ATTRACTOR_SEAT: return DeRegisterPed(pPed, pAttractor, vSeatAttractors); + case ATTRACTOR_STOP: return DeRegisterPed(pPed, pAttractor, vStopAttractors); + case ATTRACTOR_PIZZA: return DeRegisterPed(pPed, pAttractor, vPizzaAttractors); + case ATTRACTOR_SHELTER: return DeRegisterPed(pPed, pAttractor, vShelterAttractors); + case ATTRACTOR_ICECREAM: return DeRegisterPed(pPed, pAttractor, vIceCreamAttractors); + } + return nil; +} + +bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor) +{ + if (!pAttractor) + return false; + if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) + return nil; + if (IsPedRegisteredWithEffect(pPed)) + return nil; + switch (pAttractor->GetEffect()->pedattr.type) { + case ATTRACTOR_ATM: return BroadcastArrival(pPed, pAttractor, vAtmAttractors); + case ATTRACTOR_SEAT: return BroadcastArrival(pPed, pAttractor, vSeatAttractors); + case ATTRACTOR_STOP: return BroadcastArrival(pPed, pAttractor, vStopAttractors); + case ATTRACTOR_PIZZA: return BroadcastArrival(pPed, pAttractor, vPizzaAttractors); + case ATTRACTOR_SHELTER: return BroadcastArrival(pPed, pAttractor, vShelterAttractors); + case ATTRACTOR_ICECREAM: return BroadcastArrival(pPed, pAttractor, vIceCreamAttractors); + } + return nil; +} + +bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor) +{ + if (!pAttractor) + return false; + if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) + return nil; + if (IsPedRegisteredWithEffect(pPed)) + return nil; + switch (pAttractor->GetEffect()->pedattr.type) { + case ATTRACTOR_ATM: return BroadcastDeparture(pPed, pAttractor, vAtmAttractors); + case ATTRACTOR_SEAT: return BroadcastDeparture(pPed, pAttractor, vSeatAttractors); + case ATTRACTOR_STOP: return BroadcastDeparture(pPed, pAttractor, vStopAttractors); + case ATTRACTOR_PIZZA: return BroadcastDeparture(pPed, pAttractor, vPizzaAttractors); + case ATTRACTOR_SHELTER: return BroadcastDeparture(pPed, pAttractor, vShelterAttractors); + case ATTRACTOR_ICECREAM: return BroadcastDeparture(pPed, pAttractor, vIceCreamAttractors); + } + return nil; +} + +bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor) +{ + if (!pAttractor) + return false; + if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) + return nil; + if (IsPedRegisteredWithEffect(pPed)) + return nil; + switch (pAttractor->GetEffect()->pedattr.type) { + case ATTRACTOR_ATM: return IsAtHeadOfQueue(pPed, pAttractor, vAtmAttractors); + case ATTRACTOR_SEAT: return IsAtHeadOfQueue(pPed, pAttractor, vSeatAttractors); + case ATTRACTOR_STOP: return IsAtHeadOfQueue(pPed, pAttractor, vStopAttractors); + case ATTRACTOR_PIZZA: return IsAtHeadOfQueue(pPed, pAttractor, vPizzaAttractors); + case ATTRACTOR_SHELTER: return IsAtHeadOfQueue(pPed, pAttractor, vShelterAttractors); + case ATTRACTOR_ICECREAM: return IsAtHeadOfQueue(pPed, pAttractor, vIceCreamAttractors); + } + return nil; +} + +bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor) +{ + if (!pAttractor) + return false; + if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) + return nil; + if (IsPedRegisteredWithEffect(pPed)) + return nil; + switch (pAttractor->GetEffect()->pedattr.type) { + case ATTRACTOR_ATM: return IsInQueue(pPed, pAttractor, vAtmAttractors); + case ATTRACTOR_SEAT: return IsInQueue(pPed, pAttractor, vSeatAttractors); + case ATTRACTOR_STOP: return IsInQueue(pPed, pAttractor, vStopAttractors); + case ATTRACTOR_PIZZA: return IsInQueue(pPed, pAttractor, vPizzaAttractors); + case ATTRACTOR_SHELTER: return IsInQueue(pPed, pAttractor, vShelterAttractors); + case ATTRACTOR_ICECREAM: return IsInQueue(pPed, pAttractor, vIceCreamAttractors); + } + return nil; +} + +bool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed) +{ + return IsPedRegistered(pPed, vAtmAttractors) || + IsPedRegistered(pPed, vSeatAttractors) || + IsPedRegistered(pPed, vStopAttractors) || + IsPedRegistered(pPed, vPizzaAttractors) || + IsPedRegistered(pPed, vShelterAttractors) || + IsPedRegistered(pPed, vIceCreamAttractors); +} + +void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos) +{ + pos = matrix.GetPosition() + Multiply3x3(matrix, pEffect->pos); +} + +CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector& vecAttractors) +{ + CPedAttractor* pRegisteredAttractor = nil; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + CPedAttractor* pAttractor = *pAttractorIt; + CVector vEffectPos; + ComputeEffectPos(pAttractor->GetEffect(), matrix, vEffectPos); + if (pAttractor->GetEffect() == pEffect && vEffectPos == pAttractor->GetEffectPos()) { + if (!IsApproachable(pEffect, matrix, pAttractor->ComputeFreeSlot(), pPed)) + return false; + pRegisteredAttractor = pAttractor; + break; + } + } + if (pRegisteredAttractor || !IsApproachable(pEffect, matrix, 0, pPed)) { + if (pRegisteredAttractor) + pRegisteredAttractor->RegisterPed(pPed); + return pRegisteredAttractor; + } + switch (pEffect->pedattr.type) { + case ATTRACTOR_ATM: vecAttractors.push_back(new CPedAtmAttractor(pEffect, matrix, gcMaxSizeOfAtmQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.15f, 0.1f, 0.1f)); break; + } + if (pRegisteredAttractor) + pRegisteredAttractor->RegisterPed(pPed); + return pRegisteredAttractor; +} diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h new file mode 100644 index 00000000..3e7e53df --- /dev/null +++ b/src/peds/PedAttractor.h @@ -0,0 +1,188 @@ +#pragma once +#include "common.h" +#include + +#include "2dEffect.h" +#include "Ped.h" + +#define NUM_ATTRACTORS_FOR_ICECREAM_VAN 4 + +enum ePedAttractorType +{ + ATTRACTOR_ATM = 0, + ATTRACTOR_SEAT, + ATTRACTOR_STOP, + ATTRACTOR_PIZZA, + ATTRACTOR_SHELTER, + ATTRACTOR_ICECREAM +}; + +class CPedAttractor +{ +protected: + C2dEffect* p2dEffect; + std::vector vApproachingQueue; + std::vector vWaitingQueue; + int32 m_nMaxPedsInAttractor; + float m_fQueueDistance; + float m_fTimeInWaitQueue; + float m_fTimeInApproachingQueue; + float field_30; + float field_34; + float m_fMaxPositionDisplacement; + float m_fMaxHeadingDisplacement; + CVector vecEffectPos; + CVector vecQueueDir; + CVector vecUseDir; + +public: + virtual float GetHeadOfQueueWaitTime() { return 0.0f; } + virtual ~CPedAttractor() {}; + virtual ePedAttractorType GetType() const = 0; + virtual void UpdatePedStateOnDeparture() const = 0; + virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; } + virtual void ComputeAttractPos(int32 id, CVector& pos) const; + virtual void ComputeAttractHeading(int32 id, float& pHeading) const; + virtual bool BroadcastDeparture(CPed* pPed); + + bool IsRegisteredWithPed(CPed* pPed) const; + bool DeRegisterPed(CPed* pPed); + float ComputeDeltaHeading() const; + float ComputeDeltaPos() const; + void ComputeAttractTime(int32 id, bool, float& time) const; + int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); } + int32 ComputeFreeSlot() const { return vWaitingQueue.size(); } + bool IsInQueue(CPed*) const; + bool RegisterPed(CPed*); + bool BroadcastArrival(CPed*); + + CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp); + + C2dEffect* GetEffect() const { return p2dEffect; } + const CVector& GetEffectPos() const { return vecEffectPos; } +}; + +class CPedAtmAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; }; + virtual void UpdatePedStateOnDeparture() const override; + CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedIceCreamAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; } + virtual void UpdatePedStateOnDeparture() const override; + CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedPizzaAttractor : public CPedAttractor +{ +public: + virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; } + virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; } + virtual void UpdatePedStateOnDeparture() const override; + CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedSeatAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; } + virtual void UpdatePedStateOnDeparture() const override; + CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedShelterAttractor : public CPedAttractor +{ + static std::vector ms_displacements; +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; } + virtual bool BroadcastDeparture(CPed*) override; + virtual void UpdatePedStateOnDeparture() const override; + virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; } + virtual void ComputeAttractPos(int qid, CVector& pos) const override; + virtual void ComputeAttractHeading(int qid, float& heading) const override; + + CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; + + + CVector GetDisplacement(int32 qid); +}; + +class CPedStopAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; } + virtual void UpdatePedStateOnDeparture() const override; + + CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CVehicleToEffect +{ + CVehicle* m_pVehicle; + C2dEffect m_effects[NUM_ATTRACTORS_FOR_ICECREAM_VAN]; + +public: + CVehicleToEffect(CVehicle* pVehicle); + const C2dEffect* ChooseEffect(const CVector& pos) const; + CVehicleToEffect& From(const CVehicleToEffect& other); + CVehicleToEffect& operator=(const CVehicleToEffect& other) { return From(other); } + ~CVehicleToEffect() { m_pVehicle = nil; } + CVehicle* GetVehicle() const { return m_pVehicle; } + bool HasThisEffect(C2dEffect* pEffect) const; + const C2dEffect* GetEffect(int32 i) const { return &m_effects[i]; } +}; + +class CPedAttractorManager +{ + std::vector vAtmAttractors; + std::vector vSeatAttractors; + std::vector vStopAttractors; + std::vector vPizzaAttractors; + std::vector vShelterAttractors; + std::vector vIceCreamAttractors; + std::vector vVehicleToEffect; + +public: + CPedAttractor* RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix); + CPedAttractor* RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector& vecAttractors); + bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor); + bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); + const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos); + void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& dir); + bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed); + void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& dir); + void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + void RemoveIceCreamVanEffects(C2dEffect* pEffect); + bool HasEmptySlot(const C2dEffect* pEffect); + const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector vecAttractors); + bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor); + bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor); + bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor); + bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor); + bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool IsPedRegisteredWithEffect(CPed* pPed); + bool IsPedRegistered(CPed* pPed, std::vector vecAttractors); + CVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect); +}; + +CPedAttractorManager* GetPedAttractorManager(); \ No newline at end of file diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index 2a71a8d5..33b553bd 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -3,7 +3,8 @@ enum { EFFECT_LIGHT, EFFECT_PARTICLE, - EFFECT_ATTRACTOR + EFFECT_ATTRACTOR, + EFFECT_PED_ATTRACTOR }; enum { @@ -63,6 +64,11 @@ public: uint8 flags; uint8 probability; }; + struct PedAttractor { + CVector useDir; + CVector queueDir; + int8 type; + }; CVector pos; CRGBA col; @@ -71,6 +77,7 @@ public: Light light; Particle particle; Attractor attractor; + PedAttractor pedattr; }; C2dEffect(void) {} From d031943f2ab25e36422285ec9d544beff03e1492 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 14 May 2020 13:46:11 +0300 Subject: [PATCH 002/148] more pedattractor --- src/peds/CivilianPed.cpp | 113 ++++++++++ src/peds/CivilianPed.h | 4 + src/peds/Ped.cpp | 441 +++++++++++++++++++++++++++++++++++++-- src/peds/Ped.h | 37 +++- src/peds/PedAttactor.cpp | 233 +++++++++++++++++++-- src/peds/PedAttractor.h | 285 +++++++++++++------------ 6 files changed, 934 insertions(+), 179 deletions(-) diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 1d6782fc..7d4f4d12 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -9,6 +9,8 @@ #include "World.h" #include "Vehicle.h" #include "SurfaceTable.h" +#include "Weather.h" +#include "PedAttractor.h" CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype) { @@ -16,6 +18,8 @@ CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype) for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) { m_nearPeds[i] = nil; } + m_nAttractorCycleState = 0; + m_bAttractorUnk = (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 1.25f); } void @@ -365,6 +369,10 @@ CCivilianPed::ProcessControl(void) if (IsPedInControl()) CivilianAI(); + if (CharCreatedBy == RANDOM_CHAR) { + UseNearbyAttractors(); + } + if (CTimer::GetTimeInMilliseconds() > m_timerUnused) { m_stateUnused = 0; m_timerUnused = 0; @@ -373,3 +381,108 @@ CCivilianPed::ProcessControl(void) if (m_moved.Magnitude() > 0.0f) Avoid(); } + +const int32 gFrequencyOfAttractorAttempt = 11; +const float gDistanceToSeekAttractors = 50.0f; +const float gMaxDistanceToAttract = 10.0f; + +void CCivilianPed::UseNearbyAttractors() +{ + if (CWeather::Rain < 0.2f && !m_bAttractorUnk) + return; + if (HasAttractor()) + return; + if (m_nAttractorCycleState != gFrequencyOfAttractorAttempt) { + m_nAttractorCycleState++; + return; + } + m_nAttractorCycleState = 0; + if (!IsPedInControl()) + return; + if (m_nPedState == PED_FLEE_ENTITY) + return; + + float left = GetPosition().x - gDistanceToSeekAttractors; + float right = GetPosition().x + gDistanceToSeekAttractors; + float top = GetPosition().y - gDistanceToSeekAttractors; + float bottom = GetPosition().y + gDistanceToSeekAttractors; + int xstart = Max(0, CWorld::GetSectorIndexX(left)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); + int ystart = Max(0, CWorld::GetSectorIndexY(top)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); + assert(xstart <= xend); + assert(ystart <= yend); + + float minDistance = SQR(gMaxDistanceToAttract); + C2dEffect* pClosestAttractor = nil; + CEntity* pAttractorEntity = nil; + + for (int y = ystart; y <= yend; y++) { + for (int x = xstart; x <= xend; x++) { + CSector* s = CWorld::GetSector(x, y); + for (CPtrNode* pNode = s->m_lists[ENTITYLIST_BUILDINGS].first; pNode != nil; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + if (!pEntity->IsObject()) + continue; + // TODO: some flag check + CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); + for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { + C2dEffect* pEffect = pModelInfo->Get2dEffect(i); + if (pEffect->type != EFFECT_PED_ATTRACTOR) + continue; + if (!IsAttractedTo(pEffect->pedattr.type)) + continue; + CVector pos; + CPedAttractorManager::ComputeEffectPos(pEffect, GetMatrix(), pos); + if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { + CPedAttractorManager* pManager = GetPedAttractorManager(); + if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { + pClosestAttractor = pEffect; + pAttractorEntity = pEntity; + minDistance = (pos - GetPosition()).MagnitudeSqr(); + } + } + } + } + for (CPtrNode* pNode = s->m_lists[ENTITYLIST_OBJECTS].first; pNode != nil; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + if (!pEntity->IsObject()) + continue; + // TODO: some flag check + CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); + for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { + C2dEffect* pEffect = pModelInfo->Get2dEffect(i); + if (pEffect->type != EFFECT_PED_ATTRACTOR) + continue; + if (!IsAttractedTo(pEffect->pedattr.type)) + continue; + CVector pos; + CPedAttractorManager::ComputeEffectPos(pEffect, GetMatrix(), pos); + if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { + CPedAttractorManager* pManager = GetPedAttractorManager(); + if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { + pClosestAttractor = pEffect; + pAttractorEntity = pEntity; + minDistance = (pos - GetPosition()).MagnitudeSqr(); + } + } + } + } + } + } + if (pClosestAttractor) + GetPedAttractorManager()->RegisterPedWithAttractor(this, pClosestAttractor, pAttractorEntity->GetMatrix()); +} + +bool CCivilianPed::IsAttractedTo(int8 type) +{ + switch (type) { + case ATTRACTOR_ATM: return true; + case ATTRACTOR_SEAT: return true; + case ATTRACTOR_STOP: return true; + case ATTRACTOR_PIZZA: return true; + case ATTRACTOR_SHELTER: return CWeather::Rain >= 0.2f; + case ATTRACTOR_ICECREAM: return true; + } + return false; +} diff --git a/src/peds/CivilianPed.h b/src/peds/CivilianPed.h index 8418a99f..558380b7 100644 --- a/src/peds/CivilianPed.h +++ b/src/peds/CivilianPed.h @@ -4,12 +4,16 @@ class CCivilianPed : public CPed { + bool m_bAttractorUnk; + int32 m_nAttractorCycleState; public: CCivilianPed(ePedType, uint32); ~CCivilianPed(void) { } void CivilianAI(void); void ProcessControl(void); + void UseNearbyAttractors(void); + bool IsAttractedTo(int8); }; #ifndef PED_SKIN VALIDATE_SIZE(CCivilianPed, 0x53C); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index ec8a1bb9..4c3727cf 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -57,6 +57,7 @@ #include "Timecycle.h" #include "ParticleObject.h" #include "Floater.h" +#include "PedAttractor.h" #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) @@ -384,6 +385,8 @@ CPed::DebugRenderOnePedText(void) CPed::~CPed(void) { CWorld::Remove(this); + if (m_attractor) + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); if (InVehicle()){ uint8 door_flag = GetCarDoorFlag(m_vehEnterType); @@ -452,7 +455,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) CharCreatedBy = RANDOM_CHAR; m_leader = nil; m_pedInObjective = nil; + m_attractorHeading = 0.0f; m_carInObjective = nil; + m_attractorHeading = 0.0f; bInVehicle = false; m_pMyVehicle = nil; m_pVehicleAnim = nil; @@ -489,6 +494,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_wepSkills = 0; m_distanceToCountSeekDone = 1.0f; + m_acceptableHeadingOffset = 0.1f; bRunningToPhone = false; m_phoneId = -1; m_lastAccident = 0; @@ -611,6 +617,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bSomeVCflag1 = false; #endif + bReachedAttractorHeadingTarget = false; + bTurnedAroundOnAttractor = false; bCarPassenger = false; bMiamiViceCop = false; bDeadPedInFrontOfCar = false; @@ -3666,6 +3674,8 @@ CPed::SetStoredState(void) void CPed::SetDie(AnimationId animId, float delta, float speed) { + if (m_attractor) + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); CPlayerPed *player = FindPlayerPed(); if (player == this) { if (!player->m_bCanBeDamaged) @@ -5518,8 +5528,45 @@ CPed::SetWaitState(eWaitState state, void *time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500; CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); break; + case WAITSTATE_SIT_DOWN: + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); // TODO(MIAMI): proper anim! + animAssoc->SetFinishCallback(FinishedWaitCB, this); + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000; + break; + case WAITSTATE_SIT_UP: + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); // TODO(MIAMI): proper anim! + animAssoc->SetFinishCallback(FinishedWaitCB, this); + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; + break; + case WAITSTATE_SIT_IDLE: + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 5000.0f); // TODO(MIAMI): proper anim! + animAssoc->SetFinishCallback(FinishedWaitCB, this); + if (time) + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; + else + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000); + break; + case WAITSTATE_USE_ATM: + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 5000.0f); // TODO(MIAMI): proper anim! + animAssoc->SetFinishCallback(FinishedWaitCB, this); + if (time) + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; + else + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; + break; + case WAITSTATE_SUN_BATHE_PRE: + case WAITSTATE_SUN_BATHE_DOWN: + case WAITSTATE_SUN_BATHE_IDLE: + case WAITSTATE_RIOT: + case WAITSTATE_FAST_FALL: + case WAITSTATE_BOMBER: + case WAITSTATE_STRIPPER: + case WAITSTATE_GROUND_ATTACK: + case WAITSTATE_LANCESITTING: + case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE: + assert(0); default: - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); RestoreHeadingRate(); return; } @@ -7177,7 +7224,7 @@ CPed::Wait(void) CPed *pedWeLook; if (DyingOrDead()) { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); RestoreHeadingRate(); return; } @@ -7187,7 +7234,7 @@ CPed::Wait(void) case WAITSTATE_TRAFFIC_LIGHTS: if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); SetMoveState(PEDMOVE_WALK); } } @@ -7196,7 +7243,7 @@ CPed::Wait(void) case WAITSTATE_CROSS_ROAD: if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer) - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); else SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil); @@ -7210,7 +7257,7 @@ CPed::Wait(void) case WAITSTATE_CROSS_ROAD_LOOK: if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); if (animAssoc) { animAssoc->blendDelta = -8.0f; @@ -7227,7 +7274,7 @@ CPed::Wait(void) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); } } else { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); SetMoveState(PEDMOVE_WALK); } break; @@ -7238,13 +7285,13 @@ CPed::Wait(void) m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; } } else { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); } break; case WAITSTATE_TURN180: if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); SetMoveState(PEDMOVE_WALK); m_fRotationCur = m_fRotationCur + PI; if (m_nPedState == PED_INVESTIGATE) @@ -7263,7 +7310,7 @@ CPed::Wait(void) animAssoc->SetFinishCallback(FinishedWaitCB, this); m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; } else { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); } } break; @@ -7292,7 +7339,7 @@ CPed::Wait(void) if (animAssoc->animId == ANIM_TURN_180) { m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur); - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); SetMoveState(PEDMOVE_WALK); m_nStoredMoveState = PEDMOVE_NONE; m_panicCounter = 0; @@ -7329,7 +7376,7 @@ CPed::Wait(void) case WAITSTATE_LOOK_ABOUT: if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); if (animAssoc) { animAssoc->blendDelta = -8.0f; @@ -7356,7 +7403,7 @@ CPed::Wait(void) TurnBody(); } else { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); m_nWaitTimer = 0; if (m_pLookTarget && m_pLookTarget->IsPed()) { @@ -7431,7 +7478,7 @@ CPed::Wait(void) animAssoc->blendDelta = -4.0f; animAssoc->flags |= ASSOC_DELETEFADEDOUT; } - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); } #ifdef VC_PED_PORTS else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) { @@ -7455,13 +7502,59 @@ CPed::Wait(void) animAssoc->flags |= ASSOC_DELETEFADEDOUT; CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f); int timer = 2000; - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer); } } else { - m_nWaitState = WAITSTATE_FALSE; + ClearWaitState(); } break; + case WAITSTATE_SIT_DOWN: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + ClearWaitState(); + SetWaitState(WAITSTATE_SIT_IDLE, 0); + } + break; + //case WAITSTATE_SIT_DOWN_RVRS: + case WAITSTATE_SIT_UP: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + if (m_attractor) + GetPedAttractorManager()->BroadcastDeparture(this, m_attractor); + ClearWaitState(); + //TODO(MIAMI): scan for threats! + } + break; + case WAITSTATE_SIT_IDLE: + if (bTurnedAroundOnAttractor) { + m_fRotationCur += PI; + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + m_fRotationDest = m_fRotationCur; + bTurnedAroundOnAttractor = false; + } + // TODO(MIAMI): scan for threats! + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + ClearWaitState(); + SetWaitState(WAITSTATE_SIT_UP, 0); + } + break; + case WAITSTATE_USE_ATM: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + if (m_attractor) + GetPedAttractorManager()->BroadcastDeparture(this, m_attractor); + ClearWaitState(); + } + break; + case WAITSTATE_SUN_BATHE_PRE: + case WAITSTATE_SUN_BATHE_DOWN: + case WAITSTATE_SUN_BATHE_IDLE: + case WAITSTATE_RIOT: + case WAITSTATE_FAST_FALL: + case WAITSTATE_BOMBER: + case WAITSTATE_STRIPPER: + case WAITSTATE_GROUND_ATTACK: + case WAITSTATE_LANCESITTING: + case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE: + assert(0); default: break; } @@ -9461,7 +9554,7 @@ CPed::ProcessControl(void) } else if (m_nPedStateTimer < 1001) { m_nPedStateTimer = 0; } - } else { + } else if (!GetPedAttractorManager()->IsInQueue(this, m_attractor)) { if (m_panicCounter == 50 && IsPedInControl()) { SetWaitState(WAITSTATE_STUCK, nil); // Leftover @@ -12668,9 +12761,21 @@ CPed::ProcessObjective(void) case OBJECTIVE_SET_LEADER: break; case OBJECTIVE_IDLE: - SetIdle(); - m_objective = OBJECTIVE_NONE; - SetMoveState(PEDMOVE_STILL); + if (GetPedState() == PED_DRIVING) + m_objective = OBJECTIVE_NONE; + else { + SetIdle(); + if (m_attractor) { + if (m_objectiveTimer && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { + GetPedAttractorManager()->BroadcastDeparture(this, m_attractor); + m_objectiveTimer = 0; + } + } + else { + m_objective = OBJECTIVE_NONE; + SetMoveState(PEDMOVE_STILL); + } + } break; case OBJECTIVE_FLEE_TILL_SAFE: if (InVehicle()) { @@ -13851,6 +13956,187 @@ CPed::ProcessObjective(void) } break; } + case OBJECTIVE_USE_SEAT_ATTRACTOR: + case OBJECTIVE_USE_ATM_ATTRACTOR: + case OBJECTIVE_USE_STOP_ATTRACTOR: + case OBJECTIVE_USE_PIZZA_ATTRACTOR: + case OBJECTIVE_USE_SHELTER_ATTRACTOR: + case OBJECTIVE_USE_ICECREAM_ATTRACTOR: + if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { + m_objectiveTimer = 0; + if (m_attractor) + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + } + else { + CVector distance = m_nextRoutePointPos - GetPosition(); + distance.z = 0.0f; + if (m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR) { + if (m_nMoveState == PEDMOVE_SPRINT && distance.Magnitude() < SQR(2.0f)) { + SetMoveState(PEDMOVE_WALK); + bIsRunning = false; + } + else if (CWeather::Rain < 0.2f && m_attractor) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; + } + } + else if (m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR) { + if (m_nMoveState == PEDMOVE_SPRINT && distance.Magnitude() < SQR(4.0f)) { + SetMoveState(PEDMOVE_WALK); + bIsRunning = false; + } + CVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect()); + if (0.01f * CTimer::GetTimeStep() * 5.0f < pIceCreamVan->m_fDistanceTravelled) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; + } + if (!pIceCreamVan->pDriver || + !pIceCreamVan->pDriver->IsPlayer() || + pIceCreamVan->pDriver->GetPedState() == PED_ARRESTED || + pIceCreamVan->pDriver->GetPedState() == PED_DEAD) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; + } + if (!pIceCreamVan->m_bSirenOrAlarm) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; + } + if (pIceCreamVan->GetStatus() == STATUS_WRECKED) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; + } + } + if (sq(m_distanceToCountSeekDone) < distance.MagnitudeSqr()) { + if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || GetPedState() != PED_SEEK_POS) + SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); + } + else { + if (!bReachedAttractorHeadingTarget) { + float fHeadingDistance = m_fRotationCur - m_attractorHeading; + float fSinHeading = Sin(fHeadingDistance); + float fCosHeading = Cos(fHeadingDistance); + if (fSinHeading > 0.0f) { + if (fCosHeading > 0.0f) + m_attractorHeading = m_fRotationCur - Asin(fSinHeading); + else + m_attractorHeading = m_fRotationCur - Acos(fCosHeading); + } + else { + if (fCosHeading > 0.0f) + m_attractorHeading = m_fRotationCur - Asin(fSinHeading); + else + m_attractorHeading = m_fRotationCur + Acos(fCosHeading); + } + m_fRotationDest = m_attractorHeading; + m_headingRate = 3.5f; + bReachedAttractorHeadingTarget = true; + bTurnedAroundOnAttractor = false; + } + if (Abs(m_fRotationCur - m_attractorHeading) >= m_acceptableHeadingOffset && + Abs(m_fRotationCur - m_attractorHeading + TWOPI) >= m_acceptableHeadingOffset && + Abs(m_fRotationCur - m_attractorHeading - TWOPI) >= m_acceptableHeadingOffset) + SetMoveState(PEDMOVE_STILL); + else { + m_fRotationDest = m_fRotationCur; + bReachedAttractorHeadingTarget = false; + bObjectiveCompleted = true; + bScriptObjectiveCompleted = true; + RestoreHeadingRate(); + GetPedAttractorManager()->BroadcastArrival(this, m_attractor); + if (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) { + switch (m_objective) { + case OBJECTIVE_USE_SEAT_ATTRACTOR: + if (bTurnedAroundOnAttractor) { + ClearObjective(); + SetWaitState(WAITSTATE_SIT_DOWN, 0); + } + else { + ClearObjective(); + SetWaitState(WAITSTATE_SIT_DOWN_RVRS, 0); + } + break; + case OBJECTIVE_USE_ATM_ATTRACTOR: + ClearObjective(); + SetWaitState(WAITSTATE_USE_ATM, 0); + break; + case OBJECTIVE_USE_STOP_ATTRACTOR: + ClearObjective(); + SetObjective(OBJECTIVE_WAIT_FOR_BUS); + break; + case OBJECTIVE_USE_PIZZA_ATTRACTOR: + ClearObjective(); + m_prevObjective = OBJECTIVE_NONE; + SetObjective(OBJECTIVE_IDLE); + m_objectiveTimer = CTimer::GetTimeInMilliseconds() + m_attractor->GetHeadOfQueueWaitTime(); + break; + case OBJECTIVE_USE_SHELTER_ATTRACTOR: + m_prevObjective = OBJECTIVE_NONE; + SetObjective(OBJECTIVE_WAIT_FOR_RAIN_TO_END); + break; + case OBJECTIVE_USE_ICECREAM_ATTRACTOR: + m_prevObjective = OBJECTIVE_NONE; + SetObjective(OBJECTIVE_PURCHASE_ICECREAM); + break; + } + } + } + } + } + return; + case OBJECTIVE_WAIT_FOR_RAIN_TO_END: + SetIdle(); + if (m_attractor && CWeather::Rain < 0.2f) + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + break; + case OBJECTIVE_WAIT_FOR_BUS: + SetIdle(); + if (m_attractor) { + float left = GetPosition().x - 10.0f; + float right = GetPosition().x + 10.0f; + float top = GetPosition().y - 10.0f; + float bottom = GetPosition().y + 10.0f; + int xstart = Max(0, CWorld::GetSectorIndexX(left)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); + int ystart = Max(0, CWorld::GetSectorIndexY(top)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); + assert(xstart <= xend); + assert(ystart <= yend); + + float minDistance = SQR(10.0f); + CVehicle* pBus = nil; + + for (int y = ystart; y <= yend; y++) { + for (int x = xstart; x <= xend; x++) { + CSector* s = CWorld::GetSector(x, y); + for (CPtrNode* pNode = s->m_lists[ENTITYLIST_VEHICLES].first; pNode != nil; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + if (!pEntity->IsVehicle()) + continue; + CVehicle* pVehicle = (CVehicle*)pEntity; + if (!pVehicle->bIsBus) + continue; + if (pVehicle->GetMoveSpeed().MagnitudeSqr() >= SQR(0.005f)) + continue; + float distanceSq = (GetPosition() - pVehicle->GetPosition()).MagnitudeSqr(); + if (distanceSq < minDistance) { + minDistance = distanceSq; + pBus = pVehicle; + } + } + } + } + + if (pBus) { + if (pBus->m_nNumPassengers >= pBus->m_nNumMaxPassengers - 1) + SetObjective(OBJECTIVE_IDLE); + else { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus); + bDontDragMeOutCar = true; // TODO(MIAMI): check, add more flags + } + } + } + break; #endif } if (bObjectiveCompleted @@ -16939,6 +17225,22 @@ CPed::WarpPedIntoCar(CVehicle *car) bChangedSeat = true; } +void +CPed::SetObjective(eObjective newObj, float heading, const CVector& pos) +{ + switch (newObj) { + case OBJECTIVE_USE_SEAT_ATTRACTOR: + case OBJECTIVE_USE_ATM_ATTRACTOR: + case OBJECTIVE_USE_STOP_ATTRACTOR: + case OBJECTIVE_USE_PIZZA_ATTRACTOR: + case OBJECTIVE_USE_SHELTER_ATTRACTOR: + case OBJECTIVE_USE_ICECREAM_ATTRACTOR: + ClearPointGunAt(); + SetObjective(newObj, pos); + m_attractorHeading = heading; + } +} + void CPed::SetObjective(eObjective newObj, CVector dest) { @@ -16988,14 +17290,50 @@ CPed::SetObjective(eObjective newObj, CVector dest) break; case OBJECTIVE_GOTO_AREA_ANY_MEANS: case OBJECTIVE_GOTO_AREA_ON_FOOT: + case OBJECTIVE_USE_SEAT_ATTRACTOR: + case OBJECTIVE_USE_ATM_ATTRACTOR: + case OBJECTIVE_USE_STOP_ATTRACTOR: + case OBJECTIVE_USE_PIZZA_ATTRACTOR: + case OBJECTIVE_USE_SHELTER_ATTRACTOR: + case OBJECTIVE_USE_ICECREAM_ATTRACTOR: bIsRunning = false; m_pNextPathNode = nil; m_nextRoutePointPos = dest; m_vecSeekPos = m_nextRoutePointPos; m_distanceToCountSeekDone = 0.5f; - bUsePedNodeSeek = true; - if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) - return; + if (m_objective == OBJECTIVE_USE_ATM_ATTRACTOR) { + m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); + m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); + } + if (m_objective == OBJECTIVE_USE_SEAT_ATTRACTOR) { + m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); + m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); + } + if (m_objective == OBJECTIVE_USE_STOP_ATTRACTOR) { + m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); + m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); + } + if (m_objective == OBJECTIVE_USE_PIZZA_ATTRACTOR) { + m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); + m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); + } + if (m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR) { + bIsRunning = true; + m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); + m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); + } + if (m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR) { + bIsRunning = true; + m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); + m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); + } + bUsePedNodeSeek = false; + if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) { + if (!IsUseAttractorObjective(m_objective)) + return; + if (Abs(m_fRotationCur - m_attractorHeading) < m_acceptableHeadingOffset) + return; + } break; case OBJECTIVE_RUN_TO_AREA: bIsRunning = true; @@ -17622,6 +17960,65 @@ CPed::SetExitBoat(CVehicle *boat) CWaterLevel::FreeBoatWakeArray(); } +void +CPed::SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float heading, float time, int32 qid) +{ + if (!m_attractor) + m_attractor = pAttractor; + if (m_attractor != pAttractor) + return; + switch (pAttractor->GetEffect()->pedattr.type) { + case ATTRACTOR_ATM: SetObjective(OBJECTIVE_USE_ATM_ATTRACTOR, heading, pos); break; + case ATTRACTOR_SEAT: SetObjective(OBJECTIVE_USE_SEAT_ATTRACTOR, heading, pos); break; + case ATTRACTOR_STOP: SetObjective(OBJECTIVE_USE_STOP_ATTRACTOR, heading, pos); break; + case ATTRACTOR_PIZZA: SetObjective(OBJECTIVE_USE_PIZZA_ATTRACTOR, heading, pos); break; + case ATTRACTOR_SHELTER: SetObjective(OBJECTIVE_USE_SHELTER_ATTRACTOR, heading, pos); break; + case ATTRACTOR_ICECREAM: SetObjective(OBJECTIVE_USE_ICECREAM_ATTRACTOR, heading, pos); break; + default: return; + } + SetObjectiveTimer(time); + m_positionInQueue = qid; +} + +void +CPed::ClearWaitState(void) +{ + switch (m_nWaitState) { + case WAITSTATE_PLAYANIM_CHAT: + case WAITSTATE_SIT_DOWN: + case WAITSTATE_SIT_DOWN_RVRS: + case WAITSTATE_SIT_UP: + case WAITSTATE_SIT_IDLE: + case WAITSTATE_USE_ATM: + if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { + AnimationId id; + switch (m_nWaitState) { // TODO(MIAMI): actual! + case WAITSTATE_PLAYANIM_CHAT: id = ANIM_IDLE_CHAT; break; + case WAITSTATE_SIT_DOWN: id = ANIM_XPRESS_SCRATCH; break; + case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_XPRESS_SCRATCH; break; + case WAITSTATE_SIT_UP: id = ANIM_XPRESS_SCRATCH; break; + case WAITSTATE_SIT_IDLE: id = ANIM_XPRESS_SCRATCH; break; + case WAITSTATE_USE_ATM: id = ANIM_XPRESS_SCRATCH; break; + } + CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetAssociation(GetClump(), id); + if (pAssoc) + pAssoc->blendDelta = -8.0f; + if (m_attractor) + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + break; + } + case WAITSTATE_RIOT: + case WAITSTATE_FAST_FALL: + case WAITSTATE_BOMBER: + case WAITSTATE_STRIPPER: + case WAITSTATE_GROUND_ATTACK: + case WAITSTATE_LANCESITTING: + case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE: + assert(0); + } + m_nWaitState = WAITSTATE_FALSE; +} + #ifdef COMPATIBLE_SAVES void CPed::Save(uint8*& buf) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index d8df1f49..60325812 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -149,7 +149,22 @@ enum eWaitState { WAITSTATE_PLAYANIM_HANDSUP, WAITSTATE_PLAYANIM_HANDSCOWER, WAITSTATE_PLAYANIM_CHAT, - WAITSTATE_FINISH_FLEE + WAITSTATE_FINISH_FLEE, + WAITSTATE_SIT_DOWN, + WAITSTATE_SIT_DOWN_RVRS, + WAITSTATE_SIT_UP, + WAITSTATE_SIT_IDLE, + WAITSTATE_USE_ATM, + WAITSTATE_SUN_BATHE_PRE, + WAITSTATE_SUN_BATHE_DOWN, + WAITSTATE_SUN_BATHE_IDLE, + WAITSTATE_RIOT, + WAITSTATE_FAST_FALL, + WAITSTATE_BOMBER, + WAITSTATE_STRIPPER, + WAITSTATE_GROUND_ATTACK, + WAITSTATE_LANCESITTING, + WAITSTATE_PLAYANIM_HANDSUP_SIMPLE, }; enum eObjective : uint32 { @@ -201,14 +216,13 @@ enum eObjective : uint32 { OBJECTIVE_USE_SHELTER_ATTRACTOR, OBJ_46, OBJ_47, - OBJ_48, + OBJECTIVE_WAIT_FOR_RAIN_TO_END, OBJ_49, OBJ_50, OBJ_51, - OBJ_52, + OBJECTIVE_WAIT_FOR_BUS, OBJECTIVE_USE_ICECREAM_ATTRACTOR, - OBJ_53, - OBJ_54, + OBJECTIVE_PURCHASE_ICECREAM, OBJ_55, OBJ_56, OBJ_57, @@ -414,6 +428,8 @@ public: uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle + uint32 bReachedAttractorHeadingTarget : 1; // 0x154 0x40 + uint32 bTurnedAroundOnAttractor : 1; // 0x154 0x80 uint32 bHasAlreadyUsedAttractor : 1; // 0x155 0x1 uint32 bCarPassenger : 1; // 0x155 0x4 uint32 bMiamiViceCop : 1; // 0x155 0x20 @@ -425,6 +441,7 @@ public: CPed *m_pedInObjective; CVehicle *m_carInObjective; CVector m_nextRoutePointPos; + float m_attractorHeading; CPed *m_leader; eFormation m_pedFormation; uint32 m_fearFlags; @@ -482,7 +499,7 @@ public: CVehicle *m_pMyVehicle; bool bInVehicle; float m_distanceToCountSeekDone; - + float m_acceptableHeadingOffset; CPedAttractor* m_attractor; int32 m_positionInQueue; CVehicle* m_vehicleInAccident; @@ -610,6 +627,7 @@ public: void SetObjective(eObjective, int16, int16); void SetObjective(eObjective, CVector); void SetObjective(eObjective, CVector, float); + void SetObjective(eObjective, float, const CVector&); void ClearChat(void); void InformMyGangOfAttack(CEntity*); void ReactToAttack(CEntity*); @@ -822,6 +840,7 @@ public: #endif void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int); + void ClearWaitState(void); bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } @@ -837,6 +856,12 @@ public: bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; } + bool HasAttractor(void) { return m_attractor != nil; } + bool IsUseAttractorObjective(eObjective obj) { + return obj == OBJECTIVE_USE_ATM_ATTRACTOR || obj == OBJECTIVE_USE_ICECREAM_ATTRACTOR || + obj == OBJECTIVE_USE_PIZZA_ATTRACTOR || obj == OBJECTIVE_USE_SEAT_ATTRACTOR || + obj == OBJECTIVE_USE_SHELTER_ATTRACTOR || obj == OBJECTIVE_USE_STOP_ATTRACTOR; + } void ReplaceWeaponWhenExitingVehicle(void); void RemoveWeaponWhenEnteringVehicle(void); diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp index 9e3e6ae4..bef14308 100644 --- a/src/peds/PedAttactor.cpp +++ b/src/peds/PedAttactor.cpp @@ -3,9 +3,16 @@ #include "General.h" #include "Vehicle.h" +#include "World.h" const int gcMaxSizeOfAtmQueue = 1; +const int gcMaxSizeOfSeatQueue = 1; +const int gcMaxSizeOfStopQueue = 5; +const int gcMaxSizeOfPizzaQueue = 5; const int gcMaxSizeOfShelterQueue = 5; +const int gcMaxSizeOfIceCreamQueue = 1; + +std::vector CPedShelterAttractor::ms_displacements; CPedAttractorManager* GetPedAttractorManager() { @@ -107,7 +114,7 @@ CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect) return nil; } -const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector vecAttractors) +const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector& vecAttractors) { if (vecAttractors.empty()) return nil; @@ -140,20 +147,21 @@ void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect) } } -CPedAttractor::CPedAttractor(C2dEffect* pEffect, CMatrix const& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - p2dEffect(p2dEffect), +CPedAttractor::CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + p2dEffect(pEffect), m_nMaxPedsInAttractor(maxpeds), m_fQueueDistance(qdist), m_fTimeInWaitQueue(waitTime), m_fTimeInApproachingQueue(approachTime), - field_30(unk8), - field_34(unk9), + m_fDistanceToUseAttractor(distance), + m_fAcceptableHeading(headingdiff), m_fMaxPositionDisplacement(posdisp), - m_fMaxHeadingDisplacement(headdisp), - vecEffectPos(Multiply3x3(matrix, pEffect->pos)), - vecQueueDir(Multiply3x3(matrix, pEffect->pedattr.queueDir)), - vecUseDir(Multiply3x3(matrix, pEffect->pedattr.useDir)) -{} + m_fMaxHeadingDisplacement(headdisp) +{ + CPedAttractorManager::ComputeEffectPos(pEffect, matrix, vecEffectPos); + CPedAttractorManager::ComputeEffectQueueDir(pEffect, matrix, vecQueueDir); + CPedAttractorManager::ComputeEffectUseDir(pEffect, matrix, vecUseDir); +} float CPedAttractor::ComputeDeltaHeading() const { @@ -184,7 +192,7 @@ void CPedAttractor::ComputeAttractPos(int32 qid, CVector& pos) const } } -CVector CPedShelterAttractor::GetDisplacement(int32 qid) +CVector CPedShelterAttractor::GetDisplacement(int32 qid) const { if (ms_displacements.empty()) { int i = 0; @@ -208,6 +216,13 @@ CVector CPedShelterAttractor::GetDisplacement(int32 qid) return ms_displacements[qid]; } +void CPedShelterAttractor::ComputeAttractPos(int32 qid, CVector& pos) const +{ + if (!p2dEffect) + return; + pos = vecEffectPos + GetDisplacement(qid); +} + void CPedAttractor::ComputeAttractHeading(int32 qid, float& heading) const { heading = CGeneral::GetRadianAngleBetweenPoints(qid != 0 ? vecQueueDir.x : vecUseDir.x, qid != 0 ? vecQueueDir.y : vecUseDir.y, 0.0f, 0.0f); @@ -254,7 +269,7 @@ static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed) return true; break; case ATTRACTOR_STOP: - if (pPed->m_objective == OBJECTIVE_USE_STOP_ATTRACTOR || pPed->m_objective == OBJ_52 || pPed->m_objective == OBJECTIVE_IDLE) + if (pPed->m_objective == OBJECTIVE_USE_STOP_ATTRACTOR || pPed->m_objective == OBJECTIVE_WAIT_FOR_BUS || pPed->m_objective == OBJECTIVE_IDLE) return true; break; case ATTRACTOR_PIZZA: @@ -262,11 +277,11 @@ static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed) return true; break; case ATTRACTOR_SHELTER: - if (pPed->m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR || pPed->m_objective == OBJ_48) + if (pPed->m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR || pPed->m_objective == OBJECTIVE_WAIT_FOR_RAIN_TO_END) return true; break; case ATTRACTOR_ICECREAM: - if (pPed->m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR || pPed->m_objective == OBJ_54) + if (pPed->m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR || pPed->m_objective == OBJECTIVE_PURCHASE_ICECREAM) return true; break; } @@ -289,6 +304,7 @@ bool CPedAttractor::DeRegisterPed(CPed* pPed) return true; } pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y)); + vApproachingQueue.erase(pPedIt); return true; } return BroadcastDeparture(pPed); @@ -404,6 +420,29 @@ bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed) return true; } +bool CPedAttractor::IsRegisteredWithPed(CPed* pPed) const +{ + for (std::vector::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) { + if (*pPedIt == pPed) + return true; + } + for (std::vector::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) { + if (*pPedIt == pPed) { + return true; + } + } + return false; +} + +bool CPedAttractor::IsInQueue(CPed* pPed) const +{ + for (std::vector::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) { + if (*pPedIt == pPed) + return true; + } + return false; +} + CPedAttractor* CPedAttractorManager::RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix) { if (pEffect->type != EFFECT_PED_ATTRACTOR) @@ -427,7 +466,7 @@ bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor) return false; if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) return nil; - if (IsPedRegisteredWithEffect(pPed)) + if (!IsPedRegisteredWithEffect(pPed)) return nil; switch (pAttractor->GetEffect()->pedattr.type) { case ATTRACTOR_ATM: return DeRegisterPed(pPed, pAttractor, vAtmAttractors); @@ -516,6 +555,27 @@ bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor) return nil; } +bool CPedAttractorManager::HasEmptySlot(const C2dEffect* pEffect) +{ + if (!pEffect) + return false; + if (pEffect->type != EFFECT_PED_ATTRACTOR) + return nil; + const CPedAttractor* pAttractor; + switch (pEffect->pedattr.type) { + case ATTRACTOR_ATM: pAttractor = FindAssociatedAttractor(pEffect, vAtmAttractors); break; + case ATTRACTOR_SEAT: pAttractor = FindAssociatedAttractor(pEffect, vSeatAttractors); break; + case ATTRACTOR_STOP: pAttractor = FindAssociatedAttractor(pEffect, vStopAttractors); break; + case ATTRACTOR_PIZZA: pAttractor = FindAssociatedAttractor(pEffect, vPizzaAttractors); break; + case ATTRACTOR_SHELTER: pAttractor = FindAssociatedAttractor(pEffect, vShelterAttractors); break; + case ATTRACTOR_ICECREAM: pAttractor = FindAssociatedAttractor(pEffect, vIceCreamAttractors); break; + default: return true; + } + if (!pAttractor) + return true; + return pAttractor->GetNoOfRegisteredPeds() < pAttractor->GetMaxPedsInAttractor(); +} + bool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed) { return IsPedRegistered(pPed, vAtmAttractors) || @@ -526,11 +586,21 @@ bool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed) IsPedRegistered(pPed, vIceCreamAttractors); } -void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos) +void CPedAttractorManager::ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos) { pos = matrix.GetPosition() + Multiply3x3(matrix, pEffect->pos); } +void CPedAttractorManager::ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos) +{ + pos = Multiply3x3(matrix, pEffect->pedattr.queueDir); +} + +void CPedAttractorManager::ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos) +{ + pos = Multiply3x3(matrix, pEffect->pedattr.useDir); +} + CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector& vecAttractors) { CPedAttractor* pRegisteredAttractor = nil; @@ -552,8 +622,139 @@ CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, } switch (pEffect->pedattr.type) { case ATTRACTOR_ATM: vecAttractors.push_back(new CPedAtmAttractor(pEffect, matrix, gcMaxSizeOfAtmQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.15f, 0.1f, 0.1f)); break; + case ATTRACTOR_SEAT: vecAttractors.push_back(new CPedSeatAttractor(pEffect, matrix, gcMaxSizeOfSeatQueue, 1.0f, 30000.0f, 3000.0f, 0.125f, 0.1f, 0.1f, 0.1f)); break; + case ATTRACTOR_STOP: vecAttractors.push_back(new CPedStopAttractor(pEffect, matrix, gcMaxSizeOfStopQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f)); break; + case ATTRACTOR_PIZZA: vecAttractors.push_back(new CPedPizzaAttractor(pEffect, matrix, gcMaxSizeOfPizzaQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f)); break; + case ATTRACTOR_SHELTER: vecAttractors.push_back(new CPedShelterAttractor(pEffect, matrix, gcMaxSizeOfShelterQueue, 1.0f, 30000.0f, 3000.0f, 0.5f, 6.28f, 0.1f, 0.1f)); break; + case ATTRACTOR_ICECREAM: vecAttractors.push_back(new CPedIceCreamAttractor(pEffect, matrix, gcMaxSizeOfIceCreamQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.3f, 0.1f, 0.1f)); break; } if (pRegisteredAttractor) pRegisteredAttractor->RegisterPed(pPed); return pRegisteredAttractor; } + +bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors) +{ + if (!pAttractor) + return false; + CPedAttractor* pFound = nil; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + pFound = *pAttractorIt; + break; + } + } + if (!pFound) + return false; + pFound->DeRegisterPed(pPed); + if (pFound->GetNoOfRegisteredPeds() != 0) + return true; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + vecAttractors.erase(pAttractorIt); + break; + } + } + delete pAttractor; + return true; +} + +bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors) +{ + if (!pAttractor) + return false; + CPedAttractor* pFound = nil; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + pFound = *pAttractorIt; + break; + } + } + if (!pFound) + return false; + pFound->BroadcastArrival(pPed); + return true; +} + +bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors) +{ + if (!pAttractor) + return false; + CPedAttractor* pFound = nil; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + pFound = *pAttractorIt; + break; + } + } + if (!pFound) + return false; + pFound->DeRegisterPed(pPed); + if (pFound->GetNoOfRegisteredPeds() != 0) + return true; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + vecAttractors.erase(pAttractorIt); + break; + } + } + delete pAttractor; + return true; +} + +bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors) +{ + if (!pAttractor) + return false; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + return (*pAttractorIt)->IsInQueue(pPed); + } + } + return false; +} + +bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors) +{ + if (!pAttractor) + return false; + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if (*pAttractorIt == pAttractor) { + return (*pAttractorIt)->IsAtHeadOfQueue(pPed); + } + } + return false; +} + +bool CPedAttractorManager::IsPedRegistered(CPed* pPed, std::vector& vecAttractors) +{ + for (std::vector::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) { + if ((*pAttractorIt)->IsRegisteredWithPed(pPed)) + return true; + } + return false; +} + +bool CPedAttractorManager::IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed) +{ + if (pEffect->pedattr.type == ATTRACTOR_SHELTER) { + CVector pos; + ComputeEffectPos(pEffect, matrix, pos); + return CWorld::GetIsLineOfSightClear(pPed->GetPosition(), pos, true, false, false, false, false, false); + } + CVector vecUseDir, vecEffectPos; + ComputeEffectUseDir(pEffect, matrix, vecUseDir); + ComputeEffectPos(pEffect, matrix, vecEffectPos); + float dp = -DotProduct(vecUseDir, vecEffectPos); + if (pEffect->pedattr.type == ATTRACTOR_ATM || pEffect->pedattr.type == ATTRACTOR_PIZZA || pEffect->pedattr.type == ATTRACTOR_ICECREAM) { + vecUseDir = vecUseDir; + dp = -dp; + } + if (dp + DotProduct(vecEffectPos, pPed->GetPosition()) > 0.0f) { + CVector vecPedToAttractor = pPed->GetPosition() - vecEffectPos; + vecPedToAttractor.Normalise(); + if (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f /* && CWorld::IsWanderPathClear(pPed, vecEffectPos, 2.0f, 0) */) + return true; + } + return false; +} diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h index 3e7e53df..3171d228 100644 --- a/src/peds/PedAttractor.h +++ b/src/peds/PedAttractor.h @@ -7,131 +7,7 @@ #define NUM_ATTRACTORS_FOR_ICECREAM_VAN 4 -enum ePedAttractorType -{ - ATTRACTOR_ATM = 0, - ATTRACTOR_SEAT, - ATTRACTOR_STOP, - ATTRACTOR_PIZZA, - ATTRACTOR_SHELTER, - ATTRACTOR_ICECREAM -}; - -class CPedAttractor -{ -protected: - C2dEffect* p2dEffect; - std::vector vApproachingQueue; - std::vector vWaitingQueue; - int32 m_nMaxPedsInAttractor; - float m_fQueueDistance; - float m_fTimeInWaitQueue; - float m_fTimeInApproachingQueue; - float field_30; - float field_34; - float m_fMaxPositionDisplacement; - float m_fMaxHeadingDisplacement; - CVector vecEffectPos; - CVector vecQueueDir; - CVector vecUseDir; - -public: - virtual float GetHeadOfQueueWaitTime() { return 0.0f; } - virtual ~CPedAttractor() {}; - virtual ePedAttractorType GetType() const = 0; - virtual void UpdatePedStateOnDeparture() const = 0; - virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; } - virtual void ComputeAttractPos(int32 id, CVector& pos) const; - virtual void ComputeAttractHeading(int32 id, float& pHeading) const; - virtual bool BroadcastDeparture(CPed* pPed); - - bool IsRegisteredWithPed(CPed* pPed) const; - bool DeRegisterPed(CPed* pPed); - float ComputeDeltaHeading() const; - float ComputeDeltaPos() const; - void ComputeAttractTime(int32 id, bool, float& time) const; - int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); } - int32 ComputeFreeSlot() const { return vWaitingQueue.size(); } - bool IsInQueue(CPed*) const; - bool RegisterPed(CPed*); - bool BroadcastArrival(CPed*); - - CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp); - - C2dEffect* GetEffect() const { return p2dEffect; } - const CVector& GetEffectPos() const { return vecEffectPos; } -}; - -class CPedAtmAttractor : public CPedAttractor -{ -public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; }; - virtual void UpdatePedStateOnDeparture() const override; - CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; -}; - -class CPedIceCreamAttractor : public CPedAttractor -{ -public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; } - virtual void UpdatePedStateOnDeparture() const override; - CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; -}; - -class CPedPizzaAttractor : public CPedAttractor -{ -public: - virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; } - virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; } - virtual void UpdatePedStateOnDeparture() const override; - CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; -}; - -class CPedSeatAttractor : public CPedAttractor -{ -public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; } - virtual void UpdatePedStateOnDeparture() const override; - CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; -}; - -class CPedShelterAttractor : public CPedAttractor -{ - static std::vector ms_displacements; -public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; } - virtual bool BroadcastDeparture(CPed*) override; - virtual void UpdatePedStateOnDeparture() const override; - virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; } - virtual void ComputeAttractPos(int qid, CVector& pos) const override; - virtual void ComputeAttractHeading(int qid, float& heading) const override; - - CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; - - - CVector GetDisplacement(int32 qid); -}; - -class CPedStopAttractor : public CPedAttractor -{ -public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; } - virtual void UpdatePedStateOnDeparture() const override; - - CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; -}; +class CPedAttractor; class CVehicleToEffect { @@ -165,24 +41,163 @@ public: bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor); bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos); - void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& dir); bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed); - void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& dir); - void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); void RemoveIceCreamVanEffects(C2dEffect* pEffect); bool HasEmptySlot(const C2dEffect* pEffect); - const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector vecAttractors); + const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector& vecAttractors); bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor); - bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor); - bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor); - bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor); - bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector vecAttractors); + bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); bool IsPedRegisteredWithEffect(CPed* pPed); - bool IsPedRegistered(CPed* pPed, std::vector vecAttractors); + bool IsPedRegistered(CPed* pPed, std::vector& vecAttractors); CVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect); + + static void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + static void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + static void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + }; -CPedAttractorManager* GetPedAttractorManager(); \ No newline at end of file +CPedAttractorManager* GetPedAttractorManager(); + +enum ePedAttractorType +{ + ATTRACTOR_ATM = 0, + ATTRACTOR_SEAT, + ATTRACTOR_STOP, + ATTRACTOR_PIZZA, + ATTRACTOR_SHELTER, + ATTRACTOR_ICECREAM +}; + +class CPedAttractor +{ +protected: + C2dEffect* p2dEffect; + std::vector vApproachingQueue; + std::vector vWaitingQueue; + int32 m_nMaxPedsInAttractor; + float m_fQueueDistance; + float m_fTimeInWaitQueue; + float m_fTimeInApproachingQueue; + float m_fDistanceToUseAttractor; + float m_fAcceptableHeading; + float m_fMaxPositionDisplacement; + float m_fMaxHeadingDisplacement; + CVector vecEffectPos; + CVector vecQueueDir; + CVector vecUseDir; + +public: + virtual float GetHeadOfQueueWaitTime() { return 0.0f; } + virtual ~CPedAttractor() {}; + virtual ePedAttractorType GetType() const = 0; + virtual void UpdatePedStateOnDeparture(CPed* pPed) const = 0; + virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; } + virtual void ComputeAttractPos(int32 id, CVector& pos) const; + virtual void ComputeAttractHeading(int32 id, float& pHeading) const; + virtual bool BroadcastDeparture(CPed* pPed); + + bool IsRegisteredWithPed(CPed* pPed) const; + bool DeRegisterPed(CPed* pPed); + float ComputeDeltaHeading() const; + float ComputeDeltaPos() const; + void ComputeAttractTime(int32 id, bool, float& time) const; + int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); } + int32 ComputeFreeSlot() const { return vWaitingQueue.size(); } + bool IsInQueue(CPed*) const; + bool RegisterPed(CPed*); + bool BroadcastArrival(CPed*); + + CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp); + + C2dEffect* GetEffect() const { return p2dEffect; } + const CVector& GetEffectPos() const { return vecEffectPos; } + int32 GetMaxPedsInAttractor() const { return m_nMaxPedsInAttractor; } + float GetDistanceToCountSeekDone() const { return m_fDistanceToUseAttractor; } + float GetAcceptableHeading() const { return m_fAcceptableHeading; } +}; + +class CPedAtmAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; }; + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override { /* pPed->m_money += 20 * CGeneral::GetRandomNumberInRange(1, 51); */ }; + CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedIceCreamAttractor : public CPedAttractor +{ +public: + virtual ~CPedIceCreamAttractor() override { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); } + virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedPizzaAttractor : public CPedAttractor +{ +public: + virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; } + virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override + { /* + if (pPed->m_money > 10) + pPed->m_money = 0; + else + pPed->m_money -= 10; + */ + } + CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedSeatAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; + +class CPedShelterAttractor : public CPedAttractor +{ + static std::vector ms_displacements; +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; } + virtual bool BroadcastDeparture(CPed*) override; + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; } + virtual void ComputeAttractPos(int qid, CVector& pos) const override; + virtual void ComputeAttractHeading(int qid, float& heading) const override; + + CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; + + + CVector GetDisplacement(int32 qid) const; +}; + +class CPedStopAttractor : public CPedAttractor +{ +public: + virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + + CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; +}; \ No newline at end of file From 08b2138c7e59ce3350d333832ceca5c24799a34c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 01:49:30 +0300 Subject: [PATCH 003/148] ped attractors done --- src/core/FileLoader.cpp | 8 +++--- src/core/World.cpp | 55 ++++++++++++++++++++++++++++++++++++++++ src/core/World.h | 2 ++ src/peds/CivilianPed.cpp | 22 ++++++++-------- src/peds/Ped.cpp | 22 ++++++++-------- src/peds/PedAttactor.cpp | 12 ++++----- src/render/2dEffect.h | 2 +- 7 files changed, 90 insertions(+), 33 deletions(-) diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 589ec23c..41c96401 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1033,12 +1033,12 @@ CFileLoader::Load2dEffect(const char *line) sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f", &id, &x, &y, &z, &r, &g, &b, &a, &type, &ptype, - &effect->pedattr.useDir.x, - &effect->pedattr.useDir.y, - &effect->pedattr.useDir.z, &effect->pedattr.queueDir.x, &effect->pedattr.queueDir.y, - &effect->pedattr.queueDir.z); + &effect->pedattr.queueDir.z, + &effect->pedattr.useDir.x, + &effect->pedattr.useDir.y, + &effect->pedattr.useDir.z); effect->pedattr.type = ptype; break; } diff --git a/src/core/World.cpp b/src/core/World.cpp index 493ce042..0392ba2f 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -2236,3 +2236,58 @@ CWorld::UseDetonator(CEntity *pEntity) } } } + +bool +CWorld::IsWanderPathClear(CVector const& point1, CVector const& point2, float distance, int maxSteps) +{ + if (Abs(point1.z - point2.z) > distance) + return false; + if (!GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false)) + return false; + CVector vecBetween = point2 - point1; + uint32 nSteps = Max(vecBetween.Magnitude(), maxSteps); + if (nSteps == 0) + return true; + vecBetween.Normalise(); + uint32 step = 1; + for (step = 1; step < nSteps; step++) { + CVector posThisStep = point1 + vecBetween * step; + float level; + if (!CWaterLevel::GetWaterLevel(posThisStep, &level, false)) + continue; + posThisStep.z = level; + AdvanceCurrentScanCode(); + + CVector vecCheckedPos(posThisStep.x, posThisStep.y, Max(point1.z, point2.z)); + CColPoint colpoint; + CEntity* entity; + if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)), + CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil)) + return false; + } + + CVector posThisStep = point1; + AdvanceCurrentScanCode(); + CVector vecCheckedPos(posThisStep.x, posThisStep.y, point1.z - 5.0f); + + CColPoint colpoint; + CEntity* entity; + if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)), + CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil)) + return false; + + float heightNextStep = colpoint.point.z + 0.5f; + for (step = 1; step < nSteps; step++) { + CVector posThisStep = point1 + vecBetween * step; + posThisStep.z = heightNextStep; + AdvanceCurrentScanCode(); + CVector vecCheckedPos(posThisStep.x, posThisStep.y, heightNextStep - 2.0f); + if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)), + CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil)) + return false; + if (Abs(colpoint.point.z - heightNextStep) > 1.0f) + return false; + heightNextStep = colpoint.point.z + 0.5f; + } + return true; +} diff --git a/src/core/World.h b/src/core/World.h index bc905bf5..89f05cfd 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -125,6 +125,8 @@ public: static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY); static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2); + static bool IsWanderPathClear(CVector const&, CVector const&, float, int); + static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); } static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); } static int GetSectorIndexX(float f) { return (int)GetSectorX(f); } diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 7d4f4d12..f90dffa8 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -216,7 +216,7 @@ CCivilianPed::ProcessControl(void) // fall through case PED_SEEK_POS: if (Seek()) { - if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && m_pNextPathNode) { + if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) && m_pNextPathNode) { m_pNextPathNode = nil; #ifdef TOGGLEABLE_BETA_FEATURES } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) { @@ -248,7 +248,7 @@ CCivilianPed::ProcessControl(void) } else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT && m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) { SetMoveState(m_pedInObjective->m_nMoveState); - } else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) { + } else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) { SetIdle(); } else { RestorePreviousState(); @@ -422,9 +422,8 @@ void CCivilianPed::UseNearbyAttractors() CSector* s = CWorld::GetSector(x, y); for (CPtrNode* pNode = s->m_lists[ENTITYLIST_BUILDINGS].first; pNode != nil; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (!pEntity->IsObject()) - continue; - // TODO: some flag check + //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) + //continue; CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { C2dEffect* pEffect = pModelInfo->Get2dEffect(i); @@ -433,7 +432,7 @@ void CCivilianPed::UseNearbyAttractors() if (!IsAttractedTo(pEffect->pedattr.type)) continue; CVector pos; - CPedAttractorManager::ComputeEffectPos(pEffect, GetMatrix(), pos); + CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos); if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { CPedAttractorManager* pManager = GetPedAttractorManager(); if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { @@ -446,9 +445,10 @@ void CCivilianPed::UseNearbyAttractors() } for (CPtrNode* pNode = s->m_lists[ENTITYLIST_OBJECTS].first; pNode != nil; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (!pEntity->IsObject()) - continue; - // TODO: some flag check + //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) + //continue; + if (pEntity->GetModelIndex() == 3181) + debug("get2\n"); CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { C2dEffect* pEffect = pModelInfo->Get2dEffect(i); @@ -457,7 +457,7 @@ void CCivilianPed::UseNearbyAttractors() if (!IsAttractedTo(pEffect->pedattr.type)) continue; CVector pos; - CPedAttractorManager::ComputeEffectPos(pEffect, GetMatrix(), pos); + CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos); if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { CPedAttractorManager* pManager = GetPedAttractorManager(); if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { @@ -482,7 +482,7 @@ bool CCivilianPed::IsAttractedTo(int8 type) case ATTRACTOR_STOP: return true; case ATTRACTOR_PIZZA: return true; case ATTRACTOR_SHELTER: return CWeather::Rain >= 0.2f; - case ATTRACTOR_ICECREAM: return true; + case ATTRACTOR_ICECREAM: return false; } return false; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 1441e1d5..6cc16ad2 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -5529,17 +5529,17 @@ CPed::SetWaitState(eWaitState state, void *time) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); break; case WAITSTATE_SIT_DOWN: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 4.0f); // TODO(MIAMI): proper anim! animAssoc->SetFinishCallback(FinishedWaitCB, this); m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000; break; case WAITSTATE_SIT_UP: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 4.0f); // TODO(MIAMI): proper anim! animAssoc->SetFinishCallback(FinishedWaitCB, this); m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; break; case WAITSTATE_SIT_IDLE: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 5000.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 5000.0f); // TODO(MIAMI): proper anim! animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -5547,7 +5547,7 @@ CPed::SetWaitState(eWaitState state, void *time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000); break; case WAITSTATE_USE_ATM: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 5000.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 5000.0f); // TODO(MIAMI): proper anim! animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -14046,7 +14046,7 @@ CPed::ProcessObjective(void) if (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) { switch (m_objective) { case OBJECTIVE_USE_SEAT_ATTRACTOR: - if (bTurnedAroundOnAttractor) { + if (!bTurnedAroundOnAttractor) { ClearObjective(); SetWaitState(WAITSTATE_SIT_DOWN, 0); } @@ -17998,19 +17998,19 @@ CPed::ClearWaitState(void) AnimationId id; switch (m_nWaitState) { // TODO(MIAMI): actual! case WAITSTATE_PLAYANIM_CHAT: id = ANIM_IDLE_CHAT; break; - case WAITSTATE_SIT_DOWN: id = ANIM_XPRESS_SCRATCH; break; - case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_XPRESS_SCRATCH; break; - case WAITSTATE_SIT_UP: id = ANIM_XPRESS_SCRATCH; break; - case WAITSTATE_SIT_IDLE: id = ANIM_XPRESS_SCRATCH; break; - case WAITSTATE_USE_ATM: id = ANIM_XPRESS_SCRATCH; break; + case WAITSTATE_SIT_DOWN: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_UP: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_IDLE: id = ANIM_HANDSUP; break; + case WAITSTATE_USE_ATM: id = ANIM_HANDSUP; break; } CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetAssociation(GetClump(), id); if (pAssoc) pAssoc->blendDelta = -8.0f; if (m_attractor) GetPedAttractorManager()->DeRegisterPed(this, m_attractor); - break; } + break; case WAITSTATE_RIOT: case WAITSTATE_FAST_FALL: case WAITSTATE_BOMBER: diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp index bef14308..a3b93067 100644 --- a/src/peds/PedAttactor.cpp +++ b/src/peds/PedAttactor.cpp @@ -485,7 +485,7 @@ bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttracto return false; if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) return nil; - if (IsPedRegisteredWithEffect(pPed)) + if (!IsPedRegisteredWithEffect(pPed)) return nil; switch (pAttractor->GetEffect()->pedattr.type) { case ATTRACTOR_ATM: return BroadcastArrival(pPed, pAttractor, vAtmAttractors); @@ -504,7 +504,7 @@ bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttrac return false; if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) return nil; - if (IsPedRegisteredWithEffect(pPed)) + if (!IsPedRegisteredWithEffect(pPed)) return nil; switch (pAttractor->GetEffect()->pedattr.type) { case ATTRACTOR_ATM: return BroadcastDeparture(pPed, pAttractor, vAtmAttractors); @@ -523,7 +523,7 @@ bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor return false; if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) return nil; - if (IsPedRegisteredWithEffect(pPed)) + if (!IsPedRegisteredWithEffect(pPed)) return nil; switch (pAttractor->GetEffect()->pedattr.type) { case ATTRACTOR_ATM: return IsAtHeadOfQueue(pPed, pAttractor, vAtmAttractors); @@ -542,7 +542,7 @@ bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor) return false; if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR) return nil; - if (IsPedRegisteredWithEffect(pPed)) + if (!IsPedRegisteredWithEffect(pPed)) return nil; switch (pAttractor->GetEffect()->pedattr.type) { case ATTRACTOR_ATM: return IsInQueue(pPed, pAttractor, vAtmAttractors); @@ -747,13 +747,13 @@ bool CPedAttractorManager::IsApproachable(C2dEffect* pEffect, const CMatrix& mat ComputeEffectPos(pEffect, matrix, vecEffectPos); float dp = -DotProduct(vecUseDir, vecEffectPos); if (pEffect->pedattr.type == ATTRACTOR_ATM || pEffect->pedattr.type == ATTRACTOR_PIZZA || pEffect->pedattr.type == ATTRACTOR_ICECREAM) { - vecUseDir = vecUseDir; + vecUseDir = -vecUseDir; dp = -dp; } if (dp + DotProduct(vecEffectPos, pPed->GetPosition()) > 0.0f) { CVector vecPedToAttractor = pPed->GetPosition() - vecEffectPos; vecPedToAttractor.Normalise(); - if (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f /* && CWorld::IsWanderPathClear(pPed, vecEffectPos, 2.0f, 0) */) + if (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f && CWorld::IsWanderPathClear(pPed->GetPosition(), vecEffectPos, 2.0f, 0)) return true; } return false; diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index 33b553bd..ed5ce5ba 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -65,8 +65,8 @@ public: uint8 probability; }; struct PedAttractor { - CVector useDir; CVector queueDir; + CVector useDir; int8 type; }; From f864698696fc5451372dffbc37255d4be0fa08ee Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 02:10:23 +0300 Subject: [PATCH 004/148] ped attractors --- src/peds/Ped.cpp | 18 +++++++++--------- src/peds/Ped.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 094ecb7c..e67062f0 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -5859,17 +5859,17 @@ CPed::SetWaitState(eWaitState state, void *time) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f); break; case WAITSTATE_SIT_DOWN: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 4.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_DOWN, 4.0f); animAssoc->SetFinishCallback(FinishedWaitCB, this); m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000; break; case WAITSTATE_SIT_UP: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 4.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_UP, 4.0f); animAssoc->SetFinishCallback(FinishedWaitCB, this); m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; break; case WAITSTATE_SIT_IDLE: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 5000.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_IDLE, 5000.0f); animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -5877,7 +5877,7 @@ CPed::SetWaitState(eWaitState state, void *time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000); break; case WAITSTATE_USE_ATM: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 5000.0f); // TODO(MIAMI): proper anim! + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ATM, 5000.0f); animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -18335,11 +18335,11 @@ CPed::ClearWaitState(void) AnimationId id; switch (m_nWaitState) { // TODO(MIAMI): actual! case WAITSTATE_PLAYANIM_CHAT: id = ANIM_IDLE_CHAT; break; - case WAITSTATE_SIT_DOWN: id = ANIM_HANDSUP; break; - case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_HANDSUP; break; - case WAITSTATE_SIT_UP: id = ANIM_HANDSUP; break; - case WAITSTATE_SIT_IDLE: id = ANIM_HANDSUP; break; - case WAITSTATE_USE_ATM: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_DOWN: id = ANIM_SEAT_DOWN; break; + case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_SEAT_DOWN2; break; + case WAITSTATE_SIT_UP: id = ANIM_SEAT_UP; break; + case WAITSTATE_SIT_IDLE: id = ANIM_SEAT_IDLE; break; + case WAITSTATE_USE_ATM: id = ANIM_ATM; break; } CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetAssociation(GetClump(), id); if (pAssoc) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 4efad358..f86f23d3 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -865,8 +865,8 @@ public: void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int); void ClearWaitState(void); - bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } - CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } + bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; } + CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } PedState GetPedState(void) { return m_nPedState; } From a4562c5720e9b6f1591f1461b646e276821eee67 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 02:15:24 +0300 Subject: [PATCH 005/148] fixed spaces/tabs --- src/peds/PedAttractor.h | 252 ++++++++++++++++++++-------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h index 3171d228..3408be93 100644 --- a/src/peds/PedAttractor.h +++ b/src/peds/PedAttractor.h @@ -11,55 +11,55 @@ class CPedAttractor; class CVehicleToEffect { - CVehicle* m_pVehicle; - C2dEffect m_effects[NUM_ATTRACTORS_FOR_ICECREAM_VAN]; + CVehicle* m_pVehicle; + C2dEffect m_effects[NUM_ATTRACTORS_FOR_ICECREAM_VAN]; public: - CVehicleToEffect(CVehicle* pVehicle); - const C2dEffect* ChooseEffect(const CVector& pos) const; - CVehicleToEffect& From(const CVehicleToEffect& other); - CVehicleToEffect& operator=(const CVehicleToEffect& other) { return From(other); } - ~CVehicleToEffect() { m_pVehicle = nil; } - CVehicle* GetVehicle() const { return m_pVehicle; } - bool HasThisEffect(C2dEffect* pEffect) const; - const C2dEffect* GetEffect(int32 i) const { return &m_effects[i]; } + CVehicleToEffect(CVehicle* pVehicle); + const C2dEffect* ChooseEffect(const CVector& pos) const; + CVehicleToEffect& From(const CVehicleToEffect& other); + CVehicleToEffect& operator=(const CVehicleToEffect& other) { return From(other); } + ~CVehicleToEffect() { m_pVehicle = nil; } + CVehicle* GetVehicle() const { return m_pVehicle; } + bool HasThisEffect(C2dEffect* pEffect) const; + const C2dEffect* GetEffect(int32 i) const { return &m_effects[i]; } }; class CPedAttractorManager { - std::vector vAtmAttractors; - std::vector vSeatAttractors; - std::vector vStopAttractors; - std::vector vPizzaAttractors; - std::vector vShelterAttractors; - std::vector vIceCreamAttractors; - std::vector vVehicleToEffect; + std::vector vAtmAttractors; + std::vector vSeatAttractors; + std::vector vStopAttractors; + std::vector vPizzaAttractors; + std::vector vShelterAttractors; + std::vector vIceCreamAttractors; + std::vector vVehicleToEffect; public: - CPedAttractor* RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix); - CPedAttractor* RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector& vecAttractors); - bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor); - bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); - const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos); - bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed); - void RemoveIceCreamVanEffects(C2dEffect* pEffect); - bool HasEmptySlot(const C2dEffect* pEffect); - const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector& vecAttractors); - bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor); - bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); - bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor); - bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); - bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor); - bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); - bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor); - bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); - bool IsPedRegisteredWithEffect(CPed* pPed); - bool IsPedRegistered(CPed* pPed, std::vector& vecAttractors); - CVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect); + CPedAttractor* RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix); + CPedAttractor* RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector& vecAttractors); + bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor); + bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); + const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos); + bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed); + void RemoveIceCreamVanEffects(C2dEffect* pEffect); + bool HasEmptySlot(const C2dEffect* pEffect); + const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector& vecAttractors); + bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor); + bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); + bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor); + bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); + bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor); + bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); + bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor); + bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector& vecAttractors); + bool IsPedRegisteredWithEffect(CPed* pPed); + bool IsPedRegistered(CPed* pPed, std::vector& vecAttractors); + CVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect); - static void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); - static void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); - static void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + static void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + static void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); + static void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos); }; @@ -67,12 +67,12 @@ CPedAttractorManager* GetPedAttractorManager(); enum ePedAttractorType { - ATTRACTOR_ATM = 0, - ATTRACTOR_SEAT, - ATTRACTOR_STOP, - ATTRACTOR_PIZZA, - ATTRACTOR_SHELTER, - ATTRACTOR_ICECREAM + ATTRACTOR_ATM = 0, + ATTRACTOR_SEAT, + ATTRACTOR_STOP, + ATTRACTOR_PIZZA, + ATTRACTOR_SHELTER, + ATTRACTOR_ICECREAM }; class CPedAttractor @@ -81,123 +81,123 @@ protected: C2dEffect* p2dEffect; std::vector vApproachingQueue; std::vector vWaitingQueue; - int32 m_nMaxPedsInAttractor; - float m_fQueueDistance; - float m_fTimeInWaitQueue; - float m_fTimeInApproachingQueue; - float m_fDistanceToUseAttractor; - float m_fAcceptableHeading; - float m_fMaxPositionDisplacement; - float m_fMaxHeadingDisplacement; - CVector vecEffectPos; - CVector vecQueueDir; - CVector vecUseDir; + int32 m_nMaxPedsInAttractor; + float m_fQueueDistance; + float m_fTimeInWaitQueue; + float m_fTimeInApproachingQueue; + float m_fDistanceToUseAttractor; + float m_fAcceptableHeading; + float m_fMaxPositionDisplacement; + float m_fMaxHeadingDisplacement; + CVector vecEffectPos; + CVector vecQueueDir; + CVector vecUseDir; public: - virtual float GetHeadOfQueueWaitTime() { return 0.0f; } - virtual ~CPedAttractor() {}; - virtual ePedAttractorType GetType() const = 0; - virtual void UpdatePedStateOnDeparture(CPed* pPed) const = 0; - virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; } - virtual void ComputeAttractPos(int32 id, CVector& pos) const; - virtual void ComputeAttractHeading(int32 id, float& pHeading) const; - virtual bool BroadcastDeparture(CPed* pPed); + virtual float GetHeadOfQueueWaitTime() { return 0.0f; } + virtual ~CPedAttractor() {}; + virtual ePedAttractorType GetType() const = 0; + virtual void UpdatePedStateOnDeparture(CPed* pPed) const = 0; + virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; } + virtual void ComputeAttractPos(int32 id, CVector& pos) const; + virtual void ComputeAttractHeading(int32 id, float& pHeading) const; + virtual bool BroadcastDeparture(CPed* pPed); - bool IsRegisteredWithPed(CPed* pPed) const; - bool DeRegisterPed(CPed* pPed); - float ComputeDeltaHeading() const; - float ComputeDeltaPos() const; - void ComputeAttractTime(int32 id, bool, float& time) const; - int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); } - int32 ComputeFreeSlot() const { return vWaitingQueue.size(); } - bool IsInQueue(CPed*) const; - bool RegisterPed(CPed*); - bool BroadcastArrival(CPed*); + bool IsRegisteredWithPed(CPed* pPed) const; + bool DeRegisterPed(CPed* pPed); + float ComputeDeltaHeading() const; + float ComputeDeltaPos() const; + void ComputeAttractTime(int32 id, bool, float& time) const; + int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); } + int32 ComputeFreeSlot() const { return vWaitingQueue.size(); } + bool IsInQueue(CPed*) const; + bool RegisterPed(CPed*); + bool BroadcastArrival(CPed*); - CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp); + CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp); - C2dEffect* GetEffect() const { return p2dEffect; } - const CVector& GetEffectPos() const { return vecEffectPos; } - int32 GetMaxPedsInAttractor() const { return m_nMaxPedsInAttractor; } - float GetDistanceToCountSeekDone() const { return m_fDistanceToUseAttractor; } - float GetAcceptableHeading() const { return m_fAcceptableHeading; } + C2dEffect* GetEffect() const { return p2dEffect; } + const CVector& GetEffectPos() const { return vecEffectPos; } + int32 GetMaxPedsInAttractor() const { return m_nMaxPedsInAttractor; } + float GetDistanceToCountSeekDone() const { return m_fDistanceToUseAttractor; } + float GetAcceptableHeading() const { return m_fAcceptableHeading; } }; class CPedAtmAttractor : public CPedAttractor { public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; }; - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override { /* pPed->m_money += 20 * CGeneral::GetRandomNumberInRange(1, 51); */ }; - CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; + virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; }; + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override { /* pPed->m_money += 20 * CGeneral::GetRandomNumberInRange(1, 51); */ }; + CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; }; class CPedIceCreamAttractor : public CPedAttractor { public: - virtual ~CPedIceCreamAttractor() override { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); } - virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; } - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; + virtual ~CPedIceCreamAttractor() override { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); } + virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; }; class CPedPizzaAttractor : public CPedAttractor { public: - virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; } - virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; } - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override - { /* - if (pPed->m_money > 10) - pPed->m_money = 0; - else - pPed->m_money -= 10; - */ - } - CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; + virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; } + virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override + { /* + if (pPed->m_money > 10) + pPed->m_money = 0; + else + pPed->m_money -= 10; + */ + } + CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; }; class CPedSeatAttractor : public CPedAttractor { public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; } - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; + virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; }; class CPedShelterAttractor : public CPedAttractor { - static std::vector ms_displacements; + static std::vector ms_displacements; public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; } - virtual bool BroadcastDeparture(CPed*) override; - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; } - virtual void ComputeAttractPos(int qid, CVector& pos) const override; - virtual void ComputeAttractHeading(int qid, float& heading) const override; + virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; } + virtual bool BroadcastDeparture(CPed*) override; + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; } + virtual void ComputeAttractPos(int qid, CVector& pos) const override; + virtual void ComputeAttractHeading(int qid, float& heading) const override; - CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; + CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; - CVector GetDisplacement(int32 qid) const; + CVector GetDisplacement(int32 qid) const; }; class CPedStopAttractor : public CPedAttractor { public: - virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; } - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; + virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; } + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) - {}; + CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + {}; }; \ No newline at end of file From ec1b91e5270b1c91885a5e8000a5ff8286aee140 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 16 May 2020 05:06:51 +0300 Subject: [PATCH 006/148] Remove unused audio enum --- src/audio/AudioManager.cpp | 8 +- src/audio/AudioManager.h | 2 - src/audio/AudioScriptObject.cpp | 2 +- src/audio/AudioScriptObject.h | 130 ------- src/audio/soundlist.h | 586 ++++++++++++++++---------------- src/control/Phones.cpp | 5 +- src/objects/Object.cpp | 9 +- src/peds/Ped.cpp | 10 +- src/render/Glass.cpp | 11 +- src/render/Particle.cpp | 5 +- 10 files changed, 321 insertions(+), 447 deletions(-) diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index b76c2cc3..8ef439d9 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -630,10 +630,10 @@ cAudioManager::CreateEntity(int32 type, void *entity) m_asAudioEntities[i].m_nStatus = 0; m_asAudioEntities[i].m_nType = (eAudioType)type; m_asAudioEntities[i].m_pEntity = entity; - m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_TOTAL_PED_SOUNDS; - m_asAudioEntities[i].m_awAudioEvent[1] = SOUND_TOTAL_PED_SOUNDS; - m_asAudioEntities[i].m_awAudioEvent[2] = SOUND_TOTAL_PED_SOUNDS; - m_asAudioEntities[i].m_awAudioEvent[3] = SOUND_TOTAL_PED_SOUNDS; + m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_awAudioEvent[1] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_awAudioEvent[2] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_awAudioEvent[3] = SOUND_NO_SOUND; m_asAudioEntities[i].m_AudioEvents = 0; m_anAudioEntityIndices[m_nAudioEntitiesTotal++] = i; return i; diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 99d67444..bbbc84bd 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -467,8 +467,6 @@ public: // only used in pc void AdjustSamplesVolume(); uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); - - void DebugShit(); }; #ifdef AUDIO_MSS diff --git a/src/audio/AudioScriptObject.cpp b/src/audio/AudioScriptObject.cpp index 3d84006d..69d80fbc 100644 --- a/src/audio/AudioScriptObject.cpp +++ b/src/audio/AudioScriptObject.cpp @@ -7,7 +7,7 @@ void cAudioScriptObject::Reset() { - AudioId = SCRSOUND_INVALID; + AudioId = SCRIPT_SOUND_INVALID; Posn = CVector(0.0f, 0.0f, 0.0f); AudioEntity = AEHANDLE_NONE; } diff --git a/src/audio/AudioScriptObject.h b/src/audio/AudioScriptObject.h index ecc07fdf..ff36474d 100644 --- a/src/audio/AudioScriptObject.h +++ b/src/audio/AudioScriptObject.h @@ -1,135 +1,5 @@ #pragma once -enum -{ - SCRSOUND_TEST_1, - _SCRSOUND_UNK_1, - _SCRSOUND_UNK_2, - _SCRSOUND_UNK_3, - _SCRSOUND_CLUB_1_S, - _SCRSOUND_CLUB_1_L, - _SCRSOUND_CLUB_2_S, - _SCRSOUND_CLUB_2_L, - _SCRSOUND_CLUB_3_S, - _SCRSOUND_CLUB_3_L, - _SCRSOUND_CLUB_4_S, - _SCRSOUND_CLUB_4_L, - _SCRSOUND_CLUB_5_S, - _SCRSOUND_CLUB_5_L, - _SCRSOUND_CLUB_6_S, - _SCRSOUND_CLUB_6_L, - _SCRSOUND_CLUB_7_S, - _SCRSOUND_CLUB_7_L, - _SCRSOUND_CLUB_8_S, - _SCRSOUND_CLUB_8_L, - _SCRSOUND_CLUB_9_S, - _SCRSOUND_CLUB_9_L, - _SCRSOUND_CLUB_10_S, - _SCRSOUND_CLUB_10_L, - _SCRSOUND_CLUB_11_S, - _SCRSOUND_CLUB_11_L, - _SCRSOUND_CLUB_12_S, - _SCRSOUND_CLUB_12_L, - _SCRSOUND_CLUB_RAGGA_S, - _SCRSOUND_CLUB_RAGGA_L, - SCRSOUND_STRIP_CLUB_LOOP_1_S, - _SCRSOUND_STRIP_CLUB_LOOP_1_L, - SCRSOUND_STRIP_CLUB_LOOP_2_S, - _SCRSOUND_STRIP_CLUB_LOOP_2_L, - _SCRSOUND_SFX_WORKSHOP_1, - _SCRSOUND_SFX_WORKSHOP_2, - _SCRSOUND_SAWMILL_LOOP_S, - SCRSOUND_SAWMILL_LOOP_L, - _SCRSOUND_DOG_FOOD_FACTORY_S, - _SCRSOUND_DOG_FOOD_FACTORY_L, - _SCRSOUND_LAUNDERETTE_1, - _SCRSOUND_LAUNDERETTE_2, - _SCRSOUND_RESTAURANT_CHINATOWN_S, - _SCRSOUND_RESTAURANT_CHINATOWN_L, - _SCRSOUND_RESTAURANT_ITALY_S, - _SCRSOUND_RESTAURANT_ITALY_L, - _SCRSOUND_RESTAURANT_GENERIC_1_S, - _SCRSOUND_RESTAURANT_GENERIC_1_L, - _SCRSOUND_RESTAURANT_GENERIC_2_S, - _SCRSOUND_RESTAURANT_GENERIC_2_L, - _SCRSOUND_AIRPORT_ANNOUNCEMENT_S, - _SCRSOUND_AIRPORT_ANNOUNCEMENT_L, - _SCRSOUND_SHOP_LOOP_1, - _SCRSOUND_SHOP_LOOP_2, - _SCRSOUND_CINEMA_S, - _SCRSOUND_CINEMA_L, - _SCRSOUND_DOCKS_FOGHORN_S, - _SCRSOUND_DOCKS_FOGHORN_L, - _SCRSOUND_HOME_S, - _SCRSOUND_HOME_L, - _SCRSOUND_PIANO_BAR, - _SCRSOUND_CLUB, - SCRSOUND_PORN_CINEMA_1_S, - _SCRSOUND_PORN_CINEMA_1_L, - SCRSOUND_PORN_CINEMA_2_S, - _SCRSOUND_PORN_CINEMA_2_L, - SCRSOUND_PORN_CINEMA_3_S, - _SCRSOUND_PORN_CINEMA_3_L, - _SCRSOUND_BANK_ALARM_LOOP_S, - SCRSOUND_BANK_ALARM_LOOP_L, - _SCRSOUND_POLICE_BALL_LOOP_S, - SCRSOUND_POLICE_BALL_LOOP_L, - _SCRSOUND_RAVE_LOOP_INDUSTRIAL_S, - SCRSOUND_RAVE_LOOP_INDUSTRIAL_L, - _SCRSOUND_UNK_74, - _SCRSOUND_UNK_75, - _SCRSOUND_POLICE_CELL_BEATING_LOOP_S, - SCRSOUND_POLICE_CELL_BEATING_LOOP_L, - SCRSOUND_INJURED_PED_MALE_OUCH_S, - SCRSOUND_INJURED_PED_MALE_OUCH_L, - SCRSOUND_INJURED_PED_FEMALE_OUCH_S, - SCRSOUND_INJURED_PED_FEMALE_OUCH_L, - SCRSOUND_EVIDENCE_PICKUP, - SCRSOUND_UNLOAD_GOLD, - _SCRSOUND_RAVE_INDUSTRIAL_S, - _SCRSOUND_RAVE_INDUSTRIAL_L, - _SCRSOUND_RAVE_COMMERCIAL_S, - _SCRSOUND_RAVE_COMMERCIAL_L, - _SCRSOUND_RAVE_SUBURBAN_S, - _SCRSOUND_RAVE_SUBURBAN_L, - _SCRSOUND_GROAN_S, - _SCRSOUND_GROAN_L, - SCRSOUND_GATE_START_CLUNK, - SCRSOUND_GATE_STOP_CLUNK, - SCRSOUND_PART_MISSION_COMPLETE, - SCRSOUND_CHUNKY_RUN_SHOUT, - SCRSOUND_SECURITY_GUARD_RUN_AWAY_SHOUT, - SCRSOUND_RACE_START_1, - SCRSOUND_RACE_START_2, - SCRSOUND_RACE_START_3, - SCRSOUND_RACE_START_GO, - SCRSOUND_SWAT_PED_SHOUT, - SCRSOUND_PRETEND_FIRE_LOOP, - SCRSOUND_AMMUNATION_CHAT_1, - SCRSOUND_AMMUNATION_CHAT_2, - SCRSOUND_AMMUNATION_CHAT_3, - _SCRSOUND_BULLET_WALL_1, - _SCRSOUND_BULLET_WALL_2, - _SCRSOUND_BULLET_WALL_3, - _SCRSOUND_UNK_109, - _SCRSOUND_GLASSFX2_1, - _SCRSOUND_GLASSFX2_2, - _SCRSOUND_PHONE_RING, - _SCRSOUND_UNK_113, - _SCRSOUND_GLASS_SMASH_1, - _SCRSOUND_GLASS_SMASH_2, - _SCRSOUND_GLASS_CRACK, - _SCRSOUND_GLASS_SHARD, - _SCRSOUND_WOODEN_BOX_SMASH, - _SCRSOUND_CARDBOARD_BOX_SMASH, - _SCRSOUND_COL_CAR, - _SCRSOUND_TYRE_BUMP, - _SCRSOUND_BULLET_SHELL_HIT_GROUND_1, - _SCRSOUND_BULLET_SHELL_HIT_GROUND_2, - TOTAL_SCRSOUNDS, - SCRSOUND_INVALID -}; - class cAudioScriptObject { public: diff --git a/src/audio/soundlist.h b/src/audio/soundlist.h index 64d7dbcb..6d1ff6e3 100644 --- a/src/audio/soundlist.h +++ b/src/audio/soundlist.h @@ -1,301 +1,303 @@ #pragma once -enum eSound : int16 +enum eSound : uint16 { SOUND_CAR_DOOR_CLOSE_BONNET = 0, - SOUND_CAR_DOOR_CLOSE_BUMPER = 1, - SOUND_CAR_DOOR_CLOSE_FRONT_LEFT = 2, - SOUND_CAR_DOOR_CLOSE_FRONT_RIGHT = 3, - SOUND_CAR_DOOR_CLOSE_BACK_LEFT = 4, - SOUND_CAR_DOOR_CLOSE_BACK_RIGHT = 5, - SOUND_CAR_DOOR_OPEN_BONNET = 6, - SOUND_CAR_DOOR_OPEN_BUMPER = 7, - SOUND_CAR_DOOR_OPEN_FRONT_LEFT = 8, - SOUND_CAR_DOOR_OPEN_FRONT_RIGHT = 9, - SOUND_CAR_DOOR_OPEN_BACK_LEFT = 10, - SOUND_CAR_DOOR_OPEN_BACK_RIGHT = 11, - SOUND_CAR_WINDSHIELD_CRACK = 12, - SOUND_CAR_JUMP = 13, - SOUND_E = 14, - SOUND_F = 15, - SOUND_CAR_ENGINE_START = 16, - SOUND_CAR_LIGHT_BREAK = 17, - SOUND_CAR_HYDRAULIC_1 = 18, - SOUND_CAR_HYDRAULIC_2 = 19, - SOUND_CAR_HYDRAULIC_3 = 20, - SOUND_CAR_JERK = 21, - SOUND_CAR_SPLASH = 22, - SOUND_17 = 23, - SOUND_18 = 24, - SOUND_19 = 25, - SOUND_CAR_TANK_TURRET_ROTATE = 26, - SOUND_CAR_BOMB_TICK = 27, - SOUND_PLANE_ON_GROUND = 28, - SOUND_STEP_START = 29, - SOUND_STEP_END = 30, - SOUND_FALL_LAND = 31, - SOUND_FALL_COLLAPSE = 32, - SOUND_FIGHT_PUNCH_33 = 33, - SOUND_FIGHT_KICK_34 = 34, - SOUND_FIGHT_HEADBUTT_35 = 35, - SOUND_FIGHT_PUNCH_36 = 36, - SOUND_FIGHT_PUNCH_37 = 37, - SOUND_FIGHT_CLOSE_PUNCH_38 = 38, - SOUND_FIGHT_PUNCH_39 = 39, - SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 = 40, - SOUND_FIGHT_PUNCH_41 = 41, - SOUND_FIGHT_PUNCH_FROM_BEHIND_42 = 42, - SOUND_FIGHT_KNEE_OR_KICK_43 = 43, - SOUND_FIGHT_KICK_44 = 44, - SOUND_2D = 45, - SOUND_WEAPON_BAT_ATTACK = 46, - SOUND_WEAPON_SHOT_FIRED = 47, - SOUND_WEAPON_RELOAD = 48, - SOUND_WEAPON_AK47_BULLET_ECHO = 49, - SOUND_WEAPON_UZI_BULLET_ECHO = 50, - SOUND_WEAPON_M16_BULLET_ECHO = 51, - SOUND_WEAPON_FLAMETHROWER_FIRE = 52, - SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM = 53, - SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM = 54, - SOUND_WEAPON_HIT_PED = 55, - SOUND_WEAPON_HIT_VEHICLE = 56, - SOUND_GARAGE_NO_MONEY = 57, - SOUND_GARAGE_BAD_VEHICLE = 58, - SOUND_GARAGE_OPENING = 59, - SOUND_GARAGE_BOMB_ALREADY_SET = 60, - SOUND_GARAGE_BOMB1_SET = 61, - SOUND_GARAGE_BOMB2_SET = 62, - SOUND_GARAGE_BOMB3_SET = 63, - SOUND_40 = 64, - SOUND_41 = 65, - SOUND_GARAGE_VEHICLE_DECLINED = 66, - SOUND_GARAGE_VEHICLE_ACCEPTED = 67, - SOUND_GARAGE_DOOR_CLOSED = 68, - SOUND_GARAGE_DOOR_OPENED = 69, - SOUND_CRANE_PICKUP = 70, - SOUND_PICKUP_WEAPON_BOUGHT = 71, - SOUND_PICKUP_WEAPON = 72, - SOUND_PICKUP_HEALTH = 73, - SOUND_4A = 74, - SOUND_4B = 75, - SOUND_PICKUP_ADRENALINE = 76, - SOUND_PICKUP_ARMOUR = 77, - SOUND_PICKUP_BONUS = 78, - SOUND_PICKUP_MONEY = 79, - SOUND_PICKUP_HIDDEN_PACKAGE = 80, - SOUND_PICKUP_PACMAN_PILL = 81, - SOUND_PICKUP_PACMAN_PACKAGE = 82, - SOUND_PICKUP_FLOAT_PACKAGE = 83, - SOUND_BOMB_TIMED_ACTIVATED = 84, - SOUND_55 = 85, - SOUND_BOMB_ONIGNITION_ACTIVATED = 86, - SOUND_BOMB_TICK = 87, - SOUND_RAMPAGE_START = 88, - SOUND_RAMPAGE_ONGOING = 89, - SOUND_RAMPAGE_PASSED = 90, - SOUND_RAMPAGE_FAILED = 91, - SOUND_RAMPAGE_KILL = 92, - SOUND_RAMPAGE_CAR_BLOWN = 93, - SOUND_EVIDENCE_PICKUP = 94, - SOUND_UNLOAD_GOLD = 95, - SOUND_PAGER = 96, - SOUND_PED_DEATH = 97, // 103 in VC - SOUND_PED_DAMAGE = 98, // 104 in VC - SOUND_PED_HIT = 99, // 105 in VC - SOUND_PED_LAND = 100, // hopefully 106 in VC - SOUND_PED_BULLET_HIT = 101, - SOUND_PED_BOMBER = 102, - SOUND_PED_BURNING = 103, // 108 in VC - SOUND_PED_ARREST_FBI = 104, - SOUND_PED_ARREST_SWAT = 105, - SOUND_PED_ARREST_COP = 106, - SOUND_PED_HELI_PLAYER_FOUND = 107, - SOUND_PED_HANDS_UP = 108, - SOUND_PED_HANDS_COWER = 109, - SOUND_PED_FLEE_SPRINT = 110, // 120 in VC - SOUND_PED_CAR_JACKING = 111, - SOUND_PED_MUGGING = 112, - SOUND_PED_CAR_JACKED = 113, - SOUND_PED_ROBBED = 114, - SOUND_PED_TAXI_WAIT = 115, // 137 in VC - SOUND_PED_ATTACK = 116, - SOUND_PED_DEFEND = 117, - SOUND_PED_PURSUIT_ARMY = 118, - SOUND_PED_PURSUIT_FBI = 119, - SOUND_PED_PURSUIT_SWAT = 120, - SOUND_PED_PURSUIT_COP = 121, - SOUND_PED_HEALING = 122, - SOUND_PED_7B = 123, - SOUND_PED_LEAVE_VEHICLE = 124, - SOUND_PED_EVADE = 125, // 142 in VC - SOUND_PED_FLEE_RUN = 126, - SOUND_PED_CAR_COLLISION = 127, // 144-145-146 in VC - SOUND_PED_SOLICIT = 128, - SOUND_PED_EXTINGUISHING_FIRE = 129, - SOUND_PED_WAIT_DOUBLEBACK = 130, - SOUND_PED_CHAT_SEXY = 131, - SOUND_PED_CHAT_EVENT = 132, - SOUND_PED_CHAT = 133, - SOUND_PED_BODYCAST_HIT = 134, - SOUND_PED_TAXI_CALL = 135, - SOUND_INJURED_PED_MALE_OUCH = 136, - SOUND_INJURED_PED_FEMALE = 137, - SOUND_INJURED_PED_MALE_PRISON = 138, - SOUND_RACE_START_3 = 139, - SOUND_RACE_START_2 = 140, - SOUND_RACE_START_1 = 141, - SOUND_RACE_START_GO = 142, - SOUND_SPLASH = 143, - SOUND_WATER_FALL = 144, - SOUND_SPLATTER = 145, - SOUND_CAR_PED_COLLISION = 146, - SOUND_CLOCK_TICK = 147, - SOUND_PART_MISSION_COMPLETE = 148, - SOUND_FRONTEND_MENU_STARTING = 149, - SOUND_FRONTEND_MENU_COMPLETED = 150, - SOUND_FRONTEND_MENU_DENIED = 151, - SOUND_FRONTEND_MENU_SUCCESS = 152, - SOUND_FRONTEND_EXIT = 153, - SOUND_9A = 154, - SOUND_9B = 155, - SOUND_FRONTEND_AUDIO_TEST = 156, - SOUND_FRONTEND_FAIL = 157, - SOUND_FRONTEND_NO_RADIO = 158, - SOUND_FRONTEND_RADIO_CHANGE = 159, - SOUND_A0 = 160, - SOUND_AMMUNATION_WELCOME_1 = 161, - SOUND_AMMUNATION_WELCOME_2 = 162, - SOUND_AMMUNATION_WELCOME_3 = 163, - SOUND_LIGHTNING = 164, - SOUND_A5 = 165, - SOUND_TOTAL_SOUNDS = 166, - SOUND_TOTAL_PED_SOUNDS = 167, + SOUND_CAR_DOOR_CLOSE_BUMPER, + SOUND_CAR_DOOR_CLOSE_FRONT_LEFT, + SOUND_CAR_DOOR_CLOSE_FRONT_RIGHT, + SOUND_CAR_DOOR_CLOSE_BACK_LEFT, + SOUND_CAR_DOOR_CLOSE_BACK_RIGHT, + SOUND_CAR_DOOR_OPEN_BONNET, + SOUND_CAR_DOOR_OPEN_BUMPER, + SOUND_CAR_DOOR_OPEN_FRONT_LEFT, + SOUND_CAR_DOOR_OPEN_FRONT_RIGHT, + SOUND_CAR_DOOR_OPEN_BACK_LEFT, + SOUND_CAR_DOOR_OPEN_BACK_RIGHT, + SOUND_CAR_WINDSHIELD_CRACK, + SOUND_CAR_JUMP, + SOUND_E, + SOUND_F, + SOUND_CAR_ENGINE_START, + SOUND_CAR_LIGHT_BREAK, + SOUND_CAR_HYDRAULIC_1, + SOUND_CAR_HYDRAULIC_2, + SOUND_CAR_HYDRAULIC_3, + SOUND_CAR_JERK, + SOUND_CAR_SPLASH, + SOUND_17, + SOUND_18, + SOUND_19, + SOUND_CAR_TANK_TURRET_ROTATE, + SOUND_CAR_BOMB_TICK, + SOUND_PLANE_ON_GROUND, + SOUND_STEP_START, + SOUND_STEP_END, + SOUND_FALL_LAND, + SOUND_FALL_COLLAPSE, + SOUND_FIGHT_PUNCH_33, + SOUND_FIGHT_KICK_34, + SOUND_FIGHT_HEADBUTT_35, + SOUND_FIGHT_PUNCH_36, + SOUND_FIGHT_PUNCH_37, + SOUND_FIGHT_CLOSE_PUNCH_38, + SOUND_FIGHT_PUNCH_39, + SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40, + SOUND_FIGHT_PUNCH_41, + SOUND_FIGHT_PUNCH_FROM_BEHIND_42, + SOUND_FIGHT_KNEE_OR_KICK_43, + SOUND_FIGHT_KICK_44, + SOUND_2D, + SOUND_WEAPON_BAT_ATTACK, + SOUND_WEAPON_SHOT_FIRED, + SOUND_WEAPON_RELOAD, + SOUND_WEAPON_AK47_BULLET_ECHO, + SOUND_WEAPON_UZI_BULLET_ECHO, + SOUND_WEAPON_M16_BULLET_ECHO, + SOUND_WEAPON_FLAMETHROWER_FIRE, + SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, + SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM, + SOUND_WEAPON_HIT_PED, + SOUND_WEAPON_HIT_VEHICLE, + SOUND_GARAGE_NO_MONEY, + SOUND_GARAGE_BAD_VEHICLE, + SOUND_GARAGE_OPENING, + SOUND_GARAGE_BOMB_ALREADY_SET, + SOUND_GARAGE_BOMB1_SET, + SOUND_GARAGE_BOMB2_SET, + SOUND_GARAGE_BOMB3_SET, + SOUND_40, + SOUND_41, + SOUND_GARAGE_VEHICLE_DECLINED, + SOUND_GARAGE_VEHICLE_ACCEPTED, + SOUND_GARAGE_DOOR_CLOSED, + SOUND_GARAGE_DOOR_OPENED, + SOUND_CRANE_PICKUP, + SOUND_PICKUP_WEAPON_BOUGHT, + SOUND_PICKUP_WEAPON, + SOUND_PICKUP_HEALTH, + SOUND_4A, + SOUND_4B, + SOUND_PICKUP_ADRENALINE, + SOUND_PICKUP_ARMOUR, + SOUND_PICKUP_BONUS, + SOUND_PICKUP_MONEY, + SOUND_PICKUP_HIDDEN_PACKAGE, + SOUND_PICKUP_PACMAN_PILL, + SOUND_PICKUP_PACMAN_PACKAGE, + SOUND_PICKUP_FLOAT_PACKAGE, + SOUND_BOMB_TIMED_ACTIVATED, + SOUND_55, + SOUND_BOMB_ONIGNITION_ACTIVATED, + SOUND_BOMB_TICK, + SOUND_RAMPAGE_START, + SOUND_RAMPAGE_ONGOING, + SOUND_RAMPAGE_PASSED, + SOUND_RAMPAGE_FAILED, + SOUND_RAMPAGE_KILL, + SOUND_RAMPAGE_CAR_BLOWN, + SOUND_EVIDENCE_PICKUP, + SOUND_UNLOAD_GOLD, + SOUND_PAGER, + SOUND_PED_DEATH, // 103 in VC + SOUND_PED_DAMAGE, // 104 in VC + SOUND_PED_HIT, // 105 in VC + SOUND_PED_LAND, // hopefully 106 in VC + SOUND_PED_BULLET_HIT, + SOUND_PED_BOMBER, + SOUND_PED_BURNING, // 108 in VC + SOUND_PED_ARREST_FBI, + SOUND_PED_ARREST_SWAT, + SOUND_PED_ARREST_COP, + SOUND_PED_HELI_PLAYER_FOUND, + SOUND_PED_HANDS_UP, + SOUND_PED_HANDS_COWER, + SOUND_PED_FLEE_SPRINT, // 120 in VC + SOUND_PED_CAR_JACKING, + SOUND_PED_MUGGING, + SOUND_PED_CAR_JACKED, + SOUND_PED_ROBBED, + SOUND_PED_TAXI_WAIT, // 137 in VC + SOUND_PED_ATTACK, + SOUND_PED_DEFEND, + SOUND_PED_PURSUIT_ARMY, + SOUND_PED_PURSUIT_FBI, + SOUND_PED_PURSUIT_SWAT, + SOUND_PED_PURSUIT_COP, + SOUND_PED_HEALING, + SOUND_PED_7B, + SOUND_PED_LEAVE_VEHICLE, + SOUND_PED_EVADE, // 142 in VC + SOUND_PED_FLEE_RUN, + SOUND_PED_CAR_COLLISION, // 144-145-146 in VC + SOUND_PED_SOLICIT, + SOUND_PED_EXTINGUISHING_FIRE, + SOUND_PED_WAIT_DOUBLEBACK, + SOUND_PED_CHAT_SEXY, + SOUND_PED_CHAT_EVENT, + SOUND_PED_CHAT, + SOUND_PED_BODYCAST_HIT, + SOUND_PED_TAXI_CALL, + SOUND_INJURED_PED_MALE_OUCH, + SOUND_INJURED_PED_FEMALE, + SOUND_INJURED_PED_MALE_PRISON, + SOUND_RACE_START_3, + SOUND_RACE_START_2, + SOUND_RACE_START_1, + SOUND_RACE_START_GO, + SOUND_SPLASH, + SOUND_WATER_FALL, + SOUND_SPLATTER, + SOUND_CAR_PED_COLLISION, + SOUND_CLOCK_TICK, + SOUND_PART_MISSION_COMPLETE, + SOUND_FRONTEND_MENU_STARTING, + SOUND_FRONTEND_MENU_COMPLETED, + SOUND_FRONTEND_MENU_DENIED, + SOUND_FRONTEND_MENU_SUCCESS, + SOUND_FRONTEND_EXIT, + SOUND_9A, + SOUND_9B, + SOUND_FRONTEND_AUDIO_TEST, + SOUND_FRONTEND_FAIL, + SOUND_FRONTEND_NO_RADIO, + SOUND_FRONTEND_RADIO_CHANGE, + SOUND_A0, + SOUND_AMMUNATION_WELCOME_1, + SOUND_AMMUNATION_WELCOME_2, + SOUND_AMMUNATION_WELCOME_3, + SOUND_LIGHTNING, + SOUND_A5, + SOUND_TOTAL_SOUNDS, + SOUND_NO_SOUND, }; -enum eScriptSounds : int16 { +enum eScriptSounds : uint16 { SCRIPT_SOUND_0 = 0, - SCRIPT_SOUND_1 = 1, - SCRIPT_SOUND_2 = 2, - SCRIPT_SOUND_3 = 3, - SCRIPT_SOUND_PARTY_1_LOOP_S = 4, - SCRIPT_SOUND_PARTY_1_LOOP_L = 5, - SCRIPT_SOUND_PARTY_2_LOOP_S = 6, - SCRIPT_SOUND_PARTY_2_LOOP_L = 7, - SCRIPT_SOUND_PARTY_3_LOOP_S = 8, - SCRIPT_SOUND_PARTY_3_LOOP_L = 9, - SCRIPT_SOUND_PARTY_4_LOOP_S = 10, - SCRIPT_SOUND_PARTY_4_LOOP_L = 11, - SCRIPT_SOUND_PARTY_5_LOOP_S = 12, - SCRIPT_SOUND_PARTY_5_LOOP_L = 13, - SCRIPT_SOUND_PARTY_6_LOOP_S = 14, - SCRIPT_SOUND_PARTY_6_LOOP_L = 15, - SCRIPT_SOUND_PARTY_7_LOOP_S = 16, - SCRIPT_SOUND_PARTY_7_LOOP_L = 17, - SCRIPT_SOUND_PARTY_8_LOOP_S = 18, - SCRIPT_SOUND_PARTY_8_LOOP_L = 19, - SCRIPT_SOUND_PARTY_9_LOOP_S = 20, - SCRIPT_SOUND_PARTY_9_LOOP_L = 21, - SCRIPT_SOUND_PARTY_10_LOOP_S = 22, - SCRIPT_SOUND_PARTY_10_LOOP_L = 23, - SCRIPT_SOUND_PARTY_11_LOOP_S = 24, - SCRIPT_SOUND_PARTY_11_LOOP_L = 25, - SCRIPT_SOUND_PARTY_12_LOOP_S = 26, - SCRIPT_SOUND_PARTY_12_LOOP_L = 27, - SCRIPT_SOUND_PARTY_13_LOOP_S = 28, - SCRIPT_SOUND_PARTY_13_LOOP_L = 29, - SCRIPT_SOUND_STRIP_CLUB_LOOP_1_S = 30, - SCRIPT_SOUND_STRIP_CLUB_LOOP_1_L = 31, - SCRIPT_SOUND_STRIP_CLUB_LOOP_2_S = 32, - SCRIPT_SOUND_STRIP_CLUB_LOOP_2_L = 33, - SCRIPT_SOUND_WORK_SHOP_LOOP_S = 34, - SCRIPT_SOUND_WORK_SHOP_LOOP_L = 35, - SCRIPT_SOUND_SAWMILL_LOOP_S = 36, - SCRIPT_SOUND_SAWMILL_LOOP_L = 37, - SCRIPT_SOUND_38 = 38, - SCRIPT_SOUND_39 = 39, - SCRIPT_SOUND_LAUNDERETTE_LOOP_S = 40, - SCRIPT_SOUND_LAUNDERETTE_LOOP_L = 41, - SCRIPT_SOUND_CHINATOWN_RESTAURANT_S = 42, - SCRIPT_SOUND_CHINATOWN_RESTAURANT_L = 43, - SCRIPT_SOUND_CIPRIANI_RESAURANT_S = 44, - SCRIPT_SOUND_CIPRIANI_RESAURANT_L = 45, - SCRIPT_SOUND_46_S = 46, - SCRIPT_SOUND_47_L = 47, - SCRIPT_SOUND_MARCO_BISTRO_S = 48, - SCRIPT_SOUND_MARCO_BISTRO_L = 49, - SCRIPT_SOUND_AIRPORT_LOOP_S = 50, - SCRIPT_SOUND_AIRPORT_LOOP_L = 51, - SCRIPT_SOUND_SHOP_LOOP_S = 52, - SCRIPT_SOUND_SHOP_LOOP_L = 53, - SCRIPT_SOUND_CINEMA_LOOP_S = 54, - SCRIPT_SOUND_CINEMA_LOOP_L = 55, - SCRIPT_SOUND_DOCKS_LOOP_S = 56, - SCRIPT_SOUND_DOCKS_LOOP_L = 57, - SCRIPT_SOUND_HOME_LOOP_S = 58, - SCRIPT_SOUND_HOME_LOOP_L = 59, - SCRIPT_SOUND_FRANKIE_PIANO = 60, - SCRIPT_SOUND_PARTY_1_LOOP = 61, - SCRIPT_SOUND_PORN_CINEMA_1_S = 62, - SCRIPT_SOUND_PORN_CINEMA_1_L = 63, - SCRIPT_SOUND_PORN_CINEMA_2_S = 64, - SCRIPT_SOUND_PORN_CINEMA_2_L = 65, - SCRIPT_SOUND_PORN_CINEMA_3_S = 66, - SCRIPT_SOUND_PORN_CINEMA_3_L = 67, - SCRIPT_SOUND_BANK_ALARM_LOOP_S = 68, - SCRIPT_SOUND_BANK_ALARM_LOOP_L = 69, - SCRIPT_SOUND_POLICE_BALL_LOOP_S = 70, - SCRIPT_SOUND_POLICE_BALL_LOOP_L = 71, - SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_S = 72, - SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_L = 73, - SCRIPT_SOUND_74 = 74, - SCRIPT_SOUND_75 = 75, - SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S = 76, - SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L = 77, - SCRIPT_SOUND_INJURED_PED_MALE_OUCH_S = 78, - SCRIPT_SOUND_INJURED_PED_MALE_OUCH_L = 79, - SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_S = 80, - SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_L = 81, - SCRIPT_SOUND_EVIDENCE_PICKUP = 82, - SCRIPT_SOUND_UNLOAD_GOLD = 83, - SCRIPT_SOUND_RAVE_1_LOOP_S = 84, - SCRIPT_SOUND_RAVE_1_LOOP_L = 85, - SCRIPT_SOUND_RAVE_2_LOOP_S = 86, - SCRIPT_SOUND_RAVE_2_LOOP_L = 87, - SCRIPT_SOUND_RAVE_3_LOOP_S = 88, - SCRIPT_SOUND_RAVE_3_LOOP_L = 89, - SCRIPT_SOUND_MISTY_SEX_S = 90, - SCRIPT_SOUND_MISTY_SEX_L = 91, - SCRIPT_SOUND_GATE_START_CLUNK = 92, - SCRIPT_SOUND_GATE_STOP_CLUNK = 93, - SCRIPT_SOUND_PART_MISSION_COMPLETE = 94, - SCRIPT_SOUND_CHUNKY_RUN_SHOUT = 95, - SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT = 96, - SCRIPT_SOUND_RACE_START_3 = 97, - SCRIPT_SOUND_RACE_START_2 = 98, - SCRIPT_SOUND_RACE_START_1 = 99, - SCRIPT_SOUND_RACE_START_GO = 100, - SCRIPT_SOUND_SWAT_PED_SHOUT = 101, - SCRIPT_SOUND_PRETEND_FIRE_LOOP = 102, - SCRIPT_SOUND_AMMUNATION_CHAT_1 = 103, - SCRIPT_SOUND_AMMUNATION_CHAT_2 = 104, - SCRIPT_SOUND_AMMUNATION_CHAT_3 = 105, - SCRIPT_SOUND_BULLET_HIT_GROUND_1 = 106, - SCRIPT_SOUND_BULLET_HIT_GROUND_2 = 107, - SCRIPT_SOUND_BULLET_HIT_GROUND_3 = 108, - SCRIPT_SOUND_BULLET_HIT_WATER = 109, //no sound - SCRIPT_SOUND_110 = 110, - SCRIPT_SOUND_111 = 111, - SCRIPT_SOUND_PAYPHONE_RINGING = 112, - SCRIPT_SOUND_113 = 113, - SCRIPT_SOUND_GLASS_BREAK_L = 114, - SCRIPT_SOUND_GLASS_BREAK_S = 115, - SCRIPT_SOUND_GLASS_CRACK = 116, - SCRIPT_SOUND_GLASS_LIGHT_BREAK = 117, - SCRIPT_SOUND_BOX_DESTROYED_1 = 118, - SCRIPT_SOUND_BOX_DESTROYED_2 = 119, - SCRIPT_SOUND_METAL_COLLISION = 120, - SCRIPT_SOUND_TIRE_COLLISION = 121, - SCRIPT_SOUND_GUNSHELL_DROP = 122, - SCRIPT_SOUND_GUNSHELL_DROP_SOFT = 123, + SCRIPT_SOUND_1, + SCRIPT_SOUND_2, + SCRIPT_SOUND_3, + SCRIPT_SOUND_PARTY_1_LOOP_S, + SCRIPT_SOUND_PARTY_1_LOOP_L, + SCRIPT_SOUND_PARTY_2_LOOP_S, + SCRIPT_SOUND_PARTY_2_LOOP_L, + SCRIPT_SOUND_PARTY_3_LOOP_S, + SCRIPT_SOUND_PARTY_3_LOOP_L, + SCRIPT_SOUND_PARTY_4_LOOP_S, + SCRIPT_SOUND_PARTY_4_LOOP_L, + SCRIPT_SOUND_PARTY_5_LOOP_S, + SCRIPT_SOUND_PARTY_5_LOOP_L, + SCRIPT_SOUND_PARTY_6_LOOP_S, + SCRIPT_SOUND_PARTY_6_LOOP_L, + SCRIPT_SOUND_PARTY_7_LOOP_S, + SCRIPT_SOUND_PARTY_7_LOOP_L, + SCRIPT_SOUND_PARTY_8_LOOP_S, + SCRIPT_SOUND_PARTY_8_LOOP_L, + SCRIPT_SOUND_PARTY_9_LOOP_S, + SCRIPT_SOUND_PARTY_9_LOOP_L, + SCRIPT_SOUND_PARTY_10_LOOP_S, + SCRIPT_SOUND_PARTY_10_LOOP_L, + SCRIPT_SOUND_PARTY_11_LOOP_S, + SCRIPT_SOUND_PARTY_11_LOOP_L, + SCRIPT_SOUND_PARTY_12_LOOP_S, + SCRIPT_SOUND_PARTY_12_LOOP_L, + SCRIPT_SOUND_PARTY_13_LOOP_S, + SCRIPT_SOUND_PARTY_13_LOOP_L, + SCRIPT_SOUND_STRIP_CLUB_LOOP_1_S, + SCRIPT_SOUND_STRIP_CLUB_LOOP_1_L, + SCRIPT_SOUND_STRIP_CLUB_LOOP_2_S, + SCRIPT_SOUND_STRIP_CLUB_LOOP_2_L, + SCRIPT_SOUND_WORK_SHOP_LOOP_S, + SCRIPT_SOUND_WORK_SHOP_LOOP_L, + SCRIPT_SOUND_SAWMILL_LOOP_S, + SCRIPT_SOUND_SAWMILL_LOOP_L, + SCRIPT_SOUND_38, + SCRIPT_SOUND_39, + SCRIPT_SOUND_LAUNDERETTE_LOOP_S, + SCRIPT_SOUND_LAUNDERETTE_LOOP_L, + SCRIPT_SOUND_CHINATOWN_RESTAURANT_S, + SCRIPT_SOUND_CHINATOWN_RESTAURANT_L, + SCRIPT_SOUND_CIPRIANI_RESAURANT_S, + SCRIPT_SOUND_CIPRIANI_RESAURANT_L, + SCRIPT_SOUND_46_S, + SCRIPT_SOUND_47_L, + SCRIPT_SOUND_MARCO_BISTRO_S, + SCRIPT_SOUND_MARCO_BISTRO_L, + SCRIPT_SOUND_AIRPORT_LOOP_S, + SCRIPT_SOUND_AIRPORT_LOOP_L, + SCRIPT_SOUND_SHOP_LOOP_S, + SCRIPT_SOUND_SHOP_LOOP_L, + SCRIPT_SOUND_CINEMA_LOOP_S, + SCRIPT_SOUND_CINEMA_LOOP_L, + SCRIPT_SOUND_DOCKS_LOOP_S, + SCRIPT_SOUND_DOCKS_LOOP_L, + SCRIPT_SOUND_HOME_LOOP_S, + SCRIPT_SOUND_HOME_LOOP_L, + SCRIPT_SOUND_FRANKIE_PIANO, + SCRIPT_SOUND_PARTY_1_LOOP, + SCRIPT_SOUND_PORN_CINEMA_1_S, + SCRIPT_SOUND_PORN_CINEMA_1_L, + SCRIPT_SOUND_PORN_CINEMA_2_S, + SCRIPT_SOUND_PORN_CINEMA_2_L, + SCRIPT_SOUND_PORN_CINEMA_3_S, + SCRIPT_SOUND_PORN_CINEMA_3_L, + SCRIPT_SOUND_BANK_ALARM_LOOP_S, + SCRIPT_SOUND_BANK_ALARM_LOOP_L, + SCRIPT_SOUND_POLICE_BALL_LOOP_S, + SCRIPT_SOUND_POLICE_BALL_LOOP_L, + SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_S, + SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_L, + SCRIPT_SOUND_74, + SCRIPT_SOUND_75, + SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S, + SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L, + SCRIPT_SOUND_INJURED_PED_MALE_OUCH_S, + SCRIPT_SOUND_INJURED_PED_MALE_OUCH_L, + SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_S, + SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_L, + SCRIPT_SOUND_EVIDENCE_PICKUP, + SCRIPT_SOUND_UNLOAD_GOLD, + SCRIPT_SOUND_RAVE_1_LOOP_S, + SCRIPT_SOUND_RAVE_1_LOOP_L, + SCRIPT_SOUND_RAVE_2_LOOP_S, + SCRIPT_SOUND_RAVE_2_LOOP_L, + SCRIPT_SOUND_RAVE_3_LOOP_S, + SCRIPT_SOUND_RAVE_3_LOOP_L, + SCRIPT_SOUND_MISTY_SEX_S, + SCRIPT_SOUND_MISTY_SEX_L, + SCRIPT_SOUND_GATE_START_CLUNK, + SCRIPT_SOUND_GATE_STOP_CLUNK, + SCRIPT_SOUND_PART_MISSION_COMPLETE, + SCRIPT_SOUND_CHUNKY_RUN_SHOUT, + SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT, + SCRIPT_SOUND_RACE_START_3, + SCRIPT_SOUND_RACE_START_2, + SCRIPT_SOUND_RACE_START_1, + SCRIPT_SOUND_RACE_START_GO, + SCRIPT_SOUND_SWAT_PED_SHOUT, + SCRIPT_SOUND_PRETEND_FIRE_LOOP, + SCRIPT_SOUND_AMMUNATION_CHAT_1, + SCRIPT_SOUND_AMMUNATION_CHAT_2, + SCRIPT_SOUND_AMMUNATION_CHAT_3, + SCRIPT_SOUND_BULLET_HIT_GROUND_1, + SCRIPT_SOUND_BULLET_HIT_GROUND_2, + SCRIPT_SOUND_BULLET_HIT_GROUND_3, + SCRIPT_SOUND_BULLET_HIT_WATER, // no sound + SCRIPT_SOUND_110, + SCRIPT_SOUND_111, + SCRIPT_SOUND_PAYPHONE_RINGING, + SCRIPT_SOUND_113, + SCRIPT_SOUND_GLASS_BREAK_L, + SCRIPT_SOUND_GLASS_BREAK_S, + SCRIPT_SOUND_GLASS_CRACK, + SCRIPT_SOUND_GLASS_LIGHT_BREAK, + SCRIPT_SOUND_BOX_DESTROYED_1, + SCRIPT_SOUND_BOX_DESTROYED_2, + SCRIPT_SOUND_METAL_COLLISION, + SCRIPT_SOUND_TIRE_COLLISION, + SCRIPT_SOUND_GUNSHELL_DROP, + SCRIPT_SOUND_GUNSHELL_DROP_SOFT, + SCRIPT_SOUND_TOTAL, + SCRIPT_SOUND_INVALID, }; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index ee01b6c4..6fac3f9d 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -12,6 +12,7 @@ #include "AudioScriptObject.h" #include "RpAnimBlend.h" #include "AnimBlendAssociation.h" +#include "soundlist.h" #ifdef FIX_BUGS #include "Replay.h" #endif @@ -97,7 +98,7 @@ CPhoneInfo::Update(void) if (scratchTheCabinet) { m_aPhones[phoneId].m_pEntity->GetUp().z = (CGeneral::GetRandomNumber() % 1024) / 16000.0f + 1.0f; if (!phoneRings) - PlayOneShotScriptObject(_SCRSOUND_PHONE_RING, m_aPhones[phoneId].m_pEntity->GetPosition()); + PlayOneShotScriptObject(SCRIPT_SOUND_PAYPHONE_RINGING, m_aPhones[phoneId].m_pEntity->GetPosition()); } else { m_aPhones[phoneId].m_pEntity->GetUp().z = 1.0f; } @@ -136,7 +137,7 @@ CPhoneInfo::Update(void) if (scratchTheCabinet) { m_aPhones[phoneId].m_pEntity->GetUp().z = (CGeneral::GetRandomNumber() % 1024) / 16000.0f + 1.0f; if (!phoneRings) - PlayOneShotScriptObject(_SCRSOUND_PHONE_RING, m_aPhones[phoneId].m_pEntity->GetPosition()); + PlayOneShotScriptObject(SCRIPT_SOUND_PAYPHONE_RINGING, m_aPhones[phoneId].m_pEntity->GetPosition()); } else { m_aPhones[phoneId].m_pEntity->GetUp().z = 1.0f; } diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index cd2cd688..c5f73987 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -11,6 +11,7 @@ #include "ObjectData.h" #include "World.h" #include "Floater.h" +#include "soundlist.h" int16 CObject::nNoTempObjects; int16 CObject::nBodyCastHealth = 1000; @@ -219,7 +220,7 @@ CObject::ObjectDamage(float amount) int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0); } - PlayOneShotScriptObject(_SCRSOUND_CARDBOARD_BOX_SMASH, vecPos); + PlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_2, vecPos); break; } case DAMAGE_EFFECT_SMASH_WOODENBOX_COMPLETELY: { @@ -242,7 +243,7 @@ CObject::ObjectDamage(float amount) int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0); } - PlayOneShotScriptObject(_SCRSOUND_WOODEN_BOX_SMASH, vecPos); + PlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_1, vecPos); break; } case DAMAGE_EFFECT_SMASH_TRAFFICCONE_COMPLETELY: { @@ -267,7 +268,7 @@ CObject::ObjectDamage(float amount) int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0); } - PlayOneShotScriptObject(_SCRSOUND_TYRE_BUMP, vecPos); + PlayOneShotScriptObject(SCRIPT_SOUND_TIRE_COLLISION, vecPos); break; } case DAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY: { @@ -292,7 +293,7 @@ CObject::ObjectDamage(float amount) int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0); } - PlayOneShotScriptObject(_SCRSOUND_COL_CAR, vecPos); + PlayOneShotScriptObject(SCRIPT_SOUND_METAL_COLLISION, vecPos); break; } } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index fd8fd540..a1709fd7 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -441,8 +441,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_nPedType = pedType; m_lastSoundStart = 0; m_soundStart = 0; - m_lastQueuedSound = SOUND_TOTAL_PED_SOUNDS; - m_queuedSound = SOUND_TOTAL_PED_SOUNDS; + m_lastQueuedSound = SOUND_NO_SOUND; + m_queuedSound = SOUND_NO_SOUND; m_objective = OBJECTIVE_NONE; m_prevObjective = OBJECTIVE_NONE; CharCreatedBy = RANDOM_CHAR; @@ -5537,7 +5537,7 @@ CPed::PlayHitSound(CPed *hitTo) S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42, S43 = SOUND_FIGHT_KNEE_OR_KICK_43, S44 = SOUND_FIGHT_KICK_44, - NO_SND = SOUND_TOTAL_PED_SOUNDS + NO_SND = SOUND_NO_SOUND }; uint16 hitSoundsByFightMoves[12][10] = { {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42}, @@ -16283,7 +16283,7 @@ CPed::ServiceTalking(void) } else { m_queuedSound = SOUND_PED_BOMBER; } - if (m_queuedSound != SOUND_TOTAL_PED_SOUNDS) { + if (m_queuedSound != SOUND_NO_SOUND) { if (m_queuedSound == SOUND_PED_DEATH) m_soundStart = CTimer::GetTimeInMilliseconds() - 1; @@ -16295,7 +16295,7 @@ CPed::ServiceTalking(void) + CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime); m_lastQueuedSound = m_queuedSound; - m_queuedSound = SOUND_TOTAL_PED_SOUNDS; + m_queuedSound = SOUND_NO_SOUND; } } } diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index 6f17013c..ac892ddb 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -13,6 +13,7 @@ #include "Shadows.h" #include "ModelIndices.h" #include "main.h" +#include "soundlist.h" uint32 CGlass::NumGlassEntities; @@ -101,7 +102,7 @@ CFallingGlassPane::Update(void) pos = CVector(GetPosition().x, GetPosition().y, m_fGroundZ); - PlayOneShotScriptObject(_SCRSOUND_GLASS_SHARD, pos); + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_LIGHT_BREAK, pos); RwRGBA color = { 255, 255, 255, 255 }; @@ -627,7 +628,7 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, if ( amount > 300.0f ) { - PlayOneShotScriptObject(_SCRSOUND_GLASS_SMASH_1, object->GetPosition()); + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition()); GeneratePanesForWindow(0, CVector(minx, miny, minz), @@ -637,7 +638,7 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, } else { - PlayOneShotScriptObject(_SCRSOUND_GLASS_SMASH_2, object->GetPosition()); + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition()); GeneratePanesForWindow(1, CVector(minx, miny, minz), @@ -659,7 +660,7 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) if ( amount > 50.0f && !object->bGlassCracked ) { - PlayOneShotScriptObject(_SCRSOUND_GLASS_CRACK, object->GetPosition()); + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); object->bGlassCracked = true; } } @@ -675,7 +676,7 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) { if ( !object->bGlassCracked ) { - PlayOneShotScriptObject(_SCRSOUND_GLASS_CRACK, object->GetPosition()); + PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition()); object->bGlassCracked = true; } else diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index 4223ac10..a867ae13 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -11,6 +11,7 @@ #include "AudioScriptObject.h" #include "ParticleObject.h" #include "Particle.h" +#include "soundlist.h" #define MAX_PARTICLES_ON_SCREEN (1000) @@ -1268,7 +1269,7 @@ void CParticle::Update() nil, particle->m_fSize, color, particle->m_nRotationStep, 0, 0, 0); - PlayOneShotScriptObject(_SCRSOUND_BULLET_SHELL_HIT_GROUND_1, particle->m_vecPosition); + PlayOneShotScriptObject(SCRIPT_SOUND_GUNSHELL_DROP, particle->m_vecPosition); } break; @@ -1287,7 +1288,7 @@ void CParticle::Update() nil, particle->m_fSize, color, 0, 0, 0, 0); - PlayOneShotScriptObject(_SCRSOUND_BULLET_SHELL_HIT_GROUND_2, particle->m_vecPosition); + PlayOneShotScriptObject(SCRIPT_SOUND_GUNSHELL_DROP_SOFT, particle->m_vecPosition); } break; From 5491a51daa99ffadd23aec5105fe45a2e25c1e5a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 10:39:18 +0300 Subject: [PATCH 007/148] remove debug --- src/peds/CivilianPed.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index f90dffa8..f4feacf7 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -447,8 +447,6 @@ void CCivilianPed::UseNearbyAttractors() CEntity* pEntity = (CEntity*)pNode->item; //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) //continue; - if (pEntity->GetModelIndex() == 3181) - debug("get2\n"); CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { C2dEffect* pEffect = pModelInfo->Get2dEffect(i); From 03c4a979c8e2755670818882273faa26e1de3e4f Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 10:53:20 +0300 Subject: [PATCH 008/148] removed duplicate code --- src/peds/CivilianPed.cpp | 76 ++++++++++++++++------------------------ src/peds/CivilianPed.h | 1 + 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index f4feacf7..50b04df3 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -386,6 +386,34 @@ const int32 gFrequencyOfAttractorAttempt = 11; const float gDistanceToSeekAttractors = 50.0f; const float gMaxDistanceToAttract = 10.0f; +/* Probably this was inlined */ +void CCivilianPed::FindNearbyAttractorsSectorList(CPtrList& list, float& minDistance, C2dEffect*& pClosestAttractor, CEntity*& pAttractorEntity) +{ + for (CPtrNode* pNode = list.first; pNode != nil; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) + //continue; + CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); + for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { + C2dEffect* pEffect = pModelInfo->Get2dEffect(i); + if (pEffect->type != EFFECT_PED_ATTRACTOR) + continue; + if (!IsAttractedTo(pEffect->pedattr.type)) + continue; + CVector pos; + CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos); + if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { + CPedAttractorManager* pManager = GetPedAttractorManager(); + if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { + pClosestAttractor = pEffect; + pAttractorEntity = pEntity; + minDistance = (pos - GetPosition()).MagnitudeSqr(); + } + } + } + } +} + void CCivilianPed::UseNearbyAttractors() { if (CWeather::Rain < 0.2f && !m_bAttractorUnk) @@ -420,52 +448,8 @@ void CCivilianPed::UseNearbyAttractors() for (int y = ystart; y <= yend; y++) { for (int x = xstart; x <= xend; x++) { CSector* s = CWorld::GetSector(x, y); - for (CPtrNode* pNode = s->m_lists[ENTITYLIST_BUILDINGS].first; pNode != nil; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) - //continue; - CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); - for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { - C2dEffect* pEffect = pModelInfo->Get2dEffect(i); - if (pEffect->type != EFFECT_PED_ATTRACTOR) - continue; - if (!IsAttractedTo(pEffect->pedattr.type)) - continue; - CVector pos; - CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos); - if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { - CPedAttractorManager* pManager = GetPedAttractorManager(); - if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { - pClosestAttractor = pEffect; - pAttractorEntity = pEntity; - minDistance = (pos - GetPosition()).MagnitudeSqr(); - } - } - } - } - for (CPtrNode* pNode = s->m_lists[ENTITYLIST_OBJECTS].first; pNode != nil; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) - //continue; - CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); - for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { - C2dEffect* pEffect = pModelInfo->Get2dEffect(i); - if (pEffect->type != EFFECT_PED_ATTRACTOR) - continue; - if (!IsAttractedTo(pEffect->pedattr.type)) - continue; - CVector pos; - CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos); - if ((pos - GetPosition()).MagnitudeSqr() < minDistance) { - CPedAttractorManager* pManager = GetPedAttractorManager(); - if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) { - pClosestAttractor = pEffect; - pAttractorEntity = pEntity; - minDistance = (pos - GetPosition()).MagnitudeSqr(); - } - } - } - } + FindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_BUILDINGS], minDistance, pClosestAttractor, pAttractorEntity); + FindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_OBJECTS], minDistance, pClosestAttractor, pAttractorEntity); } } if (pClosestAttractor) diff --git a/src/peds/CivilianPed.h b/src/peds/CivilianPed.h index 558380b7..27d458f7 100644 --- a/src/peds/CivilianPed.h +++ b/src/peds/CivilianPed.h @@ -13,6 +13,7 @@ public: void CivilianAI(void); void ProcessControl(void); void UseNearbyAttractors(void); + void FindNearbyAttractorsSectorList(CPtrList&, float&, C2dEffect*&, CEntity*&); bool IsAttractedTo(int8); }; #ifndef PED_SKIN From cf5db7311776c26b4c2710b142a2863e88645965 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 11:22:12 +0300 Subject: [PATCH 009/148] a few fixes --- src/peds/CivilianPed.cpp | 5 +++-- src/peds/PedAttractor.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 50b04df3..48785025 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -11,6 +11,7 @@ #include "SurfaceTable.h" #include "Weather.h" #include "PedAttractor.h" +#include "Object.h" CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype) { @@ -391,8 +392,8 @@ void CCivilianPed::FindNearbyAttractorsSectorList(CPtrList& list, float& minDist { for (CPtrNode* pNode = list.first; pNode != nil; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) - //continue; + if (pEntity->IsObject() && (!pEntity->IsStatic() || ((CObject*)pEntity)->bHasBeenDamaged)) + continue; CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { C2dEffect* pEffect = pModelInfo->Get2dEffect(i); diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h index 3408be93..d2ed014e 100644 --- a/src/peds/PedAttractor.h +++ b/src/peds/PedAttractor.h @@ -152,9 +152,9 @@ public: virtual void UpdatePedStateOnDeparture(CPed* pPed) const override { /* if (pPed->m_money > 10) - pPed->m_money = 0; - else pPed->m_money -= 10; + else + pPed->m_money = 0; */ } CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : From 9067469f7c4a469e713a37ea6b86920397168e13 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 11:30:58 +0300 Subject: [PATCH 010/148] more attractor fixes --- src/peds/PedAttactor.cpp | 19 +++++++++++++++++++ src/peds/PedAttractor.h | 37 +++++++++++++++---------------------- src/peds/Population.cpp | 3 ++- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp index a3b93067..0df59b1c 100644 --- a/src/peds/PedAttactor.cpp +++ b/src/peds/PedAttactor.cpp @@ -12,6 +12,8 @@ const int gcMaxSizeOfPizzaQueue = 5; const int gcMaxSizeOfShelterQueue = 5; const int gcMaxSizeOfIceCreamQueue = 1; +//--MIAMI: file done, except TODO(MIAMI) + std::vector CPedShelterAttractor::ms_displacements; CPedAttractorManager* GetPedAttractorManager() @@ -163,6 +165,23 @@ CPedAttractor::CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 ma CPedAttractorManager::ComputeEffectUseDir(pEffect, matrix, vecUseDir); } +void CPedPizzaAttractor::UpdatePedStateOnDeparture(CPed* pPed) const +{ + /* TODO(MIAMI): uncomment + if (pPed->m_nPedMoney > 10) + pPed->m_nPedMoney -= 10; + else + pPed->m_nPedMoney = 0; + */ +} + +void CPedAtmAttractor::UpdatePedStateOnDeparture(CPed* pPed) const +{ + /* TODO(MIAMI): uncomment + pPed->m_nPedMoney += 20 * CGeneral::GetRandomNumberInRange(1, 51); + */ +}; + float CPedAttractor::ComputeDeltaHeading() const { return CGeneral::GetRandomNumberInRange(-m_fMaxHeadingDisplacement, m_fMaxHeadingDisplacement); diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h index d2ed014e..563efd3a 100644 --- a/src/peds/PedAttractor.h +++ b/src/peds/PedAttractor.h @@ -114,7 +114,7 @@ public: bool RegisterPed(CPed*); bool BroadcastArrival(CPed*); - CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp); + CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp); C2dEffect* GetEffect() const { return p2dEffect; } const CVector& GetEffectPos() const { return vecEffectPos; } @@ -127,9 +127,9 @@ class CPedAtmAttractor : public CPedAttractor { public: virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; }; - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override { /* pPed->m_money += 20 * CGeneral::GetRandomNumberInRange(1, 51); */ }; - CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override; + CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp) {}; }; @@ -139,8 +139,8 @@ public: virtual ~CPedIceCreamAttractor() override { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); } virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; } virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp) {}; }; @@ -149,16 +149,9 @@ class CPedPizzaAttractor : public CPedAttractor public: virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; } virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; } - virtual void UpdatePedStateOnDeparture(CPed* pPed) const override - { /* - if (pPed->m_money > 10) - pPed->m_money -= 10; - else - pPed->m_money = 0; - */ - } - CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + virtual void UpdatePedStateOnDeparture(CPed* pPed) const override; + CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp) {}; }; @@ -167,8 +160,8 @@ class CPedSeatAttractor : public CPedAttractor public: virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; } virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp) {}; }; @@ -183,8 +176,8 @@ public: virtual void ComputeAttractPos(int qid, CVector& pos) const override; virtual void ComputeAttractHeading(int qid, float& heading) const override; - CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp) {}; @@ -197,7 +190,7 @@ public: virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; } virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {}; - CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) : - CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp) + CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) : + CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp) {}; }; \ No newline at end of file diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 14bd042c..567f9c0f 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -1123,7 +1123,8 @@ CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit) return nil; CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - //TODO(MIAMI): set money == 0 + //TODO(MIAMI): uncomment + //pPed->m_nPedMoney = 0; pPed->bDeadPedInFrontOfCar = true; pPed->m_vehicleInAccident = pCulprit; pCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident); From 0c231663188ff4b639549c1be3c6f08df9a5afe1 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 16 May 2020 10:33:19 +0200 Subject: [PATCH 011/148] changed CPedIK names --- src/peds/Ped.cpp | 30 ++++----- src/peds/PedIK.cpp | 160 ++++++++++++++++++++++----------------------- src/peds/PedIK.h | 12 ++-- 3 files changed, 101 insertions(+), 101 deletions(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index a1709fd7..d48a6a2f 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2514,37 +2514,37 @@ CPed::CalculateNewVelocity(void) if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) { #endif LimbOrientation newUpperLegs; - newUpperLegs.phi = localWalkAngle; + newUpperLegs.yaw = localWalkAngle; - if (newUpperLegs.phi < -DEGTORAD(100.0f)) { - newUpperLegs.phi += PI; - } else if (newUpperLegs.phi > DEGTORAD(100.0f)) { - newUpperLegs.phi -= PI; + if (newUpperLegs.yaw < -DEGTORAD(100.0f)) { + newUpperLegs.yaw += PI; + } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) { + newUpperLegs.yaw -= PI; } - if (newUpperLegs.phi > -DEGTORAD(50.0f) && newUpperLegs.phi < DEGTORAD(50.0f)) { + if (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) { #ifdef PED_SKIN if(IsClumpSkinned(GetClump())){ /* // this looks shit - newUpperLegs.theta = 0.0f; + newUpperLegs.pitch = 0.0f; RwV3d axis = { -1.0f, 0.0f, 0.0f }; - RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.phi), rwCOMBINEPRECONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.phi), rwCOMBINEPRECONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT); */ - newUpperLegs.theta = 0.1f; + newUpperLegs.pitch = 0.1f; RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; RwV3d Zaxis = { 0.0f, 0.0f, 1.0f }; - RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.theta), rwCOMBINEPOSTCONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.phi), rwCOMBINEPOSTCONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.theta), rwCOMBINEPOSTCONCAT); - RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.phi), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT); bDontAcceptIKLookAts = true; }else #endif { - newUpperLegs.theta = 0.0f; + newUpperLegs.pitch = 0.0f; m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false); m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false); } diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index ae9a85b4..ebd41296 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -21,14 +21,14 @@ CPedIK::CPedIK(CPed *ped) { m_ped = ped; m_flags = 0; - m_headOrient.phi = 0.0f; - m_headOrient.theta = 0.0f; - m_torsoOrient.phi = 0.0f; - m_torsoOrient.theta = 0.0f; - m_upperArmOrient.phi = 0.0f; - m_upperArmOrient.theta = 0.0f; - m_lowerArmOrient.phi = 0.0f; - m_lowerArmOrient.theta = 0.0f; + m_headOrient.yaw = 0.0f; + m_headOrient.pitch = 0.0f; + m_torsoOrient.yaw = 0.0f; + m_torsoOrient.pitch = 0.0f; + m_upperArmOrient.yaw = 0.0f; + m_upperArmOrient.pitch = 0.0f; + m_lowerArmOrient.yaw = 0.0f; + m_lowerArmOrient.pitch = 0.0f; } #ifdef PED_SKIN @@ -55,8 +55,8 @@ CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool change RtQuat *q = &node->hanimFrame->q; #ifndef FIX_BUGS // this is what the game does (also VC), but it does not look great - RtQuatRotate(q, &XaxisIK, RADTODEG(limb->phi), rwCOMBINEPRECONCAT); - RtQuatRotate(q, &ZaxisIK, RADTODEG(limb->theta), rwCOMBINEPRECONCAT); // pitch + RtQuatRotate(q, &XaxisIK, RADTODEG(limb->yaw), rwCOMBINEPRECONCAT); + RtQuatRotate(q, &ZaxisIK, RADTODEG(limb->pitch), rwCOMBINEPRECONCAT); // pitch #else // copied the code from the non-skinned case // this seems to work ok @@ -78,8 +78,8 @@ CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool change vec2.z = -(c*mat->at.x + s*mat->at.y); // Not sure what exactly to do here - RtQuatRotate(q, &vec1, RADTODEG(limb->phi), rwCOMBINEPRECONCAT); - RtQuatRotate(q, &vec2, RADTODEG(limb->theta), rwCOMBINEPRECONCAT); + RtQuatRotate(q, &vec1, RADTODEG(limb->yaw), rwCOMBINEPRECONCAT); + RtQuatRotate(q, &vec2, RADTODEG(limb->pitch), rwCOMBINEPRECONCAT); #endif m_ped->bDontAcceptIKLookAts = true; }else @@ -122,14 +122,14 @@ CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool change float curYaw, curPitch; ExtractYawAndPitchWorld(mat, &curYaw, &curPitch); - RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->theta), rwCOMBINEPOSTCONCAT); - RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->phi - (curYaw - m_ped->m_fRotationCur)), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->pitch), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->yaw - (curYaw - m_ped->m_fRotationCur)), rwCOMBINEPOSTCONCAT); RwMatrixRotate(RwFrameGetMatrix(f), &forwardVector, RADTODEG(alpha), rwCOMBINEPOSTCONCAT); }else{ // pitch - RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->theta), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->pitch), rwCOMBINEPOSTCONCAT); // yaw - RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->phi), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->yaw), rwCOMBINEPOSTCONCAT); } RwFrameGetMatrix(f)->pos = pos; RwMatrixDestroy(mat); @@ -176,43 +176,43 @@ CPedIK::GetWorldMatrix(RwFrame *source, RwMatrix *destination) } LimbMoveStatus -CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo) +CPedIK::MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, LimbMovementInfo &moveInfo) { LimbMoveStatus result = ONE_ANGLE_COULDNT_BE_SET_EXACTLY; - // phi + // yaw - if (limb.phi > approxPhi) { - limb.phi -= moveInfo.yawD; - } else if (limb.phi < approxPhi) { - limb.phi += moveInfo.yawD; + if (limb.yaw > targetYaw) { + limb.yaw -= moveInfo.yawD; + } else if (limb.yaw < targetYaw) { + limb.yaw += moveInfo.yawD; } - if (Abs(limb.phi - approxPhi) < moveInfo.yawD) { - limb.phi = approxPhi; + if (Abs(limb.yaw - targetYaw) < moveInfo.yawD) { + limb.yaw = targetYaw; result = ANGLES_SET_EXACTLY; } - if (limb.phi > moveInfo.maxYaw || limb.phi < moveInfo.minYaw) { - limb.phi = clamp(limb.phi, moveInfo.minYaw, moveInfo.maxYaw); + if (limb.yaw > moveInfo.maxYaw || limb.yaw < moveInfo.minYaw) { + limb.yaw = clamp(limb.yaw, moveInfo.minYaw, moveInfo.maxYaw); result = ANGLES_SET_TO_MAX; } - // theta + // pitch - if (limb.theta > approxTheta) { - limb.theta -= moveInfo.pitchD; - } else if (limb.theta < approxTheta) { - limb.theta += moveInfo.pitchD; + if (limb.pitch > targetPitch) { + limb.pitch -= moveInfo.pitchD; + } else if (limb.pitch < targetPitch) { + limb.pitch += moveInfo.pitchD; } - if (Abs(limb.theta - approxTheta) < moveInfo.pitchD) - limb.theta = approxTheta; + if (Abs(limb.pitch - targetPitch) < moveInfo.pitchD) + limb.pitch = targetPitch; else result = ONE_ANGLE_COULDNT_BE_SET_EXACTLY; - if (limb.theta > moveInfo.maxPitch || limb.theta < moveInfo.minPitch) { - limb.theta = clamp(limb.theta, moveInfo.minPitch, moveInfo.maxPitch); + if (limb.pitch > moveInfo.maxPitch || limb.pitch < moveInfo.minPitch) { + limb.pitch = clamp(limb.pitch, moveInfo.minPitch, moveInfo.maxPitch); result = ANGLES_SET_TO_MAX; } return result; @@ -231,14 +231,14 @@ void CPedIK::RotateHead(void) { RtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q; - RtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.phi), rwCOMBINEREPLACE); - RtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.theta), rwCOMBINEPOSTCONCAT); + RtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.yaw), rwCOMBINEREPLACE); + RtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.pitch), rwCOMBINEPOSTCONCAT); m_ped->bDontAcceptIKLookAts = true; } #endif bool -CPedIK::LookInDirection(float phi, float theta) +CPedIK::LookInDirection(float targetYaw, float targetPitch) { bool success = true; float yaw, pitch; @@ -246,21 +246,21 @@ CPedIK::LookInDirection(float phi, float theta) if(IsClumpSkinned(m_ped->GetClump())){ if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) { m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION; - ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &m_headOrient.phi, &m_headOrient.theta); + ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &m_headOrient.yaw, &m_headOrient.pitch); } // parent of head is torso RwMatrix worldMat = *GetBoneMatrix(m_ped, BONE_torso); ExtractYawAndPitchWorld(&worldMat, &yaw, &pitch); - LimbMoveStatus headStatus = MoveLimb(m_headOrient, CGeneral::LimitRadianAngle(phi - yaw), + LimbMoveStatus headStatus = MoveLimb(m_headOrient, CGeneral::LimitRadianAngle(targetYaw - yaw), CGeneral::LimitRadianAngle(DEGTORAD(10.0f)), ms_headInfo); if (headStatus == ANGLES_SET_TO_MAX) success = false; if (headStatus != ANGLES_SET_EXACTLY){ if (!(m_flags & LOOKAROUND_HEAD_ONLY)){ - if (MoveLimb(m_torsoOrient, CGeneral::LimitRadianAngle(phi), theta, ms_torsoInfo)) + if (MoveLimb(m_torsoOrient, CGeneral::LimitRadianAngle(targetYaw), targetPitch, ms_torsoInfo)) success = true; }else{ RotateHead(); @@ -279,7 +279,7 @@ CPedIK::LookInDirection(float phi, float theta) if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) { m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION; - ExtractYawAndPitchLocal(frameMat, &m_headOrient.phi, &m_headOrient.theta); + ExtractYawAndPitchLocal(frameMat, &m_headOrient.yaw, &m_headOrient.pitch); } RwMatrix *worldMat = RwMatrixCreate(); @@ -288,25 +288,25 @@ CPedIK::LookInDirection(float phi, float theta) ExtractYawAndPitchWorld(worldMat, &yaw, &pitch); RwMatrixDestroy(worldMat); - yaw += m_torsoOrient.phi; - float neededPhiTurn = CGeneral::LimitRadianAngle(phi - yaw); - pitch *= Cos(neededPhiTurn); + yaw += m_torsoOrient.yaw; + float neededYawTurn = CGeneral::LimitRadianAngle(targetYaw - yaw); + pitch *= Cos(neededYawTurn); - float neededThetaTurn = CGeneral::LimitRadianAngle(theta - pitch); - LimbMoveStatus headStatus = MoveLimb(m_headOrient, neededPhiTurn, neededThetaTurn, ms_headInfo); + float neededPitchTurn = CGeneral::LimitRadianAngle(targetPitch - pitch); + LimbMoveStatus headStatus = MoveLimb(m_headOrient, neededYawTurn, neededPitchTurn, ms_headInfo); if (headStatus == ANGLES_SET_TO_MAX) success = false; if (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKAROUND_HEAD_ONLY)) { - float remainingTurn = CGeneral::LimitRadianAngle(phi - m_ped->m_fRotationCur); - if (MoveLimb(m_torsoOrient, remainingTurn, theta, ms_torsoInfo)) + float remainingTurn = CGeneral::LimitRadianAngle(targetYaw - m_ped->m_fRotationCur); + if (MoveLimb(m_torsoOrient, remainingTurn, targetPitch, ms_torsoInfo)) success = true; } CMatrix nextFrame = CMatrix(frameMat); CVector framePos = nextFrame.GetPosition(); - nextFrame.SetRotateZ(m_headOrient.theta); - nextFrame.RotateX(m_headOrient.phi); + nextFrame.SetRotateZ(m_headOrient.pitch); + nextFrame.RotateX(m_headOrient.yaw); nextFrame.GetPosition() += framePos; nextFrame.UpdateRW(); @@ -320,32 +320,32 @@ CPedIK::LookInDirection(float phi, float theta) bool CPedIK::LookAtPosition(CVector const &pos) { - float phiToFace = CGeneral::GetRadianAngleBetweenPoints( + float yawToFace = CGeneral::GetRadianAngleBetweenPoints( pos.x, pos.y, m_ped->GetPosition().x, m_ped->GetPosition().y); - float thetaToFace = CGeneral::GetRadianAngleBetweenPoints( + float pitchToFace = CGeneral::GetRadianAngleBetweenPoints( pos.z, (m_ped->GetPosition() - pos).Magnitude2D(), m_ped->GetPosition().z, 0.0f); - return LookInDirection(phiToFace, thetaToFace); + return LookInDirection(yawToFace, pitchToFace); } bool -CPedIK::PointGunInDirection(float phi, float theta) +CPedIK::PointGunInDirection(float targetYaw, float targetPitch) { bool result = true; bool armPointedToGun = false; - float angle = CGeneral::LimitRadianAngle(phi - m_ped->m_fRotationCur); + float angle = CGeneral::LimitRadianAngle(targetYaw - m_ped->m_fRotationCur); m_flags &= (~GUN_POINTED_SUCCESSFULLY); m_flags |= LOOKAROUND_HEAD_ONLY; if (m_flags & AIMS_WITH_ARM) { - armPointedToGun = PointGunInDirectionUsingArm(angle, theta); - angle = CGeneral::LimitRadianAngle(angle - m_upperArmOrient.phi); + armPointedToGun = PointGunInDirectionUsingArm(angle, targetPitch); + angle = CGeneral::LimitRadianAngle(angle - m_upperArmOrient.yaw); } if (armPointedToGun) { - if (m_flags & AIMS_WITH_ARM && m_torsoOrient.phi * m_upperArmOrient.phi < 0.0f) - MoveLimb(m_torsoOrient, 0.0f, m_torsoOrient.theta, ms_torsoInfo); + if (m_flags & AIMS_WITH_ARM && m_torsoOrient.yaw * m_upperArmOrient.yaw < 0.0f) + MoveLimb(m_torsoOrient, 0.0f, m_torsoOrient.pitch, ms_torsoInfo); } else { // Unused code RwMatrix *matrix; @@ -365,7 +365,7 @@ CPedIK::PointGunInDirection(float phi, float theta) } // - LimbMoveStatus status = MoveLimb(m_torsoOrient, angle, theta, ms_torsoInfo); + LimbMoveStatus status = MoveLimb(m_torsoOrient, angle, targetPitch, ms_torsoInfo); if (status == ANGLES_SET_TO_MAX) result = false; else if (status == ANGLES_SET_EXACTLY) @@ -379,7 +379,7 @@ CPedIK::PointGunInDirection(float phi, float theta) } bool -CPedIK::PointGunInDirectionUsingArm(float phi, float theta) +CPedIK::PointGunInDirectionUsingArm(float targetYaw, float targetPitch) { bool result = false; @@ -410,18 +410,18 @@ CPedIK::PointGunInDirectionUsingArm(float phi, float theta) RwV3d rightVector = { 0.0f, 0.0f, 1.0f }; RwV3d forwardVector = { 1.0f, 0.0f, 0.0f }; - float uaPhi, uaTheta; + float uaYaw, uaPitch; #ifdef PED_SKIN if(IsClumpSkinned(m_ped->GetClump())){ - uaPhi = phi; - uaTheta = theta + DEGTORAD(10.0f); + uaYaw = targetYaw; + uaPitch = targetPitch + DEGTORAD(10.0f); }else #endif { - uaPhi = phi - m_torsoOrient.phi - DEGTORAD(15.0f); - uaTheta = CGeneral::LimitRadianAngle(theta - pitch); + uaYaw = targetYaw - m_torsoOrient.yaw - DEGTORAD(15.0f); + uaPitch = CGeneral::LimitRadianAngle(targetPitch - pitch); } - LimbMoveStatus uaStatus = MoveLimb(m_upperArmOrient, uaPhi, uaTheta, ms_upperArmInfo); + LimbMoveStatus uaStatus = MoveLimb(m_upperArmOrient, uaYaw, uaPitch, ms_upperArmInfo); if (uaStatus == ANGLES_SET_EXACTLY) { m_flags |= GUN_POINTED_SUCCESSFULLY; result = true; @@ -433,13 +433,13 @@ CPedIK::PointGunInDirectionUsingArm(float phi, float theta) if(!IsClumpSkinned(m_ped->GetClump())) #endif if (uaStatus == ANGLES_SET_TO_MAX) { - float laPhi = uaPhi - m_upperArmOrient.phi; + float laYaw = uaYaw - m_upperArmOrient.yaw; LimbMoveStatus laStatus; - if (laPhi > 0.0f) - laStatus = MoveLimb(m_lowerArmOrient, laPhi, -DEGTORAD(45.0f), ms_lowerArmInfo); + if (laYaw > 0.0f) + laStatus = MoveLimb(m_lowerArmOrient, laYaw, -DEGTORAD(45.0f), ms_lowerArmInfo); else - laStatus = MoveLimb(m_lowerArmOrient, laPhi, 0.0f, ms_lowerArmInfo); + laStatus = MoveLimb(m_lowerArmOrient, laYaw, 0.0f, ms_lowerArmInfo); if (laStatus == ANGLES_SET_EXACTLY) { m_flags |= GUN_POINTED_SUCCESSFULLY; @@ -447,16 +447,16 @@ CPedIK::PointGunInDirectionUsingArm(float phi, float theta) } RwFrame *child = GetFirstChild(m_ped->m_pFrames[PED_UPPERARMR]->frame); RwV3d pos = RwFrameGetMatrix(child)->pos; - RwMatrixRotate(RwFrameGetMatrix(child), &forwardVector, RADTODEG(m_lowerArmOrient.theta), rwCOMBINEPOSTCONCAT); - RwMatrixRotate(RwFrameGetMatrix(child), &rightVector, RADTODEG(-m_lowerArmOrient.phi), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(child), &forwardVector, RADTODEG(m_lowerArmOrient.pitch), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(child), &rightVector, RADTODEG(-m_lowerArmOrient.yaw), rwCOMBINEPOSTCONCAT); RwFrameGetMatrix(child)->pos = pos; } #ifdef PED_SKIN if(IsClumpSkinned(m_ped->GetClump())){ RtQuat *q = &m_ped->m_pFrames[PED_UPPERARMR]->hanimFrame->q; - RtQuatRotate(q, &XaxisIK, RADTODEG(m_upperArmOrient.phi), rwCOMBINEPOSTCONCAT); - RtQuatRotate(q, &ZaxisIK, RADTODEG(m_upperArmOrient.theta), rwCOMBINEPOSTCONCAT); + RtQuatRotate(q, &XaxisIK, RADTODEG(m_upperArmOrient.yaw), rwCOMBINEPOSTCONCAT); + RtQuatRotate(q, &ZaxisIK, RADTODEG(m_upperArmOrient.pitch), rwCOMBINEPOSTCONCAT); m_ped->bDontAcceptIKLookAts = true; }else #endif @@ -464,8 +464,8 @@ CPedIK::PointGunInDirectionUsingArm(float phi, float theta) RwFrame *frame = m_ped->m_pFrames[PED_UPPERARMR]->frame; // with PED_SKIN we're also getting upVector here RwV3d pos = RwFrameGetMatrix(frame)->pos; - RwMatrixRotate(RwFrameGetMatrix(frame), &rightVector, RADTODEG(m_upperArmOrient.theta), rwCOMBINEPOSTCONCAT); - RwMatrixRotate(RwFrameGetMatrix(frame), &upVector, RADTODEG(m_upperArmOrient.phi), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(frame), &rightVector, RADTODEG(m_upperArmOrient.pitch), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(frame), &upVector, RADTODEG(m_upperArmOrient.yaw), rwCOMBINEPOSTCONCAT); RwFrameGetMatrix(frame)->pos = pos; } return result; @@ -511,8 +511,8 @@ CPedIK::RestoreLookAt(void) CMatrix matrix(mat); CVector pos = matrix.GetPosition(); - matrix.SetRotateZ(m_headOrient.theta); - matrix.RotateX(m_headOrient.phi); + matrix.SetRotateZ(m_headOrient.pitch); + matrix.RotateX(m_headOrient.yaw); matrix.Translate(pos); matrix.UpdateRW(); } diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index a1cb5d13..e91d7c06 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -4,8 +4,8 @@ struct LimbOrientation { - float phi; - float theta; + float yaw; + float pitch; }; struct LimbMovementInfo { @@ -48,8 +48,8 @@ public: static LimbMovementInfo ms_lowerArmInfo; CPedIK(CPed *ped); - bool PointGunInDirection(float phi, float theta); - bool PointGunInDirectionUsingArm(float phi, float theta); + bool PointGunInDirection(float targetYaw, float targetPitch); + bool PointGunInDirectionUsingArm(float targetYaw, float targetPitch); bool PointGunAtPosition(CVector const& position); void GetComponentPosition(RwV3d *pos, uint32 node); static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination); @@ -57,10 +57,10 @@ public: void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch); void ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch); void ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch); - LimbMoveStatus MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo); + LimbMoveStatus MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, LimbMovementInfo &moveInfo); bool RestoreGunPosn(void); void RotateHead(void); - bool LookInDirection(float phi, float theta); + bool LookInDirection(float targetYaw, float targetPitch); bool LookAtPosition(CVector const& pos); bool RestoreLookAt(void); }; From 9dc5dca209dce4cb846e99bc6d421444be8b22fa Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 16 May 2020 11:34:51 +0200 Subject: [PATCH 012/148] remove some unneeded plane paths for the moment; also different exe icon --- src/skel/win/gta3.ico | Bin 2238 -> 0 bytes src/skel/win/gtavc.ico | Bin 0 -> 3262 bytes src/skel/win/win.rc | 2 +- src/vehicles/Plane.cpp | 2 ++ 4 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 src/skel/win/gta3.ico create mode 100644 src/skel/win/gtavc.ico diff --git a/src/skel/win/gta3.ico b/src/skel/win/gta3.ico deleted file mode 100644 index 2017c8116bb76bf612babe81eb013c2c0250dbc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2238 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 literal 0 HcmV?d00001 diff --git a/src/skel/win/win.rc b/src/skel/win/win.rc index 379c473d..9b5aa305 100644 --- a/src/skel/win/win.rc +++ b/src/skel/win/win.rc @@ -42,6 +42,6 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_MAIN_ICON ICON DISCARDABLE "gta3.ico" +IDI_MAIN_ICON ICON DISCARDABLE "gtavc.ico" ///////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 39069364..8f32f12a 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -735,6 +735,7 @@ CPlane::InitPlanes(void) TotalDurationOfFlightPath2 = TotalLengthOfFlightPath2/CRUISE_SPEED; } +/* // Mission Cesna if(pPath3Nodes == nil){ pPath3Nodes = LoadPath("data\\paths\\flight3.dat", NumPath3Nodes, TotalLengthOfFlightPath3, false); @@ -746,6 +747,7 @@ CPlane::InitPlanes(void) pPath4Nodes = LoadPath("data\\paths\\flight4.dat", NumPath4Nodes, TotalLengthOfFlightPath4, false); TotalDurationOfFlightPath4 = TotalLengthOfFlightPath4/CRUISE_SPEED; } +*/ CStreaming::LoadAllRequestedModels(false); CStreaming::RequestModel(MI_AIRTRAIN, 0); From 4defd8b75c80341ecccbfe2a0d3a6baf34c4f02e Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 13:31:23 +0300 Subject: [PATCH 013/148] minimal weather stuff + multiple bugfixes --- src/control/Replay.cpp | 9 ++ src/control/Script.cpp | 8 +- src/core/Stats.cpp | 2 + src/core/Stats.h | 1 + src/render/Renderer.cpp | 3 +- src/render/Weather.cpp | 182 ++++++++++++++++++++++------------- src/render/Weather.h | 28 +++--- src/rw/VisibilityPlugins.cpp | 2 + src/vehicles/CarGen.cpp | 2 +- 9 files changed, 146 insertions(+), 91 deletions(-) diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index ab187c10..abd96112 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -17,6 +17,7 @@ #include "ModelInfo.h" #include "Object.h" #include "Pad.h" +#include "PedAttractor.h" #include "Phones.h" #include "Pickups.h" #include "Plane.h" @@ -1116,6 +1117,14 @@ void CReplay::StoreStuffInMem(void) for (int i = 0; i < NUMPLAYERS; i++) nHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed); #endif + int i = CPools::GetPedPool()->GetSize(); + while (--i >= 0) { + CPed* ped = CPools::GetPedPool()->GetSlot(i); + if (!ped) + continue; + if (ped->m_attractor) + GetPedAttractorManager()->DeRegisterPed(ped, ped->m_attractor); + } CPools::GetVehiclePool()->Store(pBuf0, pBuf1); CPools::GetPedPool()->Store(pBuf2, pBuf3); CPools::GetObjectPool()->Store(pBuf4, pBuf5); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 8342ef46..cd0ea5b3 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -5248,12 +5248,8 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true); return 0; } - case COMMAND_STORE_WEATHER: - CWeather::StoreWeatherState(); - return 0; - case COMMAND_RESTORE_WEATHER: - CWeather::RestoreWeatherState(); - return 0; + //case COMMAND_STORE_WEATHER: + //case COMMAND_RESTORE_WEATHER: case COMMAND_STORE_CLOCK: CClock::StoreClock(); return 0; diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index ea934dca..d50be0d5 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -60,6 +60,7 @@ int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; int32 CStats::Sprayings; float CStats::AutoPaintingBudget; +int32 CStats::NoMoreHurricanes; void CStats::Init() { @@ -119,6 +120,7 @@ void CStats::Init() Sprayings = 0; AutoPaintingBudget = 0.0f; + NoMoreHurricanes = 0; } void CStats::RegisterFastestTime(int32 index, int32 time) diff --git a/src/core/Stats.h b/src/core/Stats.h index 51f1d091..bf40a5a6 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -64,6 +64,7 @@ public: static int32 HighestScores[TOTAL_HIGHEST_SCORES]; static int32 Sprayings; static float AutoPaintingBudget; + static int32 NoMoreHurricanes; public: static void Init(void); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 406edc9f..803f4cc1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -143,7 +143,8 @@ CRenderer::RenderOneNonRoad(CEntity *e) resetLights = e->SetupLighting(); if(e->IsVehicle()){ - CVisibilityPlugins::SetupVehicleVariables(e->GetClump()); + // unfortunately can't use GetClump here + CVisibilityPlugins::SetupVehicleVariables((RpClump*)e->m_rwObject); CVisibilityPlugins::InitAlphaAtomicList(); } diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 25e67281..fc3e0d61 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -8,6 +8,7 @@ #include "DMAudio.h" #include "General.h" #include "Pad.h" +#include "PlayerPed.h" #include "Particle.h" #include "RenderBuffer.h" #include "Stats.h" @@ -40,41 +41,60 @@ float CWeather::Rain; float CWeather::InterpolationValue; float CWeather::WetRoads; float CWeather::Rainbow; +float CWeather::SunGlare; +float CWeather::WindClipped; +float CWeather::TrafficLightBrightness; bool CWeather::bScriptsForceRain; -bool CWeather::Stored_StateStored; - -float CWeather::Stored_InterpolationValue; -int16 CWeather::Stored_OldWeatherType; -int16 CWeather::Stored_NewWeatherType; -float CWeather::Stored_Rain; tRainStreak Streaks[NUM_RAIN_STREAKS]; const int16 WeatherTypesList[] = { + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, + WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_CLOUDY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_CLOUDY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, WEATHER_CLOUDY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY +}; + +const int16 WeatherTypesList_WithHurricanes[] = { + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_CLOUDY, + WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_CLOUDY, WEATHER_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY, - WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_SUNNY, - WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_RAINY, WEATHER_CLOUDY, + WEATHER_CLOUDY, WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_HURRICANE, + WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, + WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, + WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY }; const float Windiness[] = { - 0.0f, // WEATHER_SUNNY + 0.25f,// WEATHER_SUNNY 0.7f, // WEATHER_CLOUDY 1.0f, // WEATHER_RAINY - 0.5f // WEATHER_FOGGY + 0.0f, // WEATHER_FOGGY + 0.0f, // WEATHER_EXTRA_SUNNY + 2.0f, // WEATHER_HURRICANE + 0.0f }; #define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50) @@ -105,10 +125,9 @@ const float Windiness[] = { void CWeather::Init(void) { - NewWeatherType = WEATHER_SUNNY; + NewWeatherType = WEATHER_EXTRA_SUNNY; bScriptsForceRain = false; - OldWeatherType = WEATHER_CLOUDY; - Stored_StateStored = false; + OldWeatherType = WEATHER_EXTRA_SUNNY; InterpolationValue = 0.0f; WhenToPlayLightningSound = 0; WeatherTypeInList = 0; @@ -128,16 +147,8 @@ void CWeather::Update(void) NewWeatherType = ForcedWeatherType; else { WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList); - NewWeatherType = WeatherTypesList[WeatherTypeInList]; -#ifdef FIX_BUGS + NewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList]; } - if (NewWeatherType == WEATHER_RAINY) - CStats::mmRain += CGeneral::GetRandomNumber() & 7; -#else - if (NewWeatherType == WEATHER_RAINY) - CStats::mmRain += CGeneral::GetRandomNumber() & 7; - } -#endif } InterpolationValue = fNewInterpolation; if (CPad::GetPad(1)->GetRightShockJustDown()) { @@ -189,14 +200,14 @@ void CWeather::Update(void) } // Wet roads - if (OldWeatherType == WEATHER_RAINY) { - if (NewWeatherType == WEATHER_RAINY) + if (OldWeatherType == WEATHER_RAINY || OldWeatherType == WEATHER_HURRICANE) { + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) WetRoads = 1.0f; else WetRoads = 1.0f - InterpolationValue; } else { - if (NewWeatherType == WEATHER_RAINY) + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) WetRoads = InterpolationValue; else WetRoads = 0.0f; @@ -204,10 +215,10 @@ void CWeather::Update(void) // Rain float fNewRain; - if (NewWeatherType == WEATHER_RAINY) { + if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) { // if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f; - if (OldWeatherType != WEATHER_RAINY) { + if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) { if (InterpolationValue < 0.4f) // if rain has just started (<24 minutes), always 0.5 fNewRain = 0.5f; @@ -218,19 +229,14 @@ void CWeather::Update(void) } else fNewRain = 0.0f; - if (Rain != fNewRain) { // ok to use comparasion - if (Rain < fNewRain) - Rain = Min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); - else - Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); - } + Rain = fNewRain; // Clouds - if (OldWeatherType != WEATHER_SUNNY) + if (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY) CloudCoverage = 1.0f - InterpolationValue; else CloudCoverage = 0.0f; - if (NewWeatherType != WEATHER_SUNNY) + if (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY) CloudCoverage += InterpolationValue; // Fog @@ -240,12 +246,76 @@ void CWeather::Update(void) Foggyness = 0.0f; if (NewWeatherType == WEATHER_FOGGY) Foggyness += InterpolationValue; - if (OldWeatherType == WEATHER_RAINY && NewWeatherType == WEATHER_SUNNY && InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21) + + // Extra Sunnyness + if (OldWeatherType == WEATHER_EXTRA_SUNNY) + ExtraSunnyness = 1.0f - InterpolationValue; + else + ExtraSunnyness = 0.0f; + if (NewWeatherType == WEATHER_EXTRA_SUNNY) + ExtraSunnyness += InterpolationValue; + + // Rainbow + if (OldWeatherType == WEATHER_RAINY && (NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && + InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21) Rainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f; else Rainbow = 0.0f; + + // Sun Glare + if (OldWeatherType == WEATHER_EXTRA_SUNNY) + SunGlare = 1.0f - InterpolationValue; + else + SunGlare = 0.0f; + if (NewWeatherType == WEATHER_EXTRA_SUNNY) + SunGlare += InterpolationValue; + + if (SunGlare > 0.0f) { + SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunPosition().z); + SunGlare = clamp(SunGlare, 0.0f, 1.0f); + // TODO(MIAMI): if (CSpecialFX::bSnapShotActive)... + } + Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType]; + WindClipped = Max(1.0f, Wind); + + if (CClock::GetHours() == 20) + TrafficLightBrightness = CClock::GetMinutes() / 60.0f; + else if (CClock::GetHours() > 6 && CClock::GetHours() < 20) + TrafficLightBrightness = 0.0f; + else if (CClock::GetHours() == 6) + TrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f; + else + TrafficLightBrightness = 1.0f; + TrafficLightBrightness = Max(WetRoads, TrafficLightBrightness); + TrafficLightBrightness = Max(Rain, TrafficLightBrightness); + AddRain(); + + if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && + !CGame::IsInInterior() && !CCutsceneMgr::IsRunning() && (CTimer::GetFrameCounter() & 7) == 0) { +#ifdef FIX_BUGS + if (FindPlayerPed() && (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f && + CClock::GetHours() > 6 && CClock::GetHours() < 18)) +#else + if (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f && + CClock::GetHours() > 6 && CClock::GetHours() < 18) +#endif + AddHeatHaze(); + } + + if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && !CGame::IsInInterior() && !CCutsceneMgr::IsRunning()) + AddBeastie(); +} + +void CWeather::AddHeatHaze() +{ + /* TODO(MIAMI) */ +} + +void CWeather::AddBeastie() +{ + /* TODO(MIAMI) */ } void CWeather::ForceWeather(int16 weather) @@ -511,23 +581,3 @@ void CWeather::RenderRainStreaks(void) TempBufferVerticesStored = 0; TempBufferIndicesStored = 0; } - -void CWeather::StoreWeatherState() -{ - Stored_StateStored = true; - Stored_InterpolationValue = InterpolationValue; - Stored_Rain = Rain; - Stored_NewWeatherType = NewWeatherType; - Stored_OldWeatherType = OldWeatherType; -} - -void CWeather::RestoreWeatherState() -{ -#ifdef FIX_BUGS // it's not used anyway though - Stored_StateStored = false; -#endif - InterpolationValue = Stored_InterpolationValue; - Rain = Stored_Rain; - NewWeatherType = Stored_NewWeatherType; - OldWeatherType = Stored_OldWeatherType; -} diff --git a/src/render/Weather.h b/src/render/Weather.h index 4bf2fd8f..bd9b9603 100644 --- a/src/render/Weather.h +++ b/src/render/Weather.h @@ -1,21 +1,17 @@ enum { - WEATHER_SUNNY, + WEATHER_RANDOM = -1, + WEATHER_SUNNY = 0, WEATHER_CLOUDY, WEATHER_RAINY, - WEATHER_FOGGY + WEATHER_FOGGY, + WEATHER_EXTRA_SUNNY, + WEATHER_HURRICANE, + WEATHER_TOTAL }; class CWeather { public: - enum { - WEATHER_RANDOM = -1, - WEATHER_SUNNY = 0, - WEATHER_CLOUDY = 1, - WEATHER_RAINY = 2, - WEATHER_FOGGY = 3, - WEATHER_TOTAL = 4 - }; static int32 SoundHandle; static int32 WeatherTypeInList; @@ -38,13 +34,11 @@ public: static float InterpolationValue; static float WetRoads; static float Rainbow; + static float SunGlare; + static float WindClipped; + static float TrafficLightBrightness; static bool bScriptsForceRain; - static bool Stored_StateStored; - static float Stored_InterpolationValue; - static int16 Stored_OldWeatherType; - static int16 Stored_NewWeatherType; - static float Stored_Rain; static void RenderRainStreaks(void); static void Update(void); @@ -53,9 +47,9 @@ public: static void ReleaseWeather(); static void ForceWeather(int16); static void ForceWeatherNow(int16); - static void StoreWeatherState(); - static void RestoreWeatherState(); static void AddRain(); + static void AddHeatHaze(); + static void AddBeastie(); }; enum { diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 5a94e8f6..3b68c981 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -139,6 +139,8 @@ static float PitchToCamera; void CVisibilityPlugins::SetupVehicleVariables(RpClump *vehicle) { + if (vehicle->object.type != rpCLUMP) + return; DistToCameraSq = GetDistanceSquaredFromCamera(RpClumpGetFrame(vehicle)); RwV3d distToCam; RwV3dSub(&distToCam, ms_pCameraPosn, &RwFrameGetMatrix(RpClumpGetFrame(vehicle))->pos); diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 16401008..7c02f3ee 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -186,7 +186,7 @@ bool CCarGenerator::CheckForBlockage(int32 mi) CWorld::FindObjectsKindaColliding(CVector(m_vecPos), pColModel->boundingSphere.radius, 1, &entities, 8, pEntities, false, true, true, false, false); for (int i = 0; i < entities; i++) { if (m_vecPos.z + pColModel->boundingBox.min.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.max.z + 1.0f && - m_vecPos.z + pColModel->boundingBox.max.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) { + m_vecPos.z + pColModel->boundingBox.max.z > pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) { m_bIsBlocking = true; return true; } From b21f49ad6b2c3f7a22690254321776a0b15c2fed Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 16 May 2020 12:51:54 +0200 Subject: [PATCH 014/148] fixed CText to be 64 bit compatible --- src/text/Text.cpp | 16 ++++++++++++++++ src/text/Text.h | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 549f68d9..1e58fcd1 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -97,7 +97,11 @@ CText::Unload(void) wchar* CText::Get(const char *key) { +#ifdef FIX_BUGS + return keyArray.Search(key, data.chars); +#else return keyArray.Search(key); +#endif } wchar UpperCaseTable[128] = { @@ -196,9 +200,11 @@ CKeyArray::Unload(void) void CKeyArray::Update(wchar *chars) { +#ifndef FIX_BUGS int i; for(i = 0; i < numEntries; i++) entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value); +#endif } CKeyEntry* @@ -222,15 +228,25 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi } wchar* +#ifdef FIX_BUGS +CKeyArray::Search(const char *key, wchar *data) +#else CKeyArray::Search(const char *key) +#endif { CKeyEntry *found; char errstr[25]; int i; +#ifdef FIX_BUGS + found = BinarySearch(key, entries, 0, numEntries-1); + if(found) + return (wchar*)((uint8*)data + found->valueOffset); +#else found = BinarySearch(key, entries, 0, numEntries-1); if(found) return found->value; +#endif sprintf(errstr, "%s missing", key); for(i = 0; i < 25; i++) WideErrorString[i] = errstr[i]; diff --git a/src/text/Text.h b/src/text/Text.h index 4255e2a5..18a904bc 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -9,7 +9,11 @@ void TextCopy(wchar *dst, const wchar *src); struct CKeyEntry { +#ifdef FIX_BUGS + uint32 valueOffset; +#else wchar *value; +#endif char key[8]; }; @@ -28,7 +32,11 @@ public: void Unload(void); void Update(wchar *chars); CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high); +#ifdef FIX_BUGS + wchar *Search(const char *key, wchar *data); +#else wchar *Search(const char *key); +#endif }; class CData From 9558baa3537b69560813a7a71002a8338c4cb40b Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 16 May 2020 12:51:54 +0200 Subject: [PATCH 015/148] fixed CText to be 64 bit compatible --- src/text/Text.cpp | 16 ++++++++++++++++ src/text/Text.h | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 549f68d9..1e58fcd1 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -97,7 +97,11 @@ CText::Unload(void) wchar* CText::Get(const char *key) { +#ifdef FIX_BUGS + return keyArray.Search(key, data.chars); +#else return keyArray.Search(key); +#endif } wchar UpperCaseTable[128] = { @@ -196,9 +200,11 @@ CKeyArray::Unload(void) void CKeyArray::Update(wchar *chars) { +#ifndef FIX_BUGS int i; for(i = 0; i < numEntries; i++) entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value); +#endif } CKeyEntry* @@ -222,15 +228,25 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi } wchar* +#ifdef FIX_BUGS +CKeyArray::Search(const char *key, wchar *data) +#else CKeyArray::Search(const char *key) +#endif { CKeyEntry *found; char errstr[25]; int i; +#ifdef FIX_BUGS + found = BinarySearch(key, entries, 0, numEntries-1); + if(found) + return (wchar*)((uint8*)data + found->valueOffset); +#else found = BinarySearch(key, entries, 0, numEntries-1); if(found) return found->value; +#endif sprintf(errstr, "%s missing", key); for(i = 0; i < 25; i++) WideErrorString[i] = errstr[i]; diff --git a/src/text/Text.h b/src/text/Text.h index 4255e2a5..18a904bc 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -9,7 +9,11 @@ void TextCopy(wchar *dst, const wchar *src); struct CKeyEntry { +#ifdef FIX_BUGS + uint32 valueOffset; +#else wchar *value; +#endif char key[8]; }; @@ -28,7 +32,11 @@ public: void Unload(void); void Update(wchar *chars); CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high); +#ifdef FIX_BUGS + wchar *Search(const char *key, wchar *data); +#else wchar *Search(const char *key); +#endif }; class CData From c33b93793f71a8cdcdf9d8cbbc69f8873f45113a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 14:01:32 +0300 Subject: [PATCH 016/148] new horn --- src/vehicles/Automobile.cpp | 14 +++++++++++++- src/vehicles/Vehicle.cpp | 1 + src/vehicles/Vehicle.h | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 6e88b997..d1f2faaa 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -4024,10 +4024,22 @@ CAutomobile::PlayCarHorn(void) { int r; + if (m_nAlarmState && m_nAlarmState != -1) + return; + + if (GetStatus() == STATUS_WRECKED) + return; + if(m_nCarHornTimer != 0) return; - r = CGeneral::GetRandomNumber() & 7; + if (m_nCarHornDelay) { + m_nCarHornDelay--; + return; + } + + m_nCarHornDelay = (CGeneral::GetRandomNumber() & 0x7F) + 150; + r = m_nCarHornDelay & 7; if(r < 2){ m_nCarHornTimer = 45; }else if(r < 4){ diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 4149fe6c..e457f964 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -101,6 +101,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_bSirenOrAlarm = 0; m_nCarHornTimer = 0; m_nCarHornPattern = 0; + m_nCarHornDelay = 0; bPartOfConvoy = false; bCreatedAsPoliceVehicle = false; bParking = false; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index cdf0595a..c9e6bf93 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -211,8 +211,9 @@ public: uint8 m_bRainAudioCounter; uint8 m_bRainSamplesCounter; uint8 m_nCarHornTimer; - uint8 m_nCarHornPattern; // last horn? + uint8 m_nCarHornPattern; bool m_bSirenOrAlarm; + uint8 m_nCarHornDelay; int8 m_comedyControlState; CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car float m_fSteerRatio; From 793a6a6d7e5c5db61420f367e2e4c8d7567ba06d Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 16 May 2020 13:02:13 +0200 Subject: [PATCH 017/148] bla --- src/rw/VisibilityPlugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 3b68c981..cff1ff16 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -139,7 +139,7 @@ static float PitchToCamera; void CVisibilityPlugins::SetupVehicleVariables(RpClump *vehicle) { - if (vehicle->object.type != rpCLUMP) + if (RwObjectGetType((RwObject*)vehicle) != rpCLUMP) return; DistToCameraSq = GetDistanceSquaredFromCamera(RpClumpGetFrame(vehicle)); RwV3d distToCam; From 40ee29fb99cc82c720ece4eab0e06855a161d12a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 16 May 2020 15:07:09 +0300 Subject: [PATCH 018/148] Weapon fixes --- src/peds/Ped.cpp | 22 +++++++++------------- src/peds/Ped.h | 14 +++++++++++++- src/peds/PedIK.cpp | 5 ++++- src/peds/PlayerPed.cpp | 27 +++++++++++++++++++++------ src/weapons/Weapon.cpp | 16 +++++++++------- src/weapons/Weapon.h | 4 ++-- src/weapons/WeaponInfo.h | 2 +- 7 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 86333d8c..8da8249e 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -679,7 +679,7 @@ CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo, bool unused) if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1. - GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], (int32) GetWeapon(slot).m_nAmmoTotal); + GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal); } else { GetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal); } @@ -1187,7 +1187,7 @@ CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg) } } else if (weapon->m_bReloadLoop2Start && ped->bIsAttacking) { CAnimBlendAssociation *fireAssoc = - CAnimManager::BlendAnimation(ped->GetClump(), weapon->m_AnimToPlay, weapon->m_bAnimDetonate ? ANIM_BOMBER : ANIM_WEAPON_FIRE, 8.0f); + CAnimManager::BlendAnimation(ped->GetClump(), weapon->m_AnimToPlay, GetPrimaryFireAnim(weapon), 8.0f); fireAssoc->SetFinishCallback(FinishedAttackCB, ped); fireAssoc->SetRun(); if (fireAssoc->currentTime != reloadAssoc->hierarchy->totalLength) { @@ -1302,6 +1302,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) } } +// --MIAMI: Done void CPed::Attack(void) { @@ -3874,12 +3875,7 @@ CPed::ClearAttackByRemovingAnim(void) return; CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_bAnimDetonate ? ANIM_BOMBER : ANIM_WEAPON_FIRE); - - // TODO(Miami): Remove when fighting got ported - if (!weaponAssoc) { - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_PPUNCH); - } + CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(weapon)); if (!weaponAssoc) { if (!!weapon->m_bCrouchFire) @@ -4882,15 +4878,15 @@ CPed::SetAmmo(eWeaponType weaponType, uint32 ammo) if (slot == -1) return; - GetWeapon(slot).m_nAmmoTotal += ammo; + GetWeapon(slot).m_nAmmoTotal = ammo; if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1. - GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], (int32)GetWeapon(slot).m_nAmmoTotal); + GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal); } else { GetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal); } - uint32 newClip = GetWeapon(slot).m_nAmmoTotal; + int32 newClip = GetWeapon(slot).m_nAmmoTotal; if (newClip >= GetWeapon(slot).m_nAmmoInClip) newClip = GetWeapon(slot).m_nAmmoInClip; GetWeapon(slot).m_nAmmoInClip = newClip; @@ -4911,7 +4907,7 @@ CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo) if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1. - GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], (int32)GetWeapon(slot).m_nAmmoTotal); + GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal); } else { GetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal); } @@ -6341,7 +6337,7 @@ CPed::CreateDeadPedWeaponPickups(void) eWeaponType weapon = GetWeapon(i).m_eWeaponType; int weaponAmmo = GetWeapon(i).m_nAmmoTotal; - if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0) + if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || (weaponAmmo == 0 && !GetWeapon(i).IsTypeMelee())) continue; angleToPed = i * 1.75f; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index f86f23d3..32557cb6 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -704,6 +704,7 @@ public: void RemoveWeaponAnims(int, float); void CreateDeadPedMoney(void); void CreateDeadPedWeaponPickups(void); +// void CreateDeadPedPickupCoors(float *x, float *y, float *z); void SetAttackTimer(uint32); void SetBeingDraggedFromCar(CVehicle*, uint32, bool); void SetRadioStation(void); @@ -899,7 +900,7 @@ public: if (m_nPedType == PEDTYPE_COP && !!weapon->m_bCop3rd) return ANIM_WEAPON_FIRE_3RD; else - return weapon->m_bAnimDetonate ? ANIM_BOMBER : ANIM_WEAPON_FIRE; + return GetPrimaryFireAnim(weapon); } static AnimationId GetFireAnimGround(CWeaponInfo* weapon, bool kickFloorIfNone = true) { @@ -916,6 +917,17 @@ public: else return (AnimationId)0; } + + static AnimationId GetPrimaryFireAnim(CWeaponInfo* weapon) { + // TODO(Miami): Revert that when weapons got ported + if (weapon->m_AnimToPlay == ASSOCGRP_STD) + return ANIM_FIGHT_PPUNCH; + + if (weapon->m_bAnimDetonate) + return ANIM_BOMBER; + else + return ANIM_WEAPON_FIRE; + } // -- // My additions, because there were many, many instances of that. diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index 8b3835b3..6543e9a3 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -293,9 +293,12 @@ bool CPedIK::PointGunAtPosition(CVector const& position) { // TODO(MIAMI): special cases for some weapons + + RwV3d armPos; + GetComponentPosition(&armPos, PED_UPPERARMR); return PointGunInDirection( CGeneral::GetRadianAngleBetweenPoints(position.x, position.y, m_ped->GetPosition().x, m_ped->GetPosition().y), - CGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y), m_ped->GetPosition().z, 0.0f)); + CGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y), armPos.z, 0.0f)); } bool diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 04251860..826cc9e9 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -92,6 +92,11 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) void CPlayerPed::ClearWeaponTarget() { if (m_nPedType == PEDTYPE_PLAYER1) { + + // TODO(Miami) + // if (m_pPointGunAt) + // m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); + m_pPointGunAt = nil; TheCamera.ClearPlayerWeaponMode(); CWeaponEffects::ClearCrossHair(); @@ -213,13 +218,15 @@ CPlayerPed::MakeChangesForNewWeapon(eWeaponType weapon) TheCamera.ClearPlayerWeaponMode(); } SetCurrentWeapon(weapon); + m_nSelectedWepSlot = m_currentWeapon; GetWeapon()->m_nAmmoInClip = Min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAim)) ClearWeaponTarget(); - CAnimBlendAssociation* weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)->m_bAnimDetonate ? 62 : 205); + // WEAPONTYPE_SNIPERRIFLE? Wut? + CAnimBlendAssociation* weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE))); if (weaponAnim) { weaponAnim->SetRun(); weaponAnim->flags |= ASSOC_FADEOUTWHENDONE; @@ -666,7 +673,10 @@ CPlayerPed::ProcessWeaponSwitch(CPad *padUsed) for (m_nSelectedWepSlot = m_currentWeapon - 1; ; --m_nSelectedWepSlot) { if (m_nSelectedWepSlot < 0) - m_nSelectedWepSlot = 9; + m_nSelectedWepSlot = TOTAL_WEAPON_SLOTS - 1; + + if (m_nSelectedWepSlot == 0) + break; if (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) { break; @@ -690,11 +700,16 @@ spentAmmoCheck: else m_nSelectedWepSlot = 2; - // BUG: m_nSelectedWepSlot is slot in VC but they compared against weapon types, lol. for (; m_nSelectedWepSlot >= 0; --m_nSelectedWepSlot) { - if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(6).m_eWeaponType == WEAPONTYPE_BASEBALLBAT + + // BUG: m_nSelectedWepSlot and GetWeapon(..) takes slot in VC but they compared them against weapon types in whole condition! jeez +#ifdef FIX_BUGS + if (m_nSelectedWepSlot == 1 || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != 2) { +#else + if (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(WEAPONTYPE_BASEBALLBAT).m_eWeaponType == WEAPONTYPE_BASEBALLBAT || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 - /*&& m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE && m_nSelectedWepSlot != WEAPONTYPE_TEARGAS */) { + && m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE && m_nSelectedWepSlot != WEAPONTYPE_TEARGAS) { +#endif goto switchDetectDone; } } @@ -1152,7 +1167,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) { // Weapons except throwable and melee ones - if (weaponInfo->m_bCanAim || weaponInfo->m_b1stPerson || weaponInfo->m_bExpands) { + if (weaponInfo->m_nWeaponSlot > 2) { if ((padUsed->GetTarget() && weaponInfo->m_bCanAimWithArm) || padUsed->GetWeapon()) { float limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation); diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index deb77cb9..1ae26106 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -2312,13 +2312,15 @@ CWeapon::BlowUpExplosiveThings(CEntity *thing) bool CWeapon::HasWeaponAmmoToBeUsed(void) { - switch (m_eWeaponType) { - case WEAPONTYPE_UNARMED: - case WEAPONTYPE_BASEBALLBAT: - return true; - default: - return m_nAmmoTotal != 0; - } + // FIX: This is better (not bug tho) +#if 0 + if (m_eWeaponType <= WEAPONTYPE_CHAINSAW) +#else + if (CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE) +#endif + return true; + else + return m_nAmmoTotal != 0; } bool diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 32322da0..5c62a74b 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -16,8 +16,8 @@ class CWeapon public: eWeaponType m_eWeaponType; eWeaponState m_eWeaponState; - uint32 m_nAmmoInClip; - uint32 m_nAmmoTotal; + int32 m_nAmmoInClip; + int32 m_nAmmoTotal; uint32 m_nTimer; bool m_bAddRotOffset; diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index cb10f095..41450047 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -14,7 +14,7 @@ public: float m_fRange; uint32 m_nFiringRate; uint32 m_nReload; - uint32 m_nAmountofAmmunition; + int32 m_nAmountofAmmunition; uint32 m_nDamage; float m_fSpeed; float m_fRadius; From c54d3ba2ab218b9545e784abaf39b4054d3de4bc Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 16 May 2020 14:34:51 +0200 Subject: [PATCH 019/148] fixes for 64 bit build --- premake5.lua | 36 +++++++++++++++++++++++++++--------- src/control/Script.cpp | 2 +- src/fakerw/fake.cpp | 2 +- src/rw/RwHelper.cpp | 11 +++++++++++ 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/premake5.lua b/premake5.lua index 64b12d3a..c8494884 100644 --- a/premake5.lua +++ b/premake5.lua @@ -23,6 +23,22 @@ else Librw = os.getenv("LIBRW") or "librw" end +function getsys(a) + if a == 'windows' then + return 'win' + end + return a +end + +function getarch(a) + if a == 'x86_64' then + return 'amd64' + elseif a == 'ARM' then + return 'arm' + end + return a +end + workspace "re3" language "C++" configurations { "Debug", "Release" } @@ -40,6 +56,8 @@ workspace "re3" filter { "system:linux" } platforms { "linux-x86-librw_gl3_glfw-oal", + "linux-amd64-librw_gl3_glfw-oal", + "linux-arm-librw_gl3_glfw-oal", } filter "configurations:Debug" @@ -58,6 +76,12 @@ workspace "re3" filter { "platforms:*x86*" } architecture "x86" + filter { "platforms:*amd64*" } + architecture "amd64" + + filter { "platforms:*arm*" } + architecture "ARM" + filter { "platforms:*librw_d3d9*" } defines { "RW_D3D9" } if(not _OPTIONS["with-librw"]) then @@ -68,17 +92,12 @@ workspace "re3" defines { "RW_GL3" } includedirs { path.join(_OPTIONS["glfwdir"], "include") } includedirs { path.join(_OPTIONS["glewdir"], "include") } + if(not _OPTIONS["with-librw"]) then + libdirs { path.join(Librw, "lib/%{getsys(cfg.system)}-%{getarch(cfg.architecture)}-gl3/%{cfg.buildcfg}") } + end filter "platforms:win*librw_gl3_glfw*" defines { "GLEW_STATIC" } - if(not _OPTIONS["with-librw"]) then - libdirs { path.join(Librw, "lib/win-x86-gl3/%{cfg.buildcfg}") } - end - - filter "platforms:linux*librw_gl3_glfw*" - if(not _OPTIONS["with-librw"]) then - libdirs { path.join(Librw, "lib/linux-x86-gl3/%{cfg.buildcfg}") } - end filter {} @@ -181,7 +200,6 @@ project "re3" targetextension ".exe" filter "platforms:linux*" - targetextension ".elf" defines { "OPENAL" } links { "openal", "mpg123", "sndfile", "pthread" } diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 357436c6..631ca436 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -506,7 +506,7 @@ void CRunningScript::Init() #ifdef USE_DEBUG_SCRIPT_LOADER int open_script() { - static int scriptToLoad = 0; + static int scriptToLoad = 1; #ifdef _WIN32 if (GetAsyncKeyState('G') & 0x8000) diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 50d12b2f..71646020 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -470,7 +470,7 @@ RwBool RwRenderStateSet(RwRenderState state, void *value) uint32 uival = (uintptr)value; uint32 fog; switch(state){ - case rwRENDERSTATETEXTURERASTER: SetRenderState(TEXTURERASTER, uival); return true; + case rwRENDERSTATETEXTURERASTER: SetRenderStatePtr(TEXTURERASTER, value); return true; case rwRENDERSTATETEXTUREADDRESS: SetRenderState(TEXTUREADDRESS, uival); return true; case rwRENDERSTATETEXTUREADDRESSU: SetRenderState(TEXTUREADDRESSU, uival); return true; case rwRENDERSTATETEXTUREADDRESSV: SetRenderState(TEXTUREADDRESSV, uival); return true; diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 5026e2c8..191fc7ab 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -59,6 +59,16 @@ void FlushObrsPrintfs() void * RwMallocAlign(RwUInt32 size, RwUInt32 align) { +#ifdef FIX_BUGS + uintptr ptralign = align-1; + void *mem = (void *)malloc(size + sizeof(uintptr) + ptralign); + + ASSERT(mem != nil); + + void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign); + + ASSERT(addr != nil); +#else void *mem = (void *)malloc(size + align); ASSERT(mem != nil); @@ -66,6 +76,7 @@ RwMallocAlign(RwUInt32 size, RwUInt32 align) void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1)); ASSERT(addr != nil); +#endif *(((void **)addr) - 1) = mem; From dc5ece83278aca64c33f344be9d94e055c5c8fb7 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 16 May 2020 16:55:37 +0300 Subject: [PATCH 020/148] Fix audio use of number instead of enum for CAR_ACCEL --- src/audio/AudioManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 8ef439d9..ec46aa53 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -7368,7 +7368,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * return; } if (processedAccelSampleStopped) { - if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + 345, 0)) + if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) return; SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); @@ -7391,7 +7391,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * } if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1) { ++CurrentPretendGear; - if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + 345, 0)) + if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) return; SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); From e3291b0cb14811d9201a5f66f0e8633612ecef7e Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 17:00:40 +0300 Subject: [PATCH 021/148] gangs, script and replay fixes --- src/control/CarCtrl.cpp | 3 +- src/control/CarCtrl.h | 18 +++++----- src/control/Replay.cpp | 18 ++++++++-- src/control/Replay.h | 2 +- src/control/Script.cpp | 19 +++++++--- src/core/Streaming.cpp | 28 +++++++-------- src/modelinfo/ModelIndices.h | 21 +++++++++-- src/peds/Gangs.cpp | 69 ++++++++++++++++++++++++++++++------ src/peds/Gangs.h | 31 +++++++++++----- src/peds/Population.cpp | 14 +------- 10 files changed, 156 insertions(+), 67 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index c1d89884..956bad28 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -889,8 +889,7 @@ CCarCtrl::ChoosePoliceCarModel(void) int32 CCarCtrl::ChooseGangCarModel(int32 gang) { - if (CStreaming::HasModelLoaded(MI_GANG01 + 2 * gang) && - CStreaming::HasModelLoaded(MI_GANG01+1 + 2 * gang)) + if (CGangs::HaveGangModelsLoaded(gang)) return CGangs::GetGangVehicleModel(gang); return -1; } diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 8138266f..e696959c 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -39,19 +39,19 @@ public: WORKERBOAT, COPS, - MAFIA, - TRIAD, - DIABLO, - YAKUZA, - YARDIE, - COLOMB, - NINES, - GANG8, + CUBAN, + HAITIAN, + STREET, + DIAZ, + BIKER, + SECURITY, + PLAYER, + GOLFERS, GANG9, COPS_BOAT, FIRST_CAR_RATING = NORMAL, FIRST_BOAT_RATING = LEISUREBOAT, - FIRST_GANG_CAR_RATING = MAFIA, + FIRST_GANG_CAR_RATING = CUBAN, NUM_CAR_CLASSES = MOTORBIKE - FIRST_CAR_RATING + 1, NUM_BOAT_CLASSES = WORKERBOAT - FIRST_BOAT_RATING + 1, NUM_GANG_CAR_CLASSES = GANG9 - FIRST_GANG_CAR_RATING + 1, diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index abd96112..28b999f8 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -511,8 +511,12 @@ void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayB } RetrievePedAnimation(ped, &pp->anim_state); ped->RemoveWeaponModel(-1); - if (pp->weapon_model != (uint8)-1) - ped->AddWeaponModel(pp->weapon_model); + if (pp->weapon_model != (uint16)-1) { + if (CStreaming::HasModelLoaded(pp->weapon_model)) + ped->AddWeaponModel(pp->weapon_model); + else + CStreaming::RequestModel(pp->weapon_model, 0); + } CWorld::Remove(ped); CWorld::Add(ped); buffer->m_nOffset += sizeof(tPedUpdatePacket); @@ -1220,6 +1224,16 @@ void CReplay::RestoreStuffFromMem(void) ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped); DMAudio.SetEntityStatus(ped->m_audioEntityId, true); CPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false); + for (int j = 0; j < TOTAL_WEAPON_SLOTS; j++) { + int mi1 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModelId; + if (mi1 != -1) + CStreaming::RequestModel(mi1, STREAMFLAGS_DEPENDENCY); + int mi2 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModel2Id; + if (mi2 != -1) + CStreaming::RequestModel(mi2, STREAMFLAGS_DEPENDENCY); + CStreaming::LoadAllRequestedModels(false); + ped->m_weapons[j].Initialise(ped->m_weapons[j].m_eWeaponType, ped->m_weapons[j].m_nAmmoTotal); + } if (ped->m_wepModelID >= 0) ped->AddWeaponModel(ped->m_wepModelID); } diff --git a/src/control/Replay.h b/src/control/Replay.h index 09cf601e..b369c13d 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -176,7 +176,7 @@ class CReplay CStoredAnimationState anim_state; CCompressedMatrixNotAligned matrix; int8 assoc_group_id; - uint8 weapon_model; + uint16 weapon_model; }; VALIDATE_SIZE(tPedUpdatePacket, 40); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index cd0ea5b3..f496ed33 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -4723,8 +4723,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) float supX = *(float*)&ScriptParams[5]; float supY = *(float*)&ScriptParams[6]; float supZ = *(float*)&ScriptParams[7]; - - // TODO(MIAMI): new 2 parameters, requires CGarage change ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, (eGarageType)ScriptParams[8], 0); StoreParameters(&m_nIp, 1); return 0; @@ -4740,7 +4738,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) float supX = *(float*)&ScriptParams[5]; float supY = *(float*)&ScriptParams[6]; float supZ = *(float*)&ScriptParams[7]; - // TODO(MIAMI): new 2 parameters, requires CGarage change ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, (eGarageType)ScriptParams[8], ScriptParams[9]); StoreParameters(&m_nIp, 1); return 0; @@ -5010,7 +5007,10 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) //case COMMAND_SET_GANG_ATTITUDE: //case COMMAND_SET_GANG_GANG_ATTITUDE: //case COMMAND_SET_GANG_PLAYER_ATTITUDE: - //case COMMAND_SET_GANG_PED_MODELS: + case COMMAND_SET_GANG_PED_MODELS: + CollectParameters(&m_nIp, 3); + CGangs::SetGangPedModels(ScriptParams[0], ScriptParams[1], ScriptParams[2]); + return 0; case COMMAND_SET_GANG_CAR_MODEL: CollectParameters(&m_nIp, 2); CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]); @@ -10087,7 +10087,14 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON: case COMMAND_MAKE_HELI_COME_CRASHING_DOWN: case COMMAND_ADD_EXPLOSION_NO_SOUND: + assert(0); case COMMAND_SET_OBJECT_AREA_VISIBLE: + { + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + pObject->m_area = ScriptParams[1]; + return 0; + } case COMMAND_WAS_VEHICLE_EVER_POLICE: case COMMAND_SET_CHAR_NEVER_TARGETTED: case COMMAND_LOAD_UNCOMPRESSED_ANIM: @@ -10156,7 +10163,11 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA: case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE: case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA: + assert(0); case COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS: + CollectParameters(&m_nIp, 2); + CGangs::SetWillAttackPlayerWithCops((ePedType)((int)PEDTYPE_GANG1 + ScriptParams[0]), !!ScriptParams[1]); + return 0; case COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR: case COMMAND_SET_VEHICLE_TO_FADE_IN: case COMMAND_REGISTER_ODDJOB_MISSION_PASSED: diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index e854da59..09d5cc72 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1524,26 +1524,26 @@ CStreaming::StreamZoneModels(const CVector &pos) bit = 1<m_nVehicleMI < 0) + if(CGangs::GetGangVehicleModel(i) < 0) continue; if((gangCarsToLoad & bit) && (ms_loadedGangCars & bit) == 0){ - RequestModel(CGangs::GetGangInfo(i)->m_nVehicleMI, STREAMFLAGS_DEPENDENCY); + RequestModel(CGangs::GetGangVehicleModel(i), STREAMFLAGS_DEPENDENCY); }else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){ - SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); - SetModelTxdIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); + SetModelIsDeletable(CGangs::GetGangVehicleModel(i)); + SetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i)); } } ms_loadedGangCars = gangCarsToLoad; @@ -1563,10 +1563,10 @@ CStreaming::RemoveCurrentZonesModels(void) } for(i = 0; i < NUM_GANGS; i++){ - SetModelIsDeletable(MI_GANG01 + i*2); - SetModelIsDeletable(MI_GANG01 + i*2 + 1); - if(CGangs::GetGangInfo(i)->m_nVehicleMI != -1) - SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); + SetModelIsDeletable(CGangs::GetGangPedModel1(i)); + SetModelIsDeletable(CGangs::GetGangPedModel2(i)); + if(CGangs::GetGangVehicleModel(i) != -1) + SetModelIsDeletable(CGangs::GetGangVehicleModel(i)); } ms_currentPedGrp = -1; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index a21da7d3..25eb4cf0 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -180,8 +180,25 @@ enum MI_MALE01, MI_TAXI_D = 28, // HMOCA - MI_GANG01 = 83, // CBa - MI_VICE1 = 97, + + MI_WFOGO = 63, + MI_WMOGO = 64, + + MI_CBA = 83, + MI_CBB, + MI_HNA, + MI_HNB, + MI_SGA, + MI_SGB, + MI_CLA, + MI_CLB, + MI_GDA, + MI_GDB, + MI_BKA, + MI_BKB, + MI_PGA, + MI_PGB, + MI_VICE1, MI_VICE2, MI_VICE3, MI_VICE4, diff --git a/src/peds/Gangs.cpp b/src/peds/Gangs.cpp index 2a075e52..301eb3be 100644 --- a/src/peds/Gangs.cpp +++ b/src/peds/Gangs.cpp @@ -2,12 +2,17 @@ #include "ModelIndices.h" #include "Gangs.h" +#include "General.h" +#include "Streaming.h" #include "Weapon.h" CGangInfo CGangs::Gang[NUM_GANGS]; +bool CGangs::GangAttackWithCops[NUM_GANGS]; CGangInfo::CGangInfo() : - m_nVehicleMI(MI_BUS), + m_nVehicleMI(-1), + m_nPedModel1MI(-1), + m_nPedModel2MI(-1), m_nPedModelOverride(-1), m_Weapon1(WEAPONTYPE_UNARMED), m_Weapon2(WEAPONTYPE_UNARMED) @@ -15,21 +20,63 @@ CGangInfo::CGangInfo() : void CGangs::Initialise(void) { - Gang[GANG_MAFIA].m_nVehicleMI = -1; - Gang[GANG_TRIAD].m_nVehicleMI = -1; - Gang[GANG_DIABLOS].m_nVehicleMI = -1; - Gang[GANG_YAKUZA].m_nVehicleMI = -1; - Gang[GANG_YARDIE].m_nVehicleMI = -1; - Gang[GANG_COLUMB].m_nVehicleMI = -1; - Gang[GANG_HOODS].m_nVehicleMI = -1; - Gang[GANG_7].m_nVehicleMI = -1; - Gang[GANG_8].m_nVehicleMI = -1; + SetGangPedModels(GANG_CUBAN, MI_CBA, MI_CBB); + SetGangPedModels(GANG_HAITIAN, MI_HNA, MI_HNB); + SetGangPedModels(GANG_STREET, MI_SGA, MI_SGB); + SetGangPedModels(GANG_DIAZ, MI_CLA, MI_CLB); + SetGangPedModels(GANG_SECURITY, MI_GDA, MI_GDB); + SetGangPedModels(GANG_BIKER, MI_BKA, MI_BKB); + SetGangPedModels(GANG_PLAYER, MI_PGA, MI_PGB); + SetGangPedModels(GANG_GOLFER, MI_WFOGO, MI_WMOGO); + SetGangVehicleModel(GANG_CUBAN, MI_CUBAN); + SetGangVehicleModel(GANG_HAITIAN, MI_VOODOO); + SetGangVehicleModel(GANG_STREET, MI_GANGBUR); + SetGangVehicleModel(GANG_DIAZ, -1); + SetGangVehicleModel(GANG_SECURITY, -1); + SetGangVehicleModel(GANG_BIKER, MI_ANGEL); + SetGangVehicleModel(GANG_PLAYER, -1); + SetGangVehicleModel(GANG_GOLFER, MI_CADDY); + //SetGangWeapons(GANG_GOLFER, WEAPONTYPE_GOLFCLUB, WEAPONTYPE_GOLFCLUB); // TODO(MIAMI) #ifdef FIX_BUGS for (int i = 0; i < NUM_GANGS; i++) - Gang[i].m_nPedModelOverride = -1; + SetGangPedModelOverride(i, -1); #endif } +bool CGangs::HaveGangModelsLoaded(int16 gang) +{ + CGangInfo* pGangInfo = GetGangInfo(gang); + return CStreaming::HasModelLoaded(pGangInfo->m_nPedModel1MI) && CStreaming::HasModelLoaded(pGangInfo->m_nPedModel2MI); +} + +void CGangs::SetGangPedModels(int16 gang, int32 mi1, int32 mi2) +{ + GetGangInfo(gang)->m_nPedModel1MI = mi1; + GetGangInfo(gang)->m_nPedModel2MI = mi2; +} + +void CGangs::SetWillAttackPlayerWithCops(ePedType type, bool will) +{ + if (type >= PEDTYPE_GANG1 && type <= PEDTYPE_GANG9) + GangAttackWithCops[type - PEDTYPE_GANG1] = will; +} + +bool CGangs::GetWillAttackPlayerWithCops(ePedType type) +{ + if (type >= PEDTYPE_GANG1 && type <= PEDTYPE_GANG9) + return GangAttackWithCops[type - PEDTYPE_GANG1]; + return false; +} + +int32 CGangs::ChooseGangPedModel(int16 gang) +{ + CGangInfo* pGangInfo = GetGangInfo(gang); + if (pGangInfo->m_nPedModelOverride != -1 || CGeneral::GetRandomTrueFalse()) + return pGangInfo->m_nPedModel1MI; + else + return pGangInfo->m_nPedModel2MI; +} + void CGangs::SetGangVehicleModel(int16 gang, int32 model) { GetGangInfo(gang)->m_nVehicleMI = model; diff --git a/src/peds/Gangs.h b/src/peds/Gangs.h index c8ea2916..c6381343 100644 --- a/src/peds/Gangs.h +++ b/src/peds/Gangs.h @@ -1,8 +1,12 @@ #pragma once +#include "PedType.h" + struct CGangInfo { int32 m_nVehicleMI; + int32 m_nPedModel1MI; + int32 m_nPedModel2MI; int8 m_nPedModelOverride; int32 m_Weapon1; int32 m_Weapon2; @@ -13,15 +17,15 @@ struct CGangInfo VALIDATE_SIZE(CGangInfo, 0x10); enum { - GANG_MAFIA = 0, - GANG_TRIAD, - GANG_DIABLOS, - GANG_YAKUZA, - GANG_YARDIE, - GANG_COLUMB, - GANG_HOODS, - GANG_7, - GANG_8, + GANG_CUBAN = 0, + GANG_HAITIAN, + GANG_STREET, + GANG_DIAZ, + GANG_SECURITY, + GANG_BIKER, + GANG_PLAYER, + GANG_GOLFER, + GANG_9, NUM_GANGS }; @@ -36,9 +40,18 @@ public: static void SaveAllGangData(uint8 *, uint32 *); static void LoadAllGangData(uint8 *, uint32); + static void SetGangPedModels(int16, int32, int32); + static void SetWillAttackPlayerWithCops(ePedType type, bool will); + static bool GetWillAttackPlayerWithCops(ePedType type); + static int32 ChooseGangPedModel(int16); + + static bool HaveGangModelsLoaded(int16 gang); + static int32 GetGangPedModel1(int16 gang) { return Gang[gang].m_nPedModel1MI; } + static int32 GetGangPedModel2(int16 gang) { return Gang[gang].m_nPedModel2MI; } static int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; } static CGangInfo *GetGangInfo(int16 gang) { return &Gang[gang]; } private: static CGangInfo Gang[NUM_GANGS]; + static bool GangAttackWithCops[NUM_GANGS]; }; diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 567f9c0f..1c613acc 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -329,19 +329,7 @@ CPopulation::UpdatePedCount(ePedType pedType, bool decrease) int CPopulation::ChooseGangOccupation(int gangId) { - int8 modelOverride = CGangs::GetGangPedModelOverride(gangId); - - // All gangs have 2 models - int firstGangModel = 2 * gangId + MI_GANG01; - - // GetRandomNumberInRange never returns max. value - if (modelOverride == -1) - return CGeneral::GetRandomNumberInRange(firstGangModel, firstGangModel + 2); - - if (modelOverride != 0) - return firstGangModel + 1; - else - return firstGangModel; + return CGangs::ChooseGangPedModel(gangId); } //--MIAMI: done From 13a0bf1c436d6d2d66d4c53c845114fa1718ad0b Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 16 May 2020 20:29:13 +0300 Subject: [PATCH 022/148] Move sound processors to AudioLogic.cpp, plus small fixes --- src/audio/AudioLogic.cpp | 8838 ++++++++++++++++++++++++++++++ src/audio/AudioManager.cpp | 10056 +++-------------------------------- src/audio/AudioManager.h | 22 +- src/audio/DMAudio.cpp | 6 +- src/audio/DMAudio.h | 2 +- 5 files changed, 9476 insertions(+), 9448 deletions(-) create mode 100644 src/audio/AudioLogic.cpp diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp new file mode 100644 index 00000000..05483617 --- /dev/null +++ b/src/audio/AudioLogic.cpp @@ -0,0 +1,8838 @@ +#include "common.h" + +#include "AudioManager.h" +#include "audio_enums.h" + +#include "Automobile.h" +#include "Boat.h" +#include "Bridge.h" +#include "Camera.h" +#include "Cranes.h" +#include "DMAudio.h" +#include "Entity.h" +#include "Explosion.h" +#include "Fire.h" +#include "Garages.h" +#include "General.h" +#include "HandlingMgr.h" +#include "Heli.h" +#include "ModelIndices.h" +#include "MusicManager.h" +#include "Pad.h" +#include "Ped.h" +#include "Physical.h" +#include "Placeable.h" +#include "Plane.h" +#include "PlayerPed.h" +#include "Pools.h" +#include "Projectile.h" +#include "ProjectileInfo.h" +#include "Replay.h" +#include "Stats.h" +#include "SurfaceTable.h" +#include "Train.h" +#include "Transmission.h" +#include "Vehicle.h" +#include "WaterCannon.h" +#include "Weather.h" +#include "ZoneCull.h" +#include "sampman.h" + +const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); +const int policeChannel = channels + 1; +const int allChannels = channels + 2; +const int maxVolume = 127; + +uint32 gPornNextTime; +uint32 gSawMillNextTime; +uint32 gShopNextTime; +uint32 gAirportNextTime; +uint32 gCinemaNextTime; +uint32 gDocksNextTime; +uint32 gHomeNextTime; +uint32 gCellNextTime; +uint32 gNextCryTime; + +enum PLAY_STATUS : uint8 { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING = 1, PLAY_STATUS_FINISHED = 2 }; +enum LOADING_STATUS : uint8 { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED = 1 }; + +void +cAudioManager::PreInitialiseGameSpecificSetup() const +{ + BankStartOffset[SAMPLEBANK_MAIN] = SAMPLEBANK_START; + BankStartOffset[SAMPLEBANK_PED] = SAMPLEBANK_PED_START; +} + +void +cAudioManager::PostInitialiseGameSpecificSetup() +{ + m_nFireAudioEntity = CreateEntity(AUDIOTYPE_FIRE, &gFireManager); + if (m_nFireAudioEntity >= 0) + SetEntityStatus(m_nFireAudioEntity, 1); + + m_nCollisionEntity = CreateEntity(AUDIOTYPE_COLLISION, (void *)1); + if (m_nCollisionEntity >= 0) + SetEntityStatus(m_nCollisionEntity, 1); + + m_nFrontEndEntity = CreateEntity(AUDIOTYPE_FRONTEND, (void *)1); + if (m_nFrontEndEntity >= 0) + SetEntityStatus(m_nFrontEndEntity, 1); + + m_nProjectileEntity = CreateEntity(AUDIOTYPE_PROJECTILE, (void *)1); + if (m_nProjectileEntity >= 0) + SetEntityStatus(m_nProjectileEntity, 1); + + m_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATERCANNON, (void *)1); + if (m_nWaterCannonEntity >= 0) + SetEntityStatus(m_nWaterCannonEntity, 1); + + m_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_POLICERADIO, (void *)1); + if (m_nPoliceChannelEntity >= 0) + SetEntityStatus(m_nPoliceChannelEntity, 1); + + m_nBridgeEntity = CreateEntity(AUDIOTYPE_BRIDGE, (void *)1); + if (m_nBridgeEntity >= 0) + SetEntityStatus(m_nBridgeEntity, 1); + + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; + m_sMissionAudio.field_22 = 0; + m_sMissionAudio.m_bIsPlayed = false; + m_sMissionAudio.m_bPredefinedProperties = 1; + m_sMissionAudio.m_nMissionAudioCounter = 0; + ResetAudioLogicTimers(CTimer::GetTimeInMilliseconds()); +} +void +cAudioManager::PreTerminateGameSpecificShutdown() +{ + if (m_nBridgeEntity >= 0) { + DestroyEntity(m_nBridgeEntity); + m_nBridgeEntity = AEHANDLE_NONE; + } + if (m_nPoliceChannelEntity >= 0) { + DestroyEntity(m_nPoliceChannelEntity); + m_nPoliceChannelEntity = AEHANDLE_NONE; + } + if (m_nWaterCannonEntity >= 0) { + DestroyEntity(m_nWaterCannonEntity); + m_nWaterCannonEntity = AEHANDLE_NONE; + } + if (m_nFireAudioEntity >= 0) { + DestroyEntity(m_nFireAudioEntity); + m_nFireAudioEntity = AEHANDLE_NONE; + } + if (m_nCollisionEntity >= 0) { + DestroyEntity(m_nCollisionEntity); + m_nCollisionEntity = AEHANDLE_NONE; + } + if (m_nFrontEndEntity >= 0) { + DestroyEntity(m_nFrontEndEntity); + m_nFrontEndEntity = AEHANDLE_NONE; + } + if (m_nProjectileEntity >= 0) { + DestroyEntity(m_nProjectileEntity); + m_nProjectileEntity = AEHANDLE_NONE; + } +} + +void +cAudioManager::PostTerminateGameSpecificShutdown() +{ + ; +} + +void +cAudioManager::ResetAudioLogicTimers(uint32 timer) +{ + gPornNextTime = timer; + gNextCryTime = timer; + gSawMillNextTime = timer; + gCellNextTime = timer; + gShopNextTime = timer; + gHomeNextTime = timer; + gAirportNextTime = timer; + gDocksNextTime = timer; + gCinemaNextTime = timer; + for (int32 i = 0; i < m_nAudioEntitiesTotal; i++) { + if (m_asAudioEntities[m_anAudioEntityIndices[i]].m_nType == AUDIOTYPE_PHYSICAL) { + CPed *ped = (CPed *)m_asAudioEntities[m_anAudioEntityIndices[i]].m_pEntity; + if (ped->IsPed()) { + ped->m_lastSoundStart = timer; + ped->m_soundStart = timer + m_anRandomTable[0] % 3000; + } + } + } + ClearMissionAudio(); + SampleManager.StopChannel(policeChannel); +} + +void +cAudioManager::ProcessReverb() const +{ + if (SampleManager.UpdateReverb() && m_bDynamicAcousticModelingStatus) { + for (uint32 i = 0; i < +#ifdef FIX_BUGS + channels +#else + 28 +#endif + ; + i++) { + if (m_asActiveSamples[i].m_bReverbFlag) + SampleManager.SetChannelReverbFlag(i, 1); + } + } +} + +float +cAudioManager::GetDistanceSquared(const CVector &v) const +{ + const CVector &c = TheCamera.GetPosition(); + return sq(v.x - c.x) + sq(v.y - c.y) + sq((v.z - c.z) * 0.2f); +} + +void +cAudioManager::CalculateDistance(bool &distCalculated, float dist) +{ + if (!distCalculated) { + m_sQueueSample.m_fDistance = Sqrt(dist); + distCalculated = true; + } +} + +void +cAudioManager::ProcessSpecial() +{ + if (m_nUserPause) { + if (!m_nPreviousUserPause) { + MusicManager.ChangeMusicMode(MUSICMODE_FRONTEND); + SampleManager.SetEffectsFadeVolume(maxVolume); + SampleManager.SetMusicFadeVolume(maxVolume); + } + } else { + if (m_nPreviousUserPause) { + MusicManager.StopFrontEndTrack(); + MusicManager.ChangeMusicMode(MUSICMODE_GAME); + } + CPlayerPed *playerPed = FindPlayerPed(); + if (playerPed) { + const PedState &state = playerPed->m_nPedState; + if (state != PED_ENTER_CAR && state != PED_STEAL_CAR && !playerPed->bInVehicle) + SampleManager.StopChannel(m_nActiveSamples); + } + } +} + +void +cAudioManager::ProcessEntity(int32 id) +{ + if (m_asAudioEntities[id].m_nStatus) { + m_sQueueSample.m_nEntityIndex = id; + switch (m_asAudioEntities[id].m_nType) { + case AUDIOTYPE_PHYSICAL: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessPhysical(id); + } + break; + case AUDIOTYPE_EXPLOSION: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessExplosions(id); + } + break; + case AUDIOTYPE_FIRE: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessFires(id); + } + break; + case AUDIOTYPE_WEATHER: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessWeather(id); + } + break; + case AUDIOTYPE_CRANE: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessCrane(); + } + break; + case AUDIOTYPE_SCRIPTOBJECT: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessScriptObject(id); + } + break; + case AUDIOTYPE_BRIDGE: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessBridge(); + } + break; + case AUDIOTYPE_FRONTEND: + m_sQueueSample.m_bReverbFlag = false; + ProcessFrontEnd(); + break; + case AUDIOTYPE_PROJECTILE: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessProjectiles(); + } + break; + case AUDIOTYPE_GARAGE: + if (!m_nUserPause) + ProcessGarages(); + break; + case AUDIOTYPE_FIREHYDRANT: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessFireHydrant(); + } + break; + case AUDIOTYPE_WATERCANNON: + if (!m_nUserPause) { + m_sQueueSample.m_bReverbFlag = true; + ProcessWaterCannon(id); + } + break; + default: + return; + } + } +} + +void +cAudioManager::ProcessPhysical(int32 id) +{ + CPhysical *entity = (CPhysical *)m_asAudioEntities[id].m_pEntity; + if (entity) { + switch (entity->GetType()) { + case ENTITY_TYPE_VEHICLE: + ProcessVehicle((CVehicle *)m_asAudioEntities[id].m_pEntity); + break; + case ENTITY_TYPE_PED: + ProcessPed((CPhysical *)m_asAudioEntities[id].m_pEntity); + break; + default: + return; + } + } +} + +#pragma region VEHICLE AUDIO +enum eVehicleModel { + LANDSTAL, + IDAHO, + STINGER, + LINERUN, + PEREN, + SENTINEL, + PATRIOT, + FIRETRUK, + TRASH, + STRETCH, + MANANA, + INFERNUS, + BLISTA, + PONY, + MULE, + CHEETAH, + AMBULAN, + FBICAR, + MOONBEAM, + ESPERANT, + TAXI, + KURUMA, + BOBCAT, + MRWHOOP, + BFINJECT, + CORPSE, + POLICE, + ENFORCER, + SECURICA, + BANSHEE, + PREDATOR, + BUS, + RHINO, + BARRACKS, + TRAIN, + CHOPPER, + DODO, + COACH, + CABBIE, + STALLION, + RUMPO, + RCBANDIT, + BELLYUP, + MRWONGS, + MAFIA, + YARDIE, + YAKUZA, + DIABLOS, + COLUMB, + HOODS, + AIRTRAIN, + DEADDODO, + SPEEDER, + REEFER, + PANLANT, + FLATBED, + YANKEE, + ESCAPE, + BORGNINE, + TOYZ, + GHOST, + CAR151, + CAR152, + CAR153, + CAR154, + CAR155, + CAR156, + CAR157, + CAR158, + CAR159, + MAX_CARS +}; + + +struct tVehicleSampleData { + eSfxSample m_nAccelerationSampleIndex; + uint8 m_bEngineSoundType; + eSfxSample m_nHornSample; + int32 m_nHornFrequency; + uint8 m_nSirenOrAlarmSample; + int32 m_nSirenOrAlarmFrequency; + uint8 m_bDoorType; +}; + +const tVehicleSampleData aVehicleSettings[MAX_CARS] = {{SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 10928, 1}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_ALARM_1, 8941, 0}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_ALARM_1, 11922, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 7948, 2}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_ALARM_1, 8941, 2}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_ALARM_1, 12220, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_ALARM_1, 12200, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 13600, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_ALARM_1, 8000, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_ALARM_1, 8543, 1}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 10000, 0}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_ALARM_1, 10123, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_ALARM_1, 10554, 3}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 8000, 2}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 3}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_ALARM_1, 7500, 3}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_ALARM_1, 8935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 8935, 0}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_ALARM_1, 17000, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_ALARM_1, 9935, 1}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9000, 0}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}}; + + +bool bPlayerJustEnteredCar; + +const bool hornPatternsArray[8][44] = { + {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, + false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false}, + {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false}, + {false, false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, false, + false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false}, + {false, false, true, true, true, true, true, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, + true, true, true, true, true, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, false}, + {false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, true, true, true, false, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, + {false, false, true, true, true, true, false, false, false, false, true, true, true, false, false, true, true, true, false, false, true, true, + true, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, false, false}, + {false, false, true, true, true, true, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, true, + false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false}, +}; + + +void +cAudioManager::ProcessVehicle(CVehicle *veh) +{ + tHandlingData *handling = veh->pHandling; + float velChange; + cVehicleParams params; + m_sQueueSample.m_vecPos = veh->GetPosition(); + + params.m_bDistanceCalculated = false; + params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); + params.m_pVehicle = veh; + params.m_pTransmission = nil; + params.m_nIndex = 0; + params.m_fVelocityChange = 0.0f; + + if (handling) + params.m_pTransmission = &handling->Transmission; + + params.m_nIndex = veh->GetModelIndex() - MI_FIRST_VEHICLE; + if (params.m_pVehicle->GetStatus() == STATUS_SIMPLE) + velChange = params.m_pVehicle->AutoPilot.m_fMaxTrafficSpeed * 0.02f; + else + velChange = DotProduct(params.m_pVehicle->m_vecMoveSpeed, params.m_pVehicle->GetForward()); + params.m_fVelocityChange = velChange; + switch (params.m_pVehicle->m_vehType) { + case VEHICLE_TYPE_CAR: + UpdateGasPedalAudio((CAutomobile *)veh); + if (params.m_nIndex == RCBANDIT) { + ProcessModelCarEngine(¶ms); + ProcessVehicleOneShots(¶ms); + ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; + ProcessRainOnVehicle(¶ms); + break; + } + if (params.m_nIndex == DODO) { + if (!ProcessVehicleRoadNoise(¶ms)) { + ProcessVehicleOneShots(¶ms); + ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; + ProcessRainOnVehicle(¶ms); + break; + } + if (CWeather::WetRoads > 0.f) + ProcessWetRoadNoise(¶ms); + ProcessVehicleSkidding(¶ms); + } else { + if (!ProcessVehicleRoadNoise(¶ms)) { + ProcessVehicleOneShots(¶ms); + ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; + ProcessRainOnVehicle(¶ms); + break; + } + ProcessReverseGear(¶ms); + if (CWeather::WetRoads > 0.f) + ProcessWetRoadNoise(¶ms); + ProcessVehicleSkidding(¶ms); + ProcessVehicleHorn(¶ms); + ProcessVehicleSirenOrAlarm(¶ms); + if (UsesReverseWarning(params.m_nIndex)) + ProcessVehicleReverseWarning(¶ms); + if (HasAirBrakes(params.m_nIndex)) + ProcessAirBrakes(¶ms); + } + ProcessCarBombTick(¶ms); + ProcessVehicleEngine(¶ms); + ProcessEngineDamage(¶ms); + ProcessVehicleDoors(¶ms); + ProcessVehicleOneShots(¶ms); + ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; + ProcessRainOnVehicle(¶ms); + break; + case VEHICLE_TYPE_BOAT: + ProcessBoatEngine(¶ms); + ProcessBoatMovingOverWater(¶ms); + ProcessVehicleOneShots(¶ms); + ProcessRainOnVehicle(¶ms); + break; + case VEHICLE_TYPE_TRAIN: + ProcessTrainNoise(¶ms); + ProcessVehicleOneShots(¶ms); + ProcessRainOnVehicle(¶ms); + break; + case VEHICLE_TYPE_HELI: + ProcessHelicopter(¶ms); + ProcessVehicleOneShots(¶ms); + ProcessRainOnVehicle(¶ms); + break; + case VEHICLE_TYPE_PLANE: + ProcessPlane(¶ms); + ProcessVehicleOneShots(¶ms); + ProcessRainOnVehicle(¶ms); + break; + default: + ProcessRainOnVehicle(¶ms); + break; + } +} + +void +cAudioManager::ProcessRainOnVehicle(cVehicleParams *params) +{ + const int rainOnVehicleIntensity = 22; + if (params->m_fDistance < SQR(rainOnVehicleIntensity) && CWeather::Rain > 0.01f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) { + CVehicle *veh = params->m_pVehicle; + ++veh->m_bRainAudioCounter; + if (veh->m_bRainAudioCounter >= 2) { + veh->m_bRainAudioCounter = 0; + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + float emittingVol = 30.f * CWeather::Rain; + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, rainOnVehicleIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = veh->m_bRainSamplesCounter++; + if (veh->m_bRainSamplesCounter > 4) + veh->m_bRainSamplesCounter = 68; + m_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_CAR_RAIN_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 9; + m_sQueueSample.m_nFrequency = m_anRandomTable[1] % 4000 + 28000; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nEmittingVolume = (uint8)emittingVol; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = rainOnVehicleIntensity; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bReverbFlag = false; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } +} + +bool +cAudioManager::ProcessReverseGear(cVehicleParams *params) +{ + const int reverseGearIntensity = 30; + + CVehicle *veh; + CAutomobile *automobile; + int32 emittingVol; + float modificator; + + if (params->m_fDistance >= SQR(reverseGearIntensity)) + return false; + veh = params->m_pVehicle; + if (veh->bEngineOn && (veh->m_fGasPedal < 0.0f || !veh->m_nCurrentGear)) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + automobile = (CAutomobile *)params->m_pVehicle; + if (automobile->m_nWheelsOnGround) { + modificator = params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity; + } else { + if (automobile->m_nDriveWheelsOnGround) + automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.4f; + modificator = automobile->m_fGasPedalAudio; + } + modificator = Abs(modificator); + emittingVol = (24.f * modificator); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, reverseGearIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + if (params->m_pVehicle->m_fGasPedal >= 0.0f) { + m_sQueueSample.m_nCounter = 62; + m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR_2; + } else { + m_sQueueSample.m_nCounter = 61; + m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR; + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nFrequency = (6000.f * modificator) + 7000; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 3.0f; + m_sQueueSample.m_fSoundIntensity = reverseGearIntensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 5; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + return true; +} + +void +cAudioManager::ProcessModelCarEngine(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 30.0f; + CAutomobile *automobile; + float allowedVelocity; + int32 emittingVol; + float velocityChange; + + if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + automobile = (CAutomobile *)params->m_pVehicle; + if (automobile->bEngineOn) { + if (automobile->m_nWheelsOnGround) { + velocityChange = Abs(params->m_fVelocityChange); + } else { + if (automobile->m_nDriveWheelsOnGround) + automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.4f; + velocityChange = automobile->m_fGasPedalAudio * params->m_pTransmission->fMaxVelocity; + } + if (velocityChange > 0.001f) { + allowedVelocity = 0.5f * params->m_pTransmission->fMaxVelocity; + if (velocityChange < allowedVelocity) + emittingVol = (90.f * velocityChange / allowedVelocity); + else + emittingVol = 90; + if (emittingVol) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 30.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 2; + m_sQueueSample.m_nSampleIndex = SFX_REMOTE_CONTROLLED_CAR; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = (11025.f * velocityChange / params->m_pTransmission->fMaxVelocity + 11025.f); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 3.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } + } +} + + + +bool +cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 95.0f; + + int32 emittingVol; + uint32 freq; + float modificator; + int sampleFreq; + float velocity; + + if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + return false; + if (params->m_pTransmission) { + if (params->m_pVehicle->m_vecMoveSpeed.z) { + velocity = Abs(params->m_fVelocityChange); + if (velocity > 0.0f) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + emittingVol = 30.f * Min(1.f, velocity / (0.5f * params->m_pTransmission->fMaxVelocity)); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_PUDDLE) { + m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; + freq = 6050 * emittingVol / 30 + 16000; + } else { + m_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE; + modificator = m_sQueueSample.m_fDistance / 190.f; + sampleFreq = SampleManager.GetSampleBaseFrequency(SFX_ROAD_NOISE); + freq = (sampleFreq * modificator) + ((3 * sampleFreq) / 4); + } + m_sQueueSample.m_nFrequency = freq; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 6.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 4; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } + return true; +} + +bool +cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 30.0f; + + float relativeVelocity; + int32 emittingVol; + float modificator; + int freq; + float velChange; + + if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + return false; + if (params->m_pTransmission) { + if (params->m_pVehicle->m_vecMoveSpeed.z) { + velChange = Abs(params->m_fVelocityChange); + if (velChange > 0.f) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + relativeVelocity = Min(1.0f, velChange / (0.5f * params->m_pTransmission->fMaxVelocity)); + emittingVol = 23.0f * relativeVelocity * CWeather::WetRoads; + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + modificator = m_sQueueSample.m_fDistance / 6.f; + freq = SampleManager.GetSampleBaseFrequency(SFX_ROAD_NOISE); + m_sQueueSample.m_nFrequency = freq + freq * modificator; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 6.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 4; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } + return true; +} + +void +cAudioManager::ProcessVehicleEngine(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 50.0f; + + CVehicle *playerVeh; + CVehicle *veh; + CAutomobile *automobile; + float relativeGearChange; + float relativeChange; + uint8 volume; + int32 freq = 0; // uinitialized variable + uint8 emittingVol; + cTransmission *transmission; + uint8 currentGear; + float modificator; + float traction = 0.f; + + if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + playerVeh = FindPlayerVehicle(); + veh = params->m_pVehicle; + if (playerVeh == veh && veh->GetStatus() == STATUS_WRECKED) { + SampleManager.StopChannel(m_nActiveSamples); + return; + } + if (veh->bEngineOn) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + automobile = (CAutomobile *)params->m_pVehicle; + if (params->m_nIndex == DODO) { + ProcessCesna(params); + return; + } + if (FindPlayerVehicle() == veh) { + ProcessPlayersVehicleEngine(params, automobile); + return; + } + transmission = params->m_pTransmission; + if (transmission) { + currentGear = params->m_pVehicle->m_nCurrentGear; + if (automobile->m_nWheelsOnGround) { + if (automobile->bIsHandbrakeOn) { + if (params->m_fVelocityChange == 0.0f) + traction = 0.9f; + } else if (params->m_pVehicle->GetStatus() == STATUS_SIMPLE) { + traction = 0.0f; + } else { + switch (transmission->nDriveType) { + case '4': + for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { + if (automobile->m_aWheelState[i] == WHEEL_STATE_SPINNING) + traction += 0.05f; + } + break; + case 'F': + if (automobile->m_aWheelState[0] == WHEEL_STATE_SPINNING) + traction += 0.1f; + if (automobile->m_aWheelState[2] == WHEEL_STATE_SPINNING) + traction += 0.1f; + break; + case 'R': + if (automobile->m_aWheelState[1] == WHEEL_STATE_SPINNING) + traction += 0.1f; + if (automobile->m_aWheelState[3] == WHEEL_STATE_SPINNING) + traction += 0.1f; + break; + } + } + if (transmission->fMaxVelocity <= 0.f) { + relativeChange = 0.f; + } else if (currentGear) { + relativeGearChange = + Min(1.0f, (params->m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f); + if (traction == 0.0f && automobile->GetStatus() != STATUS_SIMPLE && + params->m_fVelocityChange >= transmission->Gears[1].fShiftUpVelocity) { + traction = 0.7f; + } + relativeChange = traction * automobile->m_fGasPedalAudio * 0.95f + (1.0f - traction) * relativeGearChange; + } else + relativeChange = + Min(1.0f, 1.0f - Abs((params->m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity)); + } else { + if (automobile->m_nDriveWheelsOnGround) + automobile->m_fGasPedalAudio *= 0.4f; + relativeChange = automobile->m_fGasPedalAudio; + } + modificator = relativeChange; + if (currentGear || !automobile->m_nWheelsOnGround) + freq = 1200 * currentGear + 18000.f * modificator + 14000; + else + freq = 13000.f * modificator + 14000; + if (modificator >= 0.75f) { + emittingVol = 120; + volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + } else { + emittingVol = modificator * 4.0f / 3.0f * 40.f + 80.f; + volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + } + } else { + modificator = 0.f; + emittingVol = 80; + volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + } + m_sQueueSample.m_nVolume = volume; + if (m_sQueueSample.m_nVolume) { + if (automobile->GetStatus() == STATUS_SIMPLE) { + if (modificator < 0.02f) { + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_bEngineSoundType - 1 + SFX_CAR_IDLE_1; + freq = modificator * 10000 + 22050; + m_sQueueSample.m_nCounter = 52; + } else { + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex; + m_sQueueSample.m_nCounter = 2; + } + } else { + if (automobile->m_fGasPedal < 0.05f) { + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_bEngineSoundType - 1 + SFX_CAR_IDLE_1; + freq = modificator * 10000 + 22050; + m_sQueueSample.m_nCounter = 52; + } else { + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex; + m_sQueueSample.m_nCounter = 2; + } + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nFrequency = freq + 100 * m_sQueueSample.m_nEntityIndex % 1000; + if (m_sQueueSample.m_nSampleIndex == SFX_CAR_IDLE_6 || m_sQueueSample.m_nSampleIndex == SFX_CAR_REV_6) + m_sQueueSample.m_nFrequency /= 2; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 6.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 8; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } +} + +void +cAudioManager::UpdateGasPedalAudio(CAutomobile *automobile) +{ + float newGasPedalAudio; + + float gasPedal = Abs(automobile->m_fGasPedal); + float gasPedalAudio = automobile->m_fGasPedalAudio; + + if (gasPedalAudio < gasPedal) { + newGasPedalAudio = gasPedalAudio + 0.09f; + if (gasPedal <= newGasPedalAudio) + newGasPedalAudio = gasPedal; + } else { + newGasPedalAudio = gasPedalAudio - 0.07f; + if (gasPedal >= newGasPedalAudio) + newGasPedalAudio = gasPedal; + } + automobile->m_fGasPedalAudio = newGasPedalAudio; +} + +void +cAudioManager::PlayerJustGotInCar() const +{ + if (m_bIsInitialised) { + bPlayerJustEnteredCar = true; + } +} + +void +cAudioManager::PlayerJustLeftCar(void) const +{ + // UNUSED: This is a perfectly empty function. +} + +void +cAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 unk1, uint8 counter, bool notLooping) +{ + m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, 50.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = counter; + m_sQueueSample.m_nSampleIndex = sample; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nFrequency = freq; + if (notLooping) { + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nReleasingVolumeDivider = 8; + } else { + m_sQueueSample.m_nLoopCount = 1; + } + m_sQueueSample.m_nEmittingVolume = emittingVolume; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 6.0f; + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } +} + +void +cAudioManager::ProcessCesna(cVehicleParams *params) +{ + static uint8 nAccel = 0; + + //((CAutomobile *)params->m_pVehicle)->Damage.GetEngineStatus(); + + if (FindPlayerVehicle() == params->m_pVehicle) { + if (params->m_nIndex == DODO) { + if (Pads[0].GetAccelerate() <= 0) { + if (nAccel) + --nAccel; + } else if (nAccel < 60) { + ++nAccel; + } + AddPlayerCarSample(85 * (60 - nAccel) / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_IDLE, 0, 52, 1); + AddPlayerCarSample(85 * nAccel / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_REV, 0, 2, 1); + } + } else if (params->m_nIndex == DODO) { + AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, 0, 52, 1); + } else if (params->m_fDistance < 40000.f) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 52; + m_sQueueSample.m_nSampleIndex = SFX_CESNA_IDLE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nFrequency = 12500; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nReleasingVolumeDivider = 8; + m_sQueueSample.m_nEmittingVolume = 80; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 8.0f; + m_sQueueSample.m_fSoundIntensity = 200.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + if (params->m_fDistance < 8100.f) { + m_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 2; + m_sQueueSample.m_nSampleIndex = SFX_CESNA_REV; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nFrequency = 25000; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nReleasingVolumeDivider = 4; + m_sQueueSample.m_nEmittingVolume = 80; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 8.0f; + m_sQueueSample.m_fSoundIntensity = 90.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } +} + +void +cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile) +{ + static int32 GearFreqAdj[] = {6000, 6000, 3400, 1200, 0, -1000}; + + cTransmission *transmission; + float velocityChange; + float relativeVelocityChange; + float accelerationMultipler; + uint8 wheelInUseCounter; + float time; + int baseFreq; + uint8 vol; + int gearNr; + int32 freq; + + int freqModifier; + int soundOffset; + uint8 engineSoundType; + int32 accelerateState; + bool channelUsed; + char lostTraction; + bool processedAccelSampleStopped; + uint8 currentGear; + float gasPedalAudio; + CVector pos; + + static int16 LastAccel = 0; + static int16 LastBrake = 0; + static uint8 CurrentPretendGear = 1; + static bool bLostTractionLastFrame = false; + static bool bHandbrakeOnLastFrame = 0; + static int32 nCruising = 0; + static bool bAccelSampleStopped = true; + + lostTraction = 0; + processedAccelSampleStopped = 0; + if (bPlayerJustEnteredCar) { + bAccelSampleStopped = true; + bPlayerJustEnteredCar = false; + nCruising = 0; + LastAccel = 0; + bLostTractionLastFrame = false; + LastBrake = 0; + bHandbrakeOnLastFrame = 0; + CurrentPretendGear = 1; + } + if (CReplay::IsPlayingBack()) { + accelerateState = 255.f * Max(0.0f, Min(1.0f, automobile->m_fGasPedal)); + } else { + accelerateState = Pads->GetAccelerate(); + } + channelUsed = SampleManager.GetChannelUsedFlag(m_nActiveSamples); + transmission = params->m_pTransmission; + velocityChange = params->m_fVelocityChange; + relativeVelocityChange = 2.0f * velocityChange / transmission->fMaxVelocity; + + accelerationMultipler = Min(Min(1.f, relativeVelocityChange), 0.f); + gasPedalAudio = accelerationMultipler; + currentGear = params->m_pVehicle->m_nCurrentGear; + + if (transmission->nDriveType == '4') { + wheelInUseCounter = 0; + for (uint8 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { + if (automobile->m_aWheelState[i]) + ++wheelInUseCounter; + } + if (wheelInUseCounter > 2) + lostTraction = 1; + } else if (transmission->nDriveType == 'F') { + if ((automobile->m_aWheelState[0] || automobile->m_aWheelState[2]) && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { + lostTraction = 1; + } + } else if (transmission->nDriveType == 'R' && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { + lostTraction = 1; + } + if (0.0f != velocityChange) { + time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; + if (time <= 0.0f) { + freqModifier = Max(-0.2f, time) * -15000.f; + } else { + freqModifier = -(Min(0.2f, time) * 15000.f); + } + if (params->m_fVelocityChange < -0.001f) + freqModifier = -freqModifier; + } else { + freqModifier = 0; + } + engineSoundType = aVehicleSettings[params->m_nIndex].m_bEngineSoundType; + soundOffset = 3 * (engineSoundType - 1); + if (accelerateState <= 0) { + if (params->m_fVelocityChange < -0.001f) { + if (channelUsed) { + SampleManager.StopChannel(m_nActiveSamples); + bAccelSampleStopped = true; + } + if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { + gasPedalAudio = automobile->m_fGasPedalAudio; + } else { + gasPedalAudio = Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity); + } + gasPedalAudio = Max(0.0f, gasPedalAudio); + automobile->m_fGasPedalAudio = gasPedalAudio; + } else if (LastAccel > 0) { + if (channelUsed) { + SampleManager.StopChannel(m_nActiveSamples); + bAccelSampleStopped = true; + } + nCruising = 0; + if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + params->m_fVelocityChange >= 0.01f && automobile->m_fGasPedalAudio > 0.2f) { + automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.6f; + gasPedalAudio = automobile->m_fGasPedalAudio; + } + if (gasPedalAudio > 0.05f) { + freq = (5000.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 19000; + if (engineSoundType == 6) + freq /= 2; + AddPlayerCarSample((25.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 40, freq, (soundOffset + SFX_CAR_FINGER_OFF_ACCEL_1), engineSoundType, 63, 0); + } + } + freq = (10000.f * gasPedalAudio) + 22050; + if (engineSoundType == 6) + freq /= 2; + AddPlayerCarSample(110 - (40.f * gasPedalAudio), freq, (engineSoundType + SFX_CAR_REV_10), 0, 52, 1); + + CurrentPretendGear = Max(1, currentGear); + LastAccel = accelerateState; + + bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bLostTractionLastFrame = lostTraction; + return; + } + if (!nCruising) { + if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + currentGear < 2 && velocityChange - automobile->m_fVelocityChangeForAudio < 0.01f) { // here could be used abs + if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { + if (!automobile->m_nWheelsOnGround && automobile->m_nDriveWheelsOnGround || + (automobile->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame) && automobile->m_nWheelsOnGround) { + automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.6f; + } + freqModifier = 0; + baseFreq = (15000.f * automobile->m_fGasPedalAudio) + 14000; + vol = (25.0f * automobile->m_fGasPedalAudio) + 60; + } else { + baseFreq = (8000.f * accelerationMultipler) + 16000; + vol = (25.0f * accelerationMultipler) + 60; + automobile->m_fGasPedalAudio = accelerationMultipler; + } + freq = freqModifier + baseFreq; + if (engineSoundType == 6) + freq /= 2; + if (channelUsed) { + SampleManager.StopChannel(m_nActiveSamples); + bAccelSampleStopped = true; + } + AddPlayerCarSample(vol, freq, (engineSoundType + SFX_PHONE_RING), 0, 2, 1); + LastAccel = accelerateState; + + bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bLostTractionLastFrame = lostTraction; + return; + } + TranslateEntity(&m_sQueueSample.m_vecPos, &pos); + if (bAccelSampleStopped) { + if (CurrentPretendGear != 1 || currentGear != 2) { + gearNr = currentGear - 1; + if (gearNr < 1) + gearNr = 1; + CurrentPretendGear = gearNr; + } + processedAccelSampleStopped = 1; + bAccelSampleStopped = false; + } + if (channelUsed) { + SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); + SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); + SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); + if (engineSoundType == 6) + freq = (GearFreqAdj[CurrentPretendGear] + freqModifier + 22050) / 2; + else + freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; + SampleManager.SetChannelFrequency(m_nActiveSamples, freq); + if (!channelUsed) { + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); + SampleManager.StartChannel(m_nActiveSamples); + } + LastAccel = accelerateState; + + bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bLostTractionLastFrame = lostTraction; + return; + } + if (processedAccelSampleStopped) { + if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) + return; + SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); + SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); + SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); + SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); + SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); + freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; + if (engineSoundType == 6) + freq /= 2; + SampleManager.SetChannelFrequency(m_nActiveSamples, freq); + if (!channelUsed) { + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); + SampleManager.StartChannel(m_nActiveSamples); + } + LastAccel = accelerateState; + + bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bLostTractionLastFrame = lostTraction; + return; + } + if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1) { + ++CurrentPretendGear; + if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) + return; + SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); + SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); + SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); + SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); + SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); + freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; + if (engineSoundType == 6) + freq /= 2; + SampleManager.SetChannelFrequency(m_nActiveSamples, freq); + if (!channelUsed) { + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); + SampleManager.StartChannel(m_nActiveSamples); + } + LastAccel = accelerateState; + + bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bLostTractionLastFrame = lostTraction; + return; + } + nCruising = 1; + } + bAccelSampleStopped = true; + if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + currentGear < params->m_pTransmission->nNumberOfGears - 1) { + nCruising = 0; + } else { + if (accelerateState >= 220 && 0.001f + params->m_fVelocityChange < automobile->m_fVelocityChangeForAudio) { + if (nCruising < 800) + ++nCruising; + } else if (nCruising > 3) { + --nCruising; + } + freq = 27 * nCruising + freqModifier + 22050; + if (engineSoundType == 6) + freq /= 2; + AddPlayerCarSample(85, freq, (soundOffset + SFX_CAR_AFTER_ACCEL_1), engineSoundType, 64, 1); + } + LastAccel = accelerateState; + + bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bLostTractionLastFrame = lostTraction; +} + +void +cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 40.0f; + + CAutomobile *automobile; + cTransmission *transmission; + int32 emittingVol; + float newSkidVal = 0.0f; + float skidVal = 0.0f; + + if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + return; + automobile = (CAutomobile *)params->m_pVehicle; + if (!automobile->m_nWheelsOnGround) + return; + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { + if (automobile->m_aWheelState[i] == WHEEL_STATE_NORMAL || automobile->Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING) + continue; + transmission = params->m_pTransmission; + switch (transmission->nDriveType) { + case '4': + newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + break; + case 'F': + if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) + newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + else + newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + break; + case 'R': + if (i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT) + newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + else + newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); + break; + default: + break; + } + skidVal = Max(skidVal, newSkidVal); + } + + if (skidVal > 0.0f) { + emittingVol = 50.f * skidVal; + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 3; + switch (params->m_pVehicle->m_nSurfaceTouched) { + case SURFACE_GRASS: + case SURFACE_HEDGE: + m_sQueueSample.m_nSampleIndex = SFX_RAIN; + emittingVol /= 4; + m_sQueueSample.m_nFrequency = 13000.f * skidVal + 35000.f; + m_sQueueSample.m_nVolume /= 4; + break; + case SURFACE_DIRT: + case SURFACE_DIRTTRACK: + case SURFACE_SAND: + case SURFACE_PUDDLE: + m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; + m_sQueueSample.m_nFrequency = 6000.f * skidVal + 10000.f; + break; + + default: + m_sQueueSample.m_nSampleIndex = SFX_SKID; + m_sQueueSample.m_nFrequency = 5000.f * skidVal + 11000.f; + break; + } + + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 8; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 3.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} + +float +cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange) +{ + tWheelState wheelState; + float relativeVelChange; + float gasPedalAudio = automobile->m_fGasPedalAudio; + float modificator; + float velChange; + float relativeVel; + + wheelState = automobile->m_aWheelState[wheel]; + if (wheelState == WHEEL_STATE_SPINNING && gasPedalAudio > 0.4f) { + relativeVelChange = (gasPedalAudio - 0.4f) * 1.25f; + + } else if (wheelState == WHEEL_STATE_SKIDDING) { + relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); + } else if (wheelState == WHEEL_STATE_FIXED) { + modificator = 0.4f; + relativeVelChange = gasPedalAudio; + if (relativeVelChange > 0.4f) { + relativeVelChange = relativeVelChange - 0.4f; + modificator = 5.f / 3.f; + } + velChange = Abs(velocityChange); + if (relativeVelChange > 0.4f) + relativeVelChange = relativeVelChange * modificator; + if (velChange > 0.04f) { + relativeVel = Min(1.0f, velChange / transmission->fMaxVelocity); + } else { + relativeVel = 0.0f; + } + if (relativeVel >= relativeVelChange) + relativeVelChange = relativeVel; + } else { + relativeVelChange = 0.0f; + } + + return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); +} + +float +cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange) +{ + float relativeVelChange; + + if (automobile->m_aWheelState[wheel] == 2) { + relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); + } else { + relativeVelChange = 0.0f; + } + + return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); +} + +void +cAudioManager::ProcessVehicleHorn(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 40.0f; + + CAutomobile *automobile; + + if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + automobile = (CAutomobile *)params->m_pVehicle; + if ((!automobile->m_bSirenOrAlarm || !UsesSirenSwitching(params->m_nIndex)) && automobile->GetModelIndex() != MI_MRWHOOP) { + if (automobile->m_nCarHornTimer) { + if (params->m_pVehicle->GetStatus() != STATUS_PLAYER) { + automobile->m_nCarHornTimer = Min(44, automobile->m_nCarHornTimer); + if (automobile->m_nCarHornTimer == 44) + automobile->m_nCarHornPattern = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7; + if (!hornPatternsArray[automobile->m_nCarHornPattern][44 - automobile->m_nCarHornTimer]) + return; + } + + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 4; + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nHornSample; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nHornFrequency; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 80; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 5.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } +} + +bool +cAudioManager::UsesSiren(int32 model) const +{ + switch (model) { + case FIRETRUK: + case AMBULAN: + case FBICAR: + case POLICE: + case ENFORCER: + case PREDATOR: + return true; + default: + return false; + } +} + +bool +cAudioManager::UsesSirenSwitching(int32 model) const +{ + switch (model) { + case AMBULAN: + case POLICE: + case ENFORCER: + case PREDATOR: + return true; + default: + return false; + } +} + +void +cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 110.0f; + + if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + CVehicle *veh = params->m_pVehicle; + if (veh->m_bSirenOrAlarm == 0 && veh->m_nAlarmState <= 0) + return; + +#ifdef FIX_BUGS + if (params->m_pVehicle->GetStatus() == STATUS_WRECKED) + return; +#endif + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 5; + if (UsesSiren(params->m_nIndex)) { + if (params->m_pVehicle->GetStatus() == STATUS_ABANDONED) + return; + if (veh->m_nCarHornTimer && params->m_nIndex != FIRETRUK) { + m_sQueueSample.m_nSampleIndex = SFX_SIREN_FAST; + if (params->m_nIndex == FBICAR) + m_sQueueSample.m_nFrequency = 16113; + else + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SIREN_FAST); + m_sQueueSample.m_nCounter = 60; + } else { + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample; + m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency; + } + } else { + m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample; + m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency; + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 80; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 7.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 5; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + return; + } + } +} + +bool +cAudioManager::UsesReverseWarning(int32 model) const +{ + return model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == COACH; +} + +bool +cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 50.0f; + + CVehicle *veh = params->m_pVehicle; + + if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + return false; + + if (veh->bEngineOn && veh->m_fGasPedal < 0.0f) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 12; + m_sQueueSample.m_nSampleIndex = SFX_REVERSE_WARNING; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nFrequency = (100 * m_sQueueSample.m_nEntityIndex & 1023) + SampleManager.GetSampleBaseFrequency(SFX_REVERSE_WARNING); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 60; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 3.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + return true; +} + +bool +cAudioManager::ProcessVehicleDoors(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 40.0f; + + CAutomobile *automobile; + int8 doorState; + int32 emittingVol; + float velocity; + + if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + return false; + + automobile = (CAutomobile *)params->m_pVehicle; + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + for (int32 i = 0; i < ARRAY_SIZE(automobile->Doors); i++) { + if (automobile->Damage.GetDoorStatus(i) == DOOR_STATUS_SWINGING) { + doorState = automobile->Doors[i].m_nDoorState; + if (doorState == DOOR_STATUS_SMASHED || doorState == DOOR_STATUS_SWINGING) { + velocity = Min(0.3f, Abs(automobile->Doors[i].m_fAngVel)); + if (velocity > 0.0035f) { + emittingVol = (100.f * velocity * 10.f / 3.f); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = i + 6; + m_sQueueSample.m_nSampleIndex = m_anRandomTable[1] % 6 + SFX_COL_CAR_PANEL_1; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) + RandomDisplacement(1000); + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 10; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_fSpeedMultiplier = 1.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = true; + AddSampleToRequestedQueue(); + } + } + } + } + } + return true; +} + +bool +cAudioManager::ProcessAirBrakes(cVehicleParams *params) +{ + CAutomobile *automobile; + uint8 rand; + + if (params->m_fDistance > 900.0f) + return false; + automobile = (CAutomobile *)params->m_pVehicle; + if (!automobile->bEngineOn) + return true; + + if ((automobile->m_fVelocityChangeForAudio < 0.025f || params->m_fVelocityChange >= 0.025f) && + (automobile->m_fVelocityChangeForAudio > -0.025f || params->m_fVelocityChange <= 0.025f)) + return true; + + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + rand = m_anRandomTable[0] % 10 + 70; + m_sQueueSample.m_nVolume = ComputeVolume(rand, 30.0f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 13; + m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AIR_BRAKES); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 10; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nEmittingVolume = rand; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + + return true; +} + +bool +cAudioManager::HasAirBrakes(int32 model) const +{ + return model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == COACH; +} + +bool +cAudioManager::ProcessEngineDamage(cVehicleParams *params) +{ + const int engineDamageIntensity = 40; + + CAutomobile *veh; + uint8 engineStatus; + uint8 emittingVolume; + + if (params->m_fDistance >= SQR(engineDamageIntensity)) + return false; + veh = (CAutomobile *)params->m_pVehicle; + if (veh->bEngineOn) { + engineStatus = veh->Damage.GetEngineStatus(); + if (engineStatus > 250 || engineStatus < 100) + return true; + if (engineStatus < 225) { + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; + emittingVolume = 6; + m_sQueueSample.m_nReleasingVolumeModificator = 7; + m_sQueueSample.m_nFrequency = 40000; + } else { + emittingVolume = 60; + m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; + m_sQueueSample.m_nReleasingVolumeModificator = 7; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); + } + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, engineDamageIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 28; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVolume; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = engineDamageIntensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + return true; +} + +bool +cAudioManager::ProcessCarBombTick(cVehicleParams *params) +{ + CAutomobile *automobile; + + if (params->m_fDistance >= SQR(40.f)) + return false; + automobile = (CAutomobile *)params->m_pVehicle; + if (automobile->bEngineOn && automobile->m_bombType == CARBOMB_TIMEDACTIVE) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(60, 40.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 35; + m_sQueueSample.m_nSampleIndex = SFX_COUNTDOWN; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COUNTDOWN); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 60; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = 40.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + return true; +} + +void +cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) +{ + int16 event; + uint8 emittingVol; + float relVol; + float vol; + bool noReflections; + float maxDist; + cPedParams pedParams; + + static uint8 WaveIndex = 41; + static uint8 GunIndex = 53; + static uint8 iWheelIndex = 82; + static uint8 CrunchOffset = 0; + + for (int i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { + noReflections = 0; + m_sQueueSample.m_bRequireReflection = false; + event = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; + switch (event) { + case SOUND_CAR_DOOR_CLOSE_BONNET: + case SOUND_CAR_DOOR_CLOSE_BUMPER: + case SOUND_CAR_DOOR_CLOSE_FRONT_LEFT: + case SOUND_CAR_DOOR_CLOSE_FRONT_RIGHT: + case SOUND_CAR_DOOR_CLOSE_BACK_LEFT: + case SOUND_CAR_DOOR_CLOSE_BACK_RIGHT: { + const float SOUND_INTENSITY = 50.0f; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[2] % 5 + 122; + switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { + case 0: + m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE; + break; + case 2: + m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_CLOSE; + break; + case 3: + m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; + break; + default: + m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE; + break; + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bRequireReflection = true; + break; + } + case SOUND_CAR_DOOR_OPEN_BONNET: + case SOUND_CAR_DOOR_OPEN_BUMPER: + case SOUND_CAR_DOOR_OPEN_FRONT_LEFT: + case SOUND_CAR_DOOR_OPEN_FRONT_RIGHT: + case SOUND_CAR_DOOR_OPEN_BACK_LEFT: + case SOUND_CAR_DOOR_OPEN_BACK_RIGHT: { + const float SOUND_INTENSITY = 50.0f; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[1] % 10 + 117; + switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { + case 0: + m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_OPEN; + break; + case 2: + m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_OPEN; + break; + case 3: + m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; + break; + default: + m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_OPEN; + break; + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bRequireReflection = true; + break; + } + case SOUND_CAR_WINDSHIELD_CRACK: { + const float SOUND_INTENSITY = 30.0f; + maxDist = SQR(SOUND_INTENSITY); + m_sQueueSample.m_nSampleIndex = SFX_GLASS_CRACK; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 68; + emittingVol = m_anRandomTable[1] % 30 + 60; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_CRACK); + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + } break; + case SOUND_CAR_JUMP: { + const float SOUND_INTENSITY = 35.0f; + emittingVol = Max(80.f, 2 * (100.f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i])); + maxDist = SQR(SOUND_INTENSITY); + m_sQueueSample.m_nSampleIndex = SFX_TYRE_BUMP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iWheelIndex++; + if (iWheelIndex > 85) + iWheelIndex = 82; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BUMP); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + if (params->m_nIndex == 41) { + m_sQueueSample.m_nFrequency *= 2; + emittingVol /= 2; + } + m_sQueueSample.m_nReleasingVolumeModificator = 6; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + break; + } + case SOUND_CAR_ENGINE_START: { + const float SOUND_INTENSITY = 40.0f; + emittingVol = 60; + maxDist = SQR(SOUND_INTENSITY); + m_sQueueSample.m_nSampleIndex = SFX_CAR_STARTER; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 33; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_STARTER); + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bRequireReflection = true; + break; + } + case SOUND_CAR_LIGHT_BREAK: { + const float SOUND_INTENSITY = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_GLASS_SHARD_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 37; + m_sQueueSample.m_nFrequency = 9 * SampleManager.GetSampleBaseFrequency(SFX_GLASS_SHARD_1) / 10; + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[4] % 10 + 30; + break; + } + case SOUND_CAR_HYDRAULIC_1: + case SOUND_CAR_HYDRAULIC_2: { + const float SOUND_INTENSITY = 35.0f; + if (event == MOONBEAM) // todo check + m_sQueueSample.m_nFrequency = 15600; + else + m_sQueueSample.m_nFrequency = 13118; + m_sQueueSample.m_nSampleIndex = SFX_SUSPENSION_FAST_MOVE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 51; + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[0] % 15 + 55; + break; + } + case SOUND_CAR_HYDRAULIC_3: { + const float SOUND_INTENSITY = 35.0f; + m_sQueueSample.m_nSampleIndex = SFX_SUSPENSION_SLOW_MOVE_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 86; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SUSPENSION_SLOW_MOVE_LOOP); + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_nReleasingVolumeDivider = 7; + noReflections = true; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[0] % 15 + 55; + break; + } + case SOUND_CAR_JERK: { + const float SOUND_INTENSITY = 35.0f; + m_sQueueSample.m_nSampleIndex = SFX_SHAG_SUSPENSION; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 87; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHAG_SUSPENSION); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[1] % 15 + 55; + break; + } + case SOUND_CAR_SPLASH: { + const float SOUND_INTENSITY = 40.0f; + vol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; + if (vol <= 300.f) + continue; + if (vol > 1200.f) + m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] = 1200.0f; + relVol = (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] - 300.f) / 900.f; + m_sQueueSample.m_nSampleIndex = (m_anRandomTable[0] & 1) + SFX_BOAT_SPLASH_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = WaveIndex++; + if (WaveIndex > 46) + WaveIndex = 41; + m_sQueueSample.m_nFrequency = (7000.f * relVol) + 6000; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + emittingVol = (55.f * relVol); + maxDist = SQR(SOUND_INTENSITY); + break; + } + case SOUND_17: { + const float SOUND_INTENSITY = 50.0f; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_THUMB_OFF; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 47; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BOAT_THUMB_OFF) + RandomDisplacement(600); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + emittingVol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; + maxDist = SQR(SOUND_INTENSITY); + break; + } + case SOUND_18: + case SOUND_19: { + const float SOUND_INTENSITY = 35.0f; + m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 59; + m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 11025; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 5.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[1] % 20 + 70; + break; + } + case SOUND_CAR_TANK_TURRET_ROTATE: { + const float SOUND_INTENSITY = 40.0f; + vol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; + if (vol > 96.0f / 2500.0f) + vol = 96.0f / 2500.0f; + m_sQueueSample.m_nSampleIndex = SFX_TANK_TURRET; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 79; + m_sQueueSample.m_nFrequency = (3000.f * vol * 2500.0f / 96.0f) + 9000; + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + emittingVol = (37.f * vol * 2500.0f / 96.0f) + 90; + maxDist = SQR(SOUND_INTENSITY); + noReflections = true; + break; + } + case SOUND_CAR_BOMB_TICK: { + const float SOUND_INTENSITY = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_BOMB_BEEP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 80; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BOMB_BEEP); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + m_sQueueSample.m_bRequireReflection = true; + emittingVol = 60; + break; + } + case SOUND_PLANE_ON_GROUND: { + const float SOUND_INTENSITY = 180.0f; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_LAND_WHEELS; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 81; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_LAND_WHEELS); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[4] % 25 + 75; + break; + } + case SOUND_WEAPON_SHOT_FIRED: { + const float SOUND_INTENSITY = 120.0f; + emittingVol = m_anRandomTable[2]; + maxDist = SQR(SOUND_INTENSITY); + m_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = GunIndex++; + emittingVol = emittingVol % 15 + 65; + if (GunIndex > 58) + GunIndex = 53; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + break; + } + case SOUND_WEAPON_HIT_VEHICLE: { + const float SOUND_INTENSITY = 40.0f; + m_sQueueSample.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % ARRAY_SIZE(m_anRandomTable)] % 6 + SFX_BULLET_CAR_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 34; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 7; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[3] % 20 + 90; + break; + } + case SOUND_BOMB_TIMED_ACTIVATED: + case SOUND_55: + case SOUND_BOMB_ONIGNITION_ACTIVATED: + case SOUND_BOMB_TICK: { + const float SOUND_INTENSITY = 50.0f; + m_sQueueSample.m_nSampleIndex = SFX_ARM_BOMB; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 36; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ARM_BOMB); + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bRequireReflection = true; + emittingVol = 50; + maxDist = SQR(SOUND_INTENSITY); + break; + } + case SOUND_PED_HELI_PLAYER_FOUND: + pedParams.m_pPed = nil; + pedParams.m_bDistanceCalculated = false; + pedParams.m_fDistance = 0.0f; + pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated; + pedParams.m_fDistance = params->m_fDistance; + SetupPedComments(&pedParams, SOUND_PED_HELI_PLAYER_FOUND); + continue; + case SOUND_PED_BODYCAST_HIT: + pedParams.m_pPed = nil; + pedParams.m_bDistanceCalculated = false; + pedParams.m_fDistance = 0.0f; + pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated; + pedParams.m_fDistance = params->m_fDistance; + SetupPedComments(&pedParams, SOUND_PED_BODYCAST_HIT); + continue; + case SOUND_WATER_FALL: { + const float SOUND_INTENSITY = 40.0f; + m_sQueueSample.m_nSampleIndex = SFX_SPLASH_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 15; + m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 16000; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + m_sQueueSample.m_bRequireReflection = true; + emittingVol = m_anRandomTable[4] % 20 + 90; + break; + } + case SOUND_SPLATTER: { + const float SOUND_INTENSITY = 40.0f; + m_sQueueSample.m_nSampleIndex = CrunchOffset + SFX_PED_CRUNCH_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 48; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PED_CRUNCH_1) + RandomDisplacement(600); + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 40.0f; + ++CrunchOffset; + maxDist = SQR(SOUND_INTENSITY); + emittingVol = m_anRandomTable[4] % 20 + 55; + CrunchOffset %= 2; + m_sQueueSample.m_bRequireReflection = true; + break; + } + case SOUND_CAR_PED_COLLISION: { + const float SOUND_INTENSITY = 40.0f; + vol = Min(20.0f, m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]); + emittingVol = (vol / 20.0f * 127.f); + if (!emittingVol) + continue; + + m_sQueueSample.m_nSampleIndex = (m_anRandomTable[2] & 3) + SFX_FIGHT_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 50; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + maxDist = SQR(SOUND_INTENSITY); + break; + } + default: + continue; + } + if (params->m_fDistance < maxDist) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume != 0) { + if (noReflections) { + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + } else { + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + } + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bIs2D = false; + AddSampleToRequestedQueue(); + } + } + } +} + +bool +cAudioManager::ProcessTrainNoise(cVehicleParams *params) +{ + const float SOUND_INTENSITY = 300.0f; + + CTrain *train; + uint8 emittingVol; + float speedMultipler; + + if (params->m_fDistance >= SQR(SOUND_INTENSITY)) + return false; + + if (params->m_fVelocityChange > 0.0f) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + train = (CTrain *)params->m_pVehicle; + speedMultipler = Min(1.0f, train->m_fSpeed * 250.f / 51.f); + emittingVol = (75.f * speedMultipler); + if (train->m_fWagonPosition == 0.0f) { + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 32; + m_sQueueSample.m_nSampleIndex = SFX_TRAIN_FAR; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_FAR); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 3.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + const float SOUND_INTENSITY = 70.0f; + if (params->m_fDistance < SQR(SOUND_INTENSITY)) { + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 33; + m_sQueueSample.m_nSampleIndex = SFX_TRAIN_NEAR; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_NEAR) + 100 * m_sQueueSample.m_nEntityIndex % 987; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 6.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + return true; +} + +bool +cAudioManager::ProcessBoatEngine(cVehicleParams *params) +{ + CBoat *boat; + float padRelativeAccerate; + float gasPedal; + int32 padAccelerate; + uint8 emittingVol; + float oneShotVol; + + static uint16 LastAccel = 0; + static uint8 LastVol = 0; + + static const int intensity = 50; + + if (params->m_fDistance < SQR(intensity)) { + boat = (CBoat *)params->m_pVehicle; + if (params->m_nIndex == REEFER) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(80, 50.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 39; + m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; + m_sQueueSample.m_nFrequency = 10386; + m_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 80; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = intensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 7; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + if (FindPlayerVehicle() == params->m_pVehicle) { + if (Pads[0].GetAccelerate() <= Pads[0].GetBrake()) + padAccelerate = Pads[0].GetBrake(); + else + padAccelerate = Pads[0].GetAccelerate(); + padRelativeAccerate = padAccelerate / 255; + emittingVol = (100.f * padRelativeAccerate) + 15; + m_sQueueSample.m_nFrequency = (3000.f * padRelativeAccerate) + 6000; + if (!boat->m_bIsAnchored) + m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; + } else { + gasPedal = Abs(boat->m_fGasPedal); + if (gasPedal > 0.0f) { + m_sQueueSample.m_nFrequency = 6000; + emittingVol = 15; + } else { + emittingVol = (100.f * gasPedal) + 15; + m_sQueueSample.m_nFrequency = (3000.f * gasPedal) + 6000; + if (!boat->m_bIsAnchored) + m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; + } + } + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 50.f, m_sQueueSample.m_fDistance); + if (!m_sQueueSample.m_nVolume) + return true; + m_sQueueSample.m_nCounter = 40; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; + m_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = intensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 7; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + } else { + if (FindPlayerVehicle() == params->m_pVehicle) { + if (Pads[0].GetAccelerate() <= Pads[0].GetBrake()) + padAccelerate = Pads[0].GetBrake(); + else + padAccelerate = Pads[0].GetAccelerate(); + if (padAccelerate <= 20) { + emittingVol = 45 - 45 * padAccelerate / 40; + m_sQueueSample.m_nFrequency = 100 * padAccelerate + 11025; + m_sQueueSample.m_nCounter = 39; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_IDLE; + if (LastAccel > 20) { + oneShotVol = LastVol; + PlayOneShot(m_sQueueSample.m_nEntityIndex, SOUND_17, oneShotVol); + } + } else { + emittingVol = 105 * padAccelerate / 255 + 15; + m_sQueueSample.m_nFrequency = 4000 * padAccelerate / 255 + 8000; + if (!boat->m_bIsAnchored) + m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; + m_sQueueSample.m_nCounter = 40; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; + } + LastVol = emittingVol; + LastAccel = padAccelerate; + } else { + gasPedal = Abs(boat->m_fGasPedal); + if (gasPedal > 0.0f) { + m_sQueueSample.m_nFrequency = 11025; + emittingVol = 45; + m_sQueueSample.m_nCounter = 39; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_IDLE; + } else { + emittingVol = (105.f * gasPedal) + 15; + m_sQueueSample.m_nFrequency = (4000.f * gasPedal) + 8000; + if (!boat->m_bIsAnchored) + m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; + m_sQueueSample.m_nCounter = 40; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; + } + } + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 50.f, m_sQueueSample.m_fDistance); + if (!m_sQueueSample.m_nVolume) + return true; + m_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = intensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 7; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + } + AddSampleToRequestedQueue(); + return true; + } + return false; +} + +bool +cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) +{ + float velocityChange; + int32 vol; + float multiplier; + + if (params->m_fDistance > 2500.f) + return false; + + velocityChange = Abs(params->m_fVelocityChange); + if (velocityChange <= 0.0005f && params->m_pVehicle->GetPosition().y) + return true; + + velocityChange = Min(0.75f, velocityChange); + multiplier = (velocityChange - 0.0005f) * 1.3342f; + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + vol = (30.f * multiplier); + m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 38; + m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nFrequency = (6050.f * multiplier) + 16000; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = vol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + + return true; +} + +struct tHelicopterSampleData { + float m_fMaxDistance; + float m_fBaseDistance; + uint8 m_bBaseVolume; +}; + +bool +cAudioManager::ProcessHelicopter(cVehicleParams *params) +{ + CHeli *heli; + float MaxDist; + float dist; + float baseDist; + int32 emittingVol; + static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, maxVolume}, {60.f, 30.f, maxVolume}}; + + if (gHeliSfxRanges[0].m_fMaxDistance * gHeliSfxRanges[0].m_fMaxDistance <= params->m_fDistance) + return false; + + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + heli = (CHeli *)params->m_pVehicle; + for (uint32 i = 0; i < ARRAY_SIZE(gHeliSfxRanges); i++) { + MaxDist = gHeliSfxRanges[i].m_fMaxDistance; + dist = m_sQueueSample.m_fDistance; + if (dist >= MaxDist) + return true; + baseDist = gHeliSfxRanges[i].m_fBaseDistance; + if (dist < baseDist) + emittingVol = (gHeliSfxRanges[i].m_bBaseVolume * ((MaxDist - dist) / (MaxDist - baseDist))); + else + emittingVol = gHeliSfxRanges[i].m_bBaseVolume; + + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, gHeliSfxRanges[i].m_fMaxDistance, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = i + 65; + m_sQueueSample.m_nSampleIndex = i + SFX_HELI_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nFrequency = 1200 * heli->m_nHeliId + SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 6.0f; + m_sQueueSample.m_fSoundIntensity = gHeliSfxRanges[i].m_fMaxDistance; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + return true; +} + +void +cAudioManager::ProcessPlane(cVehicleParams *params) +{ + switch (params->m_nIndex) { + case AIRTRAIN: + ProcessJumbo(params); + break; + case DEADDODO: + ProcessCesna(params); + break; + default: + debug("Plane Model Id is %d\n, ", params->m_pVehicle->GetModelIndex()); + break; + } +} + +#pragma region JUMBO +uint8 gJumboVolOffsetPercentage; + +void +DoJumboVolOffset() +{ + if (!(AudioManager.GetFrameCounter() % (AudioManager.GetRandomNumber(0) % 6 + 3))) + gJumboVolOffsetPercentage = AudioManager.GetRandomNumber(1) % 60; +} + +void +cAudioManager::ProcessJumbo(cVehicleParams *params) +{ + CPlane *plane; + float position; + + if (params->m_fDistance < 193600.0f) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + plane = (CPlane *)params->m_pVehicle; + DoJumboVolOffset(); + position = PlanePathPosition[plane->m_nPlaneId]; + if (position <= TakeOffPoint) { + if (plane->m_fSpeed <= 0.10334f) { + ProcessJumboTaxi(); + return; + } + + ProcessJumboAccel(plane); + } else if (300.0f + TakeOffPoint >= position) { + ProcessJumboTakeOff(plane); + } else if (LandingPoint - 350.0f >= position) { + ProcessJumboFlying(); + } else { + if (position > LandingPoint) { + if (plane->m_fSpeed > 0.10334f) { + ProcessJumboDecel(plane); + return; + } + ProcessJumboTaxi(); + return; + } + ProcessJumboLanding(plane); + } + } +} + +void +cAudioManager::ProcessJumboTaxi() +{ + if (SetupJumboFlySound(20)) { + if (SetupJumboTaxiSound(75)) + SetupJumboWhineSound(18, 29500); + } +} + +void +cAudioManager::ProcessJumboAccel(CPlane *plane) +{ + int32 engineFreq; + int32 vol; + float whineSoundFreq; + float modificator; + + if (SetupJumboFlySound(20)) { + modificator = (plane->m_fSpeed - 0.10334f) * 1.676f; + if (modificator > 1.0f) + modificator = 1.0f; + if (SetupJumboRumbleSound(maxVolume * modificator) && SetupJumboTaxiSound((1.0f - modificator) * 75.f)) { + if (modificator < 0.2f) { + whineSoundFreq = modificator * 5.f * 14600.0f + 29500; + vol = modificator * 5.f * maxVolume; + engineFreq = modificator * 5.f * 6050.f + 16000; + } else { + whineSoundFreq = 44100; + engineFreq = 22050; + vol = maxVolume; + } + SetupJumboEngineSound(vol, engineFreq); + SetupJumboWhineSound(18, whineSoundFreq); + } + } +} + +void +cAudioManager::ProcessJumboTakeOff(CPlane *plane) +{ + const float modificator = (PlanePathPosition[plane->m_nPlaneId] - TakeOffPoint) / 300.f; + + if (SetupJumboFlySound((107.f * modificator) + 20) && SetupJumboRumbleSound(maxVolume * (1.f - modificator))) { + if (SetupJumboEngineSound(maxVolume, 22050)) + SetupJumboWhineSound(18.f * (1.f - modificator), 44100); + } +} + +void +cAudioManager::ProcessJumboFlying() +{ + if (SetupJumboFlySound(maxVolume)) + SetupJumboEngineSound(63, 22050); +} + +void +cAudioManager::ProcessJumboLanding(CPlane *plane) +{ + const float modificator = (LandingPoint - PlanePathPosition[plane->m_nPlaneId]) / 350.f; + if (SetupJumboFlySound(107.f * modificator + 20)) { + if (SetupJumboTaxiSound(75.f * (1.f - modificator))) { + SetupJumboEngineSound(maxVolume, 22050); + SetupJumboWhineSound(18.f * (1.f - modificator), 14600.f * modificator + 29500); + } + } +} + +void +cAudioManager::ProcessJumboDecel(CPlane *plane) +{ + if (SetupJumboFlySound(20) && SetupJumboTaxiSound(75)) { + const float modificator = Min(1.f, (plane->m_fSpeed - 0.10334f) * 1.676f); + SetupJumboEngineSound(maxVolume * modificator, 6050.f * modificator + 16000); + SetupJumboWhineSound(18, 29500); + } +} + +bool +cAudioManager::SetupJumboTaxiSound(uint8 vol) +{ + const float SOUND_INTENSITY = 180.0f; + if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) + return false; + + uint8 emittingVol = (vol / 2) + ((vol / 2) * m_sQueueSample.m_fDistance / SOUND_INTENSITY); + + if (m_sQueueSample.m_fDistance / SOUND_INTENSITY < 0.7f) + emittingVol -= emittingVol * gJumboVolOffsetPercentage / 100; + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = GetJumboTaxiFreq(); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 4; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + return true; +} + +bool +cAudioManager::SetupJumboWhineSound(uint8 emittingVol, int32 freq) +{ + const float SOUND_INTENSITY = 170.0f; + + if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) + return false; + + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 2; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_WHINE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = freq; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 4; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + return true; +} + +bool +cAudioManager::SetupJumboEngineSound(uint8 vol, int32 freq) +{ + const float SOUND_INTENSITY = 180.0f; + if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) + return false; + + uint8 emittingVol = vol - gJumboVolOffsetPercentage / 100; + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 3; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_ENGINE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = freq; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 4; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + return true; +} + +bool +cAudioManager::SetupJumboFlySound(uint8 emittingVol) +{ + const float SOUND_INTENSITY = 440.0f; + if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) + return false; + + int32 vol = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + m_sQueueSample.m_nVolume = vol; + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_DIST_FLY; + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_DIST_FLY); + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_nReleasingVolumeDivider = 5; + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + AddSampleToRequestedQueue(); + } + return true; +} + +bool +cAudioManager::SetupJumboRumbleSound(uint8 emittingVol) +{ + const float SOUND_INTENSITY = 240.0f; + if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) + return false; + + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + + if (m_sQueueSample.m_nVolume != 0) { + m_sQueueSample.m_nCounter = 5; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = true; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_RUMBLE); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 12; + m_sQueueSample.m_nOffset = 0; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + m_sQueueSample.m_nCounter = 6; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE; + m_sQueueSample.m_nFrequency += 200; + m_sQueueSample.m_nOffset = maxVolume; + AddSampleToRequestedQueue(); + } + return true; +} + +int32 +cAudioManager::GetJumboTaxiFreq() const +{ + return (60.833f * m_sQueueSample.m_fDistance) + 22050; +} + +#pragma endregion Some jumbo crap + +#pragma endregion All the vehicle audio code + +#pragma region PED AUDIO +void +cAudioManager::ProcessPed(CPhysical *ped) +{ + cPedParams params; + + params.m_pPed = nil; + params.m_bDistanceCalculated = false; + params.m_fDistance = 0.0f; + + m_sQueueSample.m_vecPos = ped->GetPosition(); + + // params.m_bDistanceCalculated = false; + params.m_pPed = (CPed *)ped; + params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (ped->GetModelIndex() == MI_FATMALE02) + ProcessPedHeadphones(¶ms); + ProcessPedOneShots(¶ms); +} + +void +cAudioManager::ProcessPedHeadphones(cPedParams *params) +{ + CPed *ped; + CAutomobile *veh; + uint8 emittingVol; + + if (params->m_fDistance < 49.f) { + ped = params->m_pPed; + if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + if (ped->bInVehicle && ped->m_nPedState == PED_DRIVING) { + emittingVol = 10; + veh = (CAutomobile *)ped->m_pMyVehicle; + if (veh && veh->IsCar()) { + for (int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) { + if (!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) { + emittingVol = 42; + break; + } + } + } + } else { + emittingVol = 42; + } + + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 7.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 64; + m_sQueueSample.m_nSampleIndex = SFX_HEADPHONES; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_HEADPHONES); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = 7.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 5; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + return; + } + } +} + +void +cAudioManager::ProcessPedOneShots(cPedParams *params) +{ + uint8 emittingVol; + int32 sampleIndex; + + CPed *ped = params->m_pPed; + + bool stereo; + int16 sound; + bool noReflection; + CWeapon *weapon; + float maxDist = 0.f; // uninitialized variable + + static uint8 iSound = 21; + + weapon = params->m_pPed->GetWeapon(); + for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { + noReflection = false; + stereo = false; + m_sQueueSample.m_bRequireReflection = false; + sound = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; + switch (sound) { + case SOUND_STEP_START: + case SOUND_STEP_END: + if (!params->m_pPed->bIsLooking) { + emittingVol = m_anRandomTable[3] % 15 + 45; + if (FindPlayerPed() != m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity) + emittingVol /= 2; + maxDist = 400.f; + switch (params->m_pPed->m_nSurfaceTouched) { + case SURFACE_GRASS: + sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1; + break; + case SURFACE_DIRT: + case SURFACE_DIRTTRACK: + sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1; + break; + case SURFACE_METAL6: + case SURFACE_METAL_DOOR: + case SURFACE_BILLBOARD: + case SURFACE_STEEL: + case SURFACE_METAL_POLE: + case SURFACE_STREET_LIGHT: + case SURFACE_METAL14: + case SURFACE_METAL15: + case SURFACE_METAL_FENCE: + case SURFACE_METAL27: + case SURFACE_METAL28: + sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1; + break; + case SURFACE_SAND: + sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1; + break; + case SURFACE_PUDDLE: + sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; + break; + case SURFACE_WOOD: + case SURFACE_WOOD_BOX: + case SURFACE_WOOD_PLANK: + sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1; + break; + case SURFACE_HEDGE: + sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1; + break; + default: + sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1; + break; + } + m_sQueueSample.m_nSampleIndex = sampleIndex; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - 28; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17); + switch (params->m_pPed->m_nMoveState) { + case PEDMOVE_WALK: + emittingVol /= 4; + m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10; + break; + case PEDMOVE_RUN: + emittingVol /= 2; + m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; + break; + case PEDMOVE_SPRINT: + m_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10; + break; + default: + break; + } + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 20.0f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + } + break; + case SOUND_FALL_LAND: + case SOUND_FALL_COLLAPSE: + if (!ped->bIsLooking) { + maxDist = SQR(30); + emittingVol = m_anRandomTable[3] % 20 + 80; + if (ped->m_nSurfaceTouched == SURFACE_PUDDLE) { + m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; + } else if (sound == SOUND_FALL_LAND) { + m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND; + } else { + m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL; + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + } + break; + case SOUND_FIGHT_PUNCH_33: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; + m_sQueueSample.m_nFrequency = 18000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_KICK_34: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; + m_sQueueSample.m_nFrequency = 16500; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_HEADBUTT_35: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; + m_sQueueSample.m_nFrequency = 20000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_PUNCH_36: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; + m_sQueueSample.m_nFrequency = 18000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_PUNCH_37: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; + m_sQueueSample.m_nFrequency = 16500; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_CLOSE_PUNCH_38: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; + m_sQueueSample.m_nFrequency = 20000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_PUNCH_39: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; + m_sQueueSample.m_nFrequency = 18000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; + m_sQueueSample.m_nFrequency = 16500; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_PUNCH_41: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; + m_sQueueSample.m_nFrequency = 20000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_PUNCH_FROM_BEHIND_42: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; + m_sQueueSample.m_nFrequency = 18000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_KNEE_OR_KICK_43: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; + m_sQueueSample.m_nFrequency = 16500; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_FIGHT_KICK_44: + m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; + m_sQueueSample.m_nFrequency = 20000; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound; + stereo = true; + ++iSound; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 26 + 100; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_WEAPON_BAT_ATTACK: + m_sQueueSample.m_nSampleIndex = SFX_BAT_HIT_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 22000; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = m_anRandomTable[2] % 20 + 100; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + case SOUND_WEAPON_SHOT_FIRED: + weapon = &ped->m_weapons[ped->m_currentWeapon]; + switch (weapon->m_eWeaponType) { + case WEAPONTYPE_COLT45: + m_sQueueSample.m_nSampleIndex = SFX_COLT45_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COLT45_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 50.0f; + maxDist = SQR(50); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = m_anRandomTable[1] % 10 + 90; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + case WEAPONTYPE_UZI: + m_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 80.0f; + maxDist = SQR(80); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[3] % 15 + 70; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + break; + case WEAPONTYPE_SHOTGUN: + m_sQueueSample.m_nSampleIndex = SFX_SHOTGUN_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOTGUN_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 60.0f; + maxDist = 3600.f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = m_anRandomTable[2] % 10 + 100; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + case WEAPONTYPE_AK47: + m_sQueueSample.m_nSampleIndex = SFX_AK47_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 80.0f; + maxDist = SQR(80); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[1] % 15 + 70; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + break; + case WEAPONTYPE_M16: + m_sQueueSample.m_nSampleIndex = SFX_M16_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 80.0f; + maxDist = SQR(80); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[4] % 15 + 70; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + break; + case WEAPONTYPE_SNIPERRIFLE: + m_sQueueSample.m_nSampleIndex = SFX_SNIPER_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SNIPER_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 60.0f; + maxDist = 3600.f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = m_anRandomTable[4] % 10 + 110; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + case WEAPONTYPE_ROCKETLAUNCHER: + m_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 90.0f; + maxDist = 8100.f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = m_anRandomTable[0] % 20 + 80; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + case WEAPONTYPE_FLAMETHROWER: + m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = 9; + emittingVol = 90; + m_sQueueSample.m_nFrequency = (10 * m_sQueueSample.m_nEntityIndex & 2047) + SampleManager.GetSampleBaseFrequency(SFX_FLAMETHROWER_LEFT); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = 60.0f; + maxDist = 3600.f; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nEmittingVolume = 90; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 6; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + default: + continue; + } + + break; + case SOUND_WEAPON_RELOAD: + weapon = &ped->m_weapons[ped->m_currentWeapon]; + switch (weapon->m_eWeaponType) { + case WEAPONTYPE_COLT45: + m_sQueueSample.m_nSampleIndex = SFX_PISTOL_RELOAD; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PISTOL_RELOAD) + RandomDisplacement(300); + break; + case WEAPONTYPE_UZI: + m_sQueueSample.m_nSampleIndex = SFX_M16_RELOAD; + m_sQueueSample.m_nFrequency = 39243; + break; + case WEAPONTYPE_SHOTGUN: + m_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD; + m_sQueueSample.m_nFrequency = 30290; + break; + case WEAPONTYPE_AK47: + m_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_RELOAD); + break; + case WEAPONTYPE_M16: + m_sQueueSample.m_nSampleIndex = SFX_M16_RELOAD; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_RELOAD); + break; + case WEAPONTYPE_SNIPERRIFLE: + m_sQueueSample.m_nSampleIndex = SFX_RIFLE_RELOAD; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RIFLE_RELOAD); + break; + case WEAPONTYPE_ROCKETLAUNCHER: + m_sQueueSample.m_nSampleIndex = SFX_ROCKET_RELOAD; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_RELOAD); + break; + default: + continue; + } + emittingVol = 75; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency += RandomDisplacement(300); + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = 75; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + case SOUND_WEAPON_AK47_BULLET_ECHO: + case SOUND_WEAPON_UZI_BULLET_ECHO: + case SOUND_WEAPON_M16_BULLET_ECHO: + m_sQueueSample.m_nSampleIndex = SFX_UZI_END_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_END_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 80.0f; + maxDist = SQR(80); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = m_anRandomTable[4] % 10 + 40; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + if (m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bRequireReflection = true; + else + noReflection = true; + break; + case SOUND_WEAPON_FLAMETHROWER_FIRE: + m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_START_LEFT; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_FLAMETHROWER_START_LEFT); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = 60.0f; + maxDist = 3600.f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + emittingVol = 70; + m_sQueueSample.m_nEmittingVolume = 70; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + break; + case SOUND_WEAPON_HIT_PED: + m_sQueueSample.m_nSampleIndex = SFX_BULLET_PED; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BULLET_PED); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); + m_sQueueSample.m_nReleasingVolumeModificator = 7; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 30.0f; + maxDist = SQR(30); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[0] % 20 + 90; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + break; + case SOUND_SPLASH: + m_sQueueSample.m_nSampleIndex = SFX_SPLASH_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nCounter = iSound++; + stereo = true; + m_sQueueSample.m_nFrequency = RandomDisplacement(1400) + 20000; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = 40.0f; + maxDist = 1600.f; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + emittingVol = m_anRandomTable[2] % 30 + 70; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bRequireReflection = true; + break; + default: + SetupPedComments(params, sound); + continue; + } + + if (stereo && iSound > 60) + iSound = 21; + if (params->m_fDistance < maxDist) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + if (noReflection) { + if (0.2f * m_sQueueSample.m_fSoundIntensity <= m_sQueueSample.m_fDistance) { + noReflection = 0; + } else { + m_sQueueSample.m_bIs2D = true; + m_sQueueSample.m_nOffset = 0; + } + } + m_sQueueSample.m_bReverbFlag = true; + AddSampleToRequestedQueue(); + if (noReflection) { + m_sQueueSample.m_nOffset = 127; + ++m_sQueueSample.m_nSampleIndex; + if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] != SOUND_WEAPON_SHOT_FIRED || + weapon->m_eWeaponType != WEAPONTYPE_FLAMETHROWER) { + m_sQueueSample.m_nCounter = iSound++; + if (iSound > 60) + iSound = 21; + } else { + ++m_sQueueSample.m_nCounter; + } + AddSampleToRequestedQueue(); + } + } + } + } +} + +void +cAudioManager::SetupPedComments(cPedParams *params, uint32 sound) +{ + CPed *ped = params->m_pPed; + uint8 emittingVol; + float soundIntensity; + tPedComment pedComment; + + if (ped != nil) { + switch (sound) { + case SOUND_AMMUNATION_WELCOME_1: + pedComment.m_nSampleIndex = SFX_AMMU_D; + break; + case SOUND_AMMUNATION_WELCOME_2: + pedComment.m_nSampleIndex = SFX_AMMU_E; + break; + case SOUND_AMMUNATION_WELCOME_3: + pedComment.m_nSampleIndex = SFX_AMMU_F; + break; + default: + pedComment.m_nSampleIndex = GetPedCommentSfx(ped, sound); + if (pedComment.m_nSampleIndex == NO_SAMPLE) + return; + break; + } + + soundIntensity = 50.0f; + } else { + switch (sound) { + case SOUND_PED_HELI_PLAYER_FOUND: + soundIntensity = 400.0f; + pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_POLICE_HELI_1, SFX_POLICE_HELI_29); + break; + case SOUND_PED_BODYCAST_HIT: + if (CTimer::GetTimeInMilliseconds() <= gNextCryTime) + return; + soundIntensity = 50.0f; + gNextCryTime = CTimer::GetTimeInMilliseconds() + 500; + pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_PLASTER_BLOKE_1, SFX_PLASTER_BLOKE_4); + break; + case SOUND_INJURED_PED_MALE_OUCH: + case SOUND_INJURED_PED_MALE_PRISON: + soundIntensity = 50.0f; + pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_MALE_GRUNT_1, SFX_GENERIC_MALE_GRUNT_15); + break; + case SOUND_INJURED_PED_FEMALE: + soundIntensity = 50.0f; + pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_FEMALE_GRUNT_1, SFX_GENERIC_FEMALE_GRUNT_11); + break; + default: + return; + } + } + + if (params->m_fDistance < SQR(soundIntensity)) { + CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); + if (sound != SOUND_PAGER) { + switch (sound) { + case SOUND_AMMUNATION_WELCOME_1: + case SOUND_AMMUNATION_WELCOME_2: + case SOUND_AMMUNATION_WELCOME_3: + emittingVol = maxVolume; + break; + default: + if (CWorld::GetIsLineOfSightClear(TheCamera.GetPosition(), m_sQueueSample.m_vecPos, true, false, false, false, false, false)) + emittingVol = maxVolume; + else + emittingVol = 31; + break; + } + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, soundIntensity, m_sQueueSample.m_fDistance); + pedComment.m_nProcess = 10; + if (m_sQueueSample.m_nVolume != 0) { + pedComment.m_nEntityIndex = m_sQueueSample.m_nEntityIndex; + pedComment.m_vecPos = m_sQueueSample.m_vecPos; + pedComment.m_fDistance = m_sQueueSample.m_fDistance; + pedComment.m_bVolume = m_sQueueSample.m_nVolume; + m_sPedComments.Add(&pedComment); + } + } + } +} + +int32 +cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) +{ + if (ped->IsPlayer()) + return GetPlayerTalkSfx(sound); + + switch (ped->GetModelIndex()) { + case MI_COP: + return GetCopTalkSfx(sound); + case MI_SWAT: + return GetSwatTalkSfx(sound); + case MI_FBI: + return GetFBITalkSfx(sound); + case MI_ARMY: + return GetArmyTalkSfx(sound); + case MI_MEDIC: + return GetMedicTalkSfx(sound); + case MI_FIREMAN: + return GetFiremanTalkSfx(sound); + case MI_MALE01: + return GetNormalMaleTalkSfx(sound); + case MI_TAXI_D: + return GetTaxiDriverTalkSfx(sound); + case MI_PIMP: + return GetPimpTalkSfx(sound); + case MI_GANG01: + case MI_GANG02: + return GetMafiaTalkSfx(sound); + case MI_GANG03: + case MI_GANG04: + return GetTriadTalkSfx(sound); + case MI_GANG05: + case MI_GANG06: + return GetDiabloTalkSfx(sound); + case MI_GANG07: + case MI_GANG08: + return GetYakuzaTalkSfx(sound); + case MI_GANG09: + case MI_GANG10: + return GetYardieTalkSfx(sound); + case MI_GANG11: + case MI_GANG12: + return GetColumbianTalkSfx(sound); + case MI_GANG13: + case MI_GANG14: + return GetHoodTalkSfx(sound); + case MI_CRIMINAL01: + return GetBlackCriminalTalkSfx(sound); + case MI_CRIMINAL02: + return GetWhiteCriminalTalkSfx(sound); + case MI_SPECIAL01: + case MI_SPECIAL02: + case MI_SPECIAL03: + case MI_SPECIAL04: + return GetSpecialCharacterTalkSfx(ped->GetModelIndex(), sound); + case MI_MALE02: + return GetMaleNo2TalkSfx(sound); + case MI_MALE03: + case MI_P_MAN1: + case MI_P_MAN2: + return GetBlackProjectMaleTalkSfx(sound, ped->GetModelIndex()); + case MI_FATMALE01: + return GetWhiteFatMaleTalkSfx(sound); + case MI_FATMALE02: + return GetBlackFatMaleTalkSfx(sound); + case MI_FEMALE01: + return GetBlackCasualFemaleTalkSfx(sound); + case MI_FEMALE02: + case MI_CAS_WOM: + return GetWhiteCasualFemaleTalkSfx(sound); + case MI_FEMALE03: + return GetFemaleNo3TalkSfx(sound); + case MI_FATFEMALE01: + return GetBlackFatFemaleTalkSfx(sound); + case MI_FATFEMALE02: + return GetWhiteFatFemaleTalkSfx(sound); + case MI_PROSTITUTE: + return GetBlackFemaleProstituteTalkSfx(sound); + case MI_PROSTITUTE2: + return GetWhiteFemaleProstituteTalkSfx(sound); + case MI_P_WOM1: + return GetBlackProjectFemaleOldTalkSfx(sound); + case MI_P_WOM2: + return GetBlackProjectFemaleYoungTalkSfx(sound); + case MI_CT_MAN1: + return GetChinatownMaleOldTalkSfx(sound); + case MI_CT_MAN2: + return GetChinatownMaleYoungTalkSfx(sound); + case MI_CT_WOM1: + return GetChinatownFemaleOldTalkSfx(sound); + case MI_CT_WOM2: + return GetChinatownFemaleYoungTalkSfx(sound); + case MI_LI_MAN1: + case MI_LI_MAN2: + return GetLittleItalyMaleTalkSfx(sound); + case MI_LI_WOM1: + return GetLittleItalyFemaleOldTalkSfx(sound); + case MI_LI_WOM2: + return GetLittleItalyFemaleYoungTalkSfx(sound); + case MI_DOCKER1: + return GetWhiteDockerMaleTalkSfx(sound); + case MI_DOCKER2: + return GetBlackDockerMaleTalkSfx(sound); + case MI_SCUM_MAN: + return GetScumMaleTalkSfx(sound); + case MI_SCUM_WOM: + return GetScumFemaleTalkSfx(sound); + case MI_WORKER1: + return GetWhiteWorkerMaleTalkSfx(sound); + case MI_WORKER2: + return GetBlackWorkerMaleTalkSfx(sound); + case MI_B_MAN1: + case MI_B_MAN3: + return GetBusinessMaleYoungTalkSfx(sound, ped->GetModelIndex()); + case MI_B_MAN2: + return GetBusinessMaleOldTalkSfx(sound); + case MI_B_WOM1: + case MI_B_WOM2: + return GetWhiteBusinessFemaleTalkSfx(sound, ped->GetModelIndex()); + case MI_B_WOM3: + return GetBlackBusinessFemaleTalkSfx(sound); + case MI_MOD_MAN: + return GetSupermodelMaleTalkSfx(sound); + case MI_MOD_WOM: + return GetSupermodelFemaleTalkSfx(sound); + case MI_ST_MAN: + return GetStewardMaleTalkSfx(sound); + case MI_ST_WOM: + return GetStewardFemaleTalkSfx(sound); + case MI_FAN_MAN1: + case MI_FAN_MAN2: + return GetFanMaleTalkSfx(sound, ped->GetModelIndex()); + case MI_FAN_WOM: + return GetFanFemaleTalkSfx(sound); + case MI_HOS_MAN: + return GetHospitalMaleTalkSfx(sound); + case MI_HOS_WOM: + return GetHospitalFemaleTalkSfx(sound); + case MI_CONST1: + return GetWhiteConstructionWorkerTalkSfx(sound); + case MI_CONST2: + return GetBlackConstructionWorkerTalkSfx(sound); + case MI_SHOPPER1: + case MI_SHOPPER2: + case MI_SHOPPER3: + return GetShopperFemaleTalkSfx(sound, ped->GetModelIndex()); + case MI_STUD_MAN: + return GetStudentMaleTalkSfx(sound); + case MI_STUD_WOM: + return GetStudentFemaleTalkSfx(sound); + case MI_CAS_MAN: + return GetCasualMaleOldTalkSfx(sound); + default: + return GetGenericMaleTalkSfx(sound); + } +} + +void +cAudioManager::GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const +{ + *phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset; + + // check if the same sfx like last time, if yes, then try use next one, + // if exceeded range, then choose first available sample + if (*phrase == *prevPhrase && ++*phrase >= sample + maxOffset) + *phrase = sample; + *prevPhrase = *phrase; +} + +#pragma region PED_COMMENTS + +uint32 +cAudioManager::GetPlayerTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_DAMAGE: + GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11); + break; + case SOUND_PED_HIT: + GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_LOW_DAMAGE_GRUNT_1, 10); + break; + case SOUND_PED_LAND: + GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6); + break; + default: + sfx = NO_SAMPLE; + break; + } + return sfx; +} + +uint32 +cAudioManager::GetCopTalkSfx(int16 sound) +{ + uint32 sfx; + PedState pedState; + static uint32 lastSfx = NO_SAMPLE; + + if (sound == SOUND_PED_ARREST_COP) { + GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6); + } else { + if (sound != SOUND_PED_PURSUIT_COP) { + return GetGenericMaleTalkSfx(sound); + } + + pedState = FindPlayerPed()->m_nPedState; + if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) + return NO_SAMPLE; + GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_CHASE_1, 7); + } + + return (SFX_COP_VOICE_2_ARREST_1 - SFX_COP_VOICE_1_ARREST_1) * (m_sQueueSample.m_nEntityIndex % 5) + sfx; +} + +uint32 +cAudioManager::GetSwatTalkSfx(int16 sound) +{ + uint32 sfx; + PedState pedState; + static uint32 lastSfx = NO_SAMPLE; + + if (sound == SOUND_PED_ARREST_SWAT) { + GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); + } else { + if (sound != SOUND_PED_PURSUIT_SWAT) { + return GetGenericMaleTalkSfx(sound); + } + + pedState = FindPlayerPed()->m_nPedState; + if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) + return NO_SAMPLE; + GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); + } + + return (SFX_SWAT_VOICE_2_CHASE_1 - SFX_SWAT_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 4) + sfx; +} + +uint32 +cAudioManager::GetFBITalkSfx(int16 sound) +{ + uint32 sfx; + PedState pedState; + static uint32 lastSfx = NO_SAMPLE; + + if (sound == SOUND_PED_ARREST_FBI) { + GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); + } else { + if (sound != SOUND_PED_PURSUIT_FBI) { + return GetGenericMaleTalkSfx(sound); + } + + pedState = FindPlayerPed()->m_nPedState; + if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) + return NO_SAMPLE; + GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); + } + + return (SFX_FBI_VOICE_2_CHASE_1 - SFX_FBI_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; +} + +uint32 +cAudioManager::GetArmyTalkSfx(int16 sound) +{ + uint32 sfx; + PedState pedState; + static uint32 lastSfx = NO_SAMPLE; + + if (sound != SOUND_PED_PURSUIT_ARMY) { + return GetGenericMaleTalkSfx(sound); + } + + pedState = FindPlayerPed()->m_nPedState; + if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) + return NO_SAMPLE; + GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); + + return (SFX_ARMY_VOICE_2_CHASE_1 - SFX_ARMY_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetMedicTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_CARJACKED_1, 5); + break; + case SOUND_PED_HEALING: + GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_AT_VICTIM_1, 12); + break; + case SOUND_PED_LEAVE_VEHICLE: + GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1, 9); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_MEDIC_VOICE_2_GUN_PANIC_1 - SFX_MEDIC_VOICE_1_GUN_PANIC_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetFiremanTalkSfx(int16 sound) +{ + return GetGenericMaleTalkSfx(sound); +} + +uint32 +cAudioManager::GetNormalMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_EYING_1, 8); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetTaxiDriverTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + if (sound == SOUND_PED_CAR_JACKED) { + GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); + } else { + if (sound != SOUND_PED_CAR_COLLISION) + return GetGenericMaleTalkSfx(sound); + GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); + } + return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetPimpTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_GUN_COOL_1, 7); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_CARJACKED_1, 4); + break; + case SOUND_PED_DEFEND: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_FIGHT_1, 9); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_PIMP_CHAT_1, 17); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetMafiaTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_MAFIA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; +} + +uint32 +cAudioManager::GetTriadTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3); + break; + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetDiabloTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4); + break; + case SOUND_PED_HANDS_COWER: + sound = SOUND_PED_FLEE_SPRINT; + return GetGenericMaleTalkSfx(sound); + break; + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_EYING_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_DIABLO_MALE_VOICE_2_CHAT_1 - SFX_DIABLO_MALE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetYakuzaTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_YAKUZA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetYardieTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + sfx = SFX_YARDIE_MALE_VOICE_1_GUN_COOL_1; + break; + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + sfx = SFX_YARDIE_MALE_VOICE_1_CARJACKED_1; + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_FIGHT_1, 6); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_EYING_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_YARDIE_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetColumbianTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_EYING_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_COLUMBIAN_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetHoodTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5); + break; + case SOUND_PED_CAR_JACKING: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKING_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_FIGHT_1, 6); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_EYING_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6); + break; + + default: + return GetGenericMaleTalkSfx(sound); + break; + } + return (SFX_HOOD_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetBlackCriminalTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4); + break; + case SOUND_PED_CAR_JACKING: + sfx = SFX_BLACK_CRIMINAL_VOICE_1_CARJACKING_1; + break; + case SOUND_PED_MUGGING: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_MUGGING_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + break; + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteCriminalTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3); + break; + case SOUND_PED_CAR_JACKING: + sfx = SFX_WHITE_CRIMINAL_VOICE_1_CARJACKING_1; + break; + case SOUND_PED_MUGGING: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_MUGGING_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4); + break; + default: + return GetGenericMaleTalkSfx(sound); + break; + } + return sfx; +} + +uint32 +cAudioManager::GetMaleNo2TalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_MUGGED_1, 4); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_EYING_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); + default: + return GetGenericMaleTalkSfx(sound); + } + + if (model == MI_P_MAN2) + sfx += (SFX_BLACK_PROJECT_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1); + return sfx; +} + +uint32 +cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); + break; + case SOUND_PED_WAIT_DOUBLEBACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackFatMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_WAIT_DOUBLEBACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + sfx = SFX_WHITE_CASUAL_FEMALE_VOICE_1_MUGGED_1; + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DODGE_1, 3); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetFemaleNo3TalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CARJACKED_1, 3); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_SHOCKED_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); + break; + case SOUND_PED_WAIT_DOUBLEBACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_LOST_1, 2); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4); + break; + case SOUND_PED_ROBBED: + sfx = SFX_BLACK_PROSTITUTE_VOICE_1_MUGGED_1; + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_SOLICIT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_SOLICIT_1, 8); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return (SFX_BLACK_PROSTITUTE_VOICE_2_CHAT_1 - SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_SOLICIT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_SOLICIT_1, 8); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return (SFX_WHITE_PROSTITUTE_VOICE_2_CHAT_1 - SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DODGE_1, 10); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_CAR_JACKED: + sfx = SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CARJACKED_1; + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_SHOCKED_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_FIGHT_1, 6); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + sfx = SFX_CHINATOWN_OLD_FEMALE_VOICE_1_SHOCKED_1; + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return (SFX_LITTLE_ITALY_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_FIGHT_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetScumMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5); + break; + case SOUND_PED_ROBBED: + sfx = SFX_SCUM_MALE_VOICE_1_MUGGED_1; + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_FIGHT_1, 10); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_WAIT_DOUBLEBACK: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_LOST_1, 3); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_EYING_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetScumFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_FIGHT_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_EYING_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_FIGHT_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + + if (model == MI_B_MAN3) + sfx += (SFX_BUSINESS_MALE_YOUNG_VOICE_2_DRIVER_ABUSE_1 - SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1); + return sfx; +} + +uint32 +cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + + if (model == MI_B_WOM2) + sfx += (SFX_WHITE_BUSINESS_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1); + return sfx; +} + +uint32 +cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CARAJACKED_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetSupermodelMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_MUGGED_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_SHOCKED_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetStewardMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetStewardFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return (SFX_STEWARD_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + + if (model == MI_FAN_MAN2) + sfx += (SFX_FOOTBALL_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1); + return sfx; +} + +uint32 +cAudioManager::GetFanFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_ROBBED: + sfx = SFX_FOOTBALL_FEMALE_VOICE_1_MUGGED_1; + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return (SFX_FOOTBALL_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; +} + +uint32 +cAudioManager::GetHospitalMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetHospitalFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_CAR_JACKED: + sfx = SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CARJACKED_1; + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_EYING_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3); + break; + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_FIGHT_1, 5); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5); + break; + case SOUND_PED_CHAT_SEXY: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_EYING_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_CAR_JACKED: + GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_SHOCKED_1, 4); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + + if (model == MI_SHOPPER2) { + sfx += (SFX_SHOPPER_VOICE_2_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1); + } else if (model == MI_SHOPPER3) { + sfx += (SFX_SHOPPER_VOICE_3_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1); + } + return sfx; +} + +uint32 +cAudioManager::GetStudentMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_SHOCKED_1, 3); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetStudentFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_COWER: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4); + break; + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4); + break; + case SOUND_PED_CHAT_EVENT: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_SHOCKED_1, 2); + break; + case SOUND_PED_CHAT: + GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4); + break; + default: + return GetGenericFemaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetCasualMaleOldTalkSfx(int16 sound) +{ + return GetGenericMaleTalkSfx(sound); +} + +uint32 +cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound) +{ + char *modelName = CModelInfo::GetModelInfo(modelIndex)->GetName(); + if (!CGeneral::faststricmp(modelName, "eight") || !CGeneral::faststricmp(modelName, "eight2")) { + return GetEightTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "frankie")) { + return GetFrankieTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "misty")) { + return GetMistyTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "ojg") || !CGeneral::faststricmp(modelName, "ojg_p")) { + return GetOJGTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "cat")) { + return GetCatatalinaTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "bomber")) { + return GetBomberTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "s_guard")) { + return GetSecurityGuardTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "chunky")) { + return GetChunkyTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "asuka")) { + return GetGenericFemaleTalkSfx(sound); + } + if (!CGeneral::faststricmp(modelName, "maria")) { + return GetGenericFemaleTalkSfx(sound); + } + + return GetGenericMaleTalkSfx(sound); +} +uint32 +cAudioManager::GetEightTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_8BALL_GUN_COOL_1, 2); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_8BALL_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_8BALL_FIGHT_1, 6); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_8BALL_DODGE_1, 7); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetFrankieTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_GUN_COOL_1, 4); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_FIGHT_1, 6); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_DODGE_1, 3); + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetMistyTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_MISTY_GUN_COOL_1, 5); + break; + case SOUND_PED_ROBBED: + GetPhrase(&sfx, &lastSfx, SFX_MISTY_MUGGED_1, 2); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_MISTY_FIGHT_1, 4); + break; + case SOUND_PED_EVADE: + GetPhrase(&sfx, &lastSfx, SFX_MISTY_DODGE_1, 5); + break; + case SOUND_PED_TAXI_CALL: + GetPhrase(&sfx, &lastSfx, SFX_MISTY_HERE_1, 4); + break; + default: + return GetGenericFemaleTalkSfx(sound); + break; + } + return sfx; +} + +uint32 +cAudioManager::GetOJGTalkSfx(int16 sound) +{ + return GetGenericMaleTalkSfx(sound); +} + +uint32 +cAudioManager::GetCatatalinaTalkSfx(int16 sound) +{ + return GetGenericFemaleTalkSfx(sound); +} + +uint32 +cAudioManager::GetBomberTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + if (sound != SOUND_PED_BOMBER) + return GetGenericMaleTalkSfx(sound); + + GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7); + return sfx; +} + +uint32 +cAudioManager::GetSecurityGuardTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_HANDS_UP: + GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2); + break; + case SOUND_PED_HANDS_COWER: + sfx = SFX_SECURITY_GUARD_VOICE_1_GUN_PANIC_1; + break; + case SOUND_PED_CAR_JACKED: + case SOUND_PED_CAR_COLLISION: + GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6); + break; + case SOUND_PED_ATTACK: + GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_FIGHT_1, 2); + break; + case SOUND_PED_FLEE_RUN: +#ifdef FIX_BUGS + sfx = SFX_SECURITY_GUARD_VOICE_1_RUN_FROM_FIGHT_1; +#else + GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12); +#endif + break; + default: + return GetGenericMaleTalkSfx(sound); + } + return sfx; +} + +uint32 +cAudioManager::GetChunkyTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + if (sound == SOUND_PED_DEATH) + return SFX_CHUNKY_DEATH; + + if (sound != SOUND_PED_FLEE_RUN) + return GetGenericMaleTalkSfx(sound); + + GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5); + return sfx; +} + +uint32 +cAudioManager::GetGenericMaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_DEATH: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_DEATH_1, 8); + break; + case SOUND_PED_BULLET_HIT: + case SOUND_PED_DEFEND: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15); + break; + case SOUND_PED_BURNING: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_FIRE_1, 8); + break; + case SOUND_PED_FLEE_SPRINT: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_PANIC_1, 6); + break; + default: + return NO_SAMPLE; + } + return sfx; +} + +uint32 +cAudioManager::GetGenericFemaleTalkSfx(int16 sound) +{ + uint32 sfx; + static uint32 lastSfx = NO_SAMPLE; + + switch (sound) { + case SOUND_PED_DEATH: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10); + break; + case SOUND_PED_BULLET_HIT: + case SOUND_PED_DEFEND: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11); + break; + case SOUND_PED_BURNING: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9); + break; + case SOUND_PED_FLEE_SPRINT: + GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8); + break; + default: + return NO_SAMPLE; + } + return sfx; +} + + + +void +cPedComments::Add(tPedComment *com) +{ + uint8 index; + + if (m_nCommentsInBank[m_nActiveBank] >= NUM_PED_COMMENTS_SLOTS) { + index = m_nIndexMap[m_nActiveBank][NUM_PED_COMMENTS_SLOTS - 1]; + if (m_asPedComments[m_nActiveBank][index].m_bVolume > com->m_bVolume) + return; + } else { + index = m_nCommentsInBank[m_nActiveBank]++; + } + + m_asPedComments[m_nActiveBank][index].m_nSampleIndex = com->m_nSampleIndex; + m_asPedComments[m_nActiveBank][index].m_nEntityIndex = com->m_nEntityIndex; + m_asPedComments[m_nActiveBank][index].m_vecPos = com->m_vecPos; + m_asPedComments[m_nActiveBank][index].m_fDistance = com->m_fDistance; + m_asPedComments[m_nActiveBank][index].m_bVolume = com->m_bVolume; + + uint32 i = 0; + if (index != 0) { + for (i = 0; i < index; i++) { + if (m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][i]].m_bVolume < m_asPedComments[m_nActiveBank][index].m_bVolume) { + break; + } + } + + if (i < index) + memmove(&m_nIndexMap[m_nActiveBank][i + 1], &m_nIndexMap[m_nActiveBank][i], NUM_PED_COMMENTS_SLOTS - 1 - i); + } + + m_nIndexMap[m_nActiveBank][i] = index; +} + +void +cPedComments::Process() +{ + int sampleIndex; + uint8 actualUsedBank; + tPedComment *comment; + + static const int defaultIntensity = 50; + static const int policeHeliIntensity = 400; + + if (!AudioManager.m_nUserPause) { + if (m_nCommentsInBank[m_nActiveBank]) { + sampleIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nSampleIndex; + if (!SampleManager.IsPedCommentLoaded(sampleIndex)) + SampleManager.LoadPedComment(sampleIndex); + + AudioManager.m_sQueueSample.m_nEntityIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nEntityIndex; + AudioManager.m_sQueueSample.m_nCounter = 0; + AudioManager.m_sQueueSample.m_nSampleIndex = sampleIndex; + AudioManager.m_sQueueSample.m_nBankIndex = SAMPLEBANK_PED; + AudioManager.m_sQueueSample.m_nReleasingVolumeModificator = 3; + AudioManager.m_sQueueSample.m_nVolume = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_bVolume; + AudioManager.m_sQueueSample.m_fDistance = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_fDistance; + AudioManager.m_sQueueSample.m_nLoopCount = 1; + AudioManager.m_sQueueSample.m_nLoopStart = 0; + AudioManager.m_sQueueSample.m_nLoopEnd = -1; + AudioManager.m_sQueueSample.m_nEmittingVolume = maxVolume; + AudioManager.m_sQueueSample.m_fSpeedMultiplier = 3.0f; + switch (sampleIndex) { + case SFX_POLICE_HELI_1: + case SFX_POLICE_HELI_2: + case SFX_POLICE_HELI_3: + AudioManager.m_sQueueSample.m_fSoundIntensity = policeHeliIntensity; + break; + default: + AudioManager.m_sQueueSample.m_fSoundIntensity = defaultIntensity; + break; + } + AudioManager.m_sQueueSample.m_bReleasingSoundFlag = true; + AudioManager.m_sQueueSample.m_vecPos = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_vecPos; + + if (sampleIndex >= SFX_AMMU_D && sampleIndex <= SFX_AMMU_F) { + AudioManager.m_sQueueSample.m_bReverbFlag = false; + AudioManager.m_sQueueSample.m_bRequireReflection = false; + } else { + AudioManager.m_sQueueSample.m_bReverbFlag = true; + AudioManager.m_sQueueSample.m_bRequireReflection = true; + } + + AudioManager.m_sQueueSample.m_bIs2D = false; + AudioManager.m_sQueueSample.m_nFrequency = + SampleManager.GetSampleBaseFrequency(AudioManager.m_sQueueSample.m_nSampleIndex) + AudioManager.RandomDisplacement(750); + if (CTimer::GetIsSlowMotionActive()) + AudioManager.m_sQueueSample.m_nFrequency /= 2; + m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nProcess = -1; + AudioManager.AddSampleToRequestedQueue(); + } + + // Switch bank + if (m_nActiveBank) { + actualUsedBank = SAMPLEBANK_PED; + m_nActiveBank = SAMPLEBANK_MAIN; + } else { + actualUsedBank = SAMPLEBANK_MAIN; + m_nActiveBank = SAMPLEBANK_PED; + } + comment = m_asPedComments[actualUsedBank]; + for (uint32 i = 0; i < m_nCommentsInBank[actualUsedBank]; i++) { + if (m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess > 0) { + --m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess; + Add(&comment[m_nIndexMap[actualUsedBank][i]]); + } + } + + for (uint32 i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) { + m_nIndexMap[actualUsedBank][i] = NUM_PED_COMMENTS_SLOTS; + } + m_nCommentsInBank[actualUsedBank] = 0; + } +} + +#pragma endregion + +#pragma endregion All the ped audio code + +void +cAudioManager::ProcessExplosions(int32 explosion) +{ + uint8 type; + CVector *pos; + float distSquared; + + for (uint8 i = 0; i < ARRAY_SIZE(gaExplosion); i++) { + if (CExplosion::GetExplosionActiveCounter(i) == 1) { + CExplosion::ResetExplosionActiveCounter(i); + type = CExplosion::GetExplosionType(i); + switch (type) { + case EXPLOSION_GRENADE: + case EXPLOSION_ROCKET: + case EXPLOSION_BARREL: + case EXPLOSION_TANK_GRENADE: + m_sQueueSample.m_fSoundIntensity = 400.0f; + m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_2; + m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 38000; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + break; + case EXPLOSION_MOLOTOV: + m_sQueueSample.m_fSoundIntensity = 200.0f; + m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_3; + m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 19000; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + break; + case EXPLOSION_MINE: + case EXPLOSION_HELI_BOMB: + m_sQueueSample.m_fSoundIntensity = 300.0f; + m_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT; + m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 12347; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + break; + default: + m_sQueueSample.m_fSoundIntensity = 400.0f; + m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_1; + m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 38000; + if (type == EXPLOSION_HELI) + m_sQueueSample.m_nFrequency = 8 * m_sQueueSample.m_nFrequency / 10; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + break; + } + pos = CExplosion::GetExplosionPosition(i); + m_sQueueSample.m_vecPos = *pos; + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = true; + AddSampleToRequestedQueue(); + } + } + } + } +} + +void +cAudioManager::ProcessFires(int32) +{ + CEntity *entity; + uint8 emittingVol; + float distSquared; + + for (uint8 i = 0; i < NUM_FIRES; i++) { + if (gFireManager.m_aFires[i].m_bIsOngoing && gFireManager.m_aFires[i].m_bAudioSet) { + entity = gFireManager.m_aFires[i].m_pEntity; + if (entity) { + switch (entity->GetType()) { + case ENTITY_TYPE_BUILDING: + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; + emittingVol = 100; + m_sQueueSample.m_nFrequency = 8 * SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE) / 10; + m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); + m_sQueueSample.m_nReleasingVolumeModificator = 6; + break; + case ENTITY_TYPE_PED: + m_sQueueSample.m_fSoundIntensity = 25.0f; + m_sQueueSample.m_nSampleIndex = SFX_PED_ON_FIRE; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PED_ON_FIRE); + emittingVol = 60; + m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); + m_sQueueSample.m_nReleasingVolumeModificator = 10; + break; + default: + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); + m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); + emittingVol = 80; + m_sQueueSample.m_nReleasingVolumeModificator = 8; + } + } else { + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); + m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); + emittingVol = 80; + m_sQueueSample.m_nReleasingVolumeModificator = 8; + } + m_sQueueSample.m_vecPos = gFireManager.m_aFires[i].m_vecPos; + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nReleasingVolumeDivider = 10; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } +} + +void +cAudioManager::ProcessWaterCannon(int32) +{ + const float SOUND_INTENSITY = 900.0f; + + for (int32 i = 0; i < NUM_WATERCANNONS; i++) { + if (CWaterCannons::aCannons[i].m_nId) { + m_sQueueSample.m_vecPos = CWaterCannons::aCannons[0].m_avecPos[CWaterCannons::aCannons[i].m_nCur]; + float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SOUND_INTENSITY) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(50, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = 15591; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nReleasingVolumeDivider = 8; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nEmittingVolume = 50; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } +} + +#pragma region SCRIPT_OBJECTS +const int scriptObjectIntensityS = 30; +const int scriptObjectIntensityL = 80; + +void +cAudioManager::ProcessScriptObject(int32 id) +{ + cAudioScriptObject *entity = (cAudioScriptObject *)m_asAudioEntities[id].m_pEntity; + if (entity) { + m_sQueueSample.m_vecPos = entity->Posn; + if (m_asAudioEntities[id].m_AudioEvents == 1) + ProcessOneShotScriptObject(m_asAudioEntities[id].m_awAudioEvent[0]); + else + ProcessLoopingScriptObject(entity->AudioId); + } +} + +void +cAudioManager::ProcessOneShotScriptObject(uint8 sound) +{ + CPlayerPed *playerPed; + uint8 emittingVolume; + float distSquared; + + cPedParams male; + cPedParams female; + + static uint8 iSound = 0; + + switch (sound) { + case SCRIPT_SOUND_INJURED_PED_MALE_OUCH_S: + case SCRIPT_SOUND_INJURED_PED_MALE_OUCH_L: + male.m_pPed = nil; + male.m_bDistanceCalculated = false; + male.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); + SetupPedComments(&male, SOUND_INJURED_PED_MALE_OUCH); + return; + case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_S: + case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_L: + female.m_pPed = nil; + female.m_bDistanceCalculated = false; + female.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); + SetupPedComments(&female, SOUND_INJURED_PED_FEMALE); + return; + case SCRIPT_SOUND_GATE_START_CLUNK: + case SCRIPT_SOUND_GATE_STOP_CLUNK: + m_sQueueSample.m_fSoundIntensity = 40.0f; + m_sQueueSample.m_nSampleIndex = SFX_COL_GATE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + if (sound == SCRIPT_SOUND_GATE_START_CLUNK) + m_sQueueSample.m_nFrequency = 10600; + else + m_sQueueSample.m_nFrequency = 9000; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = true; + emittingVolume = RandomDisplacement(10) + 50; + break; + case SCRIPT_SOUND_BULLET_HIT_GROUND_1: + case SCRIPT_SOUND_BULLET_HIT_GROUND_2: + case SCRIPT_SOUND_BULLET_HIT_GROUND_3: + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_nSampleIndex = m_anRandomTable[iSound % 5] % 3 + SFX_BULLET_WALL_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); + m_sQueueSample.m_nReleasingVolumeModificator = 9; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + emittingVolume = m_anRandomTable[2] % 20 + 90; + break; + case SCRIPT_SOUND_110: + case SCRIPT_SOUND_111: + if (SampleManager.IsSampleBankLoaded(0) != 1) + return; + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_TRAIN_STATION_ANNOUNCE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_STATION_ANNOUNCE); + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_bIs2D = false; + break; + case SCRIPT_SOUND_PAYPHONE_RINGING: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_PHONE_RING; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 80; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PHONE_RING); + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = false; + break; + case SCRIPT_SOUND_GLASS_BREAK_L: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = SFX_GLASS_SMASH; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 70; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_SMASH); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + break; + case SCRIPT_SOUND_GLASS_BREAK_S: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = SFX_GLASS_SMASH; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 60; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_SMASH); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + break; + case SCRIPT_SOUND_GLASS_CRACK: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = SFX_GLASS_CRACK; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 70; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_CRACK); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = true; + break; + case SCRIPT_SOUND_GLASS_LIGHT_BREAK: + m_sQueueSample.m_fSoundIntensity = 55.0f; + m_sQueueSample.m_nSampleIndex = (m_anRandomTable[4] & 3) + SFX_GLASS_SHARD_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 19000; + m_sQueueSample.m_nReleasingVolumeModificator = 9; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + emittingVolume = RandomDisplacement(11) + 25; + break; + case SCRIPT_SOUND_BOX_DESTROYED_1: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = SFX_WOODEN_BOX_SMASH; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 18600; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = true; + emittingVolume = m_anRandomTable[2] % 20 + 80; + break; + case SCRIPT_SOUND_BOX_DESTROYED_2: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = SFX_CARDBOARD_BOX_SMASH; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 18600; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = true; + emittingVolume = m_anRandomTable[2] % 20 + 80; + break; + case SCRIPT_SOUND_METAL_COLLISION: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 5 + SFX_COL_CAR_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = true; + emittingVolume = m_anRandomTable[2] % 30 + 70; + break; + case SCRIPT_SOUND_TIRE_COLLISION: + m_sQueueSample.m_fSoundIntensity = 60.0f; + m_sQueueSample.m_nSampleIndex = SFX_TYRE_BUMP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bRequireReflection = true; + emittingVolume = m_anRandomTable[2] % 30 + 60; + break; + case SCRIPT_SOUND_GUNSHELL_DROP: + playerPed = FindPlayerPed(); + if (playerPed) { + switch (playerPed->m_nSurfaceTouched) { + case SURFACE_GRASS: + case SURFACE_DIRT: + case SURFACE_DIRTTRACK: + case SURFACE_SCAFFOLD: + case SURFACE_FLESH: + case SURFACE_SAND: + case SURFACE_TIRE: + case SURFACE_HEDGE: + m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2; + m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000; + m_sQueueSample.m_nReleasingVolumeModificator = 18; + m_sQueueSample.m_fSoundIntensity = 20.0f; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + emittingVolume = m_anRandomTable[2] % 20 + 30; + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = iSound++; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nEmittingVolume = emittingVolume; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + AddSampleToRequestedQueue(); + } + } + return; + case SURFACE_PUDDLE: + return; + default: + break; + } + } + m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_1; + m_sQueueSample.m_nFrequency = RandomDisplacement(750) + 18000; + m_sQueueSample.m_nReleasingVolumeModificator = 15; + m_sQueueSample.m_fSoundIntensity = 20.0f; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + emittingVolume = m_anRandomTable[2] % 20 + 30; + break; + case SCRIPT_SOUND_GUNSHELL_DROP_SOFT: + m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2; + m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000; + m_sQueueSample.m_nReleasingVolumeModificator = 18; + m_sQueueSample.m_fSoundIntensity = 20.0f; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_bIs2D = false; + emittingVolume = m_anRandomTable[2] % 20 + 30; + break; + default: + return; + } + + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = iSound++; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nEmittingVolume = emittingVolume; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessLoopingScriptObject(uint8 sound) +{ + uint8 emittingVolume; + float distSquared; + + switch (sound) { + case SCRIPT_SOUND_PARTY_1_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_1_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_2_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_2); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_2_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_2); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_3_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_3); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_3_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_3); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_4_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_4); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_4_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_4); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_5_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_5); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_5_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_5); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_6_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_6); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_6_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_6); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_7_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_7); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_7_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_7); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_8_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_8); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_8_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_8); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_9_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_9); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_9_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_9); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_10_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_10); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_10_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_10); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_11_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_11); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_11_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_11); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_12_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_12); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_12_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_12); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_13_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_RAGGA); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_13_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_RAGGA); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_STRIP_CLUB_LOOP_1_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_STRIP_CLUB_LOOP_1_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_STRIP_CLUB_LOOP_2_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_2); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_STRIP_CLUB_LOOP_2_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_2); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_WORK_SHOP_LOOP_S: + case SCRIPT_SOUND_WORK_SHOP_LOOP_L: + ProcessWorkShopScriptObject(sound); + return; + case SCRIPT_SOUND_SAWMILL_LOOP_S: + case SCRIPT_SOUND_SAWMILL_LOOP_L: + ProcessSawMillScriptObject(sound); + return; + case SCRIPT_SOUND_38: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_DOG_FOOD_FACTORY; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOG_FOOD_FACTORY); + m_sQueueSample.m_nReleasingVolumeModificator = 6; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_39: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_DOG_FOOD_FACTORY; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOG_FOOD_FACTORY); + m_sQueueSample.m_nReleasingVolumeModificator = 6; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_LAUNDERETTE_LOOP_S: + case SCRIPT_SOUND_LAUNDERETTE_LOOP_L: + ProcessLaunderetteScriptObject(sound); + return; + case SCRIPT_SOUND_CHINATOWN_RESTAURANT_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_CHINATOWN; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_CHINATOWN); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_CHINATOWN_RESTAURANT_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_CHINATOWN; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_CHINATOWN); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_CIPRIANI_RESAURANT_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_ITALY; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_ITALY); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_CIPRIANI_RESAURANT_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_ITALY; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_ITALY); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_46_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_47_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_MARCO_BISTRO_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_2); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_MARCO_BISTRO_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 110; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_2); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_AIRPORT_LOOP_S: + case SCRIPT_SOUND_AIRPORT_LOOP_L: + ProcessAirportScriptObject(sound); + return; + case SCRIPT_SOUND_SHOP_LOOP_S: + case SCRIPT_SOUND_SHOP_LOOP_L: + ProcessShopScriptObject(sound); + return; + case SCRIPT_SOUND_CINEMA_LOOP_S: + case SCRIPT_SOUND_CINEMA_LOOP_L: + ProcessCinemaScriptObject(sound); + return; + case SCRIPT_SOUND_DOCKS_LOOP_S: + case SCRIPT_SOUND_DOCKS_LOOP_L: + ProcessDocksScriptObject(sound); + return; + case SCRIPT_SOUND_HOME_LOOP_S: + case SCRIPT_SOUND_HOME_LOOP_L: + ProcessHomeScriptObject(sound); + return; + case SCRIPT_SOUND_FRANKIE_PIANO: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_PIANO_BAR_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PIANO_BAR_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PARTY_1_LOOP: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PORN_CINEMA_1_S: + case SCRIPT_SOUND_PORN_CINEMA_1_L: + case SCRIPT_SOUND_PORN_CINEMA_2_S: + case SCRIPT_SOUND_PORN_CINEMA_2_L: + case SCRIPT_SOUND_PORN_CINEMA_3_S: + case SCRIPT_SOUND_PORN_CINEMA_3_L: + case SCRIPT_SOUND_MISTY_SEX_S: + case SCRIPT_SOUND_MISTY_SEX_L: + ProcessPornCinema(sound); + return; + case SCRIPT_SOUND_BANK_ALARM_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_BANK_ALARM_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 90; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BANK_ALARM_1); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_BANK_ALARM_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_BANK_ALARM_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 90; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BANK_ALARM_1); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_POLICE_BALL_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BALL_1); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_POLICE_BALL_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BALL_1); + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_INDUSTRIAL); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_INDUSTRIAL); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S: + case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L: + ProcessPoliceCellBeatingScriptObject(sound); + return; + case SCRIPT_SOUND_RAVE_1_LOOP_S: + case SCRIPT_SOUND_RAVE_2_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_RAVE_1_LOOP_L: + case SCRIPT_SOUND_RAVE_2_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_RAVE_3_LOOP_S: + m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_SUBURBAN); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_RAVE_3_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = maxVolume; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_SUBURBAN); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + case SCRIPT_SOUND_PRETEND_FIRE_LOOP: + m_sQueueSample.m_fSoundIntensity = 50.0f; + m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + emittingVolume = 80; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); + m_sQueueSample.m_nReleasingVolumeModificator = 8; + m_sQueueSample.m_nReleasingVolumeDivider = 10; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + break; + default: + return; + } + + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_nEmittingVolume = emittingVolume; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessPornCinema(uint8 sound) +{ + + eSfxSample sample; + uint32 time; + int32 rand; + float distSquared; + + switch (sound) { + case SCRIPT_SOUND_PORN_CINEMA_1_S: + case SCRIPT_SOUND_MISTY_SEX_S: + m_sQueueSample.m_nSampleIndex = SFX_PORN_1_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + sample = SFX_PORN_1_GROAN_1; + m_sQueueSample.m_fSoundIntensity = 20.0f; + break; + case SCRIPT_SOUND_PORN_CINEMA_1_L: + case SCRIPT_SOUND_MISTY_SEX_L: + m_sQueueSample.m_nSampleIndex = SFX_PORN_1_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + sample = SFX_PORN_1_GROAN_1; + m_sQueueSample.m_fSoundIntensity = 80.0f; + break; + case SCRIPT_SOUND_PORN_CINEMA_2_S: + m_sQueueSample.m_nSampleIndex = SFX_PORN_2_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + sample = SFX_PORN_2_GROAN_1; + m_sQueueSample.m_fSoundIntensity = 20.0f; + break; + case SCRIPT_SOUND_PORN_CINEMA_2_L: + m_sQueueSample.m_nSampleIndex = SFX_PORN_2_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + sample = SFX_PORN_2_GROAN_1; + m_sQueueSample.m_fSoundIntensity = 80.0f; + break; + case SCRIPT_SOUND_PORN_CINEMA_3_S: + m_sQueueSample.m_nSampleIndex = SFX_PORN_3_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_fSoundIntensity = 20.0f; + sample = SFX_PORN_3_GROAN_1; + break; + case SCRIPT_SOUND_PORN_CINEMA_3_L: + m_sQueueSample.m_nSampleIndex = SFX_PORN_3_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_fSoundIntensity = 80.0f; + sample = SFX_PORN_3_GROAN_1; + break; + default: + return; + } + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + if (sound != SCRIPT_SOUND_MISTY_SEX_S && sound != SCRIPT_SOUND_MISTY_SEX_L) { + m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + + time = CTimer::GetTimeInMilliseconds(); + if (time > gPornNextTime) { + m_sQueueSample.m_nVolume = ComputeVolume(90, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + rand = m_anRandomTable[1] & 1; + m_sQueueSample.m_nSampleIndex = rand + sample; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nCounter = rand + 1; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 6; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + gPornNextTime = time + 2000 + m_anRandomTable[3] % 6000; + } + } + } +} + +void +cAudioManager::ProcessWorkShopScriptObject(uint8 sound) +{ + float distSquared; + + switch (sound) { + case SCRIPT_SOUND_WORK_SHOP_LOOP_S: + case SCRIPT_SOUND_WORK_SHOP_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 20.0f; + break; + default: + return; + } + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_WORKSHOP_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_WORKSHOP_1); + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 30; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessSawMillScriptObject(uint8 sound) +{ + + uint32 time; + float distSquared; + + switch (sound) { + case SCRIPT_SOUND_SAWMILL_LOOP_S: + case SCRIPT_SOUND_SAWMILL_LOOP_L: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + break; + default: + return; + } + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_SAWMILL_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SAWMILL_LOOP); + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 30; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + time = CTimer::GetTimeInMilliseconds(); + if (time > gSawMillNextTime) { + m_sQueueSample.m_nVolume = ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_SAWMILL_CUT_WOOD; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + gSawMillNextTime = time + 2000 + m_anRandomTable[3] % 4000; + } + } + } +} + +void +cAudioManager::ProcessLaunderetteScriptObject(uint8 sound) +{ + switch (sound) { + case SCRIPT_SOUND_LAUNDERETTE_LOOP_S: + case SCRIPT_SOUND_LAUNDERETTE_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 30.0f; + break; + default: + return; + } + float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(45, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_LAUNDERETTE_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_LAUNDERETTE_LOOP); + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 45; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + m_sQueueSample.m_nVolume = ComputeVolume(110, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_LAUNDERETTE_SONG_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_LAUNDERETTE_SONG_LOOP); + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 110; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessShopScriptObject(uint8 sound) +{ + uint32 time; + int32 rand; + float distSquared; + + switch (sound) { + case SCRIPT_SOUND_SHOP_LOOP_S: + case SCRIPT_SOUND_SHOP_LOOP_L: + m_sQueueSample.m_fSoundIntensity = 30.0f; + break; + default: + return; + } + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_SHOP_LOOP; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOP_LOOP); + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeModificator = 5; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 30; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + time = CTimer::GetTimeInMilliseconds(); + if (time > gShopNextTime) { + m_sQueueSample.m_nVolume = ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + rand = m_anRandomTable[1] & 1; + m_sQueueSample.m_nSampleIndex = rand + SFX_SHOP_TILL_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nCounter = rand + 1; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 70; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + gShopNextTime = time + 3000 + m_anRandomTable[3] % 7000; + } + } + } +} + +void +cAudioManager::ProcessAirportScriptObject(uint8 sound) +{ + static uint8 counter = 0; + + uint32 time = CTimer::GetTimeInMilliseconds(); + if (time > gAirportNextTime) { + switch (sound) { + case SCRIPT_SOUND_AIRPORT_LOOP_S: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + break; + case SCRIPT_SOUND_AIRPORT_LOOP_L: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + break; + default: + return; + } + float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(110, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_AIRPORT_ANNOUNCEMENT_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = 110; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + gAirportNextTime = time + 10000 + m_anRandomTable[3] % 20000; + } + } + } +} + +void +cAudioManager::ProcessCinemaScriptObject(uint8 sound) +{ + uint8 rand; + + static uint8 counter = 0; + + uint32 time = CTimer::GetTimeInMilliseconds(); + if (time > gCinemaNextTime) { + switch (sound) { + case SCRIPT_SOUND_CINEMA_LOOP_S: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + break; + case SCRIPT_SOUND_CINEMA_LOOP_L: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + break; + default: + return; + } + float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + rand = m_anRandomTable[0] % 90 + 30; + m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = counter % 3 + SFX_CINEMA_BASS_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 4); + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = rand; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + gCinemaNextTime = time + 1000 + m_anRandomTable[3] % 4000; + } + } + } +} + +void +cAudioManager::ProcessDocksScriptObject(uint8 sound) +{ + uint32 time; + uint8 rand; + float distSquared; + + static uint32 counter = 0; + + time = CTimer::GetTimeInMilliseconds(); + if (time > gDocksNextTime) { + switch (sound) { + case SCRIPT_SOUND_DOCKS_LOOP_S: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + break; + case SCRIPT_SOUND_DOCKS_LOOP_L: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + break; + default: + return; + } + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + rand = m_anRandomTable[0] % 60 + 40; + m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = SFX_DOCKS_FOGHORN; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOCKS_FOGHORN); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_nEmittingVolume = rand; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + gDocksNextTime = time + 10000 + m_anRandomTable[3] % 40000; + } + } + } +} +void +cAudioManager::ProcessHomeScriptObject(uint8 sound) +{ + uint32 time; + uint8 rand; + float dist; + + static uint8 counter = 0; + + time = CTimer::GetTimeInMilliseconds(); + if (time > gHomeNextTime) { + switch (sound) { + case SCRIPT_SOUND_HOME_LOOP_S: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + break; + case SCRIPT_SOUND_HOME_LOOP_L: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + break; + default: + return; + } + dist = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (dist < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(dist); + rand = m_anRandomTable[0] % 30 + 40; + m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 5 + SFX_HOME_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_nEmittingVolume = rand; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = true; + AddSampleToRequestedQueue(); + gHomeNextTime = time + 1000 + m_anRandomTable[3] % 4000; + } + } + } +} +void +cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) +{ + uint32 time = CTimer::GetTimeInMilliseconds(); + int32 sampleIndex; + uint8 emittingVol; + float distSquared; + cPedParams params; + + static uint8 counter = 0; + + if (time > gCellNextTime) { + switch (sound) { + case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + break; + case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L: + m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + break; + default: + return; + } + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + if (m_FrameCounter & 1) + sampleIndex = (m_anRandomTable[1] & 3) + SFX_FIGHT_1; + else + sampleIndex = (m_anRandomTable[3] & 1) + SFX_BAT_HIT_LEFT; + m_sQueueSample.m_nSampleIndex = sampleIndex; + emittingVol = m_anRandomTable[0] % 50 + 55; + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + params.m_bDistanceCalculated = true; + params.m_fDistance = distSquared; + params.m_pPed = nil; + SetupPedComments(¶ms, SOUND_INJURED_PED_MALE_PRISON); + } + gCellNextTime = time + 500 + m_anRandomTable[3] % 1500; + } + } +} +#pragma endregion All the code for script object audio on the map + +void +cAudioManager::ProcessWeather(int32 id) +{ + uint8 vol; + static uint8 counter = 0; + + if (m_asAudioEntities[id].m_AudioEvents && m_asAudioEntities[id].m_awAudioEvent[0] == SOUND_LIGHTNING) { + if (m_asAudioEntities[id].m_afVolume[0] >= 10.f) { + m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_1; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 4000; + vol = (m_asAudioEntities[id].m_afVolume[0] - 10.f) + 40; + } else { + m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 4000; + vol = (m_asAudioEntities[id].m_afVolume[0]) + 35; + } + m_sQueueSample.m_nVolume = vol; + if (TheCamera.SoundDistUp < 20.f) + m_sQueueSample.m_nVolume /= 2; + if (counter == 4) + counter = 0; + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nOffset = (m_anRandomTable[2] & 15) + 55; + m_sQueueSample.m_bIs2D = true; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_bReverbFlag = false; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + if (CWeather::Rain > 0.0f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) { + m_sQueueSample.m_nSampleIndex = SFX_RAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAIN); + m_sQueueSample.m_nVolume = (int32)(25.f * CWeather::Rain); + m_sQueueSample.m_nCounter = 4; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_nOffset = 63; + m_sQueueSample.m_bIs2D = true; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 30; + m_sQueueSample.m_bReverbFlag = false; + m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } +} + +void +cAudioManager::ProcessFrontEnd() +{ + bool stereo; + bool processedPickup; + bool processedMission; + int16 sample; + + static uint8 counter = 0; + static uint32 cPickupNextFrame = 0; + static uint32 cPartMisComNextFrame = 0; + + for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { + processedPickup = false; + stereo = false; + processedMission = false; + switch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]) { + case SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM: + m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_RIFLE; + break; + case SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM: + m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_ROCKET_LAUNCHER; + break; + case SOUND_GARAGE_NO_MONEY: + case SOUND_GARAGE_BAD_VEHICLE: + case SOUND_GARAGE_BOMB_ALREADY_SET: + m_sQueueSample.m_nSampleIndex = SFX_PICKUP_ERROR_LEFT; + stereo = true; + break; + case SOUND_GARAGE_OPENING: + case SOUND_GARAGE_BOMB1_SET: + case SOUND_GARAGE_BOMB2_SET: + case SOUND_GARAGE_BOMB3_SET: + case SOUND_41: + case SOUND_GARAGE_VEHICLE_DECLINED: + case SOUND_GARAGE_VEHICLE_ACCEPTED: + case SOUND_PICKUP_HEALTH: + case SOUND_4B: + case SOUND_PICKUP_ADRENALINE: + case SOUND_PICKUP_ARMOUR: + case SOUND_EVIDENCE_PICKUP: + case SOUND_UNLOAD_GOLD: + m_sQueueSample.m_nSampleIndex = SFX_PICKUP_2_LEFT; + processedPickup = true; + stereo = true; + break; + case SOUND_PICKUP_WEAPON_BOUGHT: + case SOUND_PICKUP_WEAPON: + m_sQueueSample.m_nSampleIndex = SFX_PICKUP_1_LEFT; + processedPickup = true; + stereo = true; + break; + case SOUND_4A: + m_sQueueSample.m_nSampleIndex = SFX_PICKUP_ERROR_LEFT; + processedPickup = true; + stereo = true; + break; + case SOUND_PICKUP_BONUS: + case SOUND_PICKUP_MONEY: + case SOUND_PICKUP_HIDDEN_PACKAGE: + case SOUND_PICKUP_PACMAN_PILL: + case SOUND_PICKUP_PACMAN_PACKAGE: + case SOUND_PICKUP_FLOAT_PACKAGE: + m_sQueueSample.m_nSampleIndex = SFX_PICKUP_3_LEFT; + processedPickup = true; + stereo = true; + break; + case SOUND_PAGER: + m_sQueueSample.m_nSampleIndex = SFX_PAGER; + break; + case SOUND_RACE_START_3: + case SOUND_RACE_START_2: + case SOUND_RACE_START_1: + case SOUND_CLOCK_TICK: + m_sQueueSample.m_nSampleIndex = SFX_TIMER_BEEP; + break; + case SOUND_RACE_START_GO: + m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE; + break; + case SOUND_PART_MISSION_COMPLETE: + m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE; + processedMission = true; + break; + case SOUND_FRONTEND_MENU_STARTING: + m_sQueueSample.m_nSampleIndex = SFX_START_BUTTON_LEFT; + stereo = true; + break; + case SOUND_FRONTEND_MENU_COMPLETED: + m_sQueueSample.m_nSampleIndex = SFX_PAGE_CHANGE_AND_BACK_LEFT; + stereo = true; + break; + case SOUND_FRONTEND_MENU_DENIED: + m_sQueueSample.m_nSampleIndex = SFX_HIGHLIGHT_LEFT; + stereo = true; + break; + case SOUND_FRONTEND_MENU_SUCCESS: + m_sQueueSample.m_nSampleIndex = SFX_SELECT_LEFT; + stereo = true; + break; + case SOUND_FRONTEND_EXIT: + m_sQueueSample.m_nSampleIndex = SFX_SUB_MENU_BACK_LEFT; + stereo = true; + break; + case SOUND_9A: + m_sQueueSample.m_nSampleIndex = SFX_STEREO_LEFT; + stereo = true; + break; + case SOUND_9B: + m_sQueueSample.m_nSampleIndex = SFX_MONO; + break; + case SOUND_FRONTEND_AUDIO_TEST: + m_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 3 + SFX_NOISE_BURST_1; + break; + case SOUND_FRONTEND_FAIL: + m_sQueueSample.m_nSampleIndex = SFX_ERROR_LEFT; + stereo = true; + break; + case SOUND_FRONTEND_NO_RADIO: + case SOUND_FRONTEND_RADIO_CHANGE: + m_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK; + break; + case SOUND_A0: + m_sQueueSample.m_nSampleIndex = SFX_INFO; + break; + default: + continue; + } + + if (processedPickup) { + if (m_FrameCounter <= cPickupNextFrame) + continue; + cPickupNextFrame = m_FrameCounter + 5; + } else if (processedMission) { + if (m_FrameCounter <= cPartMisComNextFrame) + continue; + cPartMisComNextFrame = m_FrameCounter + 5; + } + + sample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; + if (sample == SFX_RAIN) { + m_sQueueSample.m_nFrequency = 28509; + } else if (sample == SFX_PICKUP_1_LEFT) { + if (1.f == m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]) + m_sQueueSample.m_nFrequency = 32000; + else + m_sQueueSample.m_nFrequency = 48000; + } else { + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + } + m_sQueueSample.m_nVolume = 110; + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nReleasingVolumeModificator = 0; + m_sQueueSample.m_bIs2D = true; + m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + if (stereo) + m_sQueueSample.m_nOffset = m_anRandomTable[0] & 31; + else + m_sQueueSample.m_nOffset = 63; + m_sQueueSample.m_bReverbFlag = false; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + if (stereo) { + ++m_sQueueSample.m_nSampleIndex; + m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nOffset = maxVolume - m_sQueueSample.m_nOffset; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessCrane() +{ + CCrane *crane = (CCrane *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity; + float distSquared; + bool distCalculated = false; + static const int intensity = 80; + + if (crane) { + if (crane->m_nCraneStatus == CCrane::ACTIVATED) { + if (crane->m_nCraneState != CCrane::IDLE) { + m_sQueueSample.m_vecPos = crane->m_pCraneEntity->GetPosition(); + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(intensity)) { + CalculateDistance(distCalculated, distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(100, 80.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_nSampleIndex = SFX_CRANE_MAGNET; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 2; + m_sQueueSample.m_nFrequency = 6000; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 100; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_fSoundIntensity = intensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents) { + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_2; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COL_CAR_2); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = true; + AddSampleToRequestedQueue(); + } + } + } + } + } +} + +void +cAudioManager::ProcessProjectiles() +{ + const int rocketLauncherIntensity = 90; + const int molotovIntensity = 30; + const int molotovVolume = 50; + uint8 emittingVol; + + for (int32 i = 0; i < NUM_PROJECTILES; i++) { + if (CProjectileInfo::GetProjectileInfo(i)->m_bInUse) { + switch (CProjectileInfo::GetProjectileInfo(i)->m_eWeaponType) { + case WEAPONTYPE_ROCKETLAUNCHER: + emittingVol = maxVolume; + m_sQueueSample.m_fSoundIntensity = rocketLauncherIntensity; + m_sQueueSample.m_nSampleIndex = SFX_ROCKET_FLY; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_FLY); + m_sQueueSample.m_nReleasingVolumeModificator = 3; + break; + case WEAPONTYPE_MOLOTOV: + emittingVol = molotovVolume; + m_sQueueSample.m_fSoundIntensity = molotovIntensity; + m_sQueueSample.m_nSampleIndex = SFX_PED_ON_FIRE; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nFrequency = 32 * SampleManager.GetSampleBaseFrequency(SFX_PED_ON_FIRE) / 25; + m_sQueueSample.m_nReleasingVolumeModificator = 7; + break; + default: + return; + } + m_sQueueSample.m_fSpeedMultiplier = 4.0f; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_vecPos = CProjectileInfo::ms_apProjectile[i]->GetPosition(); + float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { + m_sQueueSample.m_fDistance = Sqrt(distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = emittingVol; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + } + } +} + +void +cAudioManager::ProcessGarages() +{ + CEntity *entity; + eGarageState state; + uint32 sampleIndex; + uint8 j; + float distSquared; + bool distCalculated; + + static uint8 iSound = 32; + +#define LOOP_HELPER \ + for (j = 0; j < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; ++j) { \ + switch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j]) { \ + case SOUND_GARAGE_DOOR_CLOSED: \ + case SOUND_GARAGE_DOOR_OPENED: \ + if (distSquared < 6400.f) { \ + CalculateDistance(distCalculated, distSquared); \ + m_sQueueSample.m_nVolume = ComputeVolume(60, 80.f, m_sQueueSample.m_fDistance); \ + if (m_sQueueSample.m_nVolume) { \ + if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { \ + m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; \ + m_sQueueSample.m_nFrequency = 6735; \ + } else if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j] == 69) { \ + m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; \ + m_sQueueSample.m_nFrequency = 22000; \ + } else { \ + m_sQueueSample.m_nSampleIndex = SFX_COL_GARAGE_DOOR_1; \ + m_sQueueSample.m_nFrequency = 18000; \ + } \ + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; \ + m_sQueueSample.m_nReleasingVolumeModificator = 4; \ + m_sQueueSample.m_nEmittingVolume = 60; \ + m_sQueueSample.m_fSpeedMultiplier = 0.0f; \ + m_sQueueSample.m_fSoundIntensity = 80.0f; \ + /*m_sQueueSample.m_nReleasingVolumeModificator = 4;*/ \ + m_sQueueSample.m_bReverbFlag = true; \ + /*m_sQueueSample.m_bReverbFlag = true;*/ \ + m_sQueueSample.m_bIs2D = false; \ + m_sQueueSample.m_bReleasingSoundFlag = true; \ + m_sQueueSample.m_nLoopCount = 1; \ + m_sQueueSample.m_nLoopStart = 0; \ + m_sQueueSample.m_nLoopEnd = -1; \ + m_sQueueSample.m_nCounter = iSound++; \ + if (iSound < 32) \ + iSound = 32; \ + m_sQueueSample.m_bRequireReflection = true; \ + AddSampleToRequestedQueue(); \ + } \ + } \ + break; \ + default: \ + continue; \ + } \ + } + + for (uint32 i = 0; i < CGarages::NumGarages; ++i) { + if (CGarages::aGarages[i].m_eGarageType == GARAGE_NONE) + continue; + entity = CGarages::aGarages[i].m_pDoor1; + if (!entity) + continue; + m_sQueueSample.m_vecPos = entity->GetPosition(); + distCalculated = false; + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < 6400.f) { + state = CGarages::aGarages[i].m_eGarageState; + if (state == GS_OPENING || state == GS_CLOSING || state == GS_AFTERDROPOFF) { + CalculateDistance(distCalculated, distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(90, 80.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { + if (CGarages::aGarages[i].m_eGarageState == GS_AFTERDROPOFF) { + if (!(m_FrameCounter & 1)) { + LOOP_HELPER + continue; + } + if (m_anRandomTable[1] & 1) { + sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_CAR_1; + } else { + sampleIndex = m_anRandomTable[2] % 6 + SFX_COL_CAR_PANEL_1; + } + m_sQueueSample.m_nSampleIndex = sampleIndex; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2; + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nCounter = iSound++; + if (iSound < 32) + iSound = 32; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nEmittingVolume = 90; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + LOOP_HELPER + continue; + } + m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; + m_sQueueSample.m_nFrequency = 6543; + } else { + m_sQueueSample.m_nSampleIndex = SFX_GARAGE_DOOR_LOOP; + m_sQueueSample.m_nFrequency = 13961; + } + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 3; + m_sQueueSample.m_nEmittingVolume = 90; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } + LOOP_HELPER + } + } +#undef LOOP_HELPER +} + +void +cAudioManager::ProcessFireHydrant() +{ + float distSquared; + bool distCalculated = false; + static const int intensity = 35; + + m_sQueueSample.m_vecPos = ((CEntity *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)->GetPosition(); + distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (distSquared < SQR(intensity)) { + CalculateDistance(distCalculated, distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(40, 35.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 4; + m_sQueueSample.m_nFrequency = 15591; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 40; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = intensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} + +#pragma region BRIDGE +const int bridgeIntensity = 400; + +void +cAudioManager::ProcessBridge() +{ + float dist; + bool distCalculated = false; + + if (CBridge::pLiftRoad) { + m_sQueueSample.m_vecPos = CBridge::pLiftRoad->GetPosition(); + dist = GetDistanceSquared(m_sQueueSample.m_vecPos); + if (dist < 202500.0f) { + CalculateDistance(distCalculated, dist); + switch (CBridge::State) { + case STATE_BRIDGE_LOCKED: + case STATE_LIFT_PART_IS_UP: + case STATE_LIFT_PART_ABOUT_TO_MOVE_UP: + ProcessBridgeWarning(); + break; + case STATE_LIFT_PART_MOVING_DOWN: + case STATE_LIFT_PART_MOVING_UP: + ProcessBridgeWarning(); + ProcessBridgeMotor(); + break; + default: + break; + } + ProcessBridgeOneShots(); + } + } +} + +void +cAudioManager::ProcessBridgeWarning() +{ + if (CStats::CommercialPassed && m_sQueueSample.m_fDistance < 450.f) { + m_sQueueSample.m_nVolume = ComputeVolume(100, 450.f, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 0; + m_sQueueSample.m_nSampleIndex = SFX_BRIDGE_OPEN_WARNING; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BRIDGE_OPEN_WARNING); + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = 100; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = 450.0f; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 8; + m_sQueueSample.m_bReverbFlag = false; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessBridgeMotor() +{ + if (m_sQueueSample.m_fDistance < bridgeIntensity) { + m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, bridgeIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 1; + m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; // todo check sfx name + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = 5500; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = bridgeIntensity; + m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReverbFlag = false; + AddSampleToRequestedQueue(); + } + } +} + +void +cAudioManager::ProcessBridgeOneShots() +{ + if (CBridge::State == STATE_LIFT_PART_IS_UP && CBridge::OldState == STATE_LIFT_PART_MOVING_UP) { + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + } else { + if (CBridge::State == STATE_LIFT_PART_IS_DOWN && CBridge::OldState == STATE_LIFT_PART_MOVING_DOWN) { + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + } else { + if (CBridge::State == STATE_LIFT_PART_MOVING_UP && CBridge::OldState == STATE_LIFT_PART_ABOUT_TO_MOVE_UP) { + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + } else { + if (CBridge::State == STATE_LIFT_PART_MOVING_DOWN && CBridge::OldState == STATE_LIFT_PART_IS_UP) { + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + } else + return; + } + } + } + if (m_sQueueSample.m_fDistance < bridgeIntensity) { + m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, bridgeIntensity, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nCounter = 2; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_nReleasingVolumeModificator = 1; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_fSpeedMultiplier = 2.0f; + m_sQueueSample.m_fSoundIntensity = bridgeIntensity; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_bReverbFlag = false; + m_sQueueSample.m_bRequireReflection = false; + AddSampleToRequestedQueue(); + } + } +} +#pragma endregion + +#pragma region MISSION_AUDIO +bool g_bMissionAudioLoadFailed; + +struct MissionAudioData { + const char *m_pName; + int32 m_nId; +}; + +const MissionAudioData MissionAudioNameSfxAssoc[] = { + {"lib_a1", STREAMED_SOUND_MISSION_LIB_A1}, {"lib_a2", STREAMED_SOUND_MISSION_LIB_A2}, {"lib_a", STREAMED_SOUND_MISSION_LIB_A}, + {"lib_b", STREAMED_SOUND_MISSION_LIB_B}, {"lib_c", STREAMED_SOUND_MISSION_LIB_C}, {"lib_d", STREAMED_SOUND_MISSION_LIB_D}, + {"l2_a", STREAMED_SOUND_MISSION_L2_A}, {"j4t_1", STREAMED_SOUND_MISSION_J4T_1}, {"j4t_2", STREAMED_SOUND_MISSION_J4T_2}, + {"j4t_3", STREAMED_SOUND_MISSION_J4T_3}, {"j4t_4", STREAMED_SOUND_MISSION_J4T_4}, {"j4_a", STREAMED_SOUND_MISSION_J4_A}, + {"j4_b", STREAMED_SOUND_MISSION_J4_B}, {"j4_c", STREAMED_SOUND_MISSION_J4_C}, {"j4_d", STREAMED_SOUND_MISSION_J4_D}, + {"j4_e", STREAMED_SOUND_MISSION_J4_E}, {"j4_f", STREAMED_SOUND_MISSION_J4_F}, {"j6_1", STREAMED_SOUND_MISSION_J6_1}, + {"j6_a", STREAMED_SOUND_MISSION_J6_A}, {"j6_b", STREAMED_SOUND_MISSION_J6_B}, {"j6_c", STREAMED_SOUND_MISSION_J6_C}, + {"j6_d", STREAMED_SOUND_MISSION_J6_D}, {"t4_a", STREAMED_SOUND_MISSION_T4_A}, {"s1_a", STREAMED_SOUND_MISSION_S1_A}, + {"s1_a1", STREAMED_SOUND_MISSION_S1_A1}, {"s1_b", STREAMED_SOUND_MISSION_S1_B}, {"s1_c", STREAMED_SOUND_MISSION_S1_C}, + {"s1_c1", STREAMED_SOUND_MISSION_S1_C1}, {"s1_d", STREAMED_SOUND_MISSION_S1_D}, {"s1_e", STREAMED_SOUND_MISSION_S1_E}, + {"s1_f", STREAMED_SOUND_MISSION_S1_F}, {"s1_g", STREAMED_SOUND_MISSION_S1_G}, {"s1_h", STREAMED_SOUND_MISSION_S1_H}, + {"s1_i", STREAMED_SOUND_MISSION_S1_I}, {"s1_j", STREAMED_SOUND_MISSION_S1_J}, {"s1_k", STREAMED_SOUND_MISSION_S1_K}, + {"s1_l", STREAMED_SOUND_MISSION_S1_L}, {"s3_a", STREAMED_SOUND_MISSION_S3_A}, {"s3_b", STREAMED_SOUND_MISSION_S3_B}, + {"el3_a", STREAMED_SOUND_MISSION_EL3_A}, {"mf1_a", STREAMED_SOUND_MISSION_MF1_A}, {"mf2_a", STREAMED_SOUND_MISSION_MF2_A}, + {"mf3_a", STREAMED_SOUND_MISSION_MF3_A}, {"mf3_b", STREAMED_SOUND_MISSION_MF3_B}, {"mf3_b1", STREAMED_SOUND_MISSION_MF3_B1}, + {"mf3_c", STREAMED_SOUND_MISSION_MF3_C}, {"mf4_a", STREAMED_SOUND_MISSION_MF4_A}, {"mf4_b", STREAMED_SOUND_MISSION_MF4_B}, + {"mf4_c", STREAMED_SOUND_MISSION_MF4_C}, {"a1_a", STREAMED_SOUND_MISSION_A1_A}, {"a3_a", STREAMED_SOUND_MISSION_A3_A}, + {"a5_a", STREAMED_SOUND_MISSION_A5_A}, {"a4_a", STREAMED_SOUND_MISSION_A4_A}, {"a4_b", STREAMED_SOUND_MISSION_A4_B}, + {"a4_c", STREAMED_SOUND_MISSION_A4_C}, {"a4_d", STREAMED_SOUND_MISSION_A4_D}, {"k1_a", STREAMED_SOUND_MISSION_K1_A}, + {"k3_a", STREAMED_SOUND_MISSION_K3_A}, {"r1_a", STREAMED_SOUND_MISSION_R1_A}, {"r2_a", STREAMED_SOUND_MISSION_R2_A}, + {"r2_b", STREAMED_SOUND_MISSION_R2_B}, {"r2_c", STREAMED_SOUND_MISSION_R2_C}, {"r2_d", STREAMED_SOUND_MISSION_R2_D}, + {"r2_e", STREAMED_SOUND_MISSION_R2_E}, {"r2_f", STREAMED_SOUND_MISSION_R2_F}, {"r2_g", STREAMED_SOUND_MISSION_R2_G}, + {"r2_h", STREAMED_SOUND_MISSION_R2_H}, {"r5_a", STREAMED_SOUND_MISSION_R5_A}, {"r6_a", STREAMED_SOUND_MISSION_R6_A}, + {"r6_a1", STREAMED_SOUND_MISSION_R6_A1}, {"r6_b", STREAMED_SOUND_MISSION_R6_B}, {"lo2_a", STREAMED_SOUND_MISSION_LO2_A}, + {"lo6_a", STREAMED_SOUND_MISSION_LO6_A}, {"yd2_a", STREAMED_SOUND_MISSION_YD2_A}, {"yd2_b", STREAMED_SOUND_MISSION_YD2_B}, + {"yd2_c", STREAMED_SOUND_MISSION_YD2_C}, {"yd2_c1", STREAMED_SOUND_MISSION_YD2_C1}, {"yd2_d", STREAMED_SOUND_MISSION_YD2_D}, + {"yd2_e", STREAMED_SOUND_MISSION_YD2_E}, {"yd2_f", STREAMED_SOUND_MISSION_YD2_F}, {"yd2_g", STREAMED_SOUND_MISSION_YD2_G}, + {"yd2_h", STREAMED_SOUND_MISSION_YD2_H}, {"yd2_ass", STREAMED_SOUND_MISSION_YD2_ASS}, {"yd2_ok", STREAMED_SOUND_MISSION_YD2_OK}, + {"h5_a", STREAMED_SOUND_MISSION_H5_A}, {"h5_b", STREAMED_SOUND_MISSION_H5_B}, {"h5_c", STREAMED_SOUND_MISSION_H5_C}, + {"ammu_a", STREAMED_SOUND_MISSION_AMMU_A}, {"ammu_b", STREAMED_SOUND_MISSION_AMMU_B}, {"ammu_c", STREAMED_SOUND_MISSION_AMMU_C}, + {"door_1", STREAMED_SOUND_MISSION_DOOR_1}, {"door_2", STREAMED_SOUND_MISSION_DOOR_2}, {"door_3", STREAMED_SOUND_MISSION_DOOR_3}, + {"door_4", STREAMED_SOUND_MISSION_DOOR_4}, {"door_5", STREAMED_SOUND_MISSION_DOOR_5}, {"door_6", STREAMED_SOUND_MISSION_DOOR_6}, + {"t3_a", STREAMED_SOUND_MISSION_T3_A}, {"t3_b", STREAMED_SOUND_MISSION_T3_B}, {"t3_c", STREAMED_SOUND_MISSION_T3_C}, + {"k1_b", STREAMED_SOUND_MISSION_K1_B}, {"c_1", STREAMED_SOUND_MISSION_CAT1}}; + +int32 +FindMissionAudioSfx(const char *name) +{ + for (uint32 i = 0; i < ARRAY_SIZE(MissionAudioNameSfxAssoc); ++i) { + if (!CGeneral::faststricmp(MissionAudioNameSfxAssoc[i].m_pName, name)) + return MissionAudioNameSfxAssoc[i].m_nId; + } + debug("Can't find mission audio %s", name); + return NO_SAMPLE; +} + +bool +cAudioManager::MissionScriptAudioUsesPoliceChannel(int32 soundMission) const +{ + switch (soundMission) { + case STREAMED_SOUND_MISSION_J6_D: + case STREAMED_SOUND_MISSION_T4_A: + case STREAMED_SOUND_MISSION_S1_H: + case STREAMED_SOUND_MISSION_S3_B: + case STREAMED_SOUND_MISSION_EL3_A: + case STREAMED_SOUND_MISSION_A3_A: + case STREAMED_SOUND_MISSION_A5_A: + case STREAMED_SOUND_MISSION_K1_A: + case STREAMED_SOUND_MISSION_R1_A: + case STREAMED_SOUND_MISSION_R5_A: + case STREAMED_SOUND_MISSION_LO2_A: + case STREAMED_SOUND_MISSION_LO6_A: + return true; + default: + return false; + } +} + +void +cAudioManager::PreloadMissionAudio(const char *name) +{ + if (m_bIsInitialised) { + int32 missionAudioSfx = FindMissionAudioSfx(name); + if (missionAudioSfx != NO_SAMPLE) { + m_sMissionAudio.m_nSampleIndex = missionAudioSfx; + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; + m_sMissionAudio.field_22 = 0; + m_sMissionAudio.m_nMissionAudioCounter = m_nTimeSpent * SampleManager.GetStreamedFileLength(missionAudioSfx) / 1000; + m_sMissionAudio.m_nMissionAudioCounter *= 4; + m_sMissionAudio.m_bIsPlayed = false; + m_sMissionAudio.m_bPredefinedProperties = 1; + g_bMissionAudioLoadFailed = false; + } + } +} + +bool +cAudioManager::GetMissionAudioLoadingStatus() const +{ + if (m_bIsInitialised) + return m_sMissionAudio.m_nLoadingStatus; + + return true; +} + +void +cAudioManager::SetMissionAudioLocation(float x, float y, float z) +{ + if (m_bIsInitialised) { + m_sMissionAudio.m_bPredefinedProperties = false; + m_sMissionAudio.m_vecPos = CVector(x, y, z); + } +} + +void +cAudioManager::PlayLoadedMissionAudio() +{ + if (m_bIsInitialised && m_sMissionAudio.m_nSampleIndex != NO_SAMPLE && m_sMissionAudio.m_nLoadingStatus == LOADING_STATUS_LOADED && + !m_sMissionAudio.m_nPlayStatus) { + m_sMissionAudio.m_bIsPlayed = true; + } +} + +bool +cAudioManager::IsMissionAudioSampleFinished() +{ + if (m_bIsInitialised) + return m_sMissionAudio.m_nPlayStatus == PLAY_STATUS_FINISHED; + + static int32 cPretendFrame = 1; + + return (cPretendFrame++ & 63) == 0; +} + +void +cAudioManager::ClearMissionAudio() +{ + if (m_bIsInitialised) { + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; + m_sMissionAudio.field_22 = 0; + m_sMissionAudio.m_bIsPlayed = false; + m_sMissionAudio.m_bPredefinedProperties = 1; + m_sMissionAudio.m_nMissionAudioCounter = 0; + } +} + +void +cAudioManager::ProcessMissionAudio() +{ + float dist; + uint8 emittingVol; + uint8 pan; + float distSquared; + CVector vec; + + static uint8 nCheckPlayingDelay = 0; + static uint8 nFramesUntilFailedLoad = 0; + static uint8 nFramesForPretendPlaying = 0; + + if (m_bIsInitialised) { + if (m_sMissionAudio.m_nSampleIndex != NO_SAMPLE) { + switch (m_sMissionAudio.m_nLoadingStatus) { + case LOADING_STATUS_NOT_LOADED: + SampleManager.PreloadStreamedFile(m_sMissionAudio.m_nSampleIndex, 1); + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; + nFramesUntilFailedLoad = 0; + return; + case LOADING_STATUS_LOADED: + if (!m_sMissionAudio.m_bIsPlayed) + return; + if (g_bMissionAudioLoadFailed) { + if (m_bTimerJustReset) { + ClearMissionAudio(); + SampleManager.StopStreamedFile(1); + nFramesForPretendPlaying = 0; + nCheckPlayingDelay = 0; + nFramesUntilFailedLoad = 0; + } else if (!m_nUserPause) { + if (++nFramesForPretendPlaying < 120) { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; + } else { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + } + } + } else { + if (m_sMissionAudio.m_nPlayStatus) { + if (m_sMissionAudio.m_nPlayStatus != PLAY_STATUS_PLAYING) + return; + if (m_bTimerJustReset) { + ClearMissionAudio(); + SampleManager.StopStreamedFile(1); + return; + } + if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { + if (!m_nUserPause) { + if (nCheckPlayingDelay) { + --nCheckPlayingDelay; + } else if (GetMissionScriptPoliceAudioPlayingStatus() == PLAY_STATUS_FINISHED || + m_sMissionAudio.m_nMissionAudioCounter-- == 0) { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + SampleManager.StopStreamedFile(1); + m_sMissionAudio.m_nMissionAudioCounter = 0; + } + } + } else if (m_sMissionAudio.field_22) { + if (SampleManager.IsStreamPlaying(1) || m_nUserPause || m_nPreviousUserPause) { + if (m_nUserPause) + SampleManager.PauseStream(1, 1); + else + SampleManager.PauseStream(0, 1); + } else { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + SampleManager.StopStreamedFile(1); + m_sMissionAudio.m_nMissionAudioCounter = 0; + } + } else { + if (m_nUserPause) + return; + if (nCheckPlayingDelay--) { + if (!SampleManager.IsStreamPlaying(1)) + return; + nCheckPlayingDelay = 0; + } + m_sMissionAudio.field_22 = 1; + } + } else { + if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { + SetMissionScriptPoliceAudio(m_sMissionAudio.m_nSampleIndex); + } else { + if (m_nUserPause) + SampleManager.PauseStream(1, 1); + if (m_sMissionAudio.m_bPredefinedProperties) { + SampleManager.SetStreamedVolumeAndPan(80, 63, 1, 1); + } else { + distSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos); + if (distSquared >= 2500.f) { + emittingVol = 0; + pan = 63; + } else { + dist = Sqrt(distSquared); + emittingVol = ComputeVolume(80, 50.0f, dist); + TranslateEntity(&m_sMissionAudio.m_vecPos, &vec); + pan = ComputePan(50.f, &vec); + } + SampleManager.SetStreamedVolumeAndPan(emittingVol, pan, 1, 1); + } + SampleManager.StartPreloadedStreamedFile(1); + } + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; + nCheckPlayingDelay = 30; + } + } + break; + case 2: + if (++nFramesUntilFailedLoad >= 90) { + nFramesForPretendPlaying = 0; + g_bMissionAudioLoadFailed = true; + nFramesUntilFailedLoad = 0; + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; + } + return; + default: + return; + } + } + } +} +#pragma endregion All the mission audio stuff \ No newline at end of file diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index ec46aa53..eecc8e7d 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -3,301 +3,21 @@ #include "AudioManager.h" #include "audio_enums.h" -#include "Automobile.h" -#include "Boat.h" -#include "Bridge.h" -#include "Camera.h" -#include "Cranes.h" -#include "DMAudio.h" -#include "Entity.h" -#include "Explosion.h" -#include "Fire.h" -#include "Garages.h" -#include "General.h" -#include "HandlingMgr.h" -#include "Heli.h" -#include "ModelIndices.h" +#include "AudioScriptObject.h" #include "MusicManager.h" -#include "Pad.h" -#include "Ped.h" -#include "Physical.h" -#include "Placeable.h" -#include "Plane.h" -#include "PlayerPed.h" -#include "Pools.h" -#include "Projectile.h" -#include "ProjectileInfo.h" -#include "Replay.h" -#include "Stats.h" -#include "SurfaceTable.h" -#include "Train.h" -#include "Transmission.h" -#include "Vehicle.h" -#include "WaterCannon.h" -#include "Weather.h" -#include "ZoneCull.h" +#include "Timer.h" +#include "DMAudio.h" #include "sampman.h" +#include "Camera.h" +#include "World.h" cAudioManager AudioManager; -uint32 gPornNextTime; -uint32 gSawMillNextTime; -uint32 gShopNextTime; -uint32 gAirportNextTime; -uint32 gCinemaNextTime; -uint32 gDocksNextTime; -uint32 gHomeNextTime; -uint32 gCellNextTime; -uint32 gNextCryTime; -uint8 gJumboVolOffsetPercentage; -bool bPlayerJustEnteredCar; -bool g_bMissionAudioLoadFailed; const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); const int policeChannel = channels + 1; const int allChannels = channels + 2; const int maxVolume = 127; -const int scriptObjectIntensityS = 30; -const int scriptObjectIntensityL = 80; -const int bridgeIntensity = 400; -const int rocketLauncherIntensity = 90; -const int molotovIntensity = 30; -const int molotovVolume = 50; - -const int rainOnVehicleIntensity = 22; -const int reverseGearIntensity = 30; -const int engineDamageIntensity = 40; - -const bool hornPatternsArray[8][44] = { - {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, - false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false}, - {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false}, - {false, false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, false, - false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false}, - {false, false, true, true, true, true, true, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, - true, true, true, true, true, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, false}, - {false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, true, true, true, false, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, - {false, false, true, true, true, true, false, false, false, false, true, true, true, false, false, true, true, true, false, false, true, true, - true, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, false, false}, - {false, false, true, true, true, true, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, true, - false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false}, -}; - -const int totalAudioEntitiesSlots = 200; - -const uint8 panTable[64]{0, 3, 8, 12, 16, 19, 22, 24, 26, 28, 30, 31, 33, 34, 36, 37, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, 53, 53, - 54, 55, 55, 56, 56, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63}; - -// TODO: where is this used? Is this the right file? -enum eVehicleModel { - LANDSTAL, - IDAHO, - STINGER, - LINERUN, - PEREN, - SENTINEL, - PATRIOT, - FIRETRUK, - TRASH, - STRETCH, - MANANA, - INFERNUS, - BLISTA, - PONY, - MULE, - CHEETAH, - AMBULAN, - FBICAR, - MOONBEAM, - ESPERANT, - TAXI, - KURUMA, - BOBCAT, - MRWHOOP, - BFINJECT, - CORPSE, - POLICE, - ENFORCER, - SECURICA, - BANSHEE, - PREDATOR, - BUS, - RHINO, - BARRACKS, - TRAIN, - CHOPPER, - DODO, - COACH, - CABBIE, - STALLION, - RUMPO, - RCBANDIT, - BELLYUP, - MRWONGS, - MAFIA, - YARDIE, - YAKUZA, - DIABLOS, - COLUMB, - HOODS, - AIRTRAIN, - DEADDODO, - SPEEDER, - REEFER, - PANLANT, - FLATBED, - YANKEE, - ESCAPE, - BORGNINE, - TOYZ, - GHOST, - CAR151, - CAR152, - CAR153, - CAR154, - CAR155, - CAR156, - CAR157, - CAR158, - CAR159, -}; - -enum PLAY_STATUS : uint8 { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING = 1, PLAY_STATUS_FINISHED = 2 }; - -enum LOADING_STATUS : uint8 { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED = 1 }; - -cPedComments::cPedComments() -{ - for (int i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) - for (int j = 0; j < NUM_PED_COMMENTS_BANKS; j++) { - m_asPedComments[j][i].m_nProcess = -1; - m_nIndexMap[j][i] = NUM_PED_COMMENTS_SLOTS; - } - - for (int i = 0; i < NUM_PED_COMMENTS_BANKS; i++) - m_nCommentsInBank[i] = 0; - m_nActiveBank = 0; -} - -void -cPedComments::Add(tPedComment *com) -{ - uint8 index; - - if (m_nCommentsInBank[m_nActiveBank] >= NUM_PED_COMMENTS_SLOTS) { - index = m_nIndexMap[m_nActiveBank][NUM_PED_COMMENTS_SLOTS - 1]; - if (m_asPedComments[m_nActiveBank][index].m_bVolume > com->m_bVolume) - return; - } else { - index = m_nCommentsInBank[m_nActiveBank]++; - } - - m_asPedComments[m_nActiveBank][index].m_nSampleIndex = com->m_nSampleIndex; - m_asPedComments[m_nActiveBank][index].m_nEntityIndex = com->m_nEntityIndex; - m_asPedComments[m_nActiveBank][index].m_vecPos = com->m_vecPos; - m_asPedComments[m_nActiveBank][index].m_fDistance = com->m_fDistance; - m_asPedComments[m_nActiveBank][index].m_bVolume = com->m_bVolume; - - uint32 i = 0; - if (index != 0) { - for (i = 0; i < index; i++) { - if (m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][i]].m_bVolume < m_asPedComments[m_nActiveBank][index].m_bVolume) { - break; - } - } - - if (i < index) - memmove(&m_nIndexMap[m_nActiveBank][i + 1], &m_nIndexMap[m_nActiveBank][i], NUM_PED_COMMENTS_SLOTS - 1 - i); - } - - m_nIndexMap[m_nActiveBank][i] = index; -} - -void -cPedComments::Process() -{ - int sampleIndex; - uint8 actualUsedBank; - tPedComment *comment; - - static const int defaultIntensity = 50; - static const int policeHeliIntensity = 400; - - if (!AudioManager.m_nUserPause) { - if (m_nCommentsInBank[m_nActiveBank]) { - sampleIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nSampleIndex; - if (!SampleManager.IsPedCommentLoaded(sampleIndex)) - SampleManager.LoadPedComment(sampleIndex); - - AudioManager.m_sQueueSample.m_nEntityIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nEntityIndex; - AudioManager.m_sQueueSample.m_nCounter = 0; - AudioManager.m_sQueueSample.m_nSampleIndex = sampleIndex; - AudioManager.m_sQueueSample.m_nBankIndex = SAMPLEBANK_PED; - AudioManager.m_sQueueSample.m_nReleasingVolumeModificator = 3; - AudioManager.m_sQueueSample.m_nVolume = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_bVolume; - AudioManager.m_sQueueSample.m_fDistance = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_fDistance; - AudioManager.m_sQueueSample.m_nLoopCount = 1; - AudioManager.m_sQueueSample.m_nLoopStart = 0; - AudioManager.m_sQueueSample.m_nLoopEnd = -1; - AudioManager.m_sQueueSample.m_nEmittingVolume = maxVolume; - AudioManager.m_sQueueSample.m_fSpeedMultiplier = 3.0f; - switch (sampleIndex) { - case SFX_POLICE_HELI_1: - case SFX_POLICE_HELI_2: - case SFX_POLICE_HELI_3: - AudioManager.m_sQueueSample.m_fSoundIntensity = policeHeliIntensity; - break; - default: - AudioManager.m_sQueueSample.m_fSoundIntensity = defaultIntensity; - break; - } - AudioManager.m_sQueueSample.m_bReleasingSoundFlag = true; - AudioManager.m_sQueueSample.m_vecPos = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_vecPos; - - if (sampleIndex >= SFX_AMMU_D && sampleIndex <= SFX_AMMU_F) { - AudioManager.m_sQueueSample.m_bReverbFlag = false; - AudioManager.m_sQueueSample.m_bRequireReflection = false; - } else { - AudioManager.m_sQueueSample.m_bReverbFlag = true; - AudioManager.m_sQueueSample.m_bRequireReflection = true; - } - - AudioManager.m_sQueueSample.m_bIs2D = false; - AudioManager.m_sQueueSample.m_nFrequency = - SampleManager.GetSampleBaseFrequency(AudioManager.m_sQueueSample.m_nSampleIndex) + AudioManager.RandomDisplacement(750); - if (CTimer::GetIsSlowMotionActive()) - AudioManager.m_sQueueSample.m_nFrequency /= 2; - m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nProcess = -1; - AudioManager.AddSampleToRequestedQueue(); - } - - // Switch bank - if (m_nActiveBank) { - actualUsedBank = SAMPLEBANK_PED; - m_nActiveBank = SAMPLEBANK_MAIN; - } else { - actualUsedBank = SAMPLEBANK_MAIN; - m_nActiveBank = SAMPLEBANK_PED; - } - comment = m_asPedComments[actualUsedBank]; - for (uint32 i = 0; i < m_nCommentsInBank[actualUsedBank]; i++) { - if (m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess > 0) { - --m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess; - Add(&comment[m_nIndexMap[actualUsedBank][i]]); - } - } - - for (uint32 i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) { - m_nIndexMap[actualUsedBank][i] = NUM_PED_COMMENTS_SLOTS; - } - m_nCommentsInBank[actualUsedBank] = 0; - } -} - cAudioManager::cAudioManager() { m_bIsInitialised = false; @@ -331,6 +51,536 @@ cAudioManager::~cAudioManager() Terminate(); } +void +cAudioManager::Initialise() +{ + if (!m_bIsInitialised) { + PreInitialiseGameSpecificSetup(); + m_bIsInitialised = SampleManager.Initialise(); + if (m_bIsInitialised) { + m_nActiveSamples = SampleManager.GetMaximumSupportedChannels(); + if (m_nActiveSamples <= 1) { + Terminate(); + } else { + --m_nActiveSamples; + PostInitialiseGameSpecificSetup(); + InitialisePoliceRadioZones(); + InitialisePoliceRadio(); + MusicManager.Initialise(); + } + } + } +} + +void +cAudioManager::Terminate() +{ + if (m_bIsInitialised) { + MusicManager.Terminate(); + + for (uint32 i = 0; i < NUM_AUDIOENTITIES; i++) { + m_asAudioEntities[i].m_bIsUsed = false; + m_anAudioEntityIndices[i] = ARRAY_SIZE(m_anAudioEntityIndices); + } + + m_nAudioEntitiesTotal = 0; + m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; + PreTerminateGameSpecificShutdown(); + + for (uint32 i = 0; i < MAX_SAMPLEBANKS; i++) { + if (SampleManager.IsSampleBankLoaded(i)) + SampleManager.UnloadSampleBank(i); + } + + SampleManager.Terminate(); + + m_bIsInitialised = false; + PostTerminateGameSpecificShutdown(); + } +} + +void +cAudioManager::Service() +{ + GenerateIntegerRandomNumberTable(); + if (m_bTimerJustReset) { + ResetAudioLogicTimers(m_nTimer); + MusicManager.ResetTimers(m_nTimer); + m_bTimerJustReset = false; + } + if (m_bIsInitialised) { + m_nPreviousUserPause = m_nUserPause; + m_nUserPause = CTimer::GetIsUserPaused(); + UpdateReflections(); + ServiceSoundEffects(); + MusicManager.Service(); + } +} + +int32 +cAudioManager::CreateEntity(eAudioType type, void *entity) +{ + if (!m_bIsInitialised) + return AEHANDLE_ERROR_NOAUDIOSYS; + if (!entity) + return AEHANDLE_ERROR_NOENTITY; + if (type >= TOTAL_AUDIO_TYPES) + return AEHANDLE_ERROR_BADAUDIOTYPE; + for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) { + if (!m_asAudioEntities[i].m_bIsUsed) { + m_asAudioEntities[i].m_bIsUsed = true; + m_asAudioEntities[i].m_nStatus = 0; + m_asAudioEntities[i].m_nType = type; + m_asAudioEntities[i].m_pEntity = entity; + m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_awAudioEvent[1] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_awAudioEvent[2] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_awAudioEvent[3] = SOUND_NO_SOUND; + m_asAudioEntities[i].m_AudioEvents = 0; + m_anAudioEntityIndices[m_nAudioEntitiesTotal++] = i; + return i; + } + } + return AEHANDLE_ERROR_NOFREESLOT; +} + +void +cAudioManager::DestroyEntity(int32 id) +{ + if (m_bIsInitialised && id >= 0 && id < NUM_AUDIOENTITIES && m_asAudioEntities[id].m_bIsUsed) { + m_asAudioEntities[id].m_bIsUsed = false; + for (int32 i = 0; i < m_nAudioEntitiesTotal; ++i) { + if (id == m_anAudioEntityIndices[i]) { + if (i < NUM_AUDIOENTITIES - 1) + memmove(&m_anAudioEntityIndices[i], &m_anAudioEntityIndices[i + 1], NUM_AUDIOENTITY_EVENTS * (m_nAudioEntitiesTotal - (i + 1))); + m_anAudioEntityIndices[--m_nAudioEntitiesTotal] = NUM_AUDIOENTITIES; + return; + } + } + } +} + +void +cAudioManager::SetEntityStatus(int32 id, uint8 status) +{ + if (m_bIsInitialised && id >= 0 && id < NUM_AUDIOENTITIES && m_asAudioEntities[id].m_bIsUsed) + m_asAudioEntities[id].m_nStatus = status; +} + +void +cAudioManager::PlayOneShot(int32 index, int16 sound, float vol) +{ + static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 3, 1, 1, 1, 9, + 2, 2, 0, 0, 0, 0, 3, 3, 5, 1, 1, 1, 1, 3, 4, 7, 6, 6, 6, 6, 1, 3, 4, 3, 4, 2, 1, 3, 5, 4, 6, 6, 1, 3, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + if (m_bIsInitialised) { + if (index >= 0 && index < NUM_AUDIOENTITIES) { + tAudioEntity &entity = m_asAudioEntities[index]; + if (entity.m_bIsUsed) { + if (sound < SOUND_TOTAL_SOUNDS) { + if (entity.m_nType == AUDIOTYPE_SCRIPTOBJECT) { + if (m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal < ARRAY_SIZE(m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices)) { + entity.m_awAudioEvent[0] = sound; + entity.m_AudioEvents = 1; + m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal++] = index; + } + } else { + int32 i = 0; + while (true) { + if (i >= entity.m_AudioEvents) { + if (entity.m_AudioEvents < ARRAY_SIZE(entity.m_awAudioEvent)) { + entity.m_awAudioEvent[i] = sound; + entity.m_afVolume[i] = vol; + ++entity.m_AudioEvents; + } + return; + } + if (OneShotPriority[entity.m_awAudioEvent[i]] > OneShotPriority[sound]) + break; + ++i; + } + if (i < NUM_AUDIOENTITY_EVENTS - 1) { + memmove(&entity.m_awAudioEvent[i + 1], &entity.m_awAudioEvent[i], (NUM_AUDIOENTITY_EVENTS - 1 - i) * NUM_AUDIOENTITY_EVENTS / 2); + memmove(&entity.m_afVolume[i + 1], &entity.m_afVolume[i], (NUM_AUDIOENTITY_EVENTS - 1 - i) * NUM_AUDIOENTITY_EVENTS); + } + entity.m_awAudioEvent[i] = sound; + entity.m_afVolume[i] = vol; + if (entity.m_AudioEvents < ARRAY_SIZE(entity.m_awAudioEvent)) + ++entity.m_AudioEvents; + } + } + } + } + } +} + +void +cAudioManager::SetEffectsMasterVolume(uint8 volume) const +{ + SampleManager.SetEffectsMasterVolume(volume); +} + +void +cAudioManager::SetMusicMasterVolume(uint8 volume) const +{ + SampleManager.SetMusicMasterVolume(volume); +} + +void +cAudioManager::SetEffectsFadeVol(uint8 volume) const +{ + SampleManager.SetEffectsFadeVolume(volume); +} + +void +cAudioManager::SetMusicFadeVol(uint8 volume) const +{ + SampleManager.SetMusicFadeVolume(volume); +} + +void +cAudioManager::ResetTimers(uint32 time) +{ + if (m_bIsInitialised) { + m_bTimerJustReset = true; + m_nTimer = time; + ClearRequestedQueue(); + if (m_nActiveSampleQueue) { + m_nActiveSampleQueue = 0; + ClearRequestedQueue(); + m_nActiveSampleQueue = 1; + } else { + m_nActiveSampleQueue = 1; + ClearRequestedQueue(); + m_nActiveSampleQueue = 0; + } + ClearActiveSamples(); + ClearMissionAudio(); + SampleManager.StopChannel(policeChannel); + SampleManager.SetEffectsFadeVolume(0); + SampleManager.SetMusicFadeVolume(0); + MusicManager.ResetMusicAfterReload(); +#ifdef AUDIO_OAL + SampleManager.Service(); +#endif + } +} + +void +cAudioManager::DestroyAllGameCreatedEntities() +{ + cAudioScriptObject *entity; + + if (m_bIsInitialised) { + for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) { + if (m_asAudioEntities[i].m_bIsUsed) { + switch (m_asAudioEntities[i].m_nType) { + case AUDIOTYPE_PHYSICAL: + case AUDIOTYPE_EXPLOSION: + case AUDIOTYPE_WEATHER: + case AUDIOTYPE_CRANE: + case AUDIOTYPE_GARAGE: + case AUDIOTYPE_FIREHYDRANT: + DestroyEntity(i); + break; + case AUDIOTYPE_SCRIPTOBJECT: + entity = (cAudioScriptObject *)m_asAudioEntities[i].m_pEntity; + if (entity) { + delete entity; + m_asAudioEntities[i].m_pEntity = nil; + } + DestroyEntity(i); + break; + default: + break; + } + } + } + m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; + } +} + +uint8 +cAudioManager::GetNum3DProvidersAvailable() const +{ + if (m_bIsInitialised) + return SampleManager.GetNum3DProvidersAvailable(); + return 0; +} + +char * +cAudioManager::Get3DProviderName(uint8 id) const +{ + if (!m_bIsInitialised) + return nil; + if (id >= SampleManager.GetNum3DProvidersAvailable()) + return nil; + return SampleManager.Get3DProviderName(id); +} + +int8 +cAudioManager::GetCurrent3DProviderIndex() const +{ + if (m_bIsInitialised) + return SampleManager.GetCurrent3DProviderIndex(); + + return -1; +} + +int8 +cAudioManager::SetCurrent3DProvider(uint8 which) +{ + if (!m_bIsInitialised) + return -1; + for (uint8 i = 0; i < m_nActiveSamples + 1; ++i) + SampleManager.StopChannel(i); + ClearRequestedQueue(); + if (m_nActiveSampleQueue == 0) + m_nActiveSampleQueue = 1; + else + m_nActiveSampleQueue = 0; + ClearRequestedQueue(); + ClearActiveSamples(); + int8 current = SampleManager.SetCurrent3DProvider(which); + if (current > 0) { + m_nActiveSamples = SampleManager.GetMaximumSupportedChannels(); + if (m_nActiveSamples > 1) + --m_nActiveSamples; + } + return current; +} + +void +cAudioManager::SetSpeakerConfig(int32 conf) const +{ + SampleManager.SetSpeakerConfig(conf); +} + +bool +cAudioManager::IsMP3RadioChannelAvailable() const +{ + if (m_bIsInitialised) + return SampleManager.IsMP3RadioChannelAvailable(); + + return false; +} + +void +cAudioManager::ReleaseDigitalHandle() const +{ + if (m_bIsInitialised) { + SampleManager.ReleaseDigitalHandle(); + } +} + +void +cAudioManager::ReacquireDigitalHandle() const +{ + if (m_bIsInitialised) { + SampleManager.ReacquireDigitalHandle(); + } +} + +void +cAudioManager::SetDynamicAcousticModelingStatus(bool status) +{ + m_bDynamicAcousticModelingStatus = status; +} + +bool +cAudioManager::CheckForAnAudioFileOnCD() const +{ + return SampleManager.CheckForAnAudioFileOnCD(); +} + +uint8 +cAudioManager::GetCDAudioDriveLetter() const +{ + if (m_bIsInitialised) + return SampleManager.GetCDAudioDriveLetter(); + + return 0; +} + +bool +cAudioManager::IsAudioInitialised() const +{ + return m_bIsInitialised; +} + +void +cAudioManager::ServiceSoundEffects() +{ + m_bFifthFrameFlag = (m_FrameCounter++ % 5) == 0; + if (m_nUserPause && !m_nPreviousUserPause) { + for (int32 i = 0; i < allChannels; i++) + SampleManager.StopChannel(i); + + ClearRequestedQueue(); + if (m_nActiveSampleQueue) { + m_nActiveSampleQueue = 0; + ClearRequestedQueue(); + m_nActiveSampleQueue = 1; + } else { + m_nActiveSampleQueue = 1; + ClearRequestedQueue(); + m_nActiveSampleQueue = 0; + } + ClearActiveSamples(); + } + m_nActiveSampleQueue = m_nActiveSampleQueue != 1; + ProcessReverb(); + ProcessSpecial(); + ClearRequestedQueue(); + InterrogateAudioEntities(); + m_sPedComments.Process(); + ServicePoliceRadio(); + ServiceCollisions(); + AddReleasingSounds(); + ProcessMissionAudio(); +#ifdef GTA_PC + AdjustSamplesVolume(); +#endif + ProcessActiveQueues(); +#ifdef AUDIO_OAL + SampleManager.Service(); +#endif + for (int32 i = 0; i < m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal; ++i) { + cAudioScriptObject *object = (cAudioScriptObject *)m_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]].m_pEntity; + delete object; + m_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]].m_pEntity = nil; + DestroyEntity(m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]); + } + m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; +} + +uint8 +cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const +{ + float newSoundIntensity; + if (soundIntensity <= 0.0f) + return 0; + newSoundIntensity = soundIntensity / 5.0f; + if (newSoundIntensity <= distance) + emittingVolume = sq((soundIntensity - newSoundIntensity - (distance - newSoundIntensity)) / (soundIntensity - newSoundIntensity)) * emittingVolume; + return emittingVolume; +} + +void +cAudioManager::TranslateEntity(Const CVector *in, CVector *out) const +{ + *out = MultiplyInverse(TheCamera.GetMatrix(), *in); +} + +int32 +cAudioManager::ComputePan(float dist, CVector *vec) +{ + const uint8 PanTable[64] = {0, 3, 8, 12, 16, 19, 22, 24, 26, 28, 30, 31, 33, 34, 36, 37, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, 53, 53, + 54, 55, 55, 56, 56, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63}; + + int32 index = Min(63, Abs(vec->x / (dist / 64.f))); + + if (vec->x > 0.f) + return Max(20, 63 - PanTable[index]); + return Min(107, PanTable[index] + 63); +} + +int32 +cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const +{ + uint32 newFreq = oldFreq; + if (!TheCamera.Get_Just_Switched_Status() && speedMultiplier != 0.0f) { + float dist = position2 - position1; + if (dist != 0.0f) { + float speedOfSource = (dist / m_nTimeSpent) * speedMultiplier; + if (m_fSpeedOfSound > Abs(speedOfSource)) { + if (speedOfSource < 0.0f) { + speedOfSource = Max(speedOfSource, -1.5f); + } else { + speedOfSource = Min(speedOfSource, 1.5f); + } + newFreq = (oldFreq * m_fSpeedOfSound) / (speedOfSource + m_fSpeedOfSound); + } + } + } + return newFreq; +} + +int32 +cAudioManager::RandomDisplacement(uint32 seed) const +{ + int32 value; + + static bool bIsEven = true; + static uint32 base = 0; + + if (!seed) + return 0; + + value = m_anRandomTable[(base + seed) % 5] % seed; + base += value; + + if (value % 2) { + bIsEven = !bIsEven; + } + if (!bIsEven) + value = -value; + return value; +} + +void +cAudioManager::InterrogateAudioEntities() +{ + for (int32 i = 0; i < m_nAudioEntitiesTotal; i++) { + ProcessEntity(m_anAudioEntityIndices[i]); + m_asAudioEntities[m_anAudioEntityIndices[i]].m_AudioEvents = 0; + } +} + +void +cAudioManager::AddSampleToRequestedQueue() +{ + int32 calculatedVolume; + uint8 sampleIndex; + bool bReflections; + + if (m_sQueueSample.m_nSampleIndex < TOTAL_AUDIO_SAMPLES) { + calculatedVolume = m_sQueueSample.m_nReleasingVolumeModificator * (maxVolume - m_sQueueSample.m_nVolume); + sampleIndex = m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; + if (sampleIndex >= m_nActiveSamples) { + sampleIndex = m_abSampleQueueIndexTable[m_nActiveSampleQueue][m_nActiveSamples - 1]; + if (m_asSamples[m_nActiveSampleQueue][sampleIndex].m_nCalculatedVolume <= calculatedVolume) + return; + } else { + ++m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; + } + m_sQueueSample.m_nCalculatedVolume = calculatedVolume; + m_sQueueSample.m_bLoopEnded = false; + if (m_sQueueSample.m_bIs2D) { + m_sQueueSample.m_bRequireReflection = false; + m_sQueueSample.m_nLoopsRemaining = 0; + } + if (m_bDynamicAcousticModelingStatus && m_sQueueSample.m_nLoopCount) { + bReflections = m_sQueueSample.m_bRequireReflection; + } else { + bReflections = false; + m_sQueueSample.m_nLoopsRemaining = 0; + } + m_sQueueSample.m_bRequireReflection = false; + + if (!m_bDynamicAcousticModelingStatus) + m_sQueueSample.m_bReverbFlag = false; + + m_asSamples[m_nActiveSampleQueue][sampleIndex] = m_sQueueSample; + + AddDetailsToRequestedOrderList(sampleIndex); + if (bReflections) + AddReflectionsToRequestedQueue(); + } +} void cAudioManager::AddDetailsToRequestedOrderList(uint8 sample) { @@ -348,35 +598,6 @@ cAudioManager::AddDetailsToRequestedOrderList(uint8 sample) m_abSampleQueueIndexTable[m_nActiveSampleQueue][i] = sample; } -void -cAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 unk1, uint8 counter, bool notLooping) -{ - m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, 50.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = counter; - m_sQueueSample.m_nSampleIndex = sample; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nFrequency = freq; - if (notLooping) { - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nReleasingVolumeDivider = 8; - } else { - m_sQueueSample.m_nLoopCount = 1; - } - m_sQueueSample.m_nEmittingVolume = emittingVolume; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 6.0f; - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } -} - void cAudioManager::AddReflectionsToRequestedQueue() { @@ -410,6 +631,51 @@ cAudioManager::AddReflectionsToRequestedQueue() } } +void +cAudioManager::UpdateReflections() +{ + const CVector &camPos = TheCamera.GetPosition(); + CColPoint colpoint; + CEntity *ent; + + if (m_FrameCounter % 8 == 0) { + m_avecReflectionsPos[0] = camPos; + m_avecReflectionsPos[0].y += 50.f; + if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[0], colpoint, ent, true, false, false, true, false, true, true)) + m_afReflectionsDistances[0] = Distance(camPos, colpoint.point); + else + m_afReflectionsDistances[0] = 50.0f; + } else if ((m_FrameCounter + 1) % 8 == 0) { + m_avecReflectionsPos[1] = camPos; + m_avecReflectionsPos[1].y -= 50.0f; + if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[1], colpoint, ent, true, false, false, true, false, true, true)) + m_afReflectionsDistances[1] = Distance(camPos, colpoint.point); + else + m_afReflectionsDistances[1] = 50.0f; + } else if ((m_FrameCounter + 2) % 8 == 0) { + m_avecReflectionsPos[2] = camPos; + m_avecReflectionsPos[2].x -= 50.0f; + if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[2], colpoint, ent, true, false, false, true, false, true, true)) + m_afReflectionsDistances[2] = Distance(camPos, colpoint.point); + else + m_afReflectionsDistances[2] = 50.0f; + } else if ((m_FrameCounter + 3) % 8 == 0) { + m_avecReflectionsPos[3] = camPos; + m_avecReflectionsPos[3].x += 50.0f; + if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[3], colpoint, ent, true, false, false, true, false, true, true)) + m_afReflectionsDistances[3] = Distance(camPos, colpoint.point); + else + m_afReflectionsDistances[3] = 50.0f; + } else if ((m_FrameCounter + 4) % 8 == 0) { + m_avecReflectionsPos[4] = camPos; + m_avecReflectionsPos[4].z += 50.0f; + if (CWorld::ProcessVerticalLine(camPos, m_avecReflectionsPos[4].z, colpoint, ent, true, false, false, false, true, false, nil)) + m_afReflectionsDistances[4] = colpoint.point.z - camPos.z; + else + m_afReflectionsDistances[4] = 50.0f; + } +} + void cAudioManager::AddReleasingSounds() { @@ -459,3064 +725,6 @@ cAudioManager::AddReleasingSounds() } } -void -cAudioManager::AddSampleToRequestedQueue() -{ - int32 calculatedVolume; - uint8 sampleIndex; - bool bReflections; - - if (m_sQueueSample.m_nSampleIndex < TOTAL_AUDIO_SAMPLES) { - calculatedVolume = m_sQueueSample.m_nReleasingVolumeModificator * (maxVolume - m_sQueueSample.m_nVolume); - sampleIndex = m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; - if (sampleIndex >= m_nActiveSamples) { - sampleIndex = m_abSampleQueueIndexTable[m_nActiveSampleQueue][m_nActiveSamples - 1]; - if (m_asSamples[m_nActiveSampleQueue][sampleIndex].m_nCalculatedVolume <= calculatedVolume) - return; - } else { - ++m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; - } - m_sQueueSample.m_nCalculatedVolume = calculatedVolume; - m_sQueueSample.m_bLoopEnded = false; - if (m_sQueueSample.m_bIs2D) { - m_sQueueSample.m_bRequireReflection = false; - m_sQueueSample.m_nLoopsRemaining = 0; - } - if (m_bDynamicAcousticModelingStatus && m_sQueueSample.m_nLoopCount) { - bReflections = m_sQueueSample.m_bRequireReflection; - } else { - bReflections = false; - m_sQueueSample.m_nLoopsRemaining = 0; - } - m_sQueueSample.m_bRequireReflection = false; - - if (!m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bReverbFlag = false; - - m_asSamples[m_nActiveSampleQueue][sampleIndex] = m_sQueueSample; - - AddDetailsToRequestedOrderList(sampleIndex); - if (bReflections) - AddReflectionsToRequestedQueue(); - } -} - -void -cAudioManager::CalculateDistance(bool &distCalculated, float dist) -{ - if (!distCalculated) { - m_sQueueSample.m_fDistance = Sqrt(dist); - distCalculated = true; - } -} - -bool -cAudioManager::CheckForAnAudioFileOnCD() const -{ - return SampleManager.CheckForAnAudioFileOnCD(); -} - -void -cAudioManager::ClearActiveSamples() -{ - for (int32 i = 0; i < m_nActiveSamples; i++) { - m_asActiveSamples[i].m_nEntityIndex = AEHANDLE_NONE; - m_asActiveSamples[i].m_nCounter = 0; - m_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE; - m_asActiveSamples[i].m_nBankIndex = SAMPLEBANK_INVALID; - m_asActiveSamples[i].m_bIs2D = false; - m_asActiveSamples[i].m_nReleasingVolumeModificator = 5; - m_asActiveSamples[i].m_nFrequency = 0; - m_asActiveSamples[i].m_nVolume = 0; - m_asActiveSamples[i].m_nEmittingVolume = 0; - m_asActiveSamples[i].m_fDistance = 0.0f; - m_asActiveSamples[i].m_bIsProcessed = false; - m_asActiveSamples[i].m_bLoopEnded = false; - m_asActiveSamples[i].m_nLoopCount = 1; - m_asActiveSamples[i].m_nLoopStart = 0; - m_asActiveSamples[i].m_nLoopEnd = -1; - m_asActiveSamples[i].m_fSpeedMultiplier = 0.0f; - m_asActiveSamples[i].m_fSoundIntensity = 200.0f; - m_asActiveSamples[i].m_nOffset = 63; - m_asActiveSamples[i].m_bReleasingSoundFlag = false; - m_asActiveSamples[i].m_nCalculatedVolume = 0; - m_asActiveSamples[i].m_nReleasingVolumeDivider = 0; - m_asActiveSamples[i].m_nVolumeChange = -1; - m_asActiveSamples[i].m_vecPos = {0.0f, 0.0f, 0.0f}; - m_asActiveSamples[i].m_bReverbFlag = false; - m_asActiveSamples[i].m_nLoopsRemaining = 0; - m_asActiveSamples[i].m_bRequireReflection = false; - } -} - -void -cAudioManager::ClearMissionAudio() -{ - if (m_bIsInitialised) { - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; - m_sMissionAudio.field_22 = 0; - m_sMissionAudio.m_bIsPlayed = false; - m_sMissionAudio.m_bPredefinedProperties = 1; - m_sMissionAudio.m_nMissionAudioCounter = 0; - } -} - -void -cAudioManager::ClearRequestedQueue() -{ - for (int32 i = 0; i < m_nActiveSamples; i++) { - m_abSampleQueueIndexTable[m_nActiveSampleQueue][i] = m_nActiveSamples; - } - m_SampleRequestQueuesStatus[m_nActiveSampleQueue] = 0; -} - -int32 -cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const -{ - uint32 newFreq = oldFreq; - if (!TheCamera.Get_Just_Switched_Status() && speedMultiplier != 0.0f) { - float dist = position2 - position1; - if (dist != 0.0f) { - float speedOfSource = (dist / m_nTimeSpent) * speedMultiplier; - if (m_fSpeedOfSound > Abs(speedOfSource)) { - if (speedOfSource < 0.0f) { - speedOfSource = Max(speedOfSource, -1.5f); - } else { - speedOfSource = Min(speedOfSource, 1.5f); - } - newFreq = (oldFreq * m_fSpeedOfSound) / (speedOfSource + m_fSpeedOfSound); - } - } - } - return newFreq; -} - -int32 -cAudioManager::ComputePan(float dist, CVector *vec) -{ - int32 index = Min(63, Abs(vec->x / (dist / 64.f))); - - if (vec->x > 0.f) - return Max(20, 63 - panTable[index]); - return Min(107, panTable[index] + 63); -} - -uint8 -cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const -{ - float newSoundIntensity; - if (soundIntensity <= 0.0f) - return 0; - newSoundIntensity = soundIntensity / 5.0f; - if (newSoundIntensity <= distance) - emittingVolume = sq((soundIntensity - newSoundIntensity - (distance - newSoundIntensity)) / (soundIntensity - newSoundIntensity)) * emittingVolume; - return emittingVolume; -} - -int32 -cAudioManager::CreateEntity(int32 type, void *entity) -{ - if (!m_bIsInitialised) - return AEHANDLE_ERROR_NOAUDIOSYS; - if (!entity) - return AEHANDLE_ERROR_NOENTITY; - if (type >= TOTAL_AUDIO_TYPES) - return AEHANDLE_ERROR_BADAUDIOTYPE; - for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) { - if (!m_asAudioEntities[i].m_bIsUsed) { - m_asAudioEntities[i].m_bIsUsed = true; - m_asAudioEntities[i].m_nStatus = 0; - m_asAudioEntities[i].m_nType = (eAudioType)type; - m_asAudioEntities[i].m_pEntity = entity; - m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_NO_SOUND; - m_asAudioEntities[i].m_awAudioEvent[1] = SOUND_NO_SOUND; - m_asAudioEntities[i].m_awAudioEvent[2] = SOUND_NO_SOUND; - m_asAudioEntities[i].m_awAudioEvent[3] = SOUND_NO_SOUND; - m_asAudioEntities[i].m_AudioEvents = 0; - m_anAudioEntityIndices[m_nAudioEntitiesTotal++] = i; - return i; - } - } - return AEHANDLE_ERROR_NOFREESLOT; -} - -void -cAudioManager::DestroyAllGameCreatedEntities() -{ - cAudioScriptObject *entity; - - if (m_bIsInitialised) { - for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) { - if (m_asAudioEntities[i].m_bIsUsed) { - switch (m_asAudioEntities[i].m_nType) { - case AUDIOTYPE_PHYSICAL: - case AUDIOTYPE_EXPLOSION: - case AUDIOTYPE_WEATHER: - case AUDIOTYPE_CRANE: - case AUDIOTYPE_GARAGE: - case AUDIOTYPE_FIREHYDRANT: - DestroyEntity(i); - break; - case AUDIOTYPE_SCRIPTOBJECT: - entity = (cAudioScriptObject *)m_asAudioEntities[i].m_pEntity; - if (entity) { - delete entity; - m_asAudioEntities[i].m_pEntity = nil; - } - DestroyEntity(i); - break; - default: - break; - } - } - } - m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; - } -} - -void -cAudioManager::DestroyEntity(int32 id) -{ - if (m_bIsInitialised && id >= 0 && id < totalAudioEntitiesSlots && m_asAudioEntities[id].m_bIsUsed) { - m_asAudioEntities[id].m_bIsUsed = false; - for (int32 i = 0; i < m_nAudioEntitiesTotal; ++i) { - if (id == m_anAudioEntityIndices[i]) { - if (i < totalAudioEntitiesSlots - 1) - memmove(&m_anAudioEntityIndices[i], &m_anAudioEntityIndices[i + 1], NUM_AUDIOENTITY_EVENTS * (m_nAudioEntitiesTotal - (i + 1))); - m_anAudioEntityIndices[--m_nAudioEntitiesTotal] = totalAudioEntitiesSlots; - return; - } - } - } -} - -void -cAudioManager::DoJumboVolOffset() const -{ - if (!(m_FrameCounter % (m_anRandomTable[0] % 6 + 3))) - gJumboVolOffsetPercentage = m_anRandomTable[1] % 60; -} - -uint32 -cAudioManager::GetPlayerTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_DAMAGE: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11); - break; - case SOUND_PED_HIT: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_LOW_DAMAGE_GRUNT_1, 10); - break; - case SOUND_PED_LAND: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6); - break; - default: - sfx = NO_SAMPLE; - break; - } - return sfx; -} - -uint32 -cAudioManager::GetCopTalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_ARREST_COP) { - GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_COP) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_CHASE_1, 7); - } - - return (SFX_COP_VOICE_2_ARREST_1 - SFX_COP_VOICE_1_ARREST_1) * (m_sQueueSample.m_nEntityIndex % 5) + sfx; -} - -uint32 -cAudioManager::GetSwatTalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_ARREST_SWAT) { - GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_SWAT) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); - } - - return (SFX_SWAT_VOICE_2_CHASE_1 - SFX_SWAT_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 4) + sfx; -} - -uint32 -cAudioManager::GetFBITalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_ARREST_FBI) { - GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_FBI) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); - } - - return (SFX_FBI_VOICE_2_CHASE_1 - SFX_FBI_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; -} - -uint32 -cAudioManager::GetArmyTalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound != SOUND_PED_PURSUIT_ARMY) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); - - return (SFX_ARMY_VOICE_2_CHASE_1 - SFX_ARMY_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetMedicTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_CARJACKED_1, 5); - break; - case SOUND_PED_HEALING: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_AT_VICTIM_1, 12); - break; - case SOUND_PED_LEAVE_VEHICLE: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1, 9); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_MEDIC_VOICE_2_GUN_PANIC_1 - SFX_MEDIC_VOICE_1_GUN_PANIC_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetFiremanTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetNormalMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_EYING_1, 8); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetTaxiDriverTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_CAR_JACKED) { - GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); - } else { - if (sound != SOUND_PED_CAR_COLLISION) - return GetGenericMaleTalkSfx(sound); - GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); - } - return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetPimpTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_GUN_COOL_1, 7); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_CARJACKED_1, 4); - break; - case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_FIGHT_1, 9); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_CHAT_1, 17); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetMafiaTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_MAFIA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; -} - -uint32 -cAudioManager::GetTriadTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3); - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetDiabloTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4); - break; - case SOUND_PED_HANDS_COWER: - sound = SOUND_PED_FLEE_SPRINT; - return GetGenericMaleTalkSfx(sound); - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_EYING_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_DIABLO_MALE_VOICE_2_CHAT_1 - SFX_DIABLO_MALE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetYakuzaTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_YAKUZA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetYardieTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - sfx = SFX_YARDIE_MALE_VOICE_1_GUN_COOL_1; - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - sfx = SFX_YARDIE_MALE_VOICE_1_CARJACKED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_YARDIE_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetColumbianTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_COLUMBIAN_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetHoodTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5); - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6); - break; - - default: - return GetGenericMaleTalkSfx(sound); - break; - } - return (SFX_HOOD_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetBlackCriminalTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4); - break; - case SOUND_PED_CAR_JACKING: - sfx = SFX_BLACK_CRIMINAL_VOICE_1_CARJACKING_1; - break; - case SOUND_PED_MUGGING: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_MUGGING_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - break; - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteCriminalTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3); - break; - case SOUND_PED_CAR_JACKING: - sfx = SFX_WHITE_CRIMINAL_VOICE_1_CARJACKING_1; - break; - case SOUND_PED_MUGGING: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_MUGGING_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - break; - } - return sfx; -} - -uint32 -cAudioManager::GetMaleNo2TalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_MUGGED_1, 4); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_EYING_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_P_MAN2) - sfx += (SFX_BLACK_PROJECT_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFatMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - sfx = SFX_WHITE_CASUAL_FEMALE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetFemaleNo3TalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CARJACKED_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_SHOCKED_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_LOST_1, 2); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4); - break; - case SOUND_PED_ROBBED: - sfx = SFX_BLACK_PROSTITUTE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_SOLICIT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_SOLICIT_1, 8); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_BLACK_PROSTITUTE_VOICE_2_CHAT_1 - SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_SOLICIT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_SOLICIT_1, 8); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_WHITE_PROSTITUTE_VOICE_2_CHAT_1 - SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DODGE_1, 10); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - sfx = SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CARJACKED_1; - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_SHOCKED_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - sfx = SFX_CHINATOWN_OLD_FEMALE_VOICE_1_SHOCKED_1; - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_LITTLE_ITALY_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetScumMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_ROBBED: - sfx = SFX_SCUM_MALE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_FIGHT_1, 10); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_LOST_1, 3); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_EYING_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetScumFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_B_MAN3) - sfx += (SFX_BUSINESS_MALE_YOUNG_VOICE_2_DRIVER_ABUSE_1 - SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - - if (model == MI_B_WOM2) - sfx += (SFX_WHITE_BUSINESS_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CARAJACKED_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetSupermodelMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_SHOCKED_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetStewardMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetStewardFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_STEWARD_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_FAN_MAN2) - sfx += (SFX_FOOTBALL_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetFanFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_ROBBED: - sfx = SFX_FOOTBALL_FEMALE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_FOOTBALL_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetHospitalMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetHospitalFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - sfx = SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CARJACKED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_EYING_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - - if (model == MI_SHOPPER2) { - sfx += (SFX_SHOPPER_VOICE_2_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1); - } else if (model == MI_SHOPPER3) { - sfx += (SFX_SHOPPER_VOICE_3_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1); - } - return sfx; -} - -uint32 -cAudioManager::GetStudentMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_SHOCKED_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetStudentFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetCasualMaleOldTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound) -{ - char *modelName = CModelInfo::GetModelInfo(modelIndex)->GetName(); - if (!CGeneral::faststricmp(modelName, "eight") || !CGeneral::faststricmp(modelName, "eight2")) { - return GetEightTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "frankie")) { - return GetFrankieTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "misty")) { - return GetMistyTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "ojg") || !CGeneral::faststricmp(modelName, "ojg_p")) { - return GetOJGTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "cat")) { - return GetCatatalinaTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "bomber")) { - return GetBomberTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "s_guard")) { - return GetSecurityGuardTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "chunky")) { - return GetChunkyTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "asuka")) { - return GetGenericFemaleTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "maria")) { - return GetGenericFemaleTalkSfx(sound); - } - - return GetGenericMaleTalkSfx(sound); -} -uint32 -cAudioManager::GetEightTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_GUN_COOL_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_DODGE_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetFrankieTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_GUN_COOL_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_DODGE_1, 3); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetMistyTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_GUN_COOL_1, 5); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_DODGE_1, 5); - break; - case SOUND_PED_TAXI_CALL: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_HERE_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - break; - } - return sfx; -} - -uint32 -cAudioManager::GetOJGTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetCatatalinaTalkSfx(int16 sound) -{ - return GetGenericFemaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetBomberTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - if (sound != SOUND_PED_BOMBER) - return GetGenericMaleTalkSfx(sound); - - GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7); - return sfx; -} - -uint32 -cAudioManager::GetSecurityGuardTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2); - break; - case SOUND_PED_HANDS_COWER: - sfx = SFX_SECURITY_GUARD_VOICE_1_GUN_PANIC_1; - break; - case SOUND_PED_CAR_JACKED: - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_FIGHT_1, 2); - break; - case SOUND_PED_FLEE_RUN: -#ifdef FIX_BUGS - sfx = SFX_SECURITY_GUARD_VOICE_1_RUN_FROM_FIGHT_1; -#else - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12); -#endif - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChunkyTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_DEATH) - return SFX_CHUNKY_DEATH; - - if (sound != SOUND_PED_FLEE_RUN) - return GetGenericMaleTalkSfx(sound); - - GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5); - return sfx; -} - -uint32 -cAudioManager::GetGenericMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_DEATH: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_DEATH_1, 8); - break; - case SOUND_PED_BULLET_HIT: - case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15); - break; - case SOUND_PED_BURNING: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_FIRE_1, 8); - break; - case SOUND_PED_FLEE_SPRINT: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_PANIC_1, 6); - break; - default: - return NO_SAMPLE; - } - return sfx; -} - -uint32 -cAudioManager::GetGenericFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_DEATH: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10); - break; - case SOUND_PED_BULLET_HIT: - case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11); - break; - case SOUND_PED_BURNING: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9); - break; - case SOUND_PED_FLEE_SPRINT: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8); - break; - default: - return NO_SAMPLE; - } - return sfx; -} - -void -cAudioManager::GenerateIntegerRandomNumberTable() -{ - for (int32 i = 0; i < ARRAY_SIZE(m_anRandomTable); i++) { - m_anRandomTable[i] = rand(); - } -} - -char * -cAudioManager::Get3DProviderName(uint8 id) const -{ - if (!m_bIsInitialised) - return nil; - if (id >= SampleManager.GetNum3DProvidersAvailable()) - return nil; - return SampleManager.Get3DProviderName(id); -} - -uint8 -cAudioManager::GetCDAudioDriveLetter() const -{ - if (m_bIsInitialised) - return SampleManager.GetCDAudioDriveLetter(); - - return 0; -} - -int8 -cAudioManager::GetCurrent3DProviderIndex() const -{ - if (m_bIsInitialised) - return SampleManager.GetCurrent3DProviderIndex(); - - return -1; -} - -float -cAudioManager::GetDistanceSquared(const CVector &v) const -{ - const CVector &c = TheCamera.GetPosition(); - return sq(v.x - c.x) + sq(v.y - c.y) + sq((v.z - c.z) * 0.2f); -} - -int32 -cAudioManager::GetJumboTaxiFreq() const -{ - return (60.833f * m_sQueueSample.m_fDistance) + 22050; -} - -bool -cAudioManager::GetMissionAudioLoadingStatus() const -{ - if (m_bIsInitialised) - return m_sMissionAudio.m_nLoadingStatus; - - return true; -} - -uint8 -cAudioManager::GetNum3DProvidersAvailable() const -{ - if (m_bIsInitialised) - return SampleManager.GetNum3DProvidersAvailable(); - return 0; -} - -int32 -cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) -{ - if (ped->IsPlayer()) - return GetPlayerTalkSfx(sound); - - switch (ped->GetModelIndex()) { - case MI_COP: - return GetCopTalkSfx(sound); - case MI_SWAT: - return GetSwatTalkSfx(sound); - case MI_FBI: - return GetFBITalkSfx(sound); - case MI_ARMY: - return GetArmyTalkSfx(sound); - case MI_MEDIC: - return GetMedicTalkSfx(sound); - case MI_FIREMAN: - return GetFiremanTalkSfx(sound); - case MI_MALE01: - return GetNormalMaleTalkSfx(sound); - case MI_TAXI_D: - return GetTaxiDriverTalkSfx(sound); - case MI_PIMP: - return GetPimpTalkSfx(sound); - case MI_GANG01: - case MI_GANG02: - return GetMafiaTalkSfx(sound); - case MI_GANG03: - case MI_GANG04: - return GetTriadTalkSfx(sound); - case MI_GANG05: - case MI_GANG06: - return GetDiabloTalkSfx(sound); - case MI_GANG07: - case MI_GANG08: - return GetYakuzaTalkSfx(sound); - case MI_GANG09: - case MI_GANG10: - return GetYardieTalkSfx(sound); - case MI_GANG11: - case MI_GANG12: - return GetColumbianTalkSfx(sound); - case MI_GANG13: - case MI_GANG14: - return GetHoodTalkSfx(sound); - case MI_CRIMINAL01: - return GetBlackCriminalTalkSfx(sound); - case MI_CRIMINAL02: - return GetWhiteCriminalTalkSfx(sound); - case MI_SPECIAL01: - case MI_SPECIAL02: - case MI_SPECIAL03: - case MI_SPECIAL04: - return GetSpecialCharacterTalkSfx(ped->GetModelIndex(), sound); - case MI_MALE02: - return GetMaleNo2TalkSfx(sound); - case MI_MALE03: - case MI_P_MAN1: - case MI_P_MAN2: - return GetBlackProjectMaleTalkSfx(sound, ped->GetModelIndex()); - case MI_FATMALE01: - return GetWhiteFatMaleTalkSfx(sound); - case MI_FATMALE02: - return GetBlackFatMaleTalkSfx(sound); - case MI_FEMALE01: - return GetBlackCasualFemaleTalkSfx(sound); - case MI_FEMALE02: - case MI_CAS_WOM: - return GetWhiteCasualFemaleTalkSfx(sound); - case MI_FEMALE03: - return GetFemaleNo3TalkSfx(sound); - case MI_FATFEMALE01: - return GetBlackFatFemaleTalkSfx(sound); - case MI_FATFEMALE02: - return GetWhiteFatFemaleTalkSfx(sound); - case MI_PROSTITUTE: - return GetBlackFemaleProstituteTalkSfx(sound); - case MI_PROSTITUTE2: - return GetWhiteFemaleProstituteTalkSfx(sound); - case MI_P_WOM1: - return GetBlackProjectFemaleOldTalkSfx(sound); - case MI_P_WOM2: - return GetBlackProjectFemaleYoungTalkSfx(sound); - case MI_CT_MAN1: - return GetChinatownMaleOldTalkSfx(sound); - case MI_CT_MAN2: - return GetChinatownMaleYoungTalkSfx(sound); - case MI_CT_WOM1: - return GetChinatownFemaleOldTalkSfx(sound); - case MI_CT_WOM2: - return GetChinatownFemaleYoungTalkSfx(sound); - case MI_LI_MAN1: - case MI_LI_MAN2: - return GetLittleItalyMaleTalkSfx(sound); - case MI_LI_WOM1: - return GetLittleItalyFemaleOldTalkSfx(sound); - case MI_LI_WOM2: - return GetLittleItalyFemaleYoungTalkSfx(sound); - case MI_DOCKER1: - return GetWhiteDockerMaleTalkSfx(sound); - case MI_DOCKER2: - return GetBlackDockerMaleTalkSfx(sound); - case MI_SCUM_MAN: - return GetScumMaleTalkSfx(sound); - case MI_SCUM_WOM: - return GetScumFemaleTalkSfx(sound); - case MI_WORKER1: - return GetWhiteWorkerMaleTalkSfx(sound); - case MI_WORKER2: - return GetBlackWorkerMaleTalkSfx(sound); - case MI_B_MAN1: - case MI_B_MAN3: - return GetBusinessMaleYoungTalkSfx(sound, ped->GetModelIndex()); - case MI_B_MAN2: - return GetBusinessMaleOldTalkSfx(sound); - case MI_B_WOM1: - case MI_B_WOM2: - return GetWhiteBusinessFemaleTalkSfx(sound, ped->GetModelIndex()); - case MI_B_WOM3: - return GetBlackBusinessFemaleTalkSfx(sound); - case MI_MOD_MAN: - return GetSupermodelMaleTalkSfx(sound); - case MI_MOD_WOM: - return GetSupermodelFemaleTalkSfx(sound); - case MI_ST_MAN: - return GetStewardMaleTalkSfx(sound); - case MI_ST_WOM: - return GetStewardFemaleTalkSfx(sound); - case MI_FAN_MAN1: - case MI_FAN_MAN2: - return GetFanMaleTalkSfx(sound, ped->GetModelIndex()); - case MI_FAN_WOM: - return GetFanFemaleTalkSfx(sound); - case MI_HOS_MAN: - return GetHospitalMaleTalkSfx(sound); - case MI_HOS_WOM: - return GetHospitalFemaleTalkSfx(sound); - case MI_CONST1: - return GetWhiteConstructionWorkerTalkSfx(sound); - case MI_CONST2: - return GetBlackConstructionWorkerTalkSfx(sound); - case MI_SHOPPER1: - case MI_SHOPPER2: - case MI_SHOPPER3: - return GetShopperFemaleTalkSfx(sound, ped->GetModelIndex()); - case MI_STUD_MAN: - return GetStudentMaleTalkSfx(sound); - case MI_STUD_WOM: - return GetStudentFemaleTalkSfx(sound); - case MI_CAS_MAN: - return GetCasualMaleOldTalkSfx(sound); - default: - return GetGenericMaleTalkSfx(sound); - } -} - -void -cAudioManager::GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const -{ - *phrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset; - - // check if the same sfx like last time, if yes, then try use next one, - // if exceeded range, then choose first available sample - if (*phrase == *prevPhrase && ++*phrase >= sample + maxOffset) - *phrase = sample; - *prevPhrase = *phrase; -} - -float -cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange) -{ - tWheelState wheelState; - float relativeVelChange; - float gasPedalAudio = automobile->m_fGasPedalAudio; - float modificator; - float velChange; - float relativeVel; - - wheelState = automobile->m_aWheelState[wheel]; - if (wheelState == WHEEL_STATE_SPINNING && gasPedalAudio > 0.4f) { - relativeVelChange = (gasPedalAudio - 0.4f) * 1.25f; - - } else if (wheelState == WHEEL_STATE_SKIDDING) { - relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); - } else if (wheelState == WHEEL_STATE_FIXED) { - modificator = 0.4f; - relativeVelChange = gasPedalAudio; - if (relativeVelChange > 0.4f) { - relativeVelChange = relativeVelChange - 0.4f; - modificator = 5.f / 3.f; - } - velChange = Abs(velocityChange); - if (relativeVelChange > 0.4f) - relativeVelChange = relativeVelChange * modificator; - if (velChange > 0.04f) { - relativeVel = Min(1.0f, velChange / transmission->fMaxVelocity); - } else { - relativeVel = 0.0f; - } - if (relativeVel >= relativeVelChange) - relativeVelChange = relativeVel; - } else { - relativeVelChange = 0.0f; - } - - return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); -} - -float -cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange) -{ - float relativeVelChange; - - if (automobile->m_aWheelState[wheel] == 2) { - relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); - } else { - relativeVelChange = 0.0f; - } - - return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); -} - -bool -cAudioManager::HasAirBrakes(int32 model) const -{ - return model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == COACH; -} - -void -cAudioManager::Initialise() -{ - if (!m_bIsInitialised) { - PreInitialiseGameSpecificSetup(); - m_bIsInitialised = SampleManager.Initialise(); - if (m_bIsInitialised) { - m_nActiveSamples = SampleManager.GetMaximumSupportedChannels(); - if (m_nActiveSamples <= 1) { - Terminate(); - } else { - --m_nActiveSamples; - PostInitialiseGameSpecificSetup(); - InitialisePoliceRadioZones(); - InitialisePoliceRadio(); - MusicManager.Initialise(); - } - } - } -} - -void -cAudioManager::InterrogateAudioEntities() -{ - for (int32 i = 0; i < m_nAudioEntitiesTotal; i++) { - ProcessEntity(m_anAudioEntityIndices[i]); - m_asAudioEntities[m_anAudioEntityIndices[i]].m_AudioEvents = 0; - } -} - -bool -cAudioManager::IsAudioInitialised() const -{ - return m_bIsInitialised; -} - -bool -cAudioManager::IsMissionAudioSampleFinished() -{ - if (m_bIsInitialised) - return m_sMissionAudio.m_nPlayStatus == PLAY_STATUS_FINISHED; - - static int32 cPretendFrame = 1; - - return (cPretendFrame++ & 63) == 0; -} - -bool -cAudioManager::IsMP3RadioChannelAvailable() const -{ - if (m_bIsInitialised) - return SampleManager.IsMP3RadioChannelAvailable(); - - return false; -} - -bool -cAudioManager::MissionScriptAudioUsesPoliceChannel(int32 soundMission) const -{ - switch (soundMission) { - case STREAMED_SOUND_MISSION_J6_D: - case STREAMED_SOUND_MISSION_T4_A: - case STREAMED_SOUND_MISSION_S1_H: - case STREAMED_SOUND_MISSION_S3_B: - case STREAMED_SOUND_MISSION_EL3_A: - case STREAMED_SOUND_MISSION_A3_A: - case STREAMED_SOUND_MISSION_A5_A: - case STREAMED_SOUND_MISSION_K1_A: - case STREAMED_SOUND_MISSION_R1_A: - case STREAMED_SOUND_MISSION_R5_A: - case STREAMED_SOUND_MISSION_LO2_A: - case STREAMED_SOUND_MISSION_LO6_A: - return true; - default: - return false; - } -} - -void -cAudioManager::PlayLoadedMissionAudio() -{ - if (m_bIsInitialised && m_sMissionAudio.m_nSampleIndex != NO_SAMPLE && m_sMissionAudio.m_nLoadingStatus == LOADING_STATUS_LOADED && - !m_sMissionAudio.m_nPlayStatus) { - m_sMissionAudio.m_bIsPlayed = true; - } -} - -void -cAudioManager::PlayOneShot(int32 index, int16 sound, float vol) -{ - static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 3, 1, 1, 1, 9, - 2, 2, 0, 0, 0, 0, 3, 3, 5, 1, 1, 1, 1, 3, 4, 7, 6, 6, 6, 6, 1, 3, 4, 3, 4, 2, 1, 3, 5, 4, 6, 6, 1, 3, - 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - if (m_bIsInitialised) { - if (index >= 0 && index < totalAudioEntitiesSlots) { - tAudioEntity &entity = m_asAudioEntities[index]; - if (entity.m_bIsUsed) { - if (sound < SOUND_TOTAL_SOUNDS) { - if (entity.m_nType == AUDIOTYPE_SCRIPTOBJECT) { - if (m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal < ARRAY_SIZE(m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices)) { - entity.m_awAudioEvent[0] = sound; - entity.m_AudioEvents = 1; - m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal++] = index; - } - } else { - int32 i = 0; - while (true) { - if (i >= entity.m_AudioEvents) { - if (entity.m_AudioEvents < ARRAY_SIZE(entity.m_awAudioEvent)) { - entity.m_awAudioEvent[i] = sound; - entity.m_afVolume[i] = vol; - ++entity.m_AudioEvents; - } - return; - } - if (OneShotPriority[entity.m_awAudioEvent[i]] > OneShotPriority[sound]) - break; - ++i; - } - if (i < NUM_AUDIOENTITY_EVENTS - 1) { - memmove(&entity.m_awAudioEvent[i + 1], &entity.m_awAudioEvent[i], (NUM_AUDIOENTITY_EVENTS - 1 - i) * NUM_AUDIOENTITY_EVENTS / 2); - memmove(&entity.m_afVolume[i + 1], &entity.m_afVolume[i], (NUM_AUDIOENTITY_EVENTS - 1 - i) * NUM_AUDIOENTITY_EVENTS); - } - entity.m_awAudioEvent[i] = sound; - entity.m_afVolume[i] = vol; - if (entity.m_AudioEvents < ARRAY_SIZE(entity.m_awAudioEvent)) - ++entity.m_AudioEvents; - } - } - } - } - } -} - -void -cAudioManager::PlayerJustGotInCar() const -{ - if (m_bIsInitialised) { - bPlayerJustEnteredCar = true; - } -} - -void -cAudioManager::PlayerJustLeftCar(void) const -{ - // UNUSED: This is a perfectly empty function. -} - -void -cAudioManager::PostInitialiseGameSpecificSetup() -{ - m_nFireAudioEntity = CreateEntity(AUDIOTYPE_FIRE, &gFireManager); - if (m_nFireAudioEntity >= 0) - SetEntityStatus(m_nFireAudioEntity, 1); - - m_nCollisionEntity = CreateEntity(AUDIOTYPE_COLLISION, (void *)1); - if (m_nCollisionEntity >= 0) - SetEntityStatus(m_nCollisionEntity, 1); - - m_nFrontEndEntity = CreateEntity(AUDIOTYPE_FRONTEND, (void *)1); - if (m_nFrontEndEntity >= 0) - SetEntityStatus(m_nFrontEndEntity, 1); - - m_nProjectileEntity = CreateEntity(AUDIOTYPE_PROJECTILE, (void *)1); - if (m_nProjectileEntity >= 0) - SetEntityStatus(m_nProjectileEntity, 1); - - m_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATERCANNON, (void *)1); - if (m_nWaterCannonEntity >= 0) - SetEntityStatus(m_nWaterCannonEntity, 1); - - m_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_POLICERADIO, (void *)1); - if (m_nPoliceChannelEntity >= 0) - SetEntityStatus(m_nPoliceChannelEntity, 1); - - m_nBridgeEntity = CreateEntity(AUDIOTYPE_BRIDGE, (void *)1); - if (m_nBridgeEntity >= 0) - SetEntityStatus(m_nBridgeEntity, 1); - - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; - m_sMissionAudio.field_22 = 0; - m_sMissionAudio.m_bIsPlayed = false; - m_sMissionAudio.m_bPredefinedProperties = 1; - m_sMissionAudio.m_nMissionAudioCounter = 0; - ResetAudioLogicTimers(CTimer::GetTimeInMilliseconds()); -} - -void -cAudioManager::PostTerminateGameSpecificShutdown() -{ - ; -} - -void -cAudioManager::PreInitialiseGameSpecificSetup() const -{ - BankStartOffset[SAMPLEBANK_MAIN] = SFX_CAR_HORN_JEEP; - BankStartOffset[SAMPLEBANK_PED] = SFX_COP_VOICE_1_ARREST_1; -} - -struct MissionAudioData { - const char *m_pName; - int32 m_nId; -}; - -const MissionAudioData MissionAudioNameSfxAssoc[] = { - {"lib_a1", STREAMED_SOUND_MISSION_LIB_A1}, {"lib_a2", STREAMED_SOUND_MISSION_LIB_A2}, {"lib_a", STREAMED_SOUND_MISSION_LIB_A}, - {"lib_b", STREAMED_SOUND_MISSION_LIB_B}, {"lib_c", STREAMED_SOUND_MISSION_LIB_C}, {"lib_d", STREAMED_SOUND_MISSION_LIB_D}, - {"l2_a", STREAMED_SOUND_MISSION_L2_A}, {"j4t_1", STREAMED_SOUND_MISSION_J4T_1}, {"j4t_2", STREAMED_SOUND_MISSION_J4T_2}, - {"j4t_3", STREAMED_SOUND_MISSION_J4T_3}, {"j4t_4", STREAMED_SOUND_MISSION_J4T_4}, {"j4_a", STREAMED_SOUND_MISSION_J4_A}, - {"j4_b", STREAMED_SOUND_MISSION_J4_B}, {"j4_c", STREAMED_SOUND_MISSION_J4_C}, {"j4_d", STREAMED_SOUND_MISSION_J4_D}, - {"j4_e", STREAMED_SOUND_MISSION_J4_E}, {"j4_f", STREAMED_SOUND_MISSION_J4_F}, {"j6_1", STREAMED_SOUND_MISSION_J6_1}, - {"j6_a", STREAMED_SOUND_MISSION_J6_A}, {"j6_b", STREAMED_SOUND_MISSION_J6_B}, {"j6_c", STREAMED_SOUND_MISSION_J6_C}, - {"j6_d", STREAMED_SOUND_MISSION_J6_D}, {"t4_a", STREAMED_SOUND_MISSION_T4_A}, {"s1_a", STREAMED_SOUND_MISSION_S1_A}, - {"s1_a1", STREAMED_SOUND_MISSION_S1_A1}, {"s1_b", STREAMED_SOUND_MISSION_S1_B}, {"s1_c", STREAMED_SOUND_MISSION_S1_C}, - {"s1_c1", STREAMED_SOUND_MISSION_S1_C1}, {"s1_d", STREAMED_SOUND_MISSION_S1_D}, {"s1_e", STREAMED_SOUND_MISSION_S1_E}, - {"s1_f", STREAMED_SOUND_MISSION_S1_F}, {"s1_g", STREAMED_SOUND_MISSION_S1_G}, {"s1_h", STREAMED_SOUND_MISSION_S1_H}, - {"s1_i", STREAMED_SOUND_MISSION_S1_I}, {"s1_j", STREAMED_SOUND_MISSION_S1_J}, {"s1_k", STREAMED_SOUND_MISSION_S1_K}, - {"s1_l", STREAMED_SOUND_MISSION_S1_L}, {"s3_a", STREAMED_SOUND_MISSION_S3_A}, {"s3_b", STREAMED_SOUND_MISSION_S3_B}, - {"el3_a", STREAMED_SOUND_MISSION_EL3_A}, {"mf1_a", STREAMED_SOUND_MISSION_MF1_A}, {"mf2_a", STREAMED_SOUND_MISSION_MF2_A}, - {"mf3_a", STREAMED_SOUND_MISSION_MF3_A}, {"mf3_b", STREAMED_SOUND_MISSION_MF3_B}, {"mf3_b1", STREAMED_SOUND_MISSION_MF3_B1}, - {"mf3_c", STREAMED_SOUND_MISSION_MF3_C}, {"mf4_a", STREAMED_SOUND_MISSION_MF4_A}, {"mf4_b", STREAMED_SOUND_MISSION_MF4_B}, - {"mf4_c", STREAMED_SOUND_MISSION_MF4_C}, {"a1_a", STREAMED_SOUND_MISSION_A1_A}, {"a3_a", STREAMED_SOUND_MISSION_A3_A}, - {"a5_a", STREAMED_SOUND_MISSION_A5_A}, {"a4_a", STREAMED_SOUND_MISSION_A4_A}, {"a4_b", STREAMED_SOUND_MISSION_A4_B}, - {"a4_c", STREAMED_SOUND_MISSION_A4_C}, {"a4_d", STREAMED_SOUND_MISSION_A4_D}, {"k1_a", STREAMED_SOUND_MISSION_K1_A}, - {"k3_a", STREAMED_SOUND_MISSION_K3_A}, {"r1_a", STREAMED_SOUND_MISSION_R1_A}, {"r2_a", STREAMED_SOUND_MISSION_R2_A}, - {"r2_b", STREAMED_SOUND_MISSION_R2_B}, {"r2_c", STREAMED_SOUND_MISSION_R2_C}, {"r2_d", STREAMED_SOUND_MISSION_R2_D}, - {"r2_e", STREAMED_SOUND_MISSION_R2_E}, {"r2_f", STREAMED_SOUND_MISSION_R2_F}, {"r2_g", STREAMED_SOUND_MISSION_R2_G}, - {"r2_h", STREAMED_SOUND_MISSION_R2_H}, {"r5_a", STREAMED_SOUND_MISSION_R5_A}, {"r6_a", STREAMED_SOUND_MISSION_R6_A}, - {"r6_a1", STREAMED_SOUND_MISSION_R6_A1}, {"r6_b", STREAMED_SOUND_MISSION_R6_B}, {"lo2_a", STREAMED_SOUND_MISSION_LO2_A}, - {"lo6_a", STREAMED_SOUND_MISSION_LO6_A}, {"yd2_a", STREAMED_SOUND_MISSION_YD2_A}, {"yd2_b", STREAMED_SOUND_MISSION_YD2_B}, - {"yd2_c", STREAMED_SOUND_MISSION_YD2_C}, {"yd2_c1", STREAMED_SOUND_MISSION_YD2_C1}, {"yd2_d", STREAMED_SOUND_MISSION_YD2_D}, - {"yd2_e", STREAMED_SOUND_MISSION_YD2_E}, {"yd2_f", STREAMED_SOUND_MISSION_YD2_F}, {"yd2_g", STREAMED_SOUND_MISSION_YD2_G}, - {"yd2_h", STREAMED_SOUND_MISSION_YD2_H}, {"yd2_ass", STREAMED_SOUND_MISSION_YD2_ASS}, {"yd2_ok", STREAMED_SOUND_MISSION_YD2_OK}, - {"h5_a", STREAMED_SOUND_MISSION_H5_A}, {"h5_b", STREAMED_SOUND_MISSION_H5_B}, {"h5_c", STREAMED_SOUND_MISSION_H5_C}, - {"ammu_a", STREAMED_SOUND_MISSION_AMMU_A}, {"ammu_b", STREAMED_SOUND_MISSION_AMMU_B}, {"ammu_c", STREAMED_SOUND_MISSION_AMMU_C}, - {"door_1", STREAMED_SOUND_MISSION_DOOR_1}, {"door_2", STREAMED_SOUND_MISSION_DOOR_2}, {"door_3", STREAMED_SOUND_MISSION_DOOR_3}, - {"door_4", STREAMED_SOUND_MISSION_DOOR_4}, {"door_5", STREAMED_SOUND_MISSION_DOOR_5}, {"door_6", STREAMED_SOUND_MISSION_DOOR_6}, - {"t3_a", STREAMED_SOUND_MISSION_T3_A}, {"t3_b", STREAMED_SOUND_MISSION_T3_B}, {"t3_c", STREAMED_SOUND_MISSION_T3_C}, - {"k1_b", STREAMED_SOUND_MISSION_K1_B}, {"c_1", STREAMED_SOUND_MISSION_CAT1}}; - -int32 -FindMissionAudioSfx(const char *name) -{ - for (uint32 i = 0; i < ARRAY_SIZE(MissionAudioNameSfxAssoc); ++i) { - if (!CGeneral::faststricmp(MissionAudioNameSfxAssoc[i].m_pName, name)) - return MissionAudioNameSfxAssoc[i].m_nId; - } - debug("Can't find mission audio %s", name); - return NO_SAMPLE; -} - -void -cAudioManager::PreloadMissionAudio(const char *name) -{ - if (m_bIsInitialised) { - int32 missionAudioSfx = FindMissionAudioSfx(name); - if (missionAudioSfx != NO_SAMPLE) { - m_sMissionAudio.m_nSampleIndex = missionAudioSfx; - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; - m_sMissionAudio.field_22 = 0; - m_sMissionAudio.m_nMissionAudioCounter = m_nTimeSpent * SampleManager.GetStreamedFileLength(missionAudioSfx) / 1000; - m_sMissionAudio.m_nMissionAudioCounter *= 4; - m_sMissionAudio.m_bIsPlayed = false; - m_sMissionAudio.m_bPredefinedProperties = 1; - g_bMissionAudioLoadFailed = false; - } - } -} -void -cAudioManager::PreTerminateGameSpecificShutdown() -{ - if (m_nBridgeEntity >= 0) { - DestroyEntity(m_nBridgeEntity); - m_nBridgeEntity = AEHANDLE_NONE; - } - if (m_nPoliceChannelEntity >= 0) { - DestroyEntity(m_nPoliceChannelEntity); - m_nPoliceChannelEntity = AEHANDLE_NONE; - } - if (m_nWaterCannonEntity >= 0) { - DestroyEntity(m_nWaterCannonEntity); - m_nWaterCannonEntity = AEHANDLE_NONE; - } - if (m_nFireAudioEntity >= 0) { - DestroyEntity(m_nFireAudioEntity); - m_nFireAudioEntity = AEHANDLE_NONE; - } - if (m_nCollisionEntity >= 0) { - DestroyEntity(m_nCollisionEntity); - m_nCollisionEntity = AEHANDLE_NONE; - } - if (m_nFrontEndEntity >= 0) { - DestroyEntity(m_nFrontEndEntity); - m_nFrontEndEntity = AEHANDLE_NONE; - } - if (m_nProjectileEntity >= 0) { - DestroyEntity(m_nProjectileEntity); - m_nProjectileEntity = AEHANDLE_NONE; - } -} - void cAudioManager::ProcessActiveQueues() { @@ -3688,6088 +896,57 @@ cAudioManager::ProcessActiveQueues() } } -bool -cAudioManager::ProcessAirBrakes(cVehicleParams *params) -{ - CAutomobile *automobile; - uint8 rand; - - if (params->m_fDistance > 900.0f) - return false; - automobile = (CAutomobile *)params->m_pVehicle; - if (!automobile->bEngineOn) - return true; - - if ((automobile->m_fVelocityChangeForAudio < 0.025f || params->m_fVelocityChange >= 0.025f) && - (automobile->m_fVelocityChangeForAudio > -0.025f || params->m_fVelocityChange <= 0.025f)) - return true; - - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - rand = m_anRandomTable[0] % 10 + 70; - m_sQueueSample.m_nVolume = ComputeVolume(rand, 30.0f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 13; - m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AIR_BRAKES); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 10; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nEmittingVolume = rand; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - - return true; -} - -void -cAudioManager::ProcessAirportScriptObject(uint8 sound) -{ - static uint8 counter = 0; - - uint32 time = CTimer::GetTimeInMilliseconds(); - if (time > gAirportNextTime) { - switch (sound) { - case SCRIPT_SOUND_AIRPORT_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; - break; - case SCRIPT_SOUND_AIRPORT_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; - break; - default: - return; - } - float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(110, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_AIRPORT_ANNOUNCEMENT_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 110; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - gAirportNextTime = time + 10000 + m_anRandomTable[3] % 20000; - } - } - } -} - -bool -cAudioManager::ProcessBoatEngine(cVehicleParams *params) -{ - CBoat *boat; - float padRelativeAccerate; - float gasPedal; - int32 padAccelerate; - uint8 emittingVol; - float oneShotVol; - - static uint16 LastAccel = 0; - static uint8 LastVol = 0; - - static const int intensity = 50; - - if (params->m_fDistance < SQR(intensity)) { - boat = (CBoat *)params->m_pVehicle; - if (params->m_nIndex == REEFER) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(80, 50.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 39; - m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; - m_sQueueSample.m_nFrequency = 10386; - m_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 80; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = intensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 7; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - if (FindPlayerVehicle() == params->m_pVehicle) { - if (Pads[0].GetAccelerate() <= Pads[0].GetBrake()) - padAccelerate = Pads[0].GetBrake(); - else - padAccelerate = Pads[0].GetAccelerate(); - padRelativeAccerate = padAccelerate / 255; - emittingVol = (100.f * padRelativeAccerate) + 15; - m_sQueueSample.m_nFrequency = (3000.f * padRelativeAccerate) + 6000; - if (!boat->m_bIsAnchored) - m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; - } else { - gasPedal = Abs(boat->m_fGasPedal); - if (gasPedal > 0.0f) { - m_sQueueSample.m_nFrequency = 6000; - emittingVol = 15; - } else { - emittingVol = (100.f * gasPedal) + 15; - m_sQueueSample.m_nFrequency = (3000.f * gasPedal) + 6000; - if (!boat->m_bIsAnchored) - m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; - } - } - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 50.f, m_sQueueSample.m_fDistance); - if (!m_sQueueSample.m_nVolume) - return true; - m_sQueueSample.m_nCounter = 40; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; - m_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = intensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 7; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - } else { - if (FindPlayerVehicle() == params->m_pVehicle) { - if (Pads[0].GetAccelerate() <= Pads[0].GetBrake()) - padAccelerate = Pads[0].GetBrake(); - else - padAccelerate = Pads[0].GetAccelerate(); - if (padAccelerate <= 20) { - emittingVol = 45 - 45 * padAccelerate / 40; - m_sQueueSample.m_nFrequency = 100 * padAccelerate + 11025; - m_sQueueSample.m_nCounter = 39; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_IDLE; - if (LastAccel > 20) { - oneShotVol = LastVol; - PlayOneShot(m_sQueueSample.m_nEntityIndex, SOUND_17, oneShotVol); - } - } else { - emittingVol = 105 * padAccelerate / 255 + 15; - m_sQueueSample.m_nFrequency = 4000 * padAccelerate / 255 + 8000; - if (!boat->m_bIsAnchored) - m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; - m_sQueueSample.m_nCounter = 40; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; - } - LastVol = emittingVol; - LastAccel = padAccelerate; - } else { - gasPedal = Abs(boat->m_fGasPedal); - if (gasPedal > 0.0f) { - m_sQueueSample.m_nFrequency = 11025; - emittingVol = 45; - m_sQueueSample.m_nCounter = 39; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_IDLE; - } else { - emittingVol = (105.f * gasPedal) + 15; - m_sQueueSample.m_nFrequency = (4000.f * gasPedal) + 8000; - if (!boat->m_bIsAnchored) - m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; - m_sQueueSample.m_nCounter = 40; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_ACCEL; - } - } - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 50.f, m_sQueueSample.m_fDistance); - if (!m_sQueueSample.m_nVolume) - return true; - m_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = intensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 7; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - } - AddSampleToRequestedQueue(); - return true; - } - return false; -} - -bool -cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) -{ - float velocityChange; - int32 vol; - float multiplier; - - if (params->m_fDistance > 2500.f) - return false; - - velocityChange = Abs(params->m_fVelocityChange); - if (velocityChange <= 0.0005f && params->m_pVehicle->GetPosition().y) - return true; - - velocityChange = Min(0.75f, velocityChange); - multiplier = (velocityChange - 0.0005f) * 1.3342f; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - vol = (30.f * multiplier); - m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 38; - m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nFrequency = (6050.f * multiplier) + 16000; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = vol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - - return true; -} - -void -cAudioManager::ProcessBridge() -{ - float dist; - bool distCalculated = false; - - if (CBridge::pLiftRoad) { - m_sQueueSample.m_vecPos = CBridge::pLiftRoad->GetPosition(); - dist = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (dist < 202500.0f) { - CalculateDistance(distCalculated, dist); - switch (CBridge::State) { - case STATE_BRIDGE_LOCKED: - case STATE_LIFT_PART_IS_UP: - case STATE_LIFT_PART_ABOUT_TO_MOVE_UP: - ProcessBridgeWarning(); - break; - case STATE_LIFT_PART_MOVING_DOWN: - case STATE_LIFT_PART_MOVING_UP: - ProcessBridgeWarning(); - ProcessBridgeMotor(); - break; - default: - break; - } - ProcessBridgeOneShots(); - } - } -} - -void -cAudioManager::ProcessBridgeMotor() -{ - if (m_sQueueSample.m_fDistance < bridgeIntensity) { - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, bridgeIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; // todo check sfx name - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = 5500; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = maxVolume; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = bridgeIntensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = false; - AddSampleToRequestedQueue(); - } - } -} - -void -cAudioManager::ProcessBridgeOneShots() -{ - if (CBridge::State == STATE_LIFT_PART_IS_UP && CBridge::OldState == STATE_LIFT_PART_MOVING_UP) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else { - if (CBridge::State == STATE_LIFT_PART_IS_DOWN && CBridge::OldState == STATE_LIFT_PART_MOVING_DOWN) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else { - if (CBridge::State == STATE_LIFT_PART_MOVING_UP && CBridge::OldState == STATE_LIFT_PART_ABOUT_TO_MOVE_UP) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else { - if (CBridge::State == STATE_LIFT_PART_MOVING_DOWN && CBridge::OldState == STATE_LIFT_PART_IS_UP) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else - return; - } - } - } - if (m_sQueueSample.m_fDistance < bridgeIntensity) { - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, bridgeIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nEmittingVolume = maxVolume; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = bridgeIntensity; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bReverbFlag = false; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -void -cAudioManager::ProcessBridgeWarning() -{ - if (CStats::CommercialPassed && m_sQueueSample.m_fDistance < 450.f) { - m_sQueueSample.m_nVolume = ComputeVolume(100, 450.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_nSampleIndex = SFX_BRIDGE_OPEN_WARNING; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BRIDGE_OPEN_WARNING); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 100; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 450.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 8; - m_sQueueSample.m_bReverbFlag = false; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -bool -cAudioManager::ProcessCarBombTick(cVehicleParams *params) -{ - CAutomobile *automobile; - - if (params->m_fDistance >= SQR(40.f)) - return false; - automobile = (CAutomobile *)params->m_pVehicle; - if (automobile->bEngineOn && automobile->m_bombType == CARBOMB_TIMEDACTIVE) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(60, 40.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 35; - m_sQueueSample.m_nSampleIndex = SFX_COUNTDOWN; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COUNTDOWN); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 60; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 40.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - return true; -} - -void -cAudioManager::ProcessCesna(cVehicleParams *params) -{ - static uint8 nAccel = 0; - - //((CAutomobile *)params->m_pVehicle)->Damage.GetEngineStatus(); - - if (FindPlayerVehicle() == params->m_pVehicle) { - if (params->m_nIndex == DODO) { - if (Pads[0].GetAccelerate() <= 0) { - if (nAccel) - --nAccel; - } else if (nAccel < 60) { - ++nAccel; - } - AddPlayerCarSample(85 * (60 - nAccel) / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_IDLE, 0, 52, 1); - AddPlayerCarSample(85 * nAccel / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_REV, 0, 2, 1); - } - } else if (params->m_nIndex == DODO) { - AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, 0, 52, 1); - } else if (params->m_fDistance < 40000.f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 52; - m_sQueueSample.m_nSampleIndex = SFX_CESNA_IDLE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nFrequency = 12500; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nReleasingVolumeDivider = 8; - m_sQueueSample.m_nEmittingVolume = 80; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 8.0f; - m_sQueueSample.m_fSoundIntensity = 200.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - if (params->m_fDistance < 8100.f) { - m_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 2; - m_sQueueSample.m_nSampleIndex = SFX_CESNA_REV; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nFrequency = 25000; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nReleasingVolumeDivider = 4; - m_sQueueSample.m_nEmittingVolume = 80; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 8.0f; - m_sQueueSample.m_fSoundIntensity = 90.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } -} - -void -cAudioManager::ProcessCinemaScriptObject(uint8 sound) -{ - uint8 rand; - - static uint8 counter = 0; - - uint32 time = CTimer::GetTimeInMilliseconds(); - if (time > gCinemaNextTime) { - switch (sound) { - case SCRIPT_SOUND_CINEMA_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; - break; - case SCRIPT_SOUND_CINEMA_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; - break; - default: - return; - } - float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - rand = m_anRandomTable[0] % 90 + 30; - m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = counter % 3 + SFX_CINEMA_BASS_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 4); - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = rand; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - gCinemaNextTime = time + 1000 + m_anRandomTable[3] % 4000; - } - } - } -} - -void -cAudioManager::ProcessCrane() -{ - CCrane *crane = (CCrane *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity; - float distSquared; - bool distCalculated = false; - static const int intensity = 80; - - if (crane) { - if (crane->m_nCraneStatus == CCrane::ACTIVATED) { - if (crane->m_nCraneState != CCrane::IDLE) { - m_sQueueSample.m_vecPos = crane->m_pCraneEntity->GetPosition(); - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(intensity)) { - CalculateDistance(distCalculated, distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(100, 80.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_nSampleIndex = SFX_CRANE_MAGNET; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nFrequency = 6000; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 100; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = intensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents) { - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_2; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COL_CAR_2); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = true; - AddSampleToRequestedQueue(); - } - } - } - } - } -} - -void -cAudioManager::ProcessDocksScriptObject(uint8 sound) -{ - uint32 time; - uint8 rand; - float distSquared; - - static uint32 counter = 0; - - time = CTimer::GetTimeInMilliseconds(); - if (time > gDocksNextTime) { - switch (sound) { - case SCRIPT_SOUND_DOCKS_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; - break; - case SCRIPT_SOUND_DOCKS_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; - break; - default: - return; - } - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - rand = m_anRandomTable[0] % 60 + 40; - m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_DOCKS_FOGHORN; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOCKS_FOGHORN); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = rand; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - gDocksNextTime = time + 10000 + m_anRandomTable[3] % 40000; - } - } - } -} - -bool -cAudioManager::ProcessEngineDamage(cVehicleParams *params) -{ - CAutomobile *veh; - uint8 engineStatus; - uint8 emittingVolume; - - if (params->m_fDistance >= SQR(engineDamageIntensity)) - return false; - veh = (CAutomobile *)params->m_pVehicle; - if (veh->bEngineOn) { - engineStatus = veh->Damage.GetEngineStatus(); - if (engineStatus > 250 || engineStatus < 100) - return true; - if (engineStatus < 225) { - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; - emittingVolume = 6; - m_sQueueSample.m_nReleasingVolumeModificator = 7; - m_sQueueSample.m_nFrequency = 40000; - } else { - emittingVolume = 60; - m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; - m_sQueueSample.m_nReleasingVolumeModificator = 7; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); - } - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, engineDamageIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 28; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVolume; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = engineDamageIntensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - return true; -} - -void -cAudioManager::ProcessEntity(int32 id) -{ - if (m_asAudioEntities[id].m_nStatus) { - m_sQueueSample.m_nEntityIndex = id; - switch (m_asAudioEntities[id].m_nType) { - case AUDIOTYPE_PHYSICAL: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessPhysical(id); - } - break; - case AUDIOTYPE_EXPLOSION: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessExplosions(id); - } - break; - case AUDIOTYPE_FIRE: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessFires(id); - } - break; - case AUDIOTYPE_WEATHER: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessWeather(id); - } - break; - case AUDIOTYPE_CRANE: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessCrane(); - } - break; - case AUDIOTYPE_SCRIPTOBJECT: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessScriptObject(id); - } - break; - case AUDIOTYPE_BRIDGE: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessBridge(); - } - break; - case AUDIOTYPE_FRONTEND: - m_sQueueSample.m_bReverbFlag = false; - ProcessFrontEnd(); - break; - case AUDIOTYPE_PROJECTILE: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessProjectiles(); - } - break; - case AUDIOTYPE_GARAGE: - if (!m_nUserPause) - ProcessGarages(); - break; - case AUDIOTYPE_FIREHYDRANT: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessFireHydrant(); - } - break; - case AUDIOTYPE_WATERCANNON: - if (!m_nUserPause) { - m_sQueueSample.m_bReverbFlag = true; - ProcessWaterCannon(id); - } - break; - default: - return; - } - } -} - -void -cAudioManager::ProcessExplosions(int32 explosion) -{ - uint8 type; - CVector *pos; - float distSquared; - - for (uint8 i = 0; i < ARRAY_SIZE(gaExplosion); i++) { - if (CExplosion::GetExplosionActiveCounter(i) == 1) { - CExplosion::ResetExplosionActiveCounter(i); - type = CExplosion::GetExplosionType(i); - switch (type) { - case EXPLOSION_GRENADE: - case EXPLOSION_ROCKET: - case EXPLOSION_BARREL: - case EXPLOSION_TANK_GRENADE: - m_sQueueSample.m_fSoundIntensity = 400.0f; - m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_2; - m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 38000; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - break; - case EXPLOSION_MOLOTOV: - m_sQueueSample.m_fSoundIntensity = 200.0f; - m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_3; - m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 19000; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - break; - case EXPLOSION_MINE: - case EXPLOSION_HELI_BOMB: - m_sQueueSample.m_fSoundIntensity = 300.0f; - m_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT; - m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 12347; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - break; - default: - m_sQueueSample.m_fSoundIntensity = 400.0f; - m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_1; - m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 38000; - if (type == EXPLOSION_HELI) - m_sQueueSample.m_nFrequency = 8 * m_sQueueSample.m_nFrequency / 10; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - break; - } - pos = CExplosion::GetExplosionPosition(i); - m_sQueueSample.m_vecPos = *pos; - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = i; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_nEmittingVolume = maxVolume; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = true; - AddSampleToRequestedQueue(); - } - } - } - } -} - -void -cAudioManager::ProcessFireHydrant() -{ - float distSquared; - bool distCalculated = false; - static const int intensity = 35; - - m_sQueueSample.m_vecPos = ((CEntity *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)->GetPosition(); - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(intensity)) { - CalculateDistance(distCalculated, distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(40, 35.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 4; - m_sQueueSample.m_nFrequency = 15591; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 40; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = intensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -void cAudioManager::ProcessFires(int32) -{ - CEntity *entity; - uint8 emittingVol; - float distSquared; - - for (uint8 i = 0; i < NUM_FIRES; i++) { - if (gFireManager.m_aFires[i].m_bIsOngoing && gFireManager.m_aFires[i].m_bAudioSet) { - entity = gFireManager.m_aFires[i].m_pEntity; - if (entity) { - switch (entity->GetType()) { - case ENTITY_TYPE_BUILDING: - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; - emittingVol = 100; - m_sQueueSample.m_nFrequency = 8 * SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE) / 10; - m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); - m_sQueueSample.m_nReleasingVolumeModificator = 6; - break; - case ENTITY_TYPE_PED: - m_sQueueSample.m_fSoundIntensity = 25.0f; - m_sQueueSample.m_nSampleIndex = SFX_PED_ON_FIRE; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PED_ON_FIRE); - emittingVol = 60; - m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); - m_sQueueSample.m_nReleasingVolumeModificator = 10; - break; - default: - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); - m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); - emittingVol = 80; - m_sQueueSample.m_nReleasingVolumeModificator = 8; - } - } else { - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); - m_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64); - emittingVol = 80; - m_sQueueSample.m_nReleasingVolumeModificator = 8; - } - m_sQueueSample.m_vecPos = gFireManager.m_aFires[i].m_vecPos; - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = i; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nReleasingVolumeDivider = 10; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } -} - -void -cAudioManager::ProcessFrontEnd() -{ - bool stereo; - bool processedPickup; - bool processedMission; - int16 sample; - - static uint8 counter = 0; - static uint32 cPickupNextFrame = 0; - static uint32 cPartMisComNextFrame = 0; - - for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { - processedPickup = false; - stereo = false; - processedMission = false; - switch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]) { - case SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM: - m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_RIFLE; - break; - case SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM: - m_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_ROCKET_LAUNCHER; - break; - case SOUND_GARAGE_NO_MONEY: - case SOUND_GARAGE_BAD_VEHICLE: - case SOUND_GARAGE_BOMB_ALREADY_SET: - m_sQueueSample.m_nSampleIndex = SFX_PICKUP_ERROR_LEFT; - stereo = true; - break; - case SOUND_GARAGE_OPENING: - case SOUND_GARAGE_BOMB1_SET: - case SOUND_GARAGE_BOMB2_SET: - case SOUND_GARAGE_BOMB3_SET: - case SOUND_41: - case SOUND_GARAGE_VEHICLE_DECLINED: - case SOUND_GARAGE_VEHICLE_ACCEPTED: - case SOUND_PICKUP_HEALTH: - case SOUND_4B: - case SOUND_PICKUP_ADRENALINE: - case SOUND_PICKUP_ARMOUR: - case SOUND_EVIDENCE_PICKUP: - case SOUND_UNLOAD_GOLD: - m_sQueueSample.m_nSampleIndex = SFX_PICKUP_2_LEFT; - processedPickup = true; - stereo = true; - break; - case SOUND_PICKUP_WEAPON_BOUGHT: - case SOUND_PICKUP_WEAPON: - m_sQueueSample.m_nSampleIndex = SFX_PICKUP_1_LEFT; - processedPickup = true; - stereo = true; - break; - case SOUND_4A: - m_sQueueSample.m_nSampleIndex = SFX_PICKUP_ERROR_LEFT; - processedPickup = true; - stereo = true; - break; - case SOUND_PICKUP_BONUS: - case SOUND_PICKUP_MONEY: - case SOUND_PICKUP_HIDDEN_PACKAGE: - case SOUND_PICKUP_PACMAN_PILL: - case SOUND_PICKUP_PACMAN_PACKAGE: - case SOUND_PICKUP_FLOAT_PACKAGE: - m_sQueueSample.m_nSampleIndex = SFX_PICKUP_3_LEFT; - processedPickup = true; - stereo = true; - break; - case SOUND_PAGER: - m_sQueueSample.m_nSampleIndex = SFX_PAGER; - break; - case SOUND_RACE_START_3: - case SOUND_RACE_START_2: - case SOUND_RACE_START_1: - case SOUND_CLOCK_TICK: - m_sQueueSample.m_nSampleIndex = SFX_TIMER_BEEP; - break; - case SOUND_RACE_START_GO: - m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE; - break; - case SOUND_PART_MISSION_COMPLETE: - m_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE; - processedMission = true; - break; - case SOUND_FRONTEND_MENU_STARTING: - m_sQueueSample.m_nSampleIndex = SFX_START_BUTTON_LEFT; - stereo = true; - break; - case SOUND_FRONTEND_MENU_COMPLETED: - m_sQueueSample.m_nSampleIndex = SFX_PAGE_CHANGE_AND_BACK_LEFT; - stereo = true; - break; - case SOUND_FRONTEND_MENU_DENIED: - m_sQueueSample.m_nSampleIndex = SFX_HIGHLIGHT_LEFT; - stereo = true; - break; - case SOUND_FRONTEND_MENU_SUCCESS: - m_sQueueSample.m_nSampleIndex = SFX_SELECT_LEFT; - stereo = true; - break; - case SOUND_FRONTEND_EXIT: - m_sQueueSample.m_nSampleIndex = SFX_SUB_MENU_BACK_LEFT; - stereo = true; - break; - case SOUND_9A: - m_sQueueSample.m_nSampleIndex = SFX_STEREO_LEFT; - stereo = true; - break; - case SOUND_9B: - m_sQueueSample.m_nSampleIndex = SFX_MONO; - break; - case SOUND_FRONTEND_AUDIO_TEST: - m_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 3 + SFX_NOISE_BURST_1; - break; - case SOUND_FRONTEND_FAIL: - m_sQueueSample.m_nSampleIndex = SFX_ERROR_LEFT; - stereo = true; - break; - case SOUND_FRONTEND_NO_RADIO: - case SOUND_FRONTEND_RADIO_CHANGE: - m_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK; - break; - case SOUND_A0: - m_sQueueSample.m_nSampleIndex = SFX_INFO; - break; - default: - continue; - } - - if (processedPickup) { - if (m_FrameCounter <= cPickupNextFrame) - continue; - cPickupNextFrame = m_FrameCounter + 5; - } else if (processedMission) { - if (m_FrameCounter <= cPartMisComNextFrame) - continue; - cPartMisComNextFrame = m_FrameCounter + 5; - } - - sample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; - if (sample == SFX_RAIN) { - m_sQueueSample.m_nFrequency = 28509; - } else if (sample == SFX_PICKUP_1_LEFT) { - if (1.f == m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]) - m_sQueueSample.m_nFrequency = 32000; - else - m_sQueueSample.m_nFrequency = 48000; - } else { - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - } - m_sQueueSample.m_nVolume = 110; - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_bIs2D = true; - m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - if (stereo) - m_sQueueSample.m_nOffset = m_anRandomTable[0] & 31; - else - m_sQueueSample.m_nOffset = 63; - m_sQueueSample.m_bReverbFlag = false; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - if (stereo) { - ++m_sQueueSample.m_nSampleIndex; - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_nOffset = maxVolume - m_sQueueSample.m_nOffset; - AddSampleToRequestedQueue(); - } - } -} - -void -cAudioManager::ProcessGarages() -{ - CEntity *entity; - eGarageState state; - uint32 sampleIndex; - uint8 j; - float distSquared; - bool distCalculated; - - static uint8 iSound = 32; - -#define LOOP_HELPER \ - for (j = 0; j < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; ++j) { \ - switch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j]) { \ - case SOUND_GARAGE_DOOR_CLOSED: \ - case SOUND_GARAGE_DOOR_OPENED: \ - if (distSquared < 6400.f) { \ - CalculateDistance(distCalculated, distSquared); \ - m_sQueueSample.m_nVolume = ComputeVolume(60, 80.f, m_sQueueSample.m_fDistance); \ - if (m_sQueueSample.m_nVolume) { \ - if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { \ - m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; \ - m_sQueueSample.m_nFrequency = 6735; \ - } else if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j] == 69) { \ - m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; \ - m_sQueueSample.m_nFrequency = 22000; \ - } else { \ - m_sQueueSample.m_nSampleIndex = SFX_COL_GARAGE_DOOR_1; \ - m_sQueueSample.m_nFrequency = 18000; \ - } \ - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; \ - m_sQueueSample.m_nReleasingVolumeModificator = 4; \ - m_sQueueSample.m_nEmittingVolume = 60; \ - m_sQueueSample.m_fSpeedMultiplier = 0.0f; \ - m_sQueueSample.m_fSoundIntensity = 80.0f; \ - /*m_sQueueSample.m_nReleasingVolumeModificator = 4;*/ \ - m_sQueueSample.m_bReverbFlag = true; \ - /*m_sQueueSample.m_bReverbFlag = true;*/ \ - m_sQueueSample.m_bIs2D = false; \ - m_sQueueSample.m_bReleasingSoundFlag = true; \ - m_sQueueSample.m_nLoopCount = 1; \ - m_sQueueSample.m_nLoopStart = 0; \ - m_sQueueSample.m_nLoopEnd = -1; \ - m_sQueueSample.m_nCounter = iSound++; \ - if (iSound < 32) \ - iSound = 32; \ - m_sQueueSample.m_bRequireReflection = true; \ - AddSampleToRequestedQueue(); \ - } \ - } \ - break; \ - default: \ - continue; \ - } \ - } - - for (uint32 i = 0; i < CGarages::NumGarages; ++i) { - if (CGarages::aGarages[i].m_eGarageType == GARAGE_NONE) - continue; - entity = CGarages::aGarages[i].m_pDoor1; - if (!entity) - continue; - m_sQueueSample.m_vecPos = entity->GetPosition(); - distCalculated = false; - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < 6400.f) { - state = CGarages::aGarages[i].m_eGarageState; - if (state == GS_OPENING || state == GS_CLOSING || state == GS_AFTERDROPOFF) { - CalculateDistance(distCalculated, distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(90, 80.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { - if (CGarages::aGarages[i].m_eGarageState == GS_AFTERDROPOFF) { - if (!(m_FrameCounter & 1)) { - LOOP_HELPER - continue; - } - if (m_anRandomTable[1] & 1) { - sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_CAR_1; - } else { - sampleIndex = m_anRandomTable[2] % 6 + SFX_COL_CAR_PANEL_1; - } - m_sQueueSample.m_nSampleIndex = sampleIndex; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2; - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nCounter = iSound++; - if (iSound < 32) - iSound = 32; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nEmittingVolume = 90; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - LOOP_HELPER - continue; - } - m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; - m_sQueueSample.m_nFrequency = 6543; - } else { - m_sQueueSample.m_nSampleIndex = SFX_GARAGE_DOOR_LOOP; - m_sQueueSample.m_nFrequency = 13961; - } - m_sQueueSample.m_nCounter = i; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nEmittingVolume = 90; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - LOOP_HELPER - } - } -#undef LOOP_HELPER -} - -struct tHelicopterSampleData { - float m_fMaxDistance; - float m_fBaseDistance; - uint8 m_bBaseVolume; -}; - -bool -cAudioManager::ProcessHelicopter(cVehicleParams *params) -{ - CHeli *heli; - float MaxDist; - float dist; - float baseDist; - int32 emittingVol; - static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, maxVolume}, {60.f, 30.f, maxVolume}}; - - if (gHeliSfxRanges[0].m_fMaxDistance * gHeliSfxRanges[0].m_fMaxDistance <= params->m_fDistance) - return false; - - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - heli = (CHeli *)params->m_pVehicle; - for (uint32 i = 0; i < ARRAY_SIZE(gHeliSfxRanges); i++) { - MaxDist = gHeliSfxRanges[i].m_fMaxDistance; - dist = m_sQueueSample.m_fDistance; - if (dist >= MaxDist) - return true; - baseDist = gHeliSfxRanges[i].m_fBaseDistance; - if (dist < baseDist) - emittingVol = (gHeliSfxRanges[i].m_bBaseVolume * ((MaxDist - dist) / (MaxDist - baseDist))); - else - emittingVol = gHeliSfxRanges[i].m_bBaseVolume; - - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, gHeliSfxRanges[i].m_fMaxDistance, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = i + 65; - m_sQueueSample.m_nSampleIndex = i + SFX_HELI_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nFrequency = 1200 * heli->m_nHeliId + SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 6.0f; - m_sQueueSample.m_fSoundIntensity = gHeliSfxRanges[i].m_fMaxDistance; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - return true; -} - -void -cAudioManager::ProcessHomeScriptObject(uint8 sound) -{ - uint32 time; - uint8 rand; - float dist; - - static uint8 counter = 0; - - time = CTimer::GetTimeInMilliseconds(); - if (time > gHomeNextTime) { - switch (sound) { - case SCRIPT_SOUND_HOME_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; - break; - case SCRIPT_SOUND_HOME_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; - break; - default: - return; - } - dist = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (dist < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(dist); - rand = m_anRandomTable[0] % 30 + 40; - m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 5 + SFX_HOME_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_nEmittingVolume = rand; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = true; - AddSampleToRequestedQueue(); - gHomeNextTime = time + 1000 + m_anRandomTable[3] % 4000; - } - } - } -} - -void -cAudioManager::ProcessJumbo(cVehicleParams *params) -{ - CPlane *plane; - float position; - - if (params->m_fDistance < 193600.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - plane = (CPlane *)params->m_pVehicle; - DoJumboVolOffset(); - position = PlanePathPosition[plane->m_nPlaneId]; - if (position <= TakeOffPoint) { - if (plane->m_fSpeed <= 0.10334f) { - ProcessJumboTaxi(); - return; - } - - ProcessJumboAccel(plane); - } else if (300.0f + TakeOffPoint >= position) { - ProcessJumboTakeOff(plane); - } else if (LandingPoint - 350.0f >= position) { - ProcessJumboFlying(); - } else { - if (position > LandingPoint) { - if (plane->m_fSpeed > 0.10334f) { - ProcessJumboDecel(plane); - return; - } - ProcessJumboTaxi(); - return; - } - ProcessJumboLanding(plane); - } - } -} - -void -cAudioManager::ProcessJumboAccel(CPlane *plane) -{ - int32 engineFreq; - int32 vol; - float whineSoundFreq; - float modificator; - - if (SetupJumboFlySound(20)) { - modificator = (plane->m_fSpeed - 0.10334f) * 1.676f; - if (modificator > 1.0f) - modificator = 1.0f; - if (SetupJumboRumbleSound(maxVolume * modificator) && SetupJumboTaxiSound((1.0f - modificator) * 75.f)) { - if (modificator < 0.2f) { - whineSoundFreq = modificator * 5.f * 14600.0f + 29500; - vol = modificator * 5.f * maxVolume; - engineFreq = modificator * 5.f * 6050.f + 16000; - } else { - whineSoundFreq = 44100; - engineFreq = 22050; - vol = maxVolume; - } - SetupJumboEngineSound(vol, engineFreq); - SetupJumboWhineSound(18, whineSoundFreq); - } - } -} - -void -cAudioManager::ProcessJumboDecel(CPlane *plane) -{ - if (SetupJumboFlySound(20) && SetupJumboTaxiSound(75)) { - const float modificator = Min(1.f, (plane->m_fSpeed - 0.10334f) * 1.676f); - SetupJumboEngineSound(maxVolume * modificator, 6050.f * modificator + 16000); - SetupJumboWhineSound(18, 29500); - } -} - -void -cAudioManager::ProcessJumboFlying() -{ - if (SetupJumboFlySound(maxVolume)) - SetupJumboEngineSound(63, 22050); -} - -void -cAudioManager::ProcessJumboLanding(CPlane *plane) -{ - const float modificator = (LandingPoint - PlanePathPosition[plane->m_nPlaneId]) / 350.f; - if (SetupJumboFlySound(107.f * modificator + 20)) { - if (SetupJumboTaxiSound(75.f * (1.f - modificator))) { - SetupJumboEngineSound(maxVolume, 22050); - SetupJumboWhineSound(18.f * (1.f - modificator), 14600.f * modificator + 29500); - } - } -} - -void -cAudioManager::ProcessJumboTakeOff(CPlane *plane) -{ - const float modificator = (PlanePathPosition[plane->m_nPlaneId] - TakeOffPoint) / 300.f; - - if (SetupJumboFlySound((107.f * modificator) + 20) && SetupJumboRumbleSound(maxVolume * (1.f - modificator))) { - if (SetupJumboEngineSound(maxVolume, 22050)) - SetupJumboWhineSound(18.f * (1.f - modificator), 44100); - } -} - -void -cAudioManager::ProcessJumboTaxi() -{ - if (SetupJumboFlySound(20)) { - if (SetupJumboTaxiSound(75)) - SetupJumboWhineSound(18, 29500); - } -} - -void -cAudioManager::ProcessLaunderetteScriptObject(uint8 sound) -{ - switch (sound) { - case SCRIPT_SOUND_LAUNDERETTE_LOOP_S: - case SCRIPT_SOUND_LAUNDERETTE_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 30.0f; - break; - default: - return; - } - float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(45, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_LAUNDERETTE_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_LAUNDERETTE_LOOP); - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 45; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - m_sQueueSample.m_nVolume = ComputeVolume(110, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_LAUNDERETTE_SONG_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_LAUNDERETTE_SONG_LOOP); - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 110; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -void -cAudioManager::ProcessLoopingScriptObject(uint8 sound) -{ - uint8 emittingVolume; - float distSquared; - - switch (sound) { - case SCRIPT_SOUND_PARTY_1_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_1_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_2_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_2); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_2_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_2); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_3_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_3); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_3_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_3); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_4_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_4); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_4_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_4); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_5_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_5); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_5_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_5); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_6_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_6); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_6_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_6); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_7_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_7); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_7_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_7); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_8_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_8); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_8_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_8); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_9_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_9); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_9_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_9); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_10_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_10); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_10_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_10); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_11_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_11); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_11_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_11); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_12_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_12); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_12_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_12); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_13_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_RAGGA); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_13_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_RAGGA); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_STRIP_CLUB_LOOP_1_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_STRIP_CLUB_LOOP_1_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_STRIP_CLUB_LOOP_2_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_2); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_STRIP_CLUB_LOOP_2_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_2); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_WORK_SHOP_LOOP_S: - case SCRIPT_SOUND_WORK_SHOP_LOOP_L: - ProcessWorkShopScriptObject(sound); - return; - case SCRIPT_SOUND_SAWMILL_LOOP_S: - case SCRIPT_SOUND_SAWMILL_LOOP_L: - ProcessSawMillScriptObject(sound); - return; - case SCRIPT_SOUND_38: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_DOG_FOOD_FACTORY; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOG_FOOD_FACTORY); - m_sQueueSample.m_nReleasingVolumeModificator = 6; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_39: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_DOG_FOOD_FACTORY; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOG_FOOD_FACTORY); - m_sQueueSample.m_nReleasingVolumeModificator = 6; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_LAUNDERETTE_LOOP_S: - case SCRIPT_SOUND_LAUNDERETTE_LOOP_L: - ProcessLaunderetteScriptObject(sound); - return; - case SCRIPT_SOUND_CHINATOWN_RESTAURANT_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_CHINATOWN; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_CHINATOWN); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_CHINATOWN_RESTAURANT_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_CHINATOWN; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_CHINATOWN); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_CIPRIANI_RESAURANT_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_ITALY; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_ITALY); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_CIPRIANI_RESAURANT_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_ITALY; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_ITALY); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_46_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_47_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_MARCO_BISTRO_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_2); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_MARCO_BISTRO_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 110; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RESTAURANT_GENERIC_2); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_AIRPORT_LOOP_S: - case SCRIPT_SOUND_AIRPORT_LOOP_L: - ProcessAirportScriptObject(sound); - return; - case SCRIPT_SOUND_SHOP_LOOP_S: - case SCRIPT_SOUND_SHOP_LOOP_L: - ProcessShopScriptObject(sound); - return; - case SCRIPT_SOUND_CINEMA_LOOP_S: - case SCRIPT_SOUND_CINEMA_LOOP_L: - ProcessCinemaScriptObject(sound); - return; - case SCRIPT_SOUND_DOCKS_LOOP_S: - case SCRIPT_SOUND_DOCKS_LOOP_L: - ProcessDocksScriptObject(sound); - return; - case SCRIPT_SOUND_HOME_LOOP_S: - case SCRIPT_SOUND_HOME_LOOP_L: - ProcessHomeScriptObject(sound); - return; - case SCRIPT_SOUND_FRANKIE_PIANO: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_PIANO_BAR_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PIANO_BAR_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PARTY_1_LOOP: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PORN_CINEMA_1_S: - case SCRIPT_SOUND_PORN_CINEMA_1_L: - case SCRIPT_SOUND_PORN_CINEMA_2_S: - case SCRIPT_SOUND_PORN_CINEMA_2_L: - case SCRIPT_SOUND_PORN_CINEMA_3_S: - case SCRIPT_SOUND_PORN_CINEMA_3_L: - case SCRIPT_SOUND_MISTY_SEX_S: - case SCRIPT_SOUND_MISTY_SEX_L: - ProcessPornCinema(sound); - return; - case SCRIPT_SOUND_BANK_ALARM_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_BANK_ALARM_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 90; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BANK_ALARM_1); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_BANK_ALARM_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_BANK_ALARM_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 90; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BANK_ALARM_1); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_POLICE_BALL_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BALL_1); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_POLICE_BALL_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BALL_1); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_INDUSTRIAL); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_INDUSTRIAL); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S: - case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L: - ProcessPoliceCellBeatingScriptObject(sound); - return; - case SCRIPT_SOUND_RAVE_1_LOOP_S: - case SCRIPT_SOUND_RAVE_2_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_RAVE_1_LOOP_L: - case SCRIPT_SOUND_RAVE_2_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_RAVE_3_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_SUBURBAN); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_RAVE_3_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_SUBURBAN); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - case SCRIPT_SOUND_PRETEND_FIRE_LOOP: - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 80; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE); - m_sQueueSample.m_nReleasingVolumeModificator = 8; - m_sQueueSample.m_nReleasingVolumeDivider = 10; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - break; - default: - return; - } - - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_nEmittingVolume = emittingVolume; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -void -cAudioManager::ProcessMissionAudio() -{ - float dist; - uint8 emittingVol; - uint8 pan; - float distSquared; - CVector vec; - - static uint8 nCheckPlayingDelay = 0; - static uint8 nFramesUntilFailedLoad = 0; - static uint8 nFramesForPretendPlaying = 0; - - if (m_bIsInitialised) { - if (m_sMissionAudio.m_nSampleIndex != NO_SAMPLE) { - switch (m_sMissionAudio.m_nLoadingStatus) { - case LOADING_STATUS_NOT_LOADED: - SampleManager.PreloadStreamedFile(m_sMissionAudio.m_nSampleIndex, 1); - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; - nFramesUntilFailedLoad = 0; - return; - case LOADING_STATUS_LOADED: - if (!m_sMissionAudio.m_bIsPlayed) - return; - if (g_bMissionAudioLoadFailed) { - if (m_bTimerJustReset) { - ClearMissionAudio(); - SampleManager.StopStreamedFile(1); - nFramesForPretendPlaying = 0; - nCheckPlayingDelay = 0; - nFramesUntilFailedLoad = 0; - } else if (!m_nUserPause) { - if (++nFramesForPretendPlaying < 120) { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; - } else { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - } - } - } else { - if (m_sMissionAudio.m_nPlayStatus) { - if (m_sMissionAudio.m_nPlayStatus != PLAY_STATUS_PLAYING) - return; - if (m_bTimerJustReset) { - ClearMissionAudio(); - SampleManager.StopStreamedFile(1); - return; - } - if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { - if (!m_nUserPause) { - if (nCheckPlayingDelay) { - --nCheckPlayingDelay; - } else if (GetMissionScriptPoliceAudioPlayingStatus() == PLAY_STATUS_FINISHED || - m_sMissionAudio.m_nMissionAudioCounter-- == 0) { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - SampleManager.StopStreamedFile(1); - m_sMissionAudio.m_nMissionAudioCounter = 0; - } - } - } else if (m_sMissionAudio.field_22) { - if (SampleManager.IsStreamPlaying(1) || m_nUserPause || m_nPreviousUserPause) { - if (m_nUserPause) - SampleManager.PauseStream(1, 1); - else - SampleManager.PauseStream(0, 1); - } else { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - SampleManager.StopStreamedFile(1); - m_sMissionAudio.m_nMissionAudioCounter = 0; - } - } else { - if (m_nUserPause) - return; - if (nCheckPlayingDelay--) { - if (!SampleManager.IsStreamPlaying(1)) - return; - nCheckPlayingDelay = 0; - } - m_sMissionAudio.field_22 = 1; - } - } else { - if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { - SetMissionScriptPoliceAudio(m_sMissionAudio.m_nSampleIndex); - } else { - if (m_nUserPause) - SampleManager.PauseStream(1, 1); - if (m_sMissionAudio.m_bPredefinedProperties) { - SampleManager.SetStreamedVolumeAndPan(80, 63, 1, 1); - } else { - distSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos); - if (distSquared >= 2500.f) { - emittingVol = 0; - pan = 63; - } else { - dist = Sqrt(distSquared); - emittingVol = ComputeVolume(80, 50.0f, dist); - TranslateEntity(&m_sMissionAudio.m_vecPos, &vec); - pan = ComputePan(50.f, &vec); - } - SampleManager.SetStreamedVolumeAndPan(emittingVol, pan, 1, 1); - } - SampleManager.StartPreloadedStreamedFile(1); - } - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; - nCheckPlayingDelay = 30; - } - } - break; - case 2: - if (++nFramesUntilFailedLoad >= 90) { - nFramesForPretendPlaying = 0; - g_bMissionAudioLoadFailed = true; - nFramesUntilFailedLoad = 0; - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; - } - return; - default: - return; - } - } - } -} - -void -cAudioManager::ProcessModelCarEngine(cVehicleParams *params) -{ - CAutomobile *automobile; - float allowedVelocity; - int32 emittingVol; - float velocityChange; - - if (params->m_fDistance < 900.f) { - automobile = (CAutomobile *)params->m_pVehicle; - if (automobile->bEngineOn) { - if (automobile->m_nWheelsOnGround) { - velocityChange = Abs(params->m_fVelocityChange); - } else { - if (automobile->m_nDriveWheelsOnGround) - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.4f; - velocityChange = automobile->m_fGasPedalAudio * params->m_pTransmission->fMaxVelocity; - } - if (velocityChange > 0.001f) { - allowedVelocity = 0.5f * params->m_pTransmission->fMaxVelocity; - if (velocityChange < allowedVelocity) - emittingVol = (90.f * velocityChange / allowedVelocity); - else - emittingVol = 90; - if (emittingVol) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 30.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 2; - m_sQueueSample.m_nSampleIndex = SFX_REMOTE_CONTROLLED_CAR; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = (11025.f * velocityChange / params->m_pTransmission->fMaxVelocity + 11025.f); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 3.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } - } -} - -void -cAudioManager::ProcessOneShotScriptObject(uint8 sound) -{ - CPlayerPed *playerPed; - uint8 emittingVolume; - float distSquared; - - cPedParams male; - cPedParams female; - - static uint8 iSound = 0; - - switch (sound) { - case SCRIPT_SOUND_INJURED_PED_MALE_OUCH_S: - case SCRIPT_SOUND_INJURED_PED_MALE_OUCH_L: - male.m_pPed = nil; - male.m_bDistanceCalculated = false; - male.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - SetupPedComments(&male, SOUND_INJURED_PED_MALE_OUCH); - return; - case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_S: - case SCRIPT_SOUND_INJURED_PED_FEMALE_OUCH_L: - female.m_pPed = nil; - female.m_bDistanceCalculated = false; - female.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - SetupPedComments(&female, SOUND_INJURED_PED_FEMALE); - return; - case SCRIPT_SOUND_GATE_START_CLUNK: - case SCRIPT_SOUND_GATE_STOP_CLUNK: - m_sQueueSample.m_fSoundIntensity = 40.0f; - m_sQueueSample.m_nSampleIndex = SFX_COL_GATE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - if (sound == SCRIPT_SOUND_GATE_START_CLUNK) - m_sQueueSample.m_nFrequency = 10600; - else - m_sQueueSample.m_nFrequency = 9000; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = true; - emittingVolume = RandomDisplacement(10) + 50; - break; - case SCRIPT_SOUND_BULLET_HIT_GROUND_1: - case SCRIPT_SOUND_BULLET_HIT_GROUND_2: - case SCRIPT_SOUND_BULLET_HIT_GROUND_3: - m_sQueueSample.m_fSoundIntensity = 50.0f; - m_sQueueSample.m_nSampleIndex = m_anRandomTable[iSound % 5] % 3 + SFX_BULLET_WALL_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 9; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - emittingVolume = m_anRandomTable[2] % 20 + 90; - break; - case SCRIPT_SOUND_110: - case SCRIPT_SOUND_111: - if (SampleManager.IsSampleBankLoaded(0) != 1) - return; - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_TRAIN_STATION_ANNOUNCE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_STATION_ANNOUNCE); - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_bIs2D = false; - break; - case SCRIPT_SOUND_PAYPHONE_RINGING: - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_nSampleIndex = SFX_PHONE_RING; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 80; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PHONE_RING); - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = false; - break; - case SCRIPT_SOUND_GLASS_BREAK_L: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = SFX_GLASS_SMASH; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 70; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_SMASH); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - break; - case SCRIPT_SOUND_GLASS_BREAK_S: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = SFX_GLASS_SMASH; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 60; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_SMASH); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - break; - case SCRIPT_SOUND_GLASS_CRACK: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = SFX_GLASS_CRACK; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = 70; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_CRACK); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = true; - break; - case SCRIPT_SOUND_GLASS_LIGHT_BREAK: - m_sQueueSample.m_fSoundIntensity = 55.0f; - m_sQueueSample.m_nSampleIndex = (m_anRandomTable[4] & 3) + SFX_GLASS_SHARD_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 19000; - m_sQueueSample.m_nReleasingVolumeModificator = 9; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - emittingVolume = RandomDisplacement(11) + 25; - break; - case SCRIPT_SOUND_BOX_DESTROYED_1: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = SFX_WOODEN_BOX_SMASH; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 18600; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = true; - emittingVolume = m_anRandomTable[2] % 20 + 80; - break; - case SCRIPT_SOUND_BOX_DESTROYED_2: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = SFX_CARDBOARD_BOX_SMASH; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 18600; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = true; - emittingVolume = m_anRandomTable[2] % 20 + 80; - break; - case SCRIPT_SOUND_METAL_COLLISION: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 5 + SFX_COL_CAR_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = true; - emittingVolume = m_anRandomTable[2] % 30 + 70; - break; - case SCRIPT_SOUND_TIRE_COLLISION: - m_sQueueSample.m_fSoundIntensity = 60.0f; - m_sQueueSample.m_nSampleIndex = SFX_TYRE_BUMP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bRequireReflection = true; - emittingVolume = m_anRandomTable[2] % 30 + 60; - break; - case SCRIPT_SOUND_GUNSHELL_DROP: - playerPed = FindPlayerPed(); - if (playerPed) { - switch (playerPed->m_nSurfaceTouched) { - case SURFACE_GRASS: - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - case SURFACE_SCAFFOLD: - case SURFACE_FLESH: - case SURFACE_SAND: - case SURFACE_TIRE: - case SURFACE_HEDGE: - m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2; - m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000; - m_sQueueSample.m_nReleasingVolumeModificator = 18; - m_sQueueSample.m_fSoundIntensity = 20.0f; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - emittingVolume = m_anRandomTable[2] % 20 + 30; - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = iSound++; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nEmittingVolume = emittingVolume; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - AddSampleToRequestedQueue(); - } - } - return; - case SURFACE_PUDDLE: - return; - default: - break; - } - } - m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_1; - m_sQueueSample.m_nFrequency = RandomDisplacement(750) + 18000; - m_sQueueSample.m_nReleasingVolumeModificator = 15; - m_sQueueSample.m_fSoundIntensity = 20.0f; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - emittingVolume = m_anRandomTable[2] % 20 + 30; - break; - case SCRIPT_SOUND_GUNSHELL_DROP_SOFT: - m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2; - m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000; - m_sQueueSample.m_nReleasingVolumeModificator = 18; - m_sQueueSample.m_fSoundIntensity = 20.0f; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_bIs2D = false; - emittingVolume = m_anRandomTable[2] % 20 + 30; - break; - default: - return; - } - - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = iSound++; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nEmittingVolume = emittingVolume; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - AddSampleToRequestedQueue(); - } - } -} - -void -cAudioManager::ProcessPed(CPhysical *ped) -{ - cPedParams params; - - params.m_pPed = nil; - params.m_bDistanceCalculated = false; - params.m_fDistance = 0.0f; - - m_sQueueSample.m_vecPos = ped->GetPosition(); - - // params.m_bDistanceCalculated = false; - params.m_pPed = (CPed *)ped; - params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (ped->GetModelIndex() == MI_FATMALE02) - ProcessPedHeadphones(¶ms); - ProcessPedOneShots(¶ms); -} - -void -cAudioManager::ProcessPedHeadphones(cPedParams *params) -{ - CPed *ped; - CAutomobile *veh; - uint8 emittingVol; - - if (params->m_fDistance < 49.f) { - ped = params->m_pPed; - if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - if (ped->bInVehicle && ped->m_nPedState == PED_DRIVING) { - emittingVol = 10; - veh = (CAutomobile *)ped->m_pMyVehicle; - if (veh && veh->IsCar()) { - for (int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) { - if (!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) { - emittingVol = 42; - break; - } - } - } - } else { - emittingVol = 42; - } - - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 7.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 64; - m_sQueueSample.m_nSampleIndex = SFX_HEADPHONES; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_HEADPHONES); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = 7.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 5; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - return; - } - } -} - -void -cAudioManager::ProcessPedOneShots(cPedParams *params) -{ - uint8 emittingVol; - int32 sampleIndex; - - CPed *ped = params->m_pPed; - - bool stereo; - int16 sound; - bool noReflection; - CWeapon *weapon; - float maxDist = 0.f; // uninitialized variable - - static uint8 iSound = 21; - - weapon = params->m_pPed->GetWeapon(); - for (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { - noReflection = false; - stereo = false; - m_sQueueSample.m_bRequireReflection = false; - sound = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; - switch (sound) { - case SOUND_STEP_START: - case SOUND_STEP_END: - if (!params->m_pPed->bIsLooking) { - emittingVol = m_anRandomTable[3] % 15 + 45; - if (FindPlayerPed() != m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity) - emittingVol /= 2; - maxDist = 400.f; - switch (params->m_pPed->m_nSurfaceTouched) { - case SURFACE_GRASS: - sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1; - break; - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1; - break; - case SURFACE_METAL6: - case SURFACE_METAL_DOOR: - case SURFACE_BILLBOARD: - case SURFACE_STEEL: - case SURFACE_METAL_POLE: - case SURFACE_STREET_LIGHT: - case SURFACE_METAL14: - case SURFACE_METAL15: - case SURFACE_METAL_FENCE: - case SURFACE_METAL27: - case SURFACE_METAL28: - sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1; - break; - case SURFACE_SAND: - sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1; - break; - case SURFACE_PUDDLE: - sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; - break; - case SURFACE_WOOD: - case SURFACE_WOOD_BOX: - case SURFACE_WOOD_PLANK: - sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1; - break; - case SURFACE_HEDGE: - sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1; - break; - default: - sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1; - break; - } - m_sQueueSample.m_nSampleIndex = sampleIndex; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - 28; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17); - switch (params->m_pPed->m_nMoveState) { - case PEDMOVE_WALK: - emittingVol /= 4; - m_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10; - break; - case PEDMOVE_RUN: - emittingVol /= 2; - m_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10; - break; - case PEDMOVE_SPRINT: - m_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10; - break; - default: - break; - } - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 20.0f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - } - break; - case SOUND_FALL_LAND: - case SOUND_FALL_COLLAPSE: - if (!ped->bIsLooking) { - maxDist = SQR(30); - emittingVol = m_anRandomTable[3] % 20 + 80; - if (ped->m_nSurfaceTouched == SURFACE_PUDDLE) { - m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; - } else if (sound == SOUND_FALL_LAND) { - m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND; - } else { - m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL; - } - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - } - break; - case SOUND_FIGHT_PUNCH_33: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; - m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_KICK_34: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; - m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_HEADBUTT_35: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_1; - m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_PUNCH_36: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; - m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_PUNCH_37: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; - m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_CLOSE_PUNCH_38: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_2; - m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_PUNCH_39: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; - m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; - m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_PUNCH_41: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_4; - m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_PUNCH_FROM_BEHIND_42: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; - m_sQueueSample.m_nFrequency = 18000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_KNEE_OR_KICK_43: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; - m_sQueueSample.m_nFrequency = 16500; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_FIGHT_KICK_44: - m_sQueueSample.m_nSampleIndex = SFX_FIGHT_5; - m_sQueueSample.m_nFrequency = 20000; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound; - stereo = true; - ++iSound; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 26 + 100; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_WEAPON_BAT_ATTACK: - m_sQueueSample.m_nSampleIndex = SFX_BAT_HIT_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 22000; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = m_anRandomTable[2] % 20 + 100; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - case SOUND_WEAPON_SHOT_FIRED: - weapon = &ped->m_weapons[ped->m_currentWeapon]; - switch (weapon->m_eWeaponType) { - case WEAPONTYPE_COLT45: - m_sQueueSample.m_nSampleIndex = SFX_COLT45_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COLT45_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 50.0f; - maxDist = SQR(50); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = m_anRandomTable[1] % 10 + 90; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - case WEAPONTYPE_UZI: - m_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - maxDist = SQR(80); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[3] % 15 + 70; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - break; - case WEAPONTYPE_SHOTGUN: - m_sQueueSample.m_nSampleIndex = SFX_SHOTGUN_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOTGUN_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = m_anRandomTable[2] % 10 + 100; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - case WEAPONTYPE_AK47: - m_sQueueSample.m_nSampleIndex = SFX_AK47_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - maxDist = SQR(80); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[1] % 15 + 70; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - break; - case WEAPONTYPE_M16: - m_sQueueSample.m_nSampleIndex = SFX_M16_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - maxDist = SQR(80); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[4] % 15 + 70; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - break; - case WEAPONTYPE_SNIPERRIFLE: - m_sQueueSample.m_nSampleIndex = SFX_SNIPER_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SNIPER_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = m_anRandomTable[4] % 10 + 110; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - case WEAPONTYPE_ROCKETLAUNCHER: - m_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 90.0f; - maxDist = 8100.f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = m_anRandomTable[0] % 20 + 80; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - case WEAPONTYPE_FLAMETHROWER: - m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 9; - emittingVol = 90; - m_sQueueSample.m_nFrequency = (10 * m_sQueueSample.m_nEntityIndex & 2047) + SampleManager.GetSampleBaseFrequency(SFX_FLAMETHROWER_LEFT); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nEmittingVolume = 90; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 6; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - default: - continue; - } - - break; - case SOUND_WEAPON_RELOAD: - weapon = &ped->m_weapons[ped->m_currentWeapon]; - switch (weapon->m_eWeaponType) { - case WEAPONTYPE_COLT45: - m_sQueueSample.m_nSampleIndex = SFX_PISTOL_RELOAD; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PISTOL_RELOAD) + RandomDisplacement(300); - break; - case WEAPONTYPE_UZI: - m_sQueueSample.m_nSampleIndex = SFX_M16_RELOAD; - m_sQueueSample.m_nFrequency = 39243; - break; - case WEAPONTYPE_SHOTGUN: - m_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD; - m_sQueueSample.m_nFrequency = 30290; - break; - case WEAPONTYPE_AK47: - m_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_RELOAD); - break; - case WEAPONTYPE_M16: - m_sQueueSample.m_nSampleIndex = SFX_M16_RELOAD; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_RELOAD); - break; - case WEAPONTYPE_SNIPERRIFLE: - m_sQueueSample.m_nSampleIndex = SFX_RIFLE_RELOAD; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RIFLE_RELOAD); - break; - case WEAPONTYPE_ROCKETLAUNCHER: - m_sQueueSample.m_nSampleIndex = SFX_ROCKET_RELOAD; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_RELOAD); - break; - default: - continue; - } - emittingVol = 75; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency += RandomDisplacement(300); - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = 75; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - case SOUND_WEAPON_AK47_BULLET_ECHO: - case SOUND_WEAPON_UZI_BULLET_ECHO: - case SOUND_WEAPON_M16_BULLET_ECHO: - m_sQueueSample.m_nSampleIndex = SFX_UZI_END_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_END_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - maxDist = SQR(80); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = m_anRandomTable[4] % 10 + 40; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - if (m_bDynamicAcousticModelingStatus) - m_sQueueSample.m_bRequireReflection = true; - else - noReflection = true; - break; - case SOUND_WEAPON_FLAMETHROWER_FIRE: - m_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_START_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_FLAMETHROWER_START_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - emittingVol = 70; - m_sQueueSample.m_nEmittingVolume = 70; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - break; - case SOUND_WEAPON_HIT_PED: - m_sQueueSample.m_nSampleIndex = SFX_BULLET_PED; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BULLET_PED); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); - m_sQueueSample.m_nReleasingVolumeModificator = 7; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 30.0f; - maxDist = SQR(30); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[0] % 20 + 90; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - break; - case SOUND_SPLASH: - m_sQueueSample.m_nSampleIndex = SFX_SPLASH_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iSound++; - stereo = true; - m_sQueueSample.m_nFrequency = RandomDisplacement(1400) + 20000; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 40.0f; - maxDist = 1600.f; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nLoopStart = 0; - emittingVol = m_anRandomTable[2] % 30 + 70; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bRequireReflection = true; - break; - default: - SetupPedComments(params, sound); - continue; - } - - if (stereo && iSound > 60) - iSound = 21; - if (params->m_fDistance < maxDist) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - if (noReflection) { - if (0.2f * m_sQueueSample.m_fSoundIntensity <= m_sQueueSample.m_fDistance) { - noReflection = 0; - } else { - m_sQueueSample.m_bIs2D = true; - m_sQueueSample.m_nOffset = 0; - } - } - m_sQueueSample.m_bReverbFlag = true; - AddSampleToRequestedQueue(); - if (noReflection) { - m_sQueueSample.m_nOffset = 127; - ++m_sQueueSample.m_nSampleIndex; - if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] != SOUND_WEAPON_SHOT_FIRED || - weapon->m_eWeaponType != WEAPONTYPE_FLAMETHROWER) { - m_sQueueSample.m_nCounter = iSound++; - if (iSound > 60) - iSound = 21; - } else { - ++m_sQueueSample.m_nCounter; - } - AddSampleToRequestedQueue(); - } - } - } - } -} - -void -cAudioManager::ProcessPhysical(int32 id) -{ - CPhysical *entity = (CPhysical *)m_asAudioEntities[id].m_pEntity; - if (entity) { - switch (entity->GetType()) { - case ENTITY_TYPE_VEHICLE: - ProcessVehicle((CVehicle *)m_asAudioEntities[id].m_pEntity); - break; - case ENTITY_TYPE_PED: - ProcessPed((CPhysical *)m_asAudioEntities[id].m_pEntity); - break; - default: - return; - } - } -} - -void -cAudioManager::ProcessPlane(cVehicleParams *params) -{ - switch (params->m_nIndex) { - case AIRTRAIN: - ProcessJumbo(params); - break; - case DEADDODO: - ProcessCesna(params); - break; - default: - debug("Plane Model Id is %d\n, ", params->m_pVehicle->GetModelIndex()); - break; - } -} - -struct tVehicleSampleData { - eSfxSample m_nAccelerationSampleIndex; - uint8 m_bEngineSoundType; - eSfxSample m_nHornSample; - int32 m_nHornFrequency; - uint8 m_nSirenOrAlarmSample; - int32 m_nSirenOrAlarmFrequency; - uint8 m_bDoorType; -}; - -const tVehicleSampleData aVehicleSettings[70] = {{SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 10928, 1}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_ALARM_1, 8941, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_ALARM_1, 11922, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 7948, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_ALARM_1, 8941, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_ALARM_1, 12220, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_ALARM_1, 12200, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 13600, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_ALARM_1, 8000, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_ALARM_1, 8543, 1}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 10000, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_ALARM_1, 10123, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_ALARM_1, 10554, 3}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 8000, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 3}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_ALARM_1, 7500, 3}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_ALARM_1, 8935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 8935, 0}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_ALARM_1, 17000, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9000, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}}; - -void -cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile) -{ - static int32 GearFreqAdj[] = {6000, 6000, 3400, 1200, 0, -1000}; - - cTransmission *transmission; - float velocityChange; - float relativeVelocityChange; - float accelerationMultipler; - uint8 wheelInUseCounter; - float time; - int baseFreq; - uint8 vol; - int gearNr; - int32 freq; - - int freqModifier; - int soundOffset; - uint8 engineSoundType; - int32 accelerateState; - bool channelUsed; - char lostTraction; - bool processedAccelSampleStopped; - uint8 currentGear; - float gasPedalAudio; - CVector pos; - - static int16 LastAccel = 0; - static int16 LastBrake = 0; - static uint8 CurrentPretendGear = 1; - static bool bLostTractionLastFrame = false; - static bool bHandbrakeOnLastFrame = 0; - static int32 nCruising = 0; - static bool bAccelSampleStopped = true; - - lostTraction = 0; - processedAccelSampleStopped = 0; - if (bPlayerJustEnteredCar) { - bAccelSampleStopped = true; - bPlayerJustEnteredCar = false; - nCruising = 0; - LastAccel = 0; - bLostTractionLastFrame = false; - LastBrake = 0; - bHandbrakeOnLastFrame = 0; - CurrentPretendGear = 1; - } - if (CReplay::IsPlayingBack()) { - accelerateState = 255.f * Max(0.0f, Min(1.0f, automobile->m_fGasPedal)); - } else { - accelerateState = Pads->GetAccelerate(); - } - channelUsed = SampleManager.GetChannelUsedFlag(m_nActiveSamples); - transmission = params->m_pTransmission; - velocityChange = params->m_fVelocityChange; - relativeVelocityChange = 2.0f * velocityChange / transmission->fMaxVelocity; - - accelerationMultipler = Min(Min(1.f, relativeVelocityChange), 0.f); - gasPedalAudio = accelerationMultipler; - currentGear = params->m_pVehicle->m_nCurrentGear; - - if (transmission->nDriveType == '4') { - wheelInUseCounter = 0; - for (uint8 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { - if (automobile->m_aWheelState[i]) - ++wheelInUseCounter; - } - if (wheelInUseCounter > 2) - lostTraction = 1; - } else if (transmission->nDriveType == 'F') { - if ((automobile->m_aWheelState[0] || automobile->m_aWheelState[2]) && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { - lostTraction = 1; - } - } else if (transmission->nDriveType == 'R' && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { - lostTraction = 1; - } - if (0.0f != velocityChange) { - time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; - if (time <= 0.0f) { - freqModifier = Max(-0.2f, time) * -15000.f; - } else { - freqModifier = -(Min(0.2f, time) * 15000.f); - } - if (params->m_fVelocityChange < -0.001f) - freqModifier = -freqModifier; - } else { - freqModifier = 0; - } - engineSoundType = aVehicleSettings[params->m_nIndex].m_bEngineSoundType; - soundOffset = 3 * (engineSoundType - 1); - if (accelerateState <= 0) { - if (params->m_fVelocityChange < -0.001f) { - if (channelUsed) { - SampleManager.StopChannel(m_nActiveSamples); - bAccelSampleStopped = true; - } - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { - gasPedalAudio = automobile->m_fGasPedalAudio; - } else { - gasPedalAudio = Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity); - } - gasPedalAudio = Max(0.0f, gasPedalAudio); - automobile->m_fGasPedalAudio = gasPedalAudio; - } else if (LastAccel > 0) { - if (channelUsed) { - SampleManager.StopChannel(m_nActiveSamples); - bAccelSampleStopped = true; - } - nCruising = 0; - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || - params->m_fVelocityChange >= 0.01f && automobile->m_fGasPedalAudio > 0.2f) { - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.6f; - gasPedalAudio = automobile->m_fGasPedalAudio; - } - if (gasPedalAudio > 0.05f) { - freq = (5000.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 19000; - if (engineSoundType == 6) - freq /= 2; - AddPlayerCarSample((25.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 40, freq, (soundOffset + SFX_CAR_FINGER_OFF_ACCEL_1), engineSoundType, 63, 0); - } - } - freq = (10000.f * gasPedalAudio) + 22050; - if (engineSoundType == 6) - freq /= 2; - AddPlayerCarSample(110 - (40.f * gasPedalAudio), freq, (engineSoundType + SFX_CAR_REV_10), 0, 52, 1); - - CurrentPretendGear = Max(1, currentGear); - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - if (!nCruising) { - if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || - currentGear < 2 && velocityChange - automobile->m_fVelocityChangeForAudio < 0.01f) { // here could be used abs - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { - if (!automobile->m_nWheelsOnGround && automobile->m_nDriveWheelsOnGround || - (automobile->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame) && automobile->m_nWheelsOnGround) { - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.6f; - } - freqModifier = 0; - baseFreq = (15000.f * automobile->m_fGasPedalAudio) + 14000; - vol = (25.0f * automobile->m_fGasPedalAudio) + 60; - } else { - baseFreq = (8000.f * accelerationMultipler) + 16000; - vol = (25.0f * accelerationMultipler) + 60; - automobile->m_fGasPedalAudio = accelerationMultipler; - } - freq = freqModifier + baseFreq; - if (engineSoundType == 6) - freq /= 2; - if (channelUsed) { - SampleManager.StopChannel(m_nActiveSamples); - bAccelSampleStopped = true; - } - AddPlayerCarSample(vol, freq, (engineSoundType + SFX_PHONE_RING), 0, 2, 1); - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - TranslateEntity(&m_sQueueSample.m_vecPos, &pos); - if (bAccelSampleStopped) { - if (CurrentPretendGear != 1 || currentGear != 2) { - gearNr = currentGear - 1; - if (gearNr < 1) - gearNr = 1; - CurrentPretendGear = gearNr; - } - processedAccelSampleStopped = 1; - bAccelSampleStopped = false; - } - if (channelUsed) { - SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); - SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); - SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); - if (engineSoundType == 6) - freq = (GearFreqAdj[CurrentPretendGear] + freqModifier + 22050) / 2; - else - freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; - SampleManager.SetChannelFrequency(m_nActiveSamples, freq); - if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); - SampleManager.StartChannel(m_nActiveSamples); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - if (processedAccelSampleStopped) { - if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) - return; - SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); - SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); - SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); - SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); - SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); - freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; - if (engineSoundType == 6) - freq /= 2; - SampleManager.SetChannelFrequency(m_nActiveSamples, freq); - if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); - SampleManager.StartChannel(m_nActiveSamples); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1) { - ++CurrentPretendGear; - if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) - return; - SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); - SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); - SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); - SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); - SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); - freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; - if (engineSoundType == 6) - freq /= 2; - SampleManager.SetChannelFrequency(m_nActiveSamples, freq); - if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); - SampleManager.StartChannel(m_nActiveSamples); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - nCruising = 1; - } - bAccelSampleStopped = true; - if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || - currentGear < params->m_pTransmission->nNumberOfGears - 1) { - nCruising = 0; - } else { - if (accelerateState >= 220 && 0.001f + params->m_fVelocityChange < automobile->m_fVelocityChangeForAudio) { - if (nCruising < 800) - ++nCruising; - } else if (nCruising > 3) { - --nCruising; - } - freq = 27 * nCruising + freqModifier + 22050; - if (engineSoundType == 6) - freq /= 2; - AddPlayerCarSample(85, freq, (soundOffset + SFX_CAR_AFTER_ACCEL_1), engineSoundType, 64, 1); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; -} - -void -cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) -{ - uint32 time = CTimer::GetTimeInMilliseconds(); - int32 sampleIndex; - uint8 emittingVol; - float distSquared; - cPedParams params; - - static uint8 counter = 0; - - if (time > gCellNextTime) { - switch (sound) { - case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; - break; - case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; - break; - default: - return; - } - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - if (m_FrameCounter & 1) - sampleIndex = (m_anRandomTable[1] & 3) + SFX_FIGHT_1; - else - sampleIndex = (m_anRandomTable[3] & 1) + SFX_BAT_HIT_LEFT; - m_sQueueSample.m_nSampleIndex = sampleIndex; - emittingVol = m_anRandomTable[0] % 50 + 55; - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - params.m_bDistanceCalculated = true; - params.m_fDistance = distSquared; - params.m_pPed = nil; - SetupPedComments(¶ms, SOUND_INJURED_PED_MALE_PRISON); - } - gCellNextTime = time + 500 + m_anRandomTable[3] % 1500; - } - } -} - -void -cAudioManager::ProcessPornCinema(uint8 sound) -{ - - eSfxSample sample; - uint32 time; - int32 rand; - float distSquared; - - switch (sound) { - case SCRIPT_SOUND_PORN_CINEMA_1_S: - case SCRIPT_SOUND_MISTY_SEX_S: - m_sQueueSample.m_nSampleIndex = SFX_PORN_1_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - sample = SFX_PORN_1_GROAN_1; - m_sQueueSample.m_fSoundIntensity = 20.0f; - break; - case SCRIPT_SOUND_PORN_CINEMA_1_L: - case SCRIPT_SOUND_MISTY_SEX_L: - m_sQueueSample.m_nSampleIndex = SFX_PORN_1_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - sample = SFX_PORN_1_GROAN_1; - m_sQueueSample.m_fSoundIntensity = 80.0f; - break; - case SCRIPT_SOUND_PORN_CINEMA_2_S: - m_sQueueSample.m_nSampleIndex = SFX_PORN_2_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - sample = SFX_PORN_2_GROAN_1; - m_sQueueSample.m_fSoundIntensity = 20.0f; - break; - case SCRIPT_SOUND_PORN_CINEMA_2_L: - m_sQueueSample.m_nSampleIndex = SFX_PORN_2_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - sample = SFX_PORN_2_GROAN_1; - m_sQueueSample.m_fSoundIntensity = 80.0f; - break; - case SCRIPT_SOUND_PORN_CINEMA_3_S: - m_sQueueSample.m_nSampleIndex = SFX_PORN_3_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSoundIntensity = 20.0f; - sample = SFX_PORN_3_GROAN_1; - break; - case SCRIPT_SOUND_PORN_CINEMA_3_L: - m_sQueueSample.m_nSampleIndex = SFX_PORN_3_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSoundIntensity = 80.0f; - sample = SFX_PORN_3_GROAN_1; - break; - default: - return; - } - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - if (sound != SCRIPT_SOUND_MISTY_SEX_S && sound != SCRIPT_SOUND_MISTY_SEX_L) { - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = maxVolume; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - - time = CTimer::GetTimeInMilliseconds(); - if (time > gPornNextTime) { - m_sQueueSample.m_nVolume = ComputeVolume(90, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - rand = m_anRandomTable[1] & 1; - m_sQueueSample.m_nSampleIndex = rand + sample; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nCounter = rand + 1; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 6; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - gPornNextTime = time + 2000 + m_anRandomTable[3] % 6000; - } - } - } -} - -void -cAudioManager::ProcessProjectiles() -{ - uint8 emittingVol; - - for (int32 i = 0; i < NUM_PROJECTILES; i++) { - if (CProjectileInfo::GetProjectileInfo(i)->m_bInUse) { - switch (CProjectileInfo::GetProjectileInfo(i)->m_eWeaponType) { - case WEAPONTYPE_ROCKETLAUNCHER: - emittingVol = maxVolume; - m_sQueueSample.m_fSoundIntensity = rocketLauncherIntensity; - m_sQueueSample.m_nSampleIndex = SFX_ROCKET_FLY; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_FLY); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - break; - case WEAPONTYPE_MOLOTOV: - emittingVol = molotovVolume; - m_sQueueSample.m_fSoundIntensity = molotovIntensity; - m_sQueueSample.m_nSampleIndex = SFX_PED_ON_FIRE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = 32 * SampleManager.GetSampleBaseFrequency(SFX_PED_ON_FIRE) / 25; - m_sQueueSample.m_nReleasingVolumeModificator = 7; - break; - default: - return; - } - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_vecPos = CProjectileInfo::ms_apProjectile[i]->GetPosition(); - float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = i; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } -} - -void -cAudioManager::ProcessRainOnVehicle(cVehicleParams *params) -{ - if (params->m_fDistance < SQR(rainOnVehicleIntensity) && CWeather::Rain > 0.01f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) { - CVehicle *veh = params->m_pVehicle; - ++veh->m_bRainAudioCounter; - if (veh->m_bRainAudioCounter >= 2) { - veh->m_bRainAudioCounter = 0; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - float emittingVol = 30.f * CWeather::Rain; - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, rainOnVehicleIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = veh->m_bRainSamplesCounter++; - if (veh->m_bRainSamplesCounter > 4) - veh->m_bRainSamplesCounter = 68; - m_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_CAR_RAIN_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 9; - m_sQueueSample.m_nFrequency = m_anRandomTable[1] % 4000 + 28000; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nEmittingVolume = (uint8)emittingVol; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = rainOnVehicleIntensity; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bReverbFlag = false; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } -} - -void -cAudioManager::ProcessReverb() const -{ - if (SampleManager.UpdateReverb() && m_bDynamicAcousticModelingStatus) { - for (uint32 i = 0; i < -#ifdef FIX_BUGS - channels -#else - 28 -#endif - ; - i++) { - if (m_asActiveSamples[i].m_bReverbFlag) - SampleManager.SetChannelReverbFlag(i, 1); - } - } -} - -bool -cAudioManager::ProcessReverseGear(cVehicleParams *params) -{ - CVehicle *veh; - CAutomobile *automobile; - int32 emittingVol; - float modificator; - - if (params->m_fDistance >= SQR(reverseGearIntensity)) - return false; - veh = params->m_pVehicle; - if (veh->bEngineOn && (veh->m_fGasPedal < 0.0f || !veh->m_nCurrentGear)) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - automobile = (CAutomobile *)params->m_pVehicle; - if (automobile->m_nWheelsOnGround) { - modificator = params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity; - } else { - if (automobile->m_nDriveWheelsOnGround) - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.4f; - modificator = automobile->m_fGasPedalAudio; - } - modificator = Abs(modificator); - emittingVol = (24.f * modificator); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, reverseGearIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - if (params->m_pVehicle->m_fGasPedal >= 0.0f) { - m_sQueueSample.m_nCounter = 62; - m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR_2; - } else { - m_sQueueSample.m_nCounter = 61; - m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR; - } - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nFrequency = (6000.f * modificator) + 7000; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 3.0f; - m_sQueueSample.m_fSoundIntensity = reverseGearIntensity; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 5; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - return true; -} - -void -cAudioManager::ProcessSawMillScriptObject(uint8 sound) -{ - uint32 time; - float distSquared; - - switch (sound) { - case SCRIPT_SOUND_SAWMILL_LOOP_S: - case SCRIPT_SOUND_SAWMILL_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; - break; - default: - return; - } - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_SAWMILL_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SAWMILL_LOOP); - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 30; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - time = CTimer::GetTimeInMilliseconds(); - if (time > gSawMillNextTime) { - m_sQueueSample.m_nVolume = ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_SAWMILL_CUT_WOOD; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - gSawMillNextTime = time + 2000 + m_anRandomTable[3] % 4000; - } - } - } -} - -void -cAudioManager::ProcessScriptObject(int32 id) -{ - cAudioScriptObject *entity = (cAudioScriptObject *)m_asAudioEntities[id].m_pEntity; - if (entity) { - m_sQueueSample.m_vecPos = entity->Posn; - if (m_asAudioEntities[id].m_AudioEvents == 1) - ProcessOneShotScriptObject(m_asAudioEntities[id].m_awAudioEvent[0]); - else - ProcessLoopingScriptObject(entity->AudioId); - } -} - -void -cAudioManager::ProcessShopScriptObject(uint8 sound) -{ - uint32 time; - int32 rand; - float distSquared; - - switch (sound) { - case SCRIPT_SOUND_SHOP_LOOP_S: - case SCRIPT_SOUND_SHOP_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 30.0f; - break; - default: - return; - } - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_SHOP_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOP_LOOP); - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 30; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - time = CTimer::GetTimeInMilliseconds(); - if (time > gShopNextTime) { - m_sQueueSample.m_nVolume = ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - rand = m_anRandomTable[1] & 1; - m_sQueueSample.m_nSampleIndex = rand + SFX_SHOP_TILL_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nCounter = rand + 1; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 70; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - gShopNextTime = time + 3000 + m_anRandomTable[3] % 7000; - } - } - } -} - -void -cAudioManager::ProcessSpecial() -{ - if (m_nUserPause) { - if (!m_nPreviousUserPause) { - MusicManager.ChangeMusicMode(MUSICMODE_FRONTEND); - SampleManager.SetEffectsFadeVolume(maxVolume); - SampleManager.SetMusicFadeVolume(maxVolume); - } - } else { - if (m_nPreviousUserPause) { - MusicManager.StopFrontEndTrack(); - MusicManager.ChangeMusicMode(MUSICMODE_GAME); - } - CPlayerPed *playerPed = FindPlayerPed(); - if (playerPed) { - const PedState &state = playerPed->m_nPedState; - if (state != PED_ENTER_CAR && state != PED_STEAL_CAR && !playerPed->bInVehicle) - SampleManager.StopChannel(m_nActiveSamples); - } - } -} - -bool -cAudioManager::ProcessTrainNoise(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 300.0f; - - CTrain *train; - uint8 emittingVol; - float speedMultipler; - - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return false; - - if (params->m_fVelocityChange > 0.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - train = (CTrain *)params->m_pVehicle; - speedMultipler = Min(1.0f, train->m_fSpeed * 250.f / 51.f); - emittingVol = (75.f * speedMultipler); - if (train->m_fWagonPosition == 0.0f) { - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 32; - m_sQueueSample.m_nSampleIndex = SFX_TRAIN_FAR; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_FAR); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 3.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - const float SOUND_INTENSITY = 70.0f; - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 33; - m_sQueueSample.m_nSampleIndex = SFX_TRAIN_NEAR; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_NEAR) + 100 * m_sQueueSample.m_nEntityIndex % 987; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 6.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - return true; -} - -void -cAudioManager::ProcessVehicle(CVehicle *veh) -{ - tHandlingData *handling = veh->pHandling; - float velChange; - cVehicleParams params; - m_sQueueSample.m_vecPos = veh->GetPosition(); - - params.m_bDistanceCalculated = false; - params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - params.m_pVehicle = veh; - params.m_pTransmission = nil; - params.m_nIndex = 0; - params.m_fVelocityChange = 0.0f; - - if (handling) - params.m_pTransmission = &handling->Transmission; - - params.m_nIndex = veh->GetModelIndex() - MI_FIRST_VEHICLE; - if (params.m_pVehicle->GetStatus() == STATUS_SIMPLE) - velChange = params.m_pVehicle->AutoPilot.m_fMaxTrafficSpeed * 0.02f; - else - velChange = DotProduct(params.m_pVehicle->m_vecMoveSpeed, params.m_pVehicle->GetForward()); - params.m_fVelocityChange = velChange; - switch (params.m_pVehicle->m_vehType) { - case VEHICLE_TYPE_CAR: - UpdateGasPedalAudio((CAutomobile *)veh); - if (params.m_nIndex == RCBANDIT) { - ProcessModelCarEngine(¶ms); - ProcessVehicleOneShots(¶ms); - ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); - break; - } - if (params.m_nIndex == DODO) { - if (!ProcessVehicleRoadNoise(¶ms)) { - ProcessVehicleOneShots(¶ms); - ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); - break; - } - if (CWeather::WetRoads > 0.f) - ProcessWetRoadNoise(¶ms); - ProcessVehicleSkidding(¶ms); - } else { - if (!ProcessVehicleRoadNoise(¶ms)) { - ProcessVehicleOneShots(¶ms); - ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); - break; - } - ProcessReverseGear(¶ms); - if (CWeather::WetRoads > 0.f) - ProcessWetRoadNoise(¶ms); - ProcessVehicleSkidding(¶ms); - ProcessVehicleHorn(¶ms); - ProcessVehicleSirenOrAlarm(¶ms); - if (UsesReverseWarning(params.m_nIndex)) - ProcessVehicleReverseWarning(¶ms); - if (HasAirBrakes(params.m_nIndex)) - ProcessAirBrakes(¶ms); - } - ProcessCarBombTick(¶ms); - ProcessVehicleEngine(¶ms); - ProcessEngineDamage(¶ms); - ProcessVehicleDoors(¶ms); - ProcessVehicleOneShots(¶ms); - ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); - break; - case VEHICLE_TYPE_BOAT: - ProcessBoatEngine(¶ms); - ProcessBoatMovingOverWater(¶ms); - ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); - break; - case VEHICLE_TYPE_TRAIN: - ProcessTrainNoise(¶ms); - ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); - break; - case VEHICLE_TYPE_HELI: - ProcessHelicopter(¶ms); - ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); - break; - case VEHICLE_TYPE_PLANE: - ProcessPlane(¶ms); - ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); - break; - default: - ProcessRainOnVehicle(¶ms); - break; - } -} - -bool -cAudioManager::ProcessVehicleDoors(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 40.0f; - - CAutomobile *automobile; - int8 doorState; - int32 emittingVol; - float velocity; - - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return false; - - automobile = (CAutomobile *)params->m_pVehicle; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - for (int32 i = 0; i < ARRAY_SIZE(automobile->Doors); i++) { - if (automobile->Damage.GetDoorStatus(i) == DOOR_STATUS_SWINGING) { - doorState = automobile->Doors[i].m_nDoorState; - if (doorState == DOOR_STATUS_SMASHED || doorState == DOOR_STATUS_SWINGING) { - velocity = Min(0.3f, Abs(automobile->Doors[i].m_fAngVel)); - if (velocity > 0.0035f) { - emittingVol = (100.f * velocity * 10.f / 3.f); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = i + 6; - m_sQueueSample.m_nSampleIndex = m_anRandomTable[1] % 6 + SFX_COL_CAR_PANEL_1; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) + RandomDisplacement(1000); - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 10; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_fSpeedMultiplier = 1.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = true; - AddSampleToRequestedQueue(); - } - } - } - } - } - return true; -} - -void -cAudioManager::ProcessVehicleEngine(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 50.0f; - - CVehicle *playerVeh; - CVehicle *veh; - CAutomobile *automobile; - float relativeGearChange; - float relativeChange; - uint8 volume; - int32 freq = 0; // uinitialized variable - uint8 emittingVol; - cTransmission *transmission; - uint8 currentGear; - float modificator; - float traction = 0.f; - - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - playerVeh = FindPlayerVehicle(); - veh = params->m_pVehicle; - if (playerVeh == veh && veh->GetStatus() == STATUS_WRECKED) { - SampleManager.StopChannel(m_nActiveSamples); - return; - } - if (veh->bEngineOn) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - automobile = (CAutomobile *)params->m_pVehicle; - if (params->m_nIndex == DODO) { - ProcessCesna(params); - return; - } - if (FindPlayerVehicle() == veh) { - ProcessPlayersVehicleEngine(params, automobile); - return; - } - transmission = params->m_pTransmission; - if (transmission) { - currentGear = params->m_pVehicle->m_nCurrentGear; - if (automobile->m_nWheelsOnGround) { - if (automobile->bIsHandbrakeOn) { - if (params->m_fVelocityChange == 0.0f) - traction = 0.9f; - } else if (params->m_pVehicle->GetStatus() == STATUS_SIMPLE) { - traction = 0.0f; - } else { - switch (transmission->nDriveType) { - case '4': - for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { - if (automobile->m_aWheelState[i] == WHEEL_STATE_SPINNING) - traction += 0.05f; - } - break; - case 'F': - if (automobile->m_aWheelState[0] == WHEEL_STATE_SPINNING) - traction += 0.1f; - if (automobile->m_aWheelState[2] == WHEEL_STATE_SPINNING) - traction += 0.1f; - break; - case 'R': - if (automobile->m_aWheelState[1] == WHEEL_STATE_SPINNING) - traction += 0.1f; - if (automobile->m_aWheelState[3] == WHEEL_STATE_SPINNING) - traction += 0.1f; - break; - } - } - if (transmission->fMaxVelocity <= 0.f) { - relativeChange = 0.f; - } else if (currentGear) { - relativeGearChange = - Min(1.0f, (params->m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f); - if (traction == 0.0f && automobile->GetStatus() != STATUS_SIMPLE && - params->m_fVelocityChange >= transmission->Gears[1].fShiftUpVelocity) { - traction = 0.7f; - } - relativeChange = traction * automobile->m_fGasPedalAudio * 0.95f + (1.0f - traction) * relativeGearChange; - } else - relativeChange = - Min(1.0f, 1.0f - Abs((params->m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity)); - } else { - if (automobile->m_nDriveWheelsOnGround) - automobile->m_fGasPedalAudio *= 0.4f; - relativeChange = automobile->m_fGasPedalAudio; - } - modificator = relativeChange; - if (currentGear || !automobile->m_nWheelsOnGround) - freq = 1200 * currentGear + 18000.f * modificator + 14000; - else - freq = 13000.f * modificator + 14000; - if (modificator >= 0.75f) { - emittingVol = 120; - volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - } else { - emittingVol = modificator * 4.0f / 3.0f * 40.f + 80.f; - volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - } - } else { - modificator = 0.f; - emittingVol = 80; - volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - } - m_sQueueSample.m_nVolume = volume; - if (m_sQueueSample.m_nVolume) { - if (automobile->GetStatus() == STATUS_SIMPLE) { - if (modificator < 0.02f) { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_bEngineSoundType - 1 + SFX_CAR_IDLE_1; - freq = modificator * 10000 + 22050; - m_sQueueSample.m_nCounter = 52; - } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex; - m_sQueueSample.m_nCounter = 2; - } - } else { - if (automobile->m_fGasPedal < 0.05f) { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_bEngineSoundType - 1 + SFX_CAR_IDLE_1; - freq = modificator * 10000 + 22050; - m_sQueueSample.m_nCounter = 52; - } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nAccelerationSampleIndex; - m_sQueueSample.m_nCounter = 2; - } - } - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nFrequency = freq + 100 * m_sQueueSample.m_nEntityIndex % 1000; - if (m_sQueueSample.m_nSampleIndex == SFX_CAR_IDLE_6 || m_sQueueSample.m_nSampleIndex == SFX_CAR_REV_6) - m_sQueueSample.m_nFrequency /= 2; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 6.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 8; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } -} - -void -cAudioManager::ProcessVehicleHorn(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 40.0f; - - CAutomobile *automobile; - - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - automobile = (CAutomobile *)params->m_pVehicle; - if ((!automobile->m_bSirenOrAlarm || !UsesSirenSwitching(params->m_nIndex)) && automobile->GetModelIndex() != MI_MRWHOOP) { - if (automobile->m_nCarHornTimer) { - if (params->m_pVehicle->GetStatus() != STATUS_PLAYER) { - automobile->m_nCarHornTimer = Min(44, automobile->m_nCarHornTimer); - if (automobile->m_nCarHornTimer == 44) - automobile->m_nCarHornPattern = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7; - if (!hornPatternsArray[automobile->m_nCarHornPattern][44 - automobile->m_nCarHornTimer]) - return; - } - - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 4; - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nHornSample; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nHornFrequency; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 80; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 5.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } -} - -void -cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) -{ - int16 event; - uint8 emittingVol; - float relVol; - float vol; - bool noReflections; - float maxDist; - cPedParams pedParams; - - static uint8 WaveIndex = 41; - static uint8 GunIndex = 53; - static uint8 iWheelIndex = 82; - static uint8 CrunchOffset = 0; - - for (int i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) { - noReflections = 0; - m_sQueueSample.m_bRequireReflection = false; - event = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; - switch (event) { - case SOUND_CAR_DOOR_CLOSE_BONNET: - case SOUND_CAR_DOOR_CLOSE_BUMPER: - case SOUND_CAR_DOOR_CLOSE_FRONT_LEFT: - case SOUND_CAR_DOOR_CLOSE_FRONT_RIGHT: - case SOUND_CAR_DOOR_CLOSE_BACK_LEFT: - case SOUND_CAR_DOOR_CLOSE_BACK_RIGHT: - { - const float SOUND_INTENSITY = 50.0f; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[2] % 5 + 122; - switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { - case 0: - m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE; - break; - case 2: - m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_CLOSE; - break; - case 3: - m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; - break; - default: - m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE; - break; - } - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bRequireReflection = true; - break; - } - case SOUND_CAR_DOOR_OPEN_BONNET: - case SOUND_CAR_DOOR_OPEN_BUMPER: - case SOUND_CAR_DOOR_OPEN_FRONT_LEFT: - case SOUND_CAR_DOOR_OPEN_FRONT_RIGHT: - case SOUND_CAR_DOOR_OPEN_BACK_LEFT: - case SOUND_CAR_DOOR_OPEN_BACK_RIGHT: - { - const float SOUND_INTENSITY = 50.0f; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[1] % 10 + 117; - switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { - case 0: - m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_OPEN; - break; - case 2: - m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_OPEN; - break; - case 3: - m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; - break; - default: - m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_OPEN; - break; - } - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bRequireReflection = true; - break; - } - case SOUND_CAR_WINDSHIELD_CRACK: - { - const float SOUND_INTENSITY = 30.0f; - maxDist = SQR(SOUND_INTENSITY); - m_sQueueSample.m_nSampleIndex = SFX_GLASS_CRACK; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 68; - emittingVol = m_anRandomTable[1] % 30 + 60; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_CRACK); - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - } break; - case SOUND_CAR_JUMP: - { - const float SOUND_INTENSITY = 35.0f; - emittingVol = Max(80.f, 2 * (100.f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i])); - maxDist = SQR(SOUND_INTENSITY); - m_sQueueSample.m_nSampleIndex = SFX_TYRE_BUMP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = iWheelIndex++; - if (iWheelIndex > 85) - iWheelIndex = 82; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BUMP); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - if (params->m_nIndex == 41) { - m_sQueueSample.m_nFrequency *= 2; - emittingVol /= 2; - } - m_sQueueSample.m_nReleasingVolumeModificator = 6; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - break; - } - case SOUND_CAR_ENGINE_START: - { - const float SOUND_INTENSITY = 40.0f; - emittingVol = 60; - maxDist = SQR(SOUND_INTENSITY); - m_sQueueSample.m_nSampleIndex = SFX_CAR_STARTER; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 33; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_STARTER); - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bRequireReflection = true; - break; - } - case SOUND_CAR_LIGHT_BREAK: - { - const float SOUND_INTENSITY = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_GLASS_SHARD_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 37; - m_sQueueSample.m_nFrequency = 9 * SampleManager.GetSampleBaseFrequency(SFX_GLASS_SHARD_1) / 10; - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[4] % 10 + 30; - break; - } - case SOUND_CAR_HYDRAULIC_1: - case SOUND_CAR_HYDRAULIC_2: - { - const float SOUND_INTENSITY = 35.0f; - if (event == MOONBEAM) // todo check - m_sQueueSample.m_nFrequency = 15600; - else - m_sQueueSample.m_nFrequency = 13118; - m_sQueueSample.m_nSampleIndex = SFX_SUSPENSION_FAST_MOVE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 51; - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[0] % 15 + 55; - break; - } - case SOUND_CAR_HYDRAULIC_3: - { - const float SOUND_INTENSITY = 35.0f; - m_sQueueSample.m_nSampleIndex = SFX_SUSPENSION_SLOW_MOVE_LOOP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 86; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SUSPENSION_SLOW_MOVE_LOOP); - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_nReleasingVolumeDivider = 7; - noReflections = true; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[0] % 15 + 55; - break; - } - case SOUND_CAR_JERK: - { - const float SOUND_INTENSITY = 35.0f; - m_sQueueSample.m_nSampleIndex = SFX_SHAG_SUSPENSION; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 87; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHAG_SUSPENSION); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[1] % 15 + 55; - break; - } - case SOUND_CAR_SPLASH: - { - const float SOUND_INTENSITY = 40.0f; - vol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; - if (vol <= 300.f) - continue; - if (vol > 1200.f) - m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] = 1200.0f; - relVol = (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] - 300.f) / 900.f; - m_sQueueSample.m_nSampleIndex = (m_anRandomTable[0] & 1) + SFX_BOAT_SPLASH_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = WaveIndex++; - if (WaveIndex > 46) - WaveIndex = 41; - m_sQueueSample.m_nFrequency = (7000.f * relVol) + 6000; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - emittingVol = (55.f * relVol); - maxDist = SQR(SOUND_INTENSITY); - break; - } - case SOUND_17: - { - const float SOUND_INTENSITY = 50.0f; - m_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_THUMB_OFF; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 47; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BOAT_THUMB_OFF) + RandomDisplacement(600); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - emittingVol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; - maxDist = SQR(SOUND_INTENSITY); - break; - } - case SOUND_18: - case SOUND_19: - { - const float SOUND_INTENSITY = 35.0f; - m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 59; - m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 11025; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 5.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[1] % 20 + 70; - break; - } - case SOUND_CAR_TANK_TURRET_ROTATE: - { - const float SOUND_INTENSITY = 40.0f; - vol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; - if (vol > 96.0f / 2500.0f) - vol = 96.0f / 2500.0f; - m_sQueueSample.m_nSampleIndex = SFX_TANK_TURRET; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 79; - m_sQueueSample.m_nFrequency = (3000.f * vol * 2500.0f / 96.0f) + 9000; - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - emittingVol = (37.f * vol * 2500.0f / 96.0f) + 90; - maxDist = SQR(SOUND_INTENSITY); - noReflections = true; - break; - } - case SOUND_CAR_BOMB_TICK: - { - const float SOUND_INTENSITY = 30.0f; - m_sQueueSample.m_nSampleIndex = SFX_BOMB_BEEP; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 80; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BOMB_BEEP); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - m_sQueueSample.m_bRequireReflection = true; - emittingVol = 60; - break; - } - case SOUND_PLANE_ON_GROUND: - { - const float SOUND_INTENSITY = 180.0f; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_LAND_WHEELS; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 81; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_LAND_WHEELS); - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[4] % 25 + 75; - break; - } - case SOUND_WEAPON_SHOT_FIRED: - { - const float SOUND_INTENSITY = 120.0f; - emittingVol = m_anRandomTable[2]; - maxDist = SQR(SOUND_INTENSITY); - m_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = GunIndex++; - emittingVol = emittingVol % 15 + 65; - if (GunIndex > 58) - GunIndex = 53; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - break; - } - case SOUND_WEAPON_HIT_VEHICLE: - { - const float SOUND_INTENSITY = 40.0f; - m_sQueueSample.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % ARRAY_SIZE(m_anRandomTable)] % 6 + SFX_BULLET_CAR_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 34; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32); - m_sQueueSample.m_nReleasingVolumeModificator = 7; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[3] % 20 + 90; - break; - } - case SOUND_BOMB_TIMED_ACTIVATED: - case SOUND_55: - case SOUND_BOMB_ONIGNITION_ACTIVATED: - case SOUND_BOMB_TICK: - { - const float SOUND_INTENSITY = 50.0f; - m_sQueueSample.m_nSampleIndex = SFX_ARM_BOMB; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 36; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ARM_BOMB); - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bRequireReflection = true; - emittingVol = 50; - maxDist = SQR(SOUND_INTENSITY); - break; - } - case SOUND_PED_HELI_PLAYER_FOUND: - pedParams.m_pPed = nil; - pedParams.m_bDistanceCalculated = false; - pedParams.m_fDistance = 0.0f; - pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated; - pedParams.m_fDistance = params->m_fDistance; - SetupPedComments(&pedParams, SOUND_PED_HELI_PLAYER_FOUND); - continue; - case SOUND_PED_BODYCAST_HIT: - pedParams.m_pPed = nil; - pedParams.m_bDistanceCalculated = false; - pedParams.m_fDistance = 0.0f; - pedParams.m_bDistanceCalculated = params->m_bDistanceCalculated; - pedParams.m_fDistance = params->m_fDistance; - SetupPedComments(&pedParams, SOUND_PED_BODYCAST_HIT); - continue; - case SOUND_WATER_FALL: - { - const float SOUND_INTENSITY = 40.0f; - m_sQueueSample.m_nSampleIndex = SFX_SPLASH_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 15; - m_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 16000; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - m_sQueueSample.m_bRequireReflection = true; - emittingVol = m_anRandomTable[4] % 20 + 90; - break; - } - case SOUND_SPLATTER: - { - const float SOUND_INTENSITY = 40.0f; - m_sQueueSample.m_nSampleIndex = CrunchOffset + SFX_PED_CRUNCH_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 48; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PED_CRUNCH_1) + RandomDisplacement(600); - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = 40.0f; - ++CrunchOffset; - maxDist = SQR(SOUND_INTENSITY); - emittingVol = m_anRandomTable[4] % 20 + 55; - CrunchOffset %= 2; - m_sQueueSample.m_bRequireReflection = true; - break; - } - case SOUND_CAR_PED_COLLISION: - { - const float SOUND_INTENSITY = 40.0f; - vol = Min(20.0f, m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]); - emittingVol = (vol / 20.0f * 127.f); - if (!emittingVol) - continue; - - m_sQueueSample.m_nSampleIndex = (m_anRandomTable[2] & 3) + SFX_FIGHT_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nCounter = 50; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_fSpeedMultiplier = 0.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - maxDist = SQR(SOUND_INTENSITY); - break; - } - default: - continue; - } - if (params->m_fDistance < maxDist) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume != 0) { - if (noReflections) { - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - } else { - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - } - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bIs2D = false; - AddSampleToRequestedQueue(); - } - } - } -} - -bool -cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 50.0f; - - CVehicle *veh = params->m_pVehicle; - - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return false; - - if (veh->bEngineOn && veh->m_fGasPedal < 0.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 12; - m_sQueueSample.m_nSampleIndex = SFX_REVERSE_WARNING; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 2; - m_sQueueSample.m_nFrequency = (100 * m_sQueueSample.m_nEntityIndex & 1023) + SampleManager.GetSampleBaseFrequency(SFX_REVERSE_WARNING); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 60; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 3.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - return true; -} - -bool -cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 95.0f; - - int32 emittingVol; - uint32 freq; - float modificator; - int sampleFreq; - float velocity; - - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return false; - if (params->m_pTransmission) { - if (params->m_pVehicle->m_vecMoveSpeed.z) { - velocity = Abs(params->m_fVelocityChange); - if (velocity > 0.0f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - emittingVol = 30.f * Min(1.f, velocity / (0.5f * params->m_pTransmission->fMaxVelocity)); - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_PUDDLE) { - m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; - freq = 6050 * emittingVol / 30 + 16000; - } else { - m_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE; - modificator = m_sQueueSample.m_fDistance / 190.f; - sampleFreq = SampleManager.GetSampleBaseFrequency(SFX_ROAD_NOISE); - freq = (sampleFreq * modificator) + ((3 * sampleFreq) / 4); - } - m_sQueueSample.m_nFrequency = freq; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 6.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 4; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } - return true; -} - -void -cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 110.0f; - - if (params->m_fDistance < SQR(SOUND_INTENSITY)) { - CVehicle *veh = params->m_pVehicle; - if (veh->m_bSirenOrAlarm == 0 && veh->m_nAlarmState <= 0) - return; - -#ifdef FIX_BUGS - if (params->m_pVehicle->GetStatus() == STATUS_WRECKED) - return; -#endif - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 5; - if (UsesSiren(params->m_nIndex)) { - if (params->m_pVehicle->GetStatus() == STATUS_ABANDONED) - return; - if (veh->m_nCarHornTimer && params->m_nIndex != FIRETRUK) { - m_sQueueSample.m_nSampleIndex = SFX_SIREN_FAST; - if (params->m_nIndex == FBICAR) - m_sQueueSample.m_nFrequency = 16113; - else - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SIREN_FAST); - m_sQueueSample.m_nCounter = 60; - } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample; - m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency; - } - } else { - m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmSample; - m_sQueueSample.m_nFrequency = aVehicleSettings[params->m_nIndex].m_nSirenOrAlarmFrequency; - } - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = 80; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 7.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 5; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - return; - } - } -} - -void -cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 40.0f; - - CAutomobile *automobile; - cTransmission *transmission; - int32 emittingVol; - float newSkidVal = 0.0f; - float skidVal = 0.0f; - - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return; - automobile = (CAutomobile *)params->m_pVehicle; - if (!automobile->m_nWheelsOnGround) - return; - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { - if (automobile->m_aWheelState[i] == WHEEL_STATE_NORMAL || automobile->Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING) - continue; - transmission = params->m_pTransmission; - switch (transmission->nDriveType) - { - case '4': - newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); - break; - case 'F': - if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) - newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); - else - newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); - break; - case 'R': - if (i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT) - newSkidVal = GetVehicleDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); - else - newSkidVal = GetVehicleNonDriveWheelSkidValue(i, automobile, transmission, params->m_fVelocityChange); - break; - default: - break; - } - skidVal = Max(skidVal, newSkidVal); - } - - if (skidVal > 0.0f) { - emittingVol = 50.f * skidVal; - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 3; - switch (params->m_pVehicle->m_nSurfaceTouched) { - case SURFACE_GRASS: - case SURFACE_HEDGE: - m_sQueueSample.m_nSampleIndex = SFX_RAIN; - emittingVol /= 4; - m_sQueueSample.m_nFrequency = 13000.f * skidVal + 35000.f; - m_sQueueSample.m_nVolume /= 4; - break; - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - case SURFACE_SAND: - case SURFACE_PUDDLE: - m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; - m_sQueueSample.m_nFrequency = 6000.f * skidVal + 10000.f; - break; - - default: - m_sQueueSample.m_nSampleIndex = SFX_SKID; - m_sQueueSample.m_nFrequency = 5000.f * skidVal + 11000.f; - break; - } - - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 8; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 3.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -void cAudioManager::ProcessWaterCannon(int32) -{ - const float SOUND_INTENSITY = 900.0f; - - for (int32 i = 0; i < NUM_WATERCANNONS; i++) { - if (CWaterCannons::aCannons[i].m_nId) { - m_sQueueSample.m_vecPos = CWaterCannons::aCannons[0].m_avecPos[CWaterCannons::aCannons[i].m_nCur]; - float distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SOUND_INTENSITY) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(50, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = 15591; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_nCounter = i; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nReleasingVolumeDivider = 8; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nEmittingVolume = 50; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } -} - -void -cAudioManager::ProcessWeather(int32 id) -{ - uint8 vol; - static uint8 counter = 0; - - if (m_asAudioEntities[id].m_AudioEvents && m_asAudioEntities[id].m_awAudioEvent[0] == SOUND_LIGHTNING) { - if (m_asAudioEntities[id].m_afVolume[0] >= 10.f) { - m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 4000; - vol = (m_asAudioEntities[id].m_afVolume[0] - 10.f) + 40; - } else { - m_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_2; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 4000; - vol = (m_asAudioEntities[id].m_afVolume[0]) + 35; - } - m_sQueueSample.m_nVolume = vol; - if (TheCamera.SoundDistUp < 20.f) - m_sQueueSample.m_nVolume /= 2; - if (counter == 4) - counter = 0; - m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nOffset = (m_anRandomTable[2] & 15) + 55; - m_sQueueSample.m_bIs2D = true; - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume; - m_sQueueSample.m_nLoopStart = 0; - m_sQueueSample.m_nLoopEnd = -1; - m_sQueueSample.m_bReverbFlag = false; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - if (CWeather::Rain > 0.0f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) { - m_sQueueSample.m_nSampleIndex = SFX_RAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAIN); - m_sQueueSample.m_nVolume = (int32)(25.f * CWeather::Rain); - m_sQueueSample.m_nCounter = 4; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nReleasingVolumeModificator = 0; - m_sQueueSample.m_nOffset = 63; - m_sQueueSample.m_bIs2D = true; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 30; - m_sQueueSample.m_bReverbFlag = false; - m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } -} - -bool -cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) -{ - const float SOUND_INTENSITY = 30.0f; - - float relativeVelocity; - int32 emittingVol; - float modificator; - int freq; - float velChange; - - if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return false; - if (params->m_pTransmission) { - if (params->m_pVehicle->m_vecMoveSpeed.z) { - velChange = Abs(params->m_fVelocityChange); - if (velChange > 0.f) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - relativeVelocity = Min(1.0f, velChange / (0.5f * params->m_pTransmission->fMaxVelocity)); - emittingVol = 23.0f * relativeVelocity * CWeather::WetRoads; - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - modificator = m_sQueueSample.m_fDistance / 6.f; - freq = SampleManager.GetSampleBaseFrequency(SFX_ROAD_NOISE); - m_sQueueSample.m_nFrequency = freq + freq * modificator; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 6.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 4; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } - } - } - return true; -} - -void -cAudioManager::ProcessWorkShopScriptObject(uint8 sound) -{ - float distSquared; - - switch (sound) { - case SCRIPT_SOUND_WORK_SHOP_LOOP_S: - case SCRIPT_SOUND_WORK_SHOP_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 20.0f; - break; - default: - return; - } - distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { - m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = SFX_WORKSHOP_1; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_WORKSHOP_1); - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = 30; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - } -} - -int32 -cAudioManager::RandomDisplacement(uint32 seed) const -{ - int32 value; - - static bool bIsEven = true; - static uint32 base = 0; - - if (!seed) - return 0; - - value = m_anRandomTable[(base + seed) % 5] % seed; - base += value; - - if (value % 2) { - bIsEven = !bIsEven; - } - if (!bIsEven) - value = -value; - return value; -} - -void -cAudioManager::ReacquireDigitalHandle() const -{ - if (m_bIsInitialised) { - SampleManager.ReacquireDigitalHandle(); - } -} - -void -cAudioManager::ReleaseDigitalHandle() const -{ - if (m_bIsInitialised) { - SampleManager.ReleaseDigitalHandle(); - } -} - -void -cAudioManager::ResetAudioLogicTimers(uint32 timer) -{ - gPornNextTime = timer; - gNextCryTime = timer; - gSawMillNextTime = timer; - gCellNextTime = timer; - gShopNextTime = timer; - gHomeNextTime = timer; - gAirportNextTime = timer; - gDocksNextTime = timer; - gCinemaNextTime = timer; - for (int32 i = 0; i < m_nAudioEntitiesTotal; i++) { - if (m_asAudioEntities[m_anAudioEntityIndices[i]].m_nType == AUDIOTYPE_PHYSICAL) { - CPed *ped = (CPed *)m_asAudioEntities[m_anAudioEntityIndices[i]].m_pEntity; - if (ped->IsPed()) { - ped->m_lastSoundStart = timer; - ped->m_soundStart = timer + m_anRandomTable[0] % 3000; - } - } - } - ClearMissionAudio(); - SampleManager.StopChannel(policeChannel); -} - -void -cAudioManager::ResetTimers(uint32 time) -{ - if (m_bIsInitialised) { - m_bTimerJustReset = true; - m_nTimer = time; - ClearRequestedQueue(); - if (m_nActiveSampleQueue) { - m_nActiveSampleQueue = 0; - ClearRequestedQueue(); - m_nActiveSampleQueue = 1; - } else { - m_nActiveSampleQueue = 1; - ClearRequestedQueue(); - m_nActiveSampleQueue = 0; - } - ClearActiveSamples(); - ClearMissionAudio(); - SampleManager.StopChannel(policeChannel); - SampleManager.SetEffectsFadeVolume(0); - SampleManager.SetMusicFadeVolume(0); - MusicManager.ResetMusicAfterReload(); -#ifdef AUDIO_OAL - SampleManager.Service(); -#endif - } -} - -void -cAudioManager::Service() -{ - GenerateIntegerRandomNumberTable(); - if (m_bTimerJustReset) { - ResetAudioLogicTimers(m_nTimer); - MusicManager.ResetTimers(m_nTimer); - m_bTimerJustReset = false; - } - if (m_bIsInitialised) { - m_nPreviousUserPause = m_nUserPause; - m_nUserPause = CTimer::GetIsUserPaused(); - UpdateReflections(); - ServiceSoundEffects(); - MusicManager.Service(); - } -} - -void -cAudioManager::ServiceSoundEffects() -{ - m_bFifthFrameFlag = (m_FrameCounter++ % 5) == 0; - if (m_nUserPause && !m_nPreviousUserPause) { - for (int32 i = 0; i < allChannels; i++) - SampleManager.StopChannel(i); - - ClearRequestedQueue(); - if (m_nActiveSampleQueue) { - m_nActiveSampleQueue = 0; - ClearRequestedQueue(); - m_nActiveSampleQueue = 1; - } else { - m_nActiveSampleQueue = 1; - ClearRequestedQueue(); - m_nActiveSampleQueue = 0; - } - ClearActiveSamples(); - } - m_nActiveSampleQueue = m_nActiveSampleQueue != 1; - ProcessReverb(); - ProcessSpecial(); - ClearRequestedQueue(); - InterrogateAudioEntities(); - m_sPedComments.Process(); - ServicePoliceRadio(); - ServiceCollisions(); - AddReleasingSounds(); - ProcessMissionAudio(); - AdjustSamplesVolume(); - ProcessActiveQueues(); -#ifdef AUDIO_OAL - SampleManager.Service(); -#endif - for (int32 i = 0; i < m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal; ++i) { - cAudioScriptObject *object = (cAudioScriptObject *)m_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]].m_pEntity; - delete object; - m_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]].m_pEntity = nil; - DestroyEntity(m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]); - } - m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; -} - -int8 -cAudioManager::SetCurrent3DProvider(uint8 which) -{ - if (!m_bIsInitialised) - return -1; - for (uint8 i = 0; i < m_nActiveSamples + 1; ++i) - SampleManager.StopChannel(i); - ClearRequestedQueue(); - if (m_nActiveSampleQueue == 0) - m_nActiveSampleQueue = 1; - else - m_nActiveSampleQueue = 0; - ClearRequestedQueue(); - ClearActiveSamples(); - int8 current = SampleManager.SetCurrent3DProvider(which); - if (current > 0) { - m_nActiveSamples = SampleManager.GetMaximumSupportedChannels(); - if (m_nActiveSamples > 1) - --m_nActiveSamples; - } - return current; -} - -void -cAudioManager::SetDynamicAcousticModelingStatus(bool status) -{ - m_bDynamicAcousticModelingStatus = status; -} - -void -cAudioManager::SetEffectsFadeVolume(uint8 volume) const -{ - SampleManager.SetEffectsFadeVolume(volume); -} - -void -cAudioManager::SetEffectsMasterVolume(uint8 volume) const -{ - SampleManager.SetEffectsMasterVolume(volume); -} - -void -cAudioManager::SetEntityStatus(int32 id, uint8 status) -{ - if (m_bIsInitialised && id >= 0 && id < totalAudioEntitiesSlots && m_asAudioEntities[id].m_bIsUsed) - m_asAudioEntities[id].m_nStatus = status; -} - -void -cAudioManager::SetMissionAudioLocation(float x, float y, float z) -{ - if (m_bIsInitialised) { - m_sMissionAudio.m_bPredefinedProperties = false; - m_sMissionAudio.m_vecPos = CVector(x, y, z); - } -} - -void -cAudioManager::SetMusicFadeVolume(uint8 volume) const -{ - SampleManager.SetMusicFadeVolume(volume); -} - -void -cAudioManager::SetMusicMasterVolume(uint8 volume) const -{ - SampleManager.SetMusicMasterVolume(volume); -} - -void -cAudioManager::SetSpeakerConfig(int32 conf) const -{ - SampleManager.SetSpeakerConfig(conf); -} - -bool -cAudioManager::SetupJumboEngineSound(uint8 vol, int32 freq) -{ - const float SOUND_INTENSITY = 180.0f; - if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) - return false; - - uint8 emittingVol = vol - gJumboVolOffsetPercentage / 100; - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 3; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_ENGINE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = freq; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 4; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - return true; -} - -bool -cAudioManager::SetupJumboFlySound(uint8 emittingVol) -{ - const float SOUND_INTENSITY = 440.0f; - if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) - return false; - - int32 vol = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - m_sQueueSample.m_nVolume = vol; - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_DIST_FLY; - m_sQueueSample.m_nCounter = 0; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_DIST_FLY); - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_nReleasingVolumeDivider = 5; - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - AddSampleToRequestedQueue(); - } - return true; -} - -bool -cAudioManager::SetupJumboRumbleSound(uint8 emittingVol) -{ - const float SOUND_INTENSITY = 240.0f; - if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) - return false; - - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 5; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = true; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_RUMBLE); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 12; - m_sQueueSample.m_nOffset = 0; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - m_sQueueSample.m_nCounter = 6; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE; - m_sQueueSample.m_nFrequency += 200; - m_sQueueSample.m_nOffset = maxVolume; - AddSampleToRequestedQueue(); - } - return true; -} - -bool -cAudioManager::SetupJumboTaxiSound(uint8 vol) -{ - const float SOUND_INTENSITY = 180.0f; - if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) - return false; - - uint8 emittingVol = (vol / 2) + ((vol / 2) * m_sQueueSample.m_fDistance / SOUND_INTENSITY); - - if (m_sQueueSample.m_fDistance / SOUND_INTENSITY < 0.7f) - emittingVol -= emittingVol * gJumboVolOffsetPercentage / 100; - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 1; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = GetJumboTaxiFreq(); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 4; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - return true; -} - -bool -cAudioManager::SetupJumboWhineSound(uint8 emittingVol, int32 freq) -{ - const float SOUND_INTENSITY = 170.0f; - - if (m_sQueueSample.m_fDistance >= SOUND_INTENSITY) - return false; - - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - - if (m_sQueueSample.m_nVolume != 0) { - m_sQueueSample.m_nCounter = 2; - m_sQueueSample.m_nSampleIndex = SFX_JUMBO_WHINE; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 1; - m_sQueueSample.m_nFrequency = freq; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 4; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - return true; -} - void -cAudioManager::SetupPedComments(cPedParams *params, uint32 sound) +cAudioManager::ClearRequestedQueue() { - CPed *ped = params->m_pPed; - uint8 emittingVol; - float soundIntensity; - tPedComment pedComment; - - if (ped != nil) { - switch (sound) { - case SOUND_AMMUNATION_WELCOME_1: - pedComment.m_nSampleIndex = SFX_AMMU_D; - break; - case SOUND_AMMUNATION_WELCOME_2: - pedComment.m_nSampleIndex = SFX_AMMU_E; - break; - case SOUND_AMMUNATION_WELCOME_3: - pedComment.m_nSampleIndex = SFX_AMMU_F; - break; - default: - pedComment.m_nSampleIndex = GetPedCommentSfx(ped, sound); - if (pedComment.m_nSampleIndex == NO_SAMPLE) - return; - break; - } - - soundIntensity = 50.0f; - } else { - switch (sound) { - case SOUND_PED_HELI_PLAYER_FOUND: - soundIntensity = 400.0f; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_POLICE_HELI_1, SFX_POLICE_HELI_29); - break; - case SOUND_PED_BODYCAST_HIT: - if (CTimer::GetTimeInMilliseconds() <= gNextCryTime) - return; - soundIntensity = 50.0f; - gNextCryTime = CTimer::GetTimeInMilliseconds() + 500; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_PLASTER_BLOKE_1, SFX_PLASTER_BLOKE_4); - break; - case SOUND_INJURED_PED_MALE_OUCH: - case SOUND_INJURED_PED_MALE_PRISON: - soundIntensity = 50.0f; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_MALE_GRUNT_1, SFX_GENERIC_MALE_GRUNT_15); - break; - case SOUND_INJURED_PED_FEMALE: - soundIntensity = 50.0f; - pedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_FEMALE_GRUNT_1, SFX_GENERIC_FEMALE_GRUNT_11); - break; - default: - return; - } - } - - if (params->m_fDistance < SQR(soundIntensity)) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - if (sound != SOUND_PAGER) { - switch (sound) { - case SOUND_AMMUNATION_WELCOME_1: - case SOUND_AMMUNATION_WELCOME_2: - case SOUND_AMMUNATION_WELCOME_3: - emittingVol = maxVolume; - break; - default: - if (CWorld::GetIsLineOfSightClear(TheCamera.GetPosition(), m_sQueueSample.m_vecPos, true, false, false, false, false, false)) - emittingVol = maxVolume; - else - emittingVol = 31; - break; - } - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, soundIntensity, m_sQueueSample.m_fDistance); - pedComment.m_nProcess = 10; - if (m_sQueueSample.m_nVolume != 0) { - pedComment.m_nEntityIndex = m_sQueueSample.m_nEntityIndex; - pedComment.m_vecPos = m_sQueueSample.m_vecPos; - pedComment.m_fDistance = m_sQueueSample.m_fDistance; - pedComment.m_bVolume = m_sQueueSample.m_nVolume; - m_sPedComments.Add(&pedComment); - } - } - } -} - -void -cAudioManager::Terminate() -{ - if (m_bIsInitialised) { - MusicManager.Terminate(); - - for (uint32 i = 0; i < totalAudioEntitiesSlots; i++) { - m_asAudioEntities[i].m_bIsUsed = false; - m_anAudioEntityIndices[i] = ARRAY_SIZE(m_anAudioEntityIndices); - } - - m_nAudioEntitiesTotal = 0; - m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; - PreTerminateGameSpecificShutdown(); - - for (uint32 i = 0; i < MAX_SAMPLEBANKS; i++) { - if (SampleManager.IsSampleBankLoaded(i)) - SampleManager.UnloadSampleBank(i); - } - - SampleManager.Terminate(); - - m_bIsInitialised = false; - PostTerminateGameSpecificShutdown(); + for (int32 i = 0; i < m_nActiveSamples; i++) { + m_abSampleQueueIndexTable[m_nActiveSampleQueue][i] = m_nActiveSamples; } + m_SampleRequestQueuesStatus[m_nActiveSampleQueue] = 0; } void -cAudioManager::TranslateEntity(Const CVector *in, CVector *out) const -{ - *out = MultiplyInverse(TheCamera.GetMatrix(), *in); -} - -void -cAudioManager::UpdateGasPedalAudio(CAutomobile *automobile) +cAudioManager::ClearActiveSamples() { - float newGasPedalAudio; - - float gasPedal = Abs(automobile->m_fGasPedal); - float gasPedalAudio = automobile->m_fGasPedalAudio; - - if (gasPedalAudio < gasPedal) { - newGasPedalAudio = gasPedalAudio + 0.09f; - if (gasPedal <= newGasPedalAudio) - newGasPedalAudio = gasPedal; - } else { - newGasPedalAudio = gasPedalAudio - 0.07f; - if (gasPedal >= newGasPedalAudio) - newGasPedalAudio = gasPedal; + for (int32 i = 0; i < m_nActiveSamples; i++) { + m_asActiveSamples[i].m_nEntityIndex = AEHANDLE_NONE; + m_asActiveSamples[i].m_nCounter = 0; + m_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE; + m_asActiveSamples[i].m_nBankIndex = SAMPLEBANK_INVALID; + m_asActiveSamples[i].m_bIs2D = false; + m_asActiveSamples[i].m_nReleasingVolumeModificator = 5; + m_asActiveSamples[i].m_nFrequency = 0; + m_asActiveSamples[i].m_nVolume = 0; + m_asActiveSamples[i].m_nEmittingVolume = 0; + m_asActiveSamples[i].m_fDistance = 0.0f; + m_asActiveSamples[i].m_bIsProcessed = false; + m_asActiveSamples[i].m_bLoopEnded = false; + m_asActiveSamples[i].m_nLoopCount = 1; + m_asActiveSamples[i].m_nLoopStart = 0; + m_asActiveSamples[i].m_nLoopEnd = -1; + m_asActiveSamples[i].m_fSpeedMultiplier = 0.0f; + m_asActiveSamples[i].m_fSoundIntensity = 200.0f; + m_asActiveSamples[i].m_nOffset = 63; + m_asActiveSamples[i].m_bReleasingSoundFlag = false; + m_asActiveSamples[i].m_nCalculatedVolume = 0; + m_asActiveSamples[i].m_nReleasingVolumeDivider = 0; + m_asActiveSamples[i].m_nVolumeChange = -1; + m_asActiveSamples[i].m_vecPos = {0.0f, 0.0f, 0.0f}; + m_asActiveSamples[i].m_bReverbFlag = false; + m_asActiveSamples[i].m_nLoopsRemaining = 0; + m_asActiveSamples[i].m_bRequireReflection = false; } - automobile->m_fGasPedalAudio = newGasPedalAudio; } void -cAudioManager::UpdateReflections() -{ - const CVector &camPos = TheCamera.GetPosition(); - CColPoint colpoint; - CEntity *ent; - - if (m_FrameCounter % 8 == 0) { - m_avecReflectionsPos[0] = camPos; - m_avecReflectionsPos[0].y += 50.f; - if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[0], colpoint, ent, true, false, false, true, false, true, true)) - m_afReflectionsDistances[0] = Distance(camPos, colpoint.point); - else - m_afReflectionsDistances[0] = 50.0f; - } else if ((m_FrameCounter + 1) % 8 == 0) { - m_avecReflectionsPos[1] = camPos; - m_avecReflectionsPos[1].y -= 50.0f; - if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[1], colpoint, ent, true, false, false, true, false, true, true)) - m_afReflectionsDistances[1] = Distance(camPos, colpoint.point); - else - m_afReflectionsDistances[1] = 50.0f; - } else if ((m_FrameCounter + 2) % 8 == 0) { - m_avecReflectionsPos[2] = camPos; - m_avecReflectionsPos[2].x -= 50.0f; - if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[2], colpoint, ent, true, false, false, true, false, true, true)) - m_afReflectionsDistances[2] = Distance(camPos, colpoint.point); - else - m_afReflectionsDistances[2] = 50.0f; - } else if ((m_FrameCounter + 3) % 8 == 0) { - m_avecReflectionsPos[3] = camPos; - m_avecReflectionsPos[3].x += 50.0f; - if (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[3], colpoint, ent, true, false, false, true, false, true, true)) - m_afReflectionsDistances[3] = Distance(camPos, colpoint.point); - else - m_afReflectionsDistances[3] = 50.0f; - } else if ((m_FrameCounter + 4) % 8 == 0) { - m_avecReflectionsPos[4] = camPos; - m_avecReflectionsPos[4].z += 50.0f; - if (CWorld::ProcessVerticalLine(camPos, m_avecReflectionsPos[4].z, colpoint, ent, true, false, false, false, true, false, nil)) - m_afReflectionsDistances[4] = colpoint.point.z - camPos.z; - else - m_afReflectionsDistances[4] = 50.0f; - } -} - -bool -cAudioManager::UsesReverseWarning(int32 model) const -{ - return model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == COACH; -} - -bool -cAudioManager::UsesSiren(int32 model) const -{ - switch (model) { - case FIRETRUK: - case AMBULAN: - case FBICAR: - case POLICE: - case ENFORCER: - case PREDATOR: - return true; - default: - return false; - } -} - -bool -cAudioManager::UsesSirenSwitching(int32 model) const +cAudioManager::GenerateIntegerRandomNumberTable() { - switch (model) { - case AMBULAN: - case POLICE: - case ENFORCER: - case PREDATOR: - return true; - default: - return false; + for (int32 i = 0; i < ARRAY_SIZE(m_anRandomTable); i++) { + m_anRandomTable[i] = rand(); } } +#ifdef GTA_PC void cAudioManager::AdjustSamplesVolume() { @@ -9790,3 +967,4 @@ cAudioManager::ComputeEmittingVolume(uint8 emittingVolume, float intensity, floa return (quatIntensity - (dist - diffIntensity)) * (float)emittingVolume / quatIntensity; return emittingVolume; } +#endif diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index bbbc84bd..b2b44c07 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -75,7 +75,18 @@ public: uint8 m_nCommentsInBank[NUM_PED_COMMENTS_BANKS]; uint8 m_nActiveBank; - cPedComments(); + cPedComments() + { + for (int i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) + for (int j = 0; j < NUM_PED_COMMENTS_BANKS; j++) { + m_asPedComments[j][i].m_nProcess = -1; + m_nIndexMap[j][i] = NUM_PED_COMMENTS_SLOTS; + } + + for (int i = 0; i < NUM_PED_COMMENTS_BANKS; i++) + m_nCommentsInBank[i] = 0; + m_nActiveBank = 0; + } void Add(tPedComment *com); void Process(); }; @@ -222,11 +233,10 @@ public: float speedMultiplier) const; int32 ComputePan(float, CVector *); uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; - int32 CreateEntity(int32 type, void *entity); + int32 CreateEntity(eAudioType type, void *entity); void DestroyAllGameCreatedEntities(); void DestroyEntity(int32 id); - void DoJumboVolOffset() const; void DoPoliceRadioCrackle(); // functions returning talk sfx, @@ -434,14 +444,14 @@ public: void ServiceSoundEffects(); int8 SetCurrent3DProvider(uint8 which); void SetDynamicAcousticModelingStatus(bool status); - void SetEffectsFadeVolume(uint8 volume) const; + void SetEffectsFadeVol(uint8 volume) const; void SetEffectsMasterVolume(uint8 volume) const; void SetEntityStatus(int32 id, uint8 status); uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); void SetMissionAudioLocation(float x, float y, float z); void SetMissionScriptPoliceAudio(int32 sfx) const; void SetMonoMode(uint8); // todo (mobile) - void SetMusicFadeVolume(uint8 volume) const; + void SetMusicFadeVol(uint8 volume) const; void SetMusicMasterVolume(uint8 volume) const; void SetSpeakerConfig(int32 conf) const; void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter); @@ -464,9 +474,11 @@ public: bool UsesSiren(int32 model) const; bool UsesSirenSwitching(int32 model) const; +#ifdef GTA_PC // only used in pc void AdjustSamplesVolume(); uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); +#endif }; #ifdef AUDIO_MSS diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 888081b7..18d13c9d 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -29,7 +29,7 @@ cDMAudio::Service(void) } int32 -cDMAudio::CreateEntity(int32 type, void *UID) +cDMAudio::CreateEntity(eAudioType type, void *UID) { return AudioManager.CreateEntity(type, (CPhysical *)UID); } @@ -82,7 +82,7 @@ cDMAudio::SetEffectsFadeVol(uint8 volume) uint8 vol = volume; if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; - AudioManager.SetEffectsFadeVolume(vol); + AudioManager.SetEffectsFadeVol(vol); } void @@ -91,7 +91,7 @@ cDMAudio::SetMusicFadeVol(uint8 volume) uint8 vol = volume; if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; - AudioManager.SetMusicFadeVolume(vol); + AudioManager.SetMusicFadeVol(vol); } uint8 diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 052fdb81..e1a18830 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -20,7 +20,7 @@ public: void Terminate(void); void Service(void); - int32 CreateEntity(int32 type, void *UID); + int32 CreateEntity(eAudioType type, void *UID); void DestroyEntity(int32 audioEntity); void SetEntityStatus(int32 audioEntity, uint8 status); void PlayOneShot(int32 audioEntity, uint16 oneShot, float volume); From 4ff0697b4d29144e6dfad4ca14a98aa1bce5bf5e Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 16 May 2020 21:00:27 +0300 Subject: [PATCH 023/148] More small audio fixes --- src/audio/AudioLogic.cpp | 13 ++++++------- src/audio/AudioManager.cpp | 14 +++++++------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 05483617..2a6581ee 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1304,7 +1304,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; SampleManager.SetChannelFrequency(m_nActiveSamples, freq); if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); SampleManager.StartChannel(m_nActiveSamples); } LastAccel = accelerateState; @@ -1326,7 +1326,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * freq /= 2; SampleManager.SetChannelFrequency(m_nActiveSamples, freq); if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); SampleManager.StartChannel(m_nActiveSamples); } LastAccel = accelerateState; @@ -1349,7 +1349,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * freq /= 2; SampleManager.SetChannelFrequency(m_nActiveSamples, freq); if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != 0); + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); SampleManager.StartChannel(m_nActiveSamples); } LastAccel = accelerateState; @@ -1515,11 +1515,10 @@ cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automo { float relativeVelChange; - if (automobile->m_aWheelState[wheel] == 2) { + if (automobile->m_aWheelState[wheel] == WHEEL_STATE_SKIDDING) relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); - } else { + else relativeVelChange = 0.0f; - } return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); } @@ -1606,7 +1605,7 @@ cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) if (params->m_fDistance < SQR(SOUND_INTENSITY)) { CVehicle *veh = params->m_pVehicle; - if (veh->m_bSirenOrAlarm == 0 && veh->m_nAlarmState <= 0) + if (veh->m_bSirenOrAlarm == false && veh->m_nAlarmState <= 0) return; #ifdef FIX_BUGS diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index eecc8e7d..458341b9 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -32,7 +32,7 @@ cAudioManager::cAudioManager() ClearActiveSamples(); GenerateIntegerRandomNumberTable(); field_4 = 0; - m_bDynamicAcousticModelingStatus = 1; + m_bDynamicAcousticModelingStatus = true; for (int i = 0; i < NUM_AUDIOENTITIES; i++) { m_asAudioEntities[i].m_bIsUsed = false; @@ -514,19 +514,19 @@ cAudioManager::RandomDisplacement(uint32 seed) const { int32 value; - static bool bIsEven = true; - static uint32 base = 0; + static bool bPos = true; + static uint32 Adjustment = 0; if (!seed) return 0; - value = m_anRandomTable[(base + seed) % 5] % seed; - base += value; + value = m_anRandomTable[(Adjustment + seed) % 5] % seed; + Adjustment += value; if (value % 2) { - bIsEven = !bIsEven; + bPos = !bPos; } - if (!bIsEven) + if (!bPos) value = -value; return value; } From b587d835e8d31c1e61b3eadbced099326c156644 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 23:06:33 +0300 Subject: [PATCH 024/148] more script stuff --- src/control/Pickups.cpp | 12 +++++----- src/control/Pickups.h | 2 +- src/control/Script.cpp | 44 ++++++++++++++++++++++++++++++++++-- src/core/Pad.cpp | 4 ++-- src/core/PlayerInfo.cpp | 1 + src/core/PlayerInfo.h | 3 +++ src/core/Stats.cpp | 19 ++++++++++++++++ src/core/Stats.h | 4 ++++ src/modelinfo/ModelIndices.h | 3 ++- src/peds/CivilianPed.cpp | 4 ++-- src/vehicles/Vehicle.cpp | 4 ++-- 11 files changed, 84 insertions(+), 16 deletions(-) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 330b5788..b2cd1e05 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -129,12 +129,12 @@ CPickup::GiveUsAPickUpObject(int32 handle) } bool -CPickup::CanBePickedUp(CPlayerPed *player) +CPickup::CanBePickedUp(CPlayerPed *player, int playerId) { assert(m_pObject != nil); bool cannotBePickedUp = - (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f) - || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f) + (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > CWorld::Players[playerId].m_nMaxArmour - 0.5f) + || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > CWorld::Players[playerId].m_nMaxHealth - 0.5f) || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0) || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame)); return !cannotBePickedUp; @@ -190,7 +190,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) } // if we didn't then we've got nothing to do - if (isPickupTouched && CanBePickedUp(player)) { + if (isPickupTouched && CanBePickedUp(player, playerId)) { CPad::GetPad(0)->StartShake(120, 100); switch (m_eType) { @@ -430,14 +430,14 @@ CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex) DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0); return true; } else if (modelIndex == MI_PICKUP_BODYARMOUR) { - player->m_fArmour = 100.0f; + player->m_fArmour = CWorld::Players[playerIndex].m_nMaxArmour; DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0); return true; } else if (modelIndex == MI_PICKUP_INFO) { DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); return true; } else if (modelIndex == MI_PICKUP_HEALTH) { - player->m_fHealth = 100.0f; + player->m_fHealth = CWorld::Players[playerIndex].m_nMaxHealth; DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0); return true; } else if (modelIndex == MI_PICKUP_BONUS) { diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 2842edfa..fde3e134 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -46,7 +46,7 @@ public: bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId); private: bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } - inline bool CanBePickedUp(CPlayerPed *player); + inline bool CanBePickedUp(CPlayerPed *player, int playerId); void RemoveKeepType(); void Remove(); }; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index f496ed33..805d6469 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -4821,7 +4821,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CollectParameters(&m_nIp, 2); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - pPed->m_fHealth = ScriptParams[1]; + pPed->m_fHealth = Min(ScriptParams[1], CWorld::Players[ScriptParams[0]].m_nMaxHealth); return 0; } case COMMAND_SET_CHAR_HEALTH: @@ -7173,7 +7173,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CollectParameters(&m_nIp, 2); CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPlayerPed); - pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f); + pPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, CWorld::Players[ScriptParams[0]].m_nMaxArmour); return 0; } case COMMAND_ADD_ARMOUR_TO_CHAR: @@ -9870,6 +9870,10 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) return 0; } case COMMAND_ADD_MONEY_SPENT_ON_CLOTHES: + CollectParameters(&m_nIp, 1); + CStats::MoneySpentOnFashion(ScriptParams[0]); + return 0; + case COMMAND_SET_HELI_ORIENTATION: case COMMAND_CLEAR_HELI_ORIENTATION: case COMMAND_PLANE_GOTO_COORDS: @@ -10077,10 +10081,41 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_GET_CLOSEST_WATER_NODE: case COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH: case COMMAND_CREATE_CLOTHES_PICKUP: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); + ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_CLOTHES, PICKUP_ON_STREET, ScriptParams[3]); + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_CHANGE_BLIP_THRESHOLD: + assert(0); case COMMAND_MAKE_PLAYER_FIRE_PROOF: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + pPlayerInfo->m_bFireproof = ScriptParams[1]; + return 0; + } case COMMAND_INCREASE_PLAYER_MAX_HEALTH: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + pPlayerInfo->m_nMaxHealth += ScriptParams[1]; + pPlayerInfo->m_pPed->m_fHealth = pPlayerInfo->m_nMaxHealth; + return 0; + } case COMMAND_INCREASE_PLAYER_MAX_ARMOUR: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + pPlayerInfo->m_nMaxArmour += ScriptParams[1]; + pPlayerInfo->m_pPed->m_fArmour = pPlayerInfo->m_nMaxArmour; + return 0; + } case COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER: case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER: case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS: @@ -10090,6 +10125,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) assert(0); case COMMAND_SET_OBJECT_AREA_VISIBLE: { + CollectParameters(&m_nIp, 2); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); assert(pObject); pObject->m_area = ScriptParams[1]; @@ -10157,7 +10193,11 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG: case COMMAND_ADD_BIG_GUN_FLASH: case COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM: + assert(0); case COMMAND_GET_PROGRESS_PERCENTAGE: + *(float*)&ScriptParams[0] = CStats::GetPercentageProgress(); + StoreParameters(&m_nIp, 1); + return 0; case COMMAND_SET_SHORTCUT_PICKUP_POINT: case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION: case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA: diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index a40366ad..ae7fcdb4 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -100,7 +100,7 @@ void WeaponCheat() void HealthCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT3"), true); - FindPlayerPed()->m_fHealth = 100.0f; + FindPlayerPed()->m_fHealth = CWorld::Players[0].m_nMaxHealth; if (FindPlayerVehicle()) { FindPlayerVehicle()->m_fHealth = 1000.0f; if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR) @@ -224,7 +224,7 @@ void MoneyCheat() void ArmourCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT4"), true); - FindPlayerPed()->m_fArmour = 100.0f; + FindPlayerPed()->m_fArmour = CWorld::Players[0].m_nMaxArmour; } void WantedLevelUpCheat() diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index d7b3f0e5..48425a23 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -140,6 +140,7 @@ CPlayerInfo::Clear(void) m_nUpsideDownCounter = 0; m_bInfiniteSprint = false; m_bFastReload = false; + m_nMaxHealth = m_nMaxArmour = 100; m_bGetOutOfJailFree = false; m_bGetOutOfHospitalFree = false; m_nPreviousTimeRewardedForExplosion = 0; diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index c649d49d..1b5778d5 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -52,6 +52,9 @@ public: int32 field_272; bool m_bInfiniteSprint; bool m_bFastReload; + bool m_bFireproof; + uint8 m_nMaxHealth; + uint8 m_nMaxArmour; bool m_bGetOutOfJailFree; bool m_bGetOutOfHospitalFree; char m_aSkinName[32]; diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index d50be0d5..a4bf409e 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -61,6 +61,7 @@ int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; int32 CStats::Sprayings; float CStats::AutoPaintingBudget; int32 CStats::NoMoreHurricanes; +float CStats::FashionBudget; void CStats::Init() { @@ -208,6 +209,19 @@ void CStats::SetTotalNumberMissions(int32 total) TotalNumberMissions = total; } +float CStats::GetPercentageProgress() +{ + float p; + if (TotalProgressInGame == 0.0f) + p = 0.0f; + else if (CGame::nastyGame) + p = 100.0f * ProgressMade / TotalProgressInGame; + else + p = 100.0f * ProgressMade / (TotalProgressInGame - 1); + + return Min(100.0f, p); +} + wchar *CStats::FindCriminalRatingString() { int rating = FindCriminalRatingNumber(); @@ -249,6 +263,11 @@ int32 CStats::FindCriminalRatingNumber() return rating; } +void CStats::MoneySpentOnFashion(int32 money) +{ + FashionBudget += money; +} + void CStats::SaveStats(uint8 *buf, uint32 *size) { CheckPointReachedSuccessfully(); diff --git a/src/core/Stats.h b/src/core/Stats.h index bf40a5a6..6ff74dc1 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -65,6 +65,7 @@ public: static int32 Sprayings; static float AutoPaintingBudget; static int32 NoMoreHurricanes; + static float FashionBudget; public: static void Init(void); @@ -88,6 +89,9 @@ public: static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; }; static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; }; static int32 FindCriminalRatingNumber(); + static float GetPercentageProgress(); static void SaveStats(uint8 *buf, uint32 *size); static void LoadStats(uint8 *buf, uint32 size); + + static void MoneySpentOnFashion(int32); }; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 25eb4cf0..3a53074d 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -160,7 +160,8 @@ X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \ X("files", MI_FILES, 0x5F5BC4) \ X("property_locked", MI_PICKUP_PROPERTY, 0x0) \ - X("property_fsale", MI_PICKUP_PROPERTY_FORSALE, 0x0) + X("property_fsale", MI_PICKUP_PROPERTY_FORSALE, 0x0) \ + X("clothesp", MI_PICKUP_CLOTHES, 0x0) #define X(name, var, addr) extern int16 var; MODELINDICES diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 48785025..8cc6b92c 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -325,7 +325,7 @@ CCivilianPed::ProcessControl(void) CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10); } - m_pMyVehicle->pDriver->m_fHealth = Min(125.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth); + m_pMyVehicle->pDriver->m_fHealth = Min(CWorld::Players[0].m_nMaxHealth + 25.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth); if (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250) CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; } else { @@ -336,7 +336,7 @@ CCivilianPed::ProcessControl(void) } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; - m_pMyVehicle->pDriver->m_fHealth = 125.0f; + m_pMyVehicle->pDriver->m_fHealth = CWorld::Players[0].m_nMaxHealth + 25.0f; SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); } } else { diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index e457f964..df8c71b0 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1080,14 +1080,14 @@ CVehicle::SetDriver(CPed *driver) if(bFreebies && driver == FindPlayerPed()){ if(GetModelIndex() == MI_AMBULAN) - FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f); + FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth); else if(GetModelIndex() == MI_TAXI) CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; else if (GetModelIndex() == MI_POLICE) { CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE); driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5); } else if (GetModelIndex() == MI_ENFORCER) - driver->m_fArmour = Max(driver->m_fArmour, 100.0f); + driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour); else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA) // TODO(MIAMI): check zebra CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; bFreebies = false; From ad0b99231e31c5374a822a3f2173958f6a0ce517 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 16 May 2020 23:54:44 +0300 Subject: [PATCH 025/148] Remove magic consts from ms_aAnimAssocDefinitions --- src/animation/AnimManager.cpp | 53 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index 8fb1576c..444b6d45 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -530,33 +530,36 @@ char const *aRocketStrafeRightAnimations[] = { "idle_rocket", "walkst_rocket_right", }; + +#define awc(a) ARRAY_SIZE(a), a const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = { - { "man", "ped", MI_COP, 173, aStdAnimations, aStdAnimDescs }, - { "player", "ped", MI_COP, 5, aPlayerAnimations, aStdAnimDescs }, - { "playerrocket", "ped", MI_COP, 5, aPlayerWithRocketAnimations, aStdAnimDescs }, - { "player1armed", "ped", MI_COP, 5, aPlayer1ArmedAnimations, aStdAnimDescs }, - { "player2armed", "ped", MI_COP, 5, aPlayer2ArmedAnimations, aStdAnimDescs }, - { "playerBBBat", "ped", MI_COP, 5, aPlayerBBBatAnimations, aStdAnimDescs }, - { "shuffle", "ped", MI_COP, 4, aShuffleAnimations, aStdAnimDescs }, - { "oldman", "ped", MI_COP, 4, aOldAnimations, aStdAnimDescs }, - { "gang1", "ped", MI_COP, 4, aGang1Animations, aStdAnimDescs }, - { "gang2", "ped", MI_COP, 4, aGang2Animations, aStdAnimDescs }, - { "fatman", "ped", MI_COP, 4, aFatAnimations, aStdAnimDescs }, - { "oldfatman", "ped", MI_COP, 4, aOldFatAnimations, aStdAnimDescs }, - { "woman", "ped", MI_COP, 4, aStdWomanAnimations, aStdAnimDescs }, - { "shopping", "ped", MI_COP, 4, aWomanShopAnimations, aStdAnimDescs }, - { "busywoman", "ped", MI_COP, 4, aBusyWomanAnimations, aStdAnimDescs }, - { "sexywoman", "ped", MI_COP, 4, aSexyWomanAnimations, aStdAnimDescs }, - { "oldwoman", "ped", MI_COP, 4, aOldWomanAnimations, aStdAnimDescs }, - { "fatwoman", "ped", MI_COP, 4, aFatWomanAnimations, aStdAnimDescs }, - { "panicchunky", "ped", MI_COP, 4, aPanicChunkyAnimations, aStdAnimDescs }, - { "playerback", "ped", MI_COP, 5, aPlayerStrafeBackAnimations, aStdAnimDescs }, - { "playerleft", "ped", MI_COP, 5, aPlayerStrafeLeftAnimations, aStdAnimDescsSide }, - { "playerright", "ped", MI_COP, 5, aPlayerStrafeRightAnimations, aStdAnimDescsSide }, - { "rocketback", "ped", MI_COP, 5, aRocketStrafeBackAnimations, aStdAnimDescs }, - { "rocketleft", "ped", MI_COP, 5, aRocketStrafeLeftAnimations, aStdAnimDescsSide }, - { "rocketright", "ped", MI_COP, 5, aRocketStrafeRightAnimations, aStdAnimDescsSide }, + { "man", "ped", MI_COP, awc(aStdAnimations), aStdAnimDescs }, + { "player", "ped", MI_COP, awc(aPlayerAnimations), aStdAnimDescs }, + { "playerrocket", "ped", MI_COP, awc(aPlayerWithRocketAnimations), aStdAnimDescs }, + { "player1armed", "ped", MI_COP, awc(aPlayer1ArmedAnimations), aStdAnimDescs }, + { "player2armed", "ped", MI_COP, awc(aPlayer2ArmedAnimations), aStdAnimDescs }, + { "playerBBBat", "ped", MI_COP, awc(aPlayerBBBatAnimations), aStdAnimDescs }, + { "shuffle", "ped", MI_COP, awc(aShuffleAnimations), aStdAnimDescs }, + { "oldman", "ped", MI_COP, awc(aOldAnimations), aStdAnimDescs }, + { "gang1", "ped", MI_COP, awc(aGang1Animations), aStdAnimDescs }, + { "gang2", "ped", MI_COP, awc(aGang2Animations), aStdAnimDescs }, + { "fatman", "ped", MI_COP, awc(aFatAnimations), aStdAnimDescs }, + { "oldfatman", "ped", MI_COP, awc(aOldFatAnimations), aStdAnimDescs }, + { "woman", "ped", MI_COP, awc(aStdWomanAnimations), aStdAnimDescs }, + { "shopping", "ped", MI_COP, awc(aWomanShopAnimations), aStdAnimDescs }, + { "busywoman", "ped", MI_COP, awc(aBusyWomanAnimations), aStdAnimDescs }, + { "sexywoman", "ped", MI_COP, awc(aSexyWomanAnimations), aStdAnimDescs }, + { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs }, + { "fatwoman", "ped", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs }, + { "panicchunky", "ped", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs }, + { "playerback", "ped", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs }, + { "playerleft", "ped", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide }, + { "playerright", "ped", MI_COP, awc(aPlayerStrafeRightAnimations), aStdAnimDescsSide }, + { "rocketback", "ped", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs }, + { "rocketleft", "ped", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide }, + { "rocketright", "ped", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide }, }; +#undef awc void CAnimManager::Initialise(void) From 37480fb617a4b8ecd7203af53a1711aa5cdda19d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 17 May 2020 00:33:52 +0300 Subject: [PATCH 026/148] Fix compilation errors --- src/animation/AnimManager.cpp | 122 +- src/audio/AudioLogic.cpp | 2705 +++------------------------------ src/audio/AudioManager.h | 78 +- 3 files changed, 247 insertions(+), 2658 deletions(-) diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index bf4bab53..ed98be1d 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -899,69 +899,69 @@ char const* aChainsawStrafeRightAnimations[] = { }; - +#define awc(a) ARRAY_SIZE(a), a const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = { { "man", "ped", MI_COP, awc(aStdAnimations), aStdAnimDescs }, - { "van", "van", MI_COP, 8, aVanAnimations, aVanAnimDescs }, - { "coach", "coach", MI_COP, 5, aCoachAnimations, aCoachAnimDescs }, - { "bikes", "bikes", MI_COP, 18, aBikesAnimations, aBikeAnimDescs }, - { "bikev", "bikev", MI_COP, 18, aBikevAnimations, aBikeAnimDescs }, - { "bikeh", "bikeh", MI_COP, 18, aBikehAnimations, aBikeAnimDescs }, - { "biked", "biked", MI_COP, 18, aBikedAnimations, aBikeAnimDescs }, - { "unarmed", "ped", MI_COP, 3, aUnarmedAnimations, aMeleeAnimDescs }, - { "screwdrv", "ped", MI_COP, 5, aScrewdriverAnimations, aMeleeAnimDescs }, - { "knife", "knife", MI_COP, 5, aKnifeAnimations, aMeleeAnimDescs }, - { "baseball", "baseball", MI_COP, 5, aBaseballbatAnimations, aSwingAnimDescs }, - { "golfclub", "baseball", MI_COP, 5, aGolfclubAnimations, aSwingAnimDescs }, - { "chainsaw", "chainsaw", MI_COP, 3, aChainsawAnimations, aMeleeAnimDescs }, - { "python", "python", MI_COP, 4, aPythonAnimations, aWeaponAnimDescs }, - { "colt45", "colt45", MI_COP, 5, aColtAnimations, aWeaponAnimDescs }, - { "shotgun", "shotgun", MI_COP, 2, aShotgunAnimations, aWeaponAnimDescs }, - { "buddy", "buddy", MI_COP, 2, aBuddyAnimations, aWeaponAnimDescs }, - { "tec", "tec", MI_COP, 4, aTecAnimations, aWeaponAnimDescs }, - { "uzi", "uzi", MI_COP, 4, aUziAnimations, aWeaponAnimDescs }, - { "rifle", "rifle", MI_COP, 4, aRifleAnimations, aWeaponAnimDescs }, - { "m60", "m60", MI_COP, 3, aM60Animations, aWeaponAnimDescs }, - { "sniper", "sniper", MI_COP, 1, aSniperAnimations, aWeaponAnimDescs }, - { "grenade", "grenade", MI_COP, 3, aThrowAnimations, aWeaponAnimDescs }, - { "flame", "flame", MI_COP, 1, aFlamethrowerAnimations, aWeaponAnimDescs }, - { "medic", "medic", MI_COP, 1, aMedicAnimations, aMedicAnimDescs }, - { "sunbathe", "sunbathe", MI_COP, 1, aSunbatheAnimations, aSunbatheAnimDescs }, - { "playidles", "playidles", MI_COP, 4, aPlayerIdleAnimations, aPlayerIdleAnimDescs }, - { "riot", "riot", MI_COP, 7, aRiotAnimations, aRiotAnimDescs }, - { "strip", "strip", MI_COP, 7, aStripAnimations, aStripAnimDescs }, - { "lance", "lance", MI_COP, 1, aLanceAnimations, aSunbatheAnimDescs }, - { "player", "ped", MI_COP, 5, aPlayerAnimations, aStdAnimDescs }, - { "playerrocket", "ped", MI_COP, 5, aPlayerWithRocketAnimations, aStdAnimDescs }, - { "player1armed", "ped", MI_COP, 5, aPlayer1ArmedAnimations, aStdAnimDescs }, - { "player2armed", "ped", MI_COP, 5, aPlayer2ArmedAnimations, aStdAnimDescs }, - { "playerBBBat", "ped", MI_COP, 5, aPlayerBBBatAnimations, aStdAnimDescs }, - { "playercsaw", "ped", MI_COP, 5, aPlayerChainsawAnimations, aStdAnimDescs }, - { "shuffle", "ped", MI_COP, 4, aShuffleAnimations, aStdAnimDescs }, - { "oldman", "ped", MI_COP, 4, aOldAnimations, aStdAnimDescs }, - { "gang1", "ped", MI_COP, 4, aGang1Animations, aStdAnimDescs }, - { "gang2", "ped", MI_COP, 4, aGang2Animations, aStdAnimDescs }, - { "fatman", "ped", MI_COP, 4, aFatAnimations, aStdAnimDescs }, - { "oldfatman", "ped", MI_COP, 4, aOldFatAnimations, aStdAnimDescs }, - { "jogger", "ped", MI_COP, 4, aJoggerAnimations, aStdAnimDescs }, - { "woman", "ped", MI_COP, 4, aStdWomanAnimations, aStdAnimDescs }, - { "shopping", "ped", MI_COP, 4, aWomanShopAnimations, aStdAnimDescs }, - { "busywoman", "ped", MI_COP, 4, aBusyWomanAnimations, aStdAnimDescs }, - { "sexywoman", "ped", MI_COP, 4, aSexyWomanAnimations, aStdAnimDescs }, - { "fatwoman", "ped", MI_COP, 4, aFatWomanAnimations, aStdAnimDescs }, - { "oldwoman", "ped", MI_COP, 4, aOldWomanAnimations, aStdAnimDescs }, - { "jogwoman", "ped", MI_COP, 4, aJoggerWomanAnimations, aStdAnimDescs }, - { "panicchunky", "ped", MI_COP, 4, aPanicChunkyAnimations, aStdAnimDescs }, - { "skate", "skate", MI_COP, 4, aSkateAnimations, aStdAnimDescs }, - { "playerback", "ped", MI_COP, 5, aPlayerStrafeBackAnimations, aStdAnimDescs }, - { "playerleft", "ped", MI_COP, 5, aPlayerStrafeLeftAnimations, aStdAnimDescsSide }, - { "playerright", "ped", MI_COP, 5, aPlayerStrafeRightAnimations, aStdAnimDescsSide }, - { "rocketback", "ped", MI_COP, 5, aRocketStrafeBackAnimations, aStdAnimDescs }, - { "rocketleft", "ped", MI_COP, 5, aRocketStrafeLeftAnimations, aStdAnimDescsSide }, - { "rocketright", "ped", MI_COP, 5, aRocketStrafeRightAnimations, aStdAnimDescsSide }, - { "csawback", "ped", MI_COP, 5, aChainsawStrafeBackAnimations, aStdAnimDescs }, - { "csawleft", "ped", MI_COP, 5, aChainsawStrafeLeftAnimations, aStdAnimDescsSide }, - { "csawright", "ped", MI_COP, 5, aChainsawStrafeRightAnimations, aStdAnimDescsSide }, + { "van", "van", MI_COP, awc(aVanAnimations), aVanAnimDescs }, + { "coach", "coach", MI_COP, awc(aCoachAnimations), aCoachAnimDescs }, + { "bikes", "bikes", MI_COP, awc(aBikesAnimations), aBikeAnimDescs }, + { "bikev", "bikev", MI_COP, awc(aBikevAnimations), aBikeAnimDescs }, + { "bikeh", "bikeh", MI_COP, awc(aBikehAnimations), aBikeAnimDescs }, + { "biked", "biked", MI_COP, awc(aBikedAnimations), aBikeAnimDescs }, + { "unarmed", "ped", MI_COP, awc(aUnarmedAnimations), aMeleeAnimDescs }, + { "screwdrv", "ped", MI_COP, awc(aScrewdriverAnimations), aMeleeAnimDescs }, + { "knife", "knife", MI_COP, awc(aKnifeAnimations), aMeleeAnimDescs }, + { "baseball", "baseball", MI_COP, awc(aBaseballbatAnimations), aSwingAnimDescs }, + { "golfclub", "baseball", MI_COP, awc(aGolfclubAnimations), aSwingAnimDescs }, + { "chainsaw", "chainsaw", MI_COP, awc(aChainsawAnimations), aMeleeAnimDescs }, + { "python", "python", MI_COP, awc(aPythonAnimations), aWeaponAnimDescs }, + { "colt45", "colt45", MI_COP, awc(aColtAnimations), aWeaponAnimDescs }, + { "shotgun", "shotgun", MI_COP, awc(aShotgunAnimations), aWeaponAnimDescs }, + { "buddy", "buddy", MI_COP, awc(aBuddyAnimations), aWeaponAnimDescs }, + { "tec", "tec", MI_COP, awc(aTecAnimations), aWeaponAnimDescs }, + { "uzi", "uzi", MI_COP, awc(aUziAnimations), aWeaponAnimDescs }, + { "rifle", "rifle", MI_COP, awc(aRifleAnimations), aWeaponAnimDescs }, + { "m60", "m60", MI_COP, awc(aM60Animations), aWeaponAnimDescs }, + { "sniper", "sniper", MI_COP, awc(aSniperAnimations), aWeaponAnimDescs }, + { "grenade", "grenade", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs }, + { "flame", "flame", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs }, + { "medic", "medic", MI_COP, awc(aMedicAnimations), aMedicAnimDescs }, + { "sunbathe", "sunbathe", MI_COP, awc(aSunbatheAnimations), aSunbatheAnimDescs }, + { "playidles", "playidles", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs }, + { "riot", "riot", MI_COP, awc(aRiotAnimations), aRiotAnimDescs }, + { "strip", "strip", MI_COP, awc(aStripAnimations), aStripAnimDescs }, + { "lance", "lance", MI_COP, awc(aLanceAnimations), aSunbatheAnimDescs }, + { "player", "ped", MI_COP, awc(aPlayerAnimations), aStdAnimDescs }, + { "playerrocket", "ped", MI_COP, awc(aPlayerWithRocketAnimations), aStdAnimDescs }, + { "player1armed", "ped", MI_COP, awc(aPlayer1ArmedAnimations), aStdAnimDescs }, + { "player2armed", "ped", MI_COP, awc(aPlayer2ArmedAnimations), aStdAnimDescs }, + { "playerBBBat", "ped", MI_COP, awc(aPlayerBBBatAnimations), aStdAnimDescs }, + { "playercsaw", "ped", MI_COP, awc(aPlayerChainsawAnimations), aStdAnimDescs }, + { "shuffle", "ped", MI_COP, awc(aShuffleAnimations), aStdAnimDescs }, + { "oldman", "ped", MI_COP, awc(aOldAnimations), aStdAnimDescs }, + { "gang1", "ped", MI_COP, awc(aGang1Animations), aStdAnimDescs }, + { "gang2", "ped", MI_COP, awc(aGang2Animations), aStdAnimDescs }, + { "fatman", "ped", MI_COP, awc(aFatAnimations), aStdAnimDescs }, + { "oldfatman", "ped", MI_COP, awc(aOldFatAnimations), aStdAnimDescs }, + { "jogger", "ped", MI_COP, awc(aJoggerAnimations), aStdAnimDescs }, + { "woman", "ped", MI_COP, awc(aStdWomanAnimations), aStdAnimDescs }, + { "shopping", "ped", MI_COP, awc(aWomanShopAnimations), aStdAnimDescs }, + { "busywoman", "ped", MI_COP, awc(aBusyWomanAnimations), aStdAnimDescs }, + { "sexywoman", "ped", MI_COP, awc(aSexyWomanAnimations), aStdAnimDescs }, + { "fatwoman", "ped", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs }, + { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs }, + { "jogwoman", "ped", MI_COP, awc(aJoggerWomanAnimations), aStdAnimDescs }, + { "panicchunky", "ped", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs }, + { "skate", "skate", MI_COP, awc(aSkateAnimations), aStdAnimDescs }, + { "playerback", "ped", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs }, + { "playerleft", "ped", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide }, + { "playerright", "ped", MI_COP, awc(aPlayerStrafeRightAnimations), aStdAnimDescsSide }, + { "rocketback", "ped", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs }, + { "rocketleft", "ped", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide }, + { "rocketright", "ped", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide }, + { "csawback", "ped", MI_COP, awc(aChainsawStrafeBackAnimations), aStdAnimDescs }, + { "csawleft", "ped", MI_COP, awc(aChainsawStrafeLeftAnimations), aStdAnimDescsSide }, + { "csawright", "ped", MI_COP, awc(aChainsawStrafeRightAnimations), aStdAnimDescsSide }, }; #undef awc diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 2a6581ee..f92ad464 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -330,13 +330,13 @@ enum eVehicleModel { LINERUN, PEREN, SENTINEL, - PATRIOT, + RIO, FIRETRUK, TRASH, STRETCH, MANANA, INFERNUS, - BLISTA, + VOODOO, PONY, MULE, CHEETAH, @@ -345,11 +345,11 @@ enum eVehicleModel { MOONBEAM, ESPERANT, TAXI, - KURUMA, + WASHING, BOBCAT, MRWHOOP, BFINJECT, - CORPSE, + HUNTER, POLICE, ENFORCER, SECURICA, @@ -358,43 +358,83 @@ enum eVehicleModel { BUS, RHINO, BARRACKS, - TRAIN, + CUBAN, CHOPPER, - DODO, + ANGEL, COACH, CABBIE, STALLION, RUMPO, RCBANDIT, - BELLYUP, - MRWONGS, - MAFIA, - YARDIE, - YAKUZA, - DIABLOS, - COLUMB, - HOODS, + ROMERO, + PACKER, + SENTXS, + ADMIRAL, + SQUALO, + SEASPAR, + PIZZABOY, + GANGBUR, AIRTRAIN, DEADDODO, SPEEDER, REEFER, - PANLANT, + TROPIC, FLATBED, YANKEE, - ESCAPE, - BORGNINE, - TOYZ, - GHOST, - CAR151, - CAR152, - CAR153, - CAR154, - CAR155, - CAR156, - CAR157, - CAR158, - CAR159, - MAX_CARS + CADDY, + ZEBRA, + TOPFUN, + SKIMMER, + PCJ600, + FAGGIO, + FREEWAY, + RCBARON, + RCRAIDER, + GLENDALE, + OCEANIC, + SANCHEZ, + SPARROW, + PATRIOT, + LOVEFIST, + COASTG, + DINGHY, + HERMES, + SABRE, + SABRETUR, + PHEONIX, + WALTON, + REGINA, + COMET, + DELUXO, + BURRITO, + SPAND, + MARQUIS, + BAGGAGE, + KAUFMAN, + MAVERICK, + VCNMAV, + RANCHER, + FBIRANCH, + VIRGO, + GREENWOO, + JETMAX, + HOTRING, + SANDKING, + BLISTAC, + POLMAV, + BOXVILLE, + BENSON, + MESA, + RCGOBLIN, + HOTRINA, + HOTRINB, + BLOODRA, + BLOODRB, + VICECHEE, + + // HACK so this compiles + // TODO(MIAMI): check it out + DODO = -1 }; @@ -408,76 +448,116 @@ struct tVehicleSampleData { uint8 m_bDoorType; }; -const tVehicleSampleData aVehicleSettings[MAX_CARS] = {{SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 10928, 1}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_ALARM_1, 8941, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_ALARM_1, 11922, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 7948, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_ALARM_1, 8941, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_ALARM_1, 12220, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_ALARM_1, 12200, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 13600, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_ALARM_1, 8000, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_ALARM_1, 8543, 1}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 10000, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_ALARM_1, 10123, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_ALARM_1, 10554, 3}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 8000, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 3}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_ALARM_1, 7500, 3}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_ALARM_1, 8935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 8935, 0}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_ALARM_1, 17000, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9000, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}}; +const tVehicleSampleData aVehicleSettings[110] = { {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_HORN_JEEP, 10928, 1}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_HORN_JEEP, 8941, 0}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_HORN_JEEP, 11922, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 7948, 2}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_HORN_JEEP, 8941, 2}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_HORN_JEEP, 12220, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_HORN_JEEP, 12200, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 13400, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_HORN_JEEP, 13600, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_HORN_JEEP, 8000, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_HORN_JEEP, 8543, 1}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 10000, 0}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_HORN_JEEP, 10123, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_HORN_JEEP, 10554, 3}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 8000, 2}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9935, 3}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_HORN_JEEP, 7500, 3}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_HORN_JEEP, 8935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_HORN_JEEP, 8935, 0}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_HORN_JEEP, 17000, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_HORN_JEEP, 9935, 1}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9000, 0}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_HORN_JEEP, 9935, 2}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 13400, 1}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9935, 0} }; bool bPlayerJustEnteredCar; @@ -2937,62 +3017,9 @@ cAudioManager::ProcessPed(CPhysical *ped) // params.m_bDistanceCalculated = false; params.m_pPed = (CPed *)ped; params.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (ped->GetModelIndex() == MI_FATMALE02) - ProcessPedHeadphones(¶ms); ProcessPedOneShots(¶ms); } -void -cAudioManager::ProcessPedHeadphones(cPedParams *params) -{ - CPed *ped; - CAutomobile *veh; - uint8 emittingVol; - - if (params->m_fDistance < 49.f) { - ped = params->m_pPed; - if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) { - CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); - if (ped->bInVehicle && ped->m_nPedState == PED_DRIVING) { - emittingVol = 10; - veh = (CAutomobile *)ped->m_pMyVehicle; - if (veh && veh->IsCar()) { - for (int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) { - if (!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) { - emittingVol = 42; - break; - } - } - } - } else { - emittingVol = 42; - } - - m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 7.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nCounter = 64; - m_sQueueSample.m_nSampleIndex = SFX_HEADPHONES; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 5; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_HEADPHONES); - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = emittingVol; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 4.0f; - m_sQueueSample.m_fSoundIntensity = 7.0f; - m_sQueueSample.m_bReleasingSoundFlag = false; - m_sQueueSample.m_nReleasingVolumeDivider = 5; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - } - return; - } - } -} - void cAudioManager::ProcessPedOneShots(cPedParams *params) { @@ -3820,158 +3847,12 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound) int32 cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) { - if (ped->IsPlayer()) - return GetPlayerTalkSfx(sound); + //if (ped->IsPlayer()) + // return GetPlayerTalkSfx(sound); - switch (ped->GetModelIndex()) { - case MI_COP: - return GetCopTalkSfx(sound); - case MI_SWAT: - return GetSwatTalkSfx(sound); - case MI_FBI: - return GetFBITalkSfx(sound); - case MI_ARMY: - return GetArmyTalkSfx(sound); - case MI_MEDIC: - return GetMedicTalkSfx(sound); - case MI_FIREMAN: - return GetFiremanTalkSfx(sound); - case MI_MALE01: - return GetNormalMaleTalkSfx(sound); - case MI_TAXI_D: - return GetTaxiDriverTalkSfx(sound); - case MI_PIMP: - return GetPimpTalkSfx(sound); - case MI_GANG01: - case MI_GANG02: - return GetMafiaTalkSfx(sound); - case MI_GANG03: - case MI_GANG04: - return GetTriadTalkSfx(sound); - case MI_GANG05: - case MI_GANG06: - return GetDiabloTalkSfx(sound); - case MI_GANG07: - case MI_GANG08: - return GetYakuzaTalkSfx(sound); - case MI_GANG09: - case MI_GANG10: - return GetYardieTalkSfx(sound); - case MI_GANG11: - case MI_GANG12: - return GetColumbianTalkSfx(sound); - case MI_GANG13: - case MI_GANG14: - return GetHoodTalkSfx(sound); - case MI_CRIMINAL01: - return GetBlackCriminalTalkSfx(sound); - case MI_CRIMINAL02: - return GetWhiteCriminalTalkSfx(sound); - case MI_SPECIAL01: - case MI_SPECIAL02: - case MI_SPECIAL03: - case MI_SPECIAL04: - return GetSpecialCharacterTalkSfx(ped->GetModelIndex(), sound); - case MI_MALE02: - return GetMaleNo2TalkSfx(sound); - case MI_MALE03: - case MI_P_MAN1: - case MI_P_MAN2: - return GetBlackProjectMaleTalkSfx(sound, ped->GetModelIndex()); - case MI_FATMALE01: - return GetWhiteFatMaleTalkSfx(sound); - case MI_FATMALE02: - return GetBlackFatMaleTalkSfx(sound); - case MI_FEMALE01: - return GetBlackCasualFemaleTalkSfx(sound); - case MI_FEMALE02: - case MI_CAS_WOM: - return GetWhiteCasualFemaleTalkSfx(sound); - case MI_FEMALE03: - return GetFemaleNo3TalkSfx(sound); - case MI_FATFEMALE01: - return GetBlackFatFemaleTalkSfx(sound); - case MI_FATFEMALE02: - return GetWhiteFatFemaleTalkSfx(sound); - case MI_PROSTITUTE: - return GetBlackFemaleProstituteTalkSfx(sound); - case MI_PROSTITUTE2: - return GetWhiteFemaleProstituteTalkSfx(sound); - case MI_P_WOM1: - return GetBlackProjectFemaleOldTalkSfx(sound); - case MI_P_WOM2: - return GetBlackProjectFemaleYoungTalkSfx(sound); - case MI_CT_MAN1: - return GetChinatownMaleOldTalkSfx(sound); - case MI_CT_MAN2: - return GetChinatownMaleYoungTalkSfx(sound); - case MI_CT_WOM1: - return GetChinatownFemaleOldTalkSfx(sound); - case MI_CT_WOM2: - return GetChinatownFemaleYoungTalkSfx(sound); - case MI_LI_MAN1: - case MI_LI_MAN2: - return GetLittleItalyMaleTalkSfx(sound); - case MI_LI_WOM1: - return GetLittleItalyFemaleOldTalkSfx(sound); - case MI_LI_WOM2: - return GetLittleItalyFemaleYoungTalkSfx(sound); - case MI_DOCKER1: - return GetWhiteDockerMaleTalkSfx(sound); - case MI_DOCKER2: - return GetBlackDockerMaleTalkSfx(sound); - case MI_SCUM_MAN: - return GetScumMaleTalkSfx(sound); - case MI_SCUM_WOM: - return GetScumFemaleTalkSfx(sound); - case MI_WORKER1: - return GetWhiteWorkerMaleTalkSfx(sound); - case MI_WORKER2: - return GetBlackWorkerMaleTalkSfx(sound); - case MI_B_MAN1: - case MI_B_MAN3: - return GetBusinessMaleYoungTalkSfx(sound, ped->GetModelIndex()); - case MI_B_MAN2: - return GetBusinessMaleOldTalkSfx(sound); - case MI_B_WOM1: - case MI_B_WOM2: - return GetWhiteBusinessFemaleTalkSfx(sound, ped->GetModelIndex()); - case MI_B_WOM3: - return GetBlackBusinessFemaleTalkSfx(sound); - case MI_MOD_MAN: - return GetSupermodelMaleTalkSfx(sound); - case MI_MOD_WOM: - return GetSupermodelFemaleTalkSfx(sound); - case MI_ST_MAN: - return GetStewardMaleTalkSfx(sound); - case MI_ST_WOM: - return GetStewardFemaleTalkSfx(sound); - case MI_FAN_MAN1: - case MI_FAN_MAN2: - return GetFanMaleTalkSfx(sound, ped->GetModelIndex()); - case MI_FAN_WOM: - return GetFanFemaleTalkSfx(sound); - case MI_HOS_MAN: - return GetHospitalMaleTalkSfx(sound); - case MI_HOS_WOM: - return GetHospitalFemaleTalkSfx(sound); - case MI_CONST1: - return GetWhiteConstructionWorkerTalkSfx(sound); - case MI_CONST2: - return GetBlackConstructionWorkerTalkSfx(sound); - case MI_SHOPPER1: - case MI_SHOPPER2: - case MI_SHOPPER3: - return GetShopperFemaleTalkSfx(sound, ped->GetModelIndex()); - case MI_STUD_MAN: - return GetStudentMaleTalkSfx(sound); - case MI_STUD_WOM: - return GetStudentFemaleTalkSfx(sound); - case MI_CAS_MAN: - return GetCasualMaleOldTalkSfx(sound); - default: - return GetGenericMaleTalkSfx(sound); - } + // TODO: miami peds + + return TOTAL_AUDIO_SAMPLES; } void @@ -3987,2223 +3868,7 @@ cAudioManager::GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint } #pragma region PED_COMMENTS - -uint32 -cAudioManager::GetPlayerTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_DAMAGE: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIGH_DAMAGE_GRUNT_1, 11); - break; - case SOUND_PED_HIT: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_LOW_DAMAGE_GRUNT_1, 10); - break; - case SOUND_PED_LAND: - GetPhrase(&sfx, &lastSfx, SFX_CLAUDE_HIT_GROUND_GRUNT_1, 6); - break; - default: - sfx = NO_SAMPLE; - break; - } - return sfx; -} - -uint32 -cAudioManager::GetCopTalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_ARREST_COP) { - GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_COP) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_CHASE_1, 7); - } - - return (SFX_COP_VOICE_2_ARREST_1 - SFX_COP_VOICE_1_ARREST_1) * (m_sQueueSample.m_nEntityIndex % 5) + sfx; -} - -uint32 -cAudioManager::GetSwatTalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_ARREST_SWAT) { - GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_SWAT) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); - } - - return (SFX_SWAT_VOICE_2_CHASE_1 - SFX_SWAT_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 4) + sfx; -} - -uint32 -cAudioManager::GetFBITalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_ARREST_FBI) { - GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_FBI) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); - } - - return (SFX_FBI_VOICE_2_CHASE_1 - SFX_FBI_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; -} - -uint32 -cAudioManager::GetArmyTalkSfx(int16 sound) -{ - uint32 sfx; - PedState pedState; - static uint32 lastSfx = NO_SAMPLE; - - if (sound != SOUND_PED_PURSUIT_ARMY) { - return GetGenericMaleTalkSfx(sound); - } - - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); - - return (SFX_ARMY_VOICE_2_CHASE_1 - SFX_ARMY_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetMedicTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_CARJACKED_1, 5); - break; - case SOUND_PED_HEALING: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_AT_VICTIM_1, 12); - break; - case SOUND_PED_LEAVE_VEHICLE: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1, 9); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_MEDIC_VOICE_1_RUN_FROM_FIGHT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_MEDIC_VOICE_2_GUN_PANIC_1 - SFX_MEDIC_VOICE_1_GUN_PANIC_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetFiremanTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetNormalMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_GUN_PANIC_1, 7); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CARJACKED_1, 7); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DODGE_1, 9); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_RUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_DRIVER_ABUSE_1, 12); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_EYING_1, 8); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_SHOCKED_1, 10); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_NORMAL_MALE_CHAT_1, 25); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetTaxiDriverTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_CAR_JACKED) { - GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); - } else { - if (sound != SOUND_PED_CAR_COLLISION) - return GetGenericMaleTalkSfx(sound); - GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); - } - return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetPimpTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_GUN_COOL_1, 7); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_CARJACKED_1, 4); - break; - case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_FIGHT_1, 9); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_PIMP_CHAT_1, 17); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetMafiaTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MAFIA_MALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_MAFIA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_MAFIA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; -} - -uint32 -cAudioManager::GetTriadTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_GUN_COOL_1, 3); - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_TRIAD_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetDiabloTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_GUN_COOL_1, 4); - break; - case SOUND_PED_HANDS_COWER: - sound = SOUND_PED_FLEE_SPRINT; - return GetGenericMaleTalkSfx(sound); - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_EYING_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_DIABLO_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_DIABLO_MALE_VOICE_2_CHAT_1 - SFX_DIABLO_MALE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetYakuzaTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_YAKUZA_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_YAKUZA_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YAKUZA_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetYardieTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - sfx = SFX_YARDIE_MALE_VOICE_1_GUN_COOL_1; - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - sfx = SFX_YARDIE_MALE_VOICE_1_CARJACKED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_YARDIE_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_YARDIE_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_YARDIE_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetColumbianTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_COLUMBIAN_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_COLUMBIAN_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_COLUMBIAN_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetHoodTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_GUN_COOL_1, 5); - break; - case SOUND_PED_CAR_JACKING: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKING_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOOD_MALE_VOICE_1_CHAT_1, 6); - break; - - default: - return GetGenericMaleTalkSfx(sound); - break; - } - return (SFX_HOOD_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_HOOD_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetBlackCriminalTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_GUN_COOL_1, 4); - break; - case SOUND_PED_CAR_JACKING: - sfx = SFX_BLACK_CRIMINAL_VOICE_1_CARJACKING_1; - break; - case SOUND_PED_MUGGING: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_MUGGING_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - break; - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteCriminalTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_GUN_COOL_1, 3); - break; - case SOUND_PED_CAR_JACKING: - sfx = SFX_WHITE_CRIMINAL_VOICE_1_CARJACKING_1; - break; - case SOUND_PED_MUGGING: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_MUGGING_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CRIMINAL_VOICE_1_DRIVER_ABUSE_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - break; - } - return sfx; -} - -uint32 -cAudioManager::GetMaleNo2TalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CARJACKED_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_MUGGED_1, 4); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_EYING_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CASUAL_MALE_OLD_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackProjectMaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_GUN_COOL_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_MALE_VOICE_1_CHAT_1, 6); - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_P_MAN2) - sfx += (SFX_BLACK_PROJECT_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_BLACK_PROJECT_MALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetWhiteFatMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CARJACKED_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DODGE_1, 9); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 9); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_LOST_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_MALE_VOICE_1_CHAT_1, 9); - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFatMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CARJACKED_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DODGE_1, 7); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_LOST_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_MALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackCasualFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_RUN_FROM_FIGHT_1, 2); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_1_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteCasualFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - sfx = SFX_WHITE_CASUAL_FEMALE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 2); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_CASUAL_FEMALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetFemaleNo3TalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CARJACKED_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_RUN_FROM_FIGHT_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FEMALE_3_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFatFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_SHOCKED_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_FAT_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteFatFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 8); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_LOST_1, 2); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_FAT_FEMALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackFemaleProstituteTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_GUN_COOL_1, 4); - break; - case SOUND_PED_ROBBED: - sfx = SFX_BLACK_PROSTITUTE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_SOLICIT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_SOLICIT_1, 8); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_BLACK_PROSTITUTE_VOICE_2_CHAT_1 - SFX_BLACK_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetWhiteFemaleProstituteTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_SOLICIT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_SOLICIT_1, 8); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_WHITE_PROSTITUTE_VOICE_2_CHAT_1 - SFX_WHITE_PROSTITUTE_VOICE_1_CHAT_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetBlackProjectFemaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CARJACKED_1, 6); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DODGE_1, 10); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_RUN_FROM_FIGHT_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_OLD_VOICE_1_CHAT_1, 10); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackProjectFemaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - sfx = SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CARJACKED_1; - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_SHOCKED_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_PROJECT_FEMALE_YOUNG_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownMaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_OLD_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownMaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_MALE_YOUNG_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownFemaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - sfx = SFX_CHINATOWN_OLD_FEMALE_VOICE_1_SHOCKED_1; - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_OLD_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChinatownFemaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_CHINATOWN_YOUNG_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetLittleItalyMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return (SFX_LITTLE_ITALY_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_LITTLE_ITALY_MALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetLittleItalyFemaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_OLD_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetLittleItalyFemaleYoungTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DODGE_1, 7); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_LITTLE_ITALY_YOUNG_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteDockerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_DOCKER_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackDockerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_DOCKER_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetScumMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_ROBBED: - sfx = SFX_SCUM_MALE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_FIGHT_1, 10); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_WAIT_DOUBLEBACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_LOST_1, 3); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_EYING_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_MALE_VOICE_1_CHAT_1, 9); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetScumFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DODGE_1, 8); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SCUM_FEMALE_VOICE_1_CHAT_1, 13); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteWorkerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_EYING_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_WORKER_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackWorkerMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_WORKER_MALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBusinessMaleYoungTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_RUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_YOUNG_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_B_MAN3) - sfx += (SFX_BUSINESS_MALE_YOUNG_VOICE_2_DRIVER_ABUSE_1 - SFX_BUSINESS_MALE_YOUNG_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetBusinessMaleOldTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_MRUN_FROM_FIGHT_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BUSINESS_MALE_OLD_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - - if (model == MI_B_WOM2) - sfx += (SFX_WHITE_BUSINESS_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_WHITE_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetBlackBusinessFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_GUN_PANIC_1, 5); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CARAJACKED_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_FLEE_RUN: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_RUN_FROM_FIGHT_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_BUSINESS_FEMALE_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetSupermodelMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetSupermodelFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_MUGGED_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_SHOCKED_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_MODEL_FEMALE_VOICE_1_CHAT_1, 8); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetStewardMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DODGE_1, 3); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_MALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetStewardFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STEWARD_FEMALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_STEWARD_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_STEWARD_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetFanMaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_FIGHT_1, 3); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_MALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - - if (model == MI_FAN_MAN2) - sfx += (SFX_FOOTBALL_MALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_MALE_VOICE_1_DRIVER_ABUSE_1); - return sfx; -} - -uint32 -cAudioManager::GetFanFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_ROBBED: - sfx = SFX_FOOTBALL_FEMALE_VOICE_1_MUGGED_1; - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_FOOTBALL_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return (SFX_FOOTBALL_FEMALE_VOICE_2_DRIVER_ABUSE_1 - SFX_FOOTBALL_FEMALE_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; -} - -uint32 -cAudioManager::GetHospitalMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetHospitalFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_HOSPITAL_FEMALE_VOICE_1_CHAT_1, 6); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetWhiteConstructionWorkerTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - sfx = SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CARJACKED_1; - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_EYING_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_WHITE_MALE_CONSTRUCTION_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetBlackConstructionWorkerTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_GUN_PANIC_1, 3); - break; - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_FIGHT_1, 5); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DODGE_1, 5); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_DRIVER_ABUSE_1, 5); - break; - case SOUND_PED_CHAT_SEXY: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_EYING_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_BLACK_CONSTRUCTION_MALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetShopperFemaleTalkSfx(int16 sound, int32 model) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_CAR_JACKED: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CARJACKED_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DODGE_1, 6); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1, 7); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_SHOCKED_1, 4); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_SHOPPER_VOICE_1_CHAT_1, 7); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - - if (model == MI_SHOPPER2) { - sfx += (SFX_SHOPPER_VOICE_2_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1); - } else if (model == MI_SHOPPER3) { - sfx += (SFX_SHOPPER_VOICE_3_DRIVER_ABUSE_1 - SFX_SHOPPER_VOICE_1_DRIVER_ABUSE_1); - } - return sfx; -} - -uint32 -cAudioManager::GetStudentMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_GUN_PANIC_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_SHOCKED_1, 3); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_MALE_VOICE_1_CHAT_1, 5); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetStudentFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_COWER: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_GUN_PANIC_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DODGE_1, 4); - break; - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_DRIVER_ABUSE_1, 4); - break; - case SOUND_PED_CHAT_EVENT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_SHOCKED_1, 2); - break; - case SOUND_PED_CHAT: - GetPhrase(&sfx, &lastSfx, SFX_STUDENT_FEMALE_VOICE_1_CHAT_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetCasualMaleOldTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound) -{ - char *modelName = CModelInfo::GetModelInfo(modelIndex)->GetName(); - if (!CGeneral::faststricmp(modelName, "eight") || !CGeneral::faststricmp(modelName, "eight2")) { - return GetEightTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "frankie")) { - return GetFrankieTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "misty")) { - return GetMistyTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "ojg") || !CGeneral::faststricmp(modelName, "ojg_p")) { - return GetOJGTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "cat")) { - return GetCatatalinaTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "bomber")) { - return GetBomberTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "s_guard")) { - return GetSecurityGuardTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "chunky")) { - return GetChunkyTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "asuka")) { - return GetGenericFemaleTalkSfx(sound); - } - if (!CGeneral::faststricmp(modelName, "maria")) { - return GetGenericFemaleTalkSfx(sound); - } - - return GetGenericMaleTalkSfx(sound); -} -uint32 -cAudioManager::GetEightTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_GUN_COOL_1, 2); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_8BALL_DODGE_1, 7); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetFrankieTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_GUN_COOL_1, 4); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_FIGHT_1, 6); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_SALVATORE_DODGE_1, 3); - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetMistyTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_GUN_COOL_1, 5); - break; - case SOUND_PED_ROBBED: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_MUGGED_1, 2); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_FIGHT_1, 4); - break; - case SOUND_PED_EVADE: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_DODGE_1, 5); - break; - case SOUND_PED_TAXI_CALL: - GetPhrase(&sfx, &lastSfx, SFX_MISTY_HERE_1, 4); - break; - default: - return GetGenericFemaleTalkSfx(sound); - break; - } - return sfx; -} - -uint32 -cAudioManager::GetOJGTalkSfx(int16 sound) -{ - return GetGenericMaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetCatatalinaTalkSfx(int16 sound) -{ - return GetGenericFemaleTalkSfx(sound); -} - -uint32 -cAudioManager::GetBomberTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - if (sound != SOUND_PED_BOMBER) - return GetGenericMaleTalkSfx(sound); - - GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7); - return sfx; -} - -uint32 -cAudioManager::GetSecurityGuardTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_HANDS_UP: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_GUN_COOL_1, 2); - break; - case SOUND_PED_HANDS_COWER: - sfx = SFX_SECURITY_GUARD_VOICE_1_GUN_PANIC_1; - break; - case SOUND_PED_CAR_JACKED: - case SOUND_PED_CAR_COLLISION: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 6); - break; - case SOUND_PED_ATTACK: - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_FIGHT_1, 2); - break; - case SOUND_PED_FLEE_RUN: -#ifdef FIX_BUGS - sfx = SFX_SECURITY_GUARD_VOICE_1_RUN_FROM_FIGHT_1; -#else - GetPhrase(&sfx, &lastSfx, SFX_SECURITY_GUARD_VOICE_1_DRIVER_ABUSE_1, 12); -#endif - break; - default: - return GetGenericMaleTalkSfx(sound); - } - return sfx; -} - -uint32 -cAudioManager::GetChunkyTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - if (sound == SOUND_PED_DEATH) - return SFX_CHUNKY_DEATH; - - if (sound != SOUND_PED_FLEE_RUN) - return GetGenericMaleTalkSfx(sound); - - GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5); - return sfx; -} - -uint32 -cAudioManager::GetGenericMaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_DEATH: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_DEATH_1, 8); - break; - case SOUND_PED_BULLET_HIT: - case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_GRUNT_1, 15); - break; - case SOUND_PED_BURNING: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_FIRE_1, 8); - break; - case SOUND_PED_FLEE_SPRINT: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_MALE_PANIC_1, 6); - break; - default: - return NO_SAMPLE; - } - return sfx; -} - -uint32 -cAudioManager::GetGenericFemaleTalkSfx(int16 sound) -{ - uint32 sfx; - static uint32 lastSfx = NO_SAMPLE; - - switch (sound) { - case SOUND_PED_DEATH: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_DEATH_1, 10); - break; - case SOUND_PED_BULLET_HIT: - case SOUND_PED_DEFEND: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_GRUNT_1, 11); - break; - case SOUND_PED_BURNING: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_FIRE_1, 9); - break; - case SOUND_PED_FLEE_SPRINT: - GetPhrase(&sfx, &lastSfx, SFX_GENERIC_FEMALE_PANIC_1, 8); - break; - default: - return NO_SAMPLE; - } - return sfx; -} - - +// TODO: all the ped comment funcs should follow here void cPedComments::Add(tPedComment *com) diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index b2b44c07..ba7db091 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -241,82 +241,7 @@ public: // functions returning talk sfx, // order from GetPedCommentSfx - uint32 GetPlayerTalkSfx(int16 sound); - uint32 GetCopTalkSfx(int16 sound); - uint32 GetSwatTalkSfx(int16 sound); - uint32 GetFBITalkSfx(int16 sound); - uint32 GetArmyTalkSfx(int16 sound); - uint32 GetMedicTalkSfx(int16 sound); - uint32 GetFiremanTalkSfx(int16 sound); - uint32 GetNormalMaleTalkSfx(int16 sound); - uint32 GetTaxiDriverTalkSfx(int16 sound); - uint32 GetPimpTalkSfx(int16 sound); - uint32 GetMafiaTalkSfx(int16 sound); - uint32 GetTriadTalkSfx(int16 sound); - uint32 GetDiabloTalkSfx(int16 sound); - uint32 GetYakuzaTalkSfx(int16 sound); - uint32 GetYardieTalkSfx(int16 sound); - uint32 GetColumbianTalkSfx(int16 sound); - uint32 GetHoodTalkSfx(int16 sound); - uint32 GetBlackCriminalTalkSfx(int16 sound); - uint32 GetWhiteCriminalTalkSfx(int16 sound); - uint32 GetMaleNo2TalkSfx(int16 sound); - uint32 GetBlackProjectMaleTalkSfx(int16 sound, int32 model); - uint32 GetWhiteFatMaleTalkSfx(int16 sound); - uint32 GetBlackFatMaleTalkSfx(int16 sound); - uint32 GetBlackCasualFemaleTalkSfx(int16 sound); - uint32 GetWhiteCasualFemaleTalkSfx(int16 sound); - uint32 GetFemaleNo3TalkSfx(int16 sound); - uint32 GetBlackFatFemaleTalkSfx(int16 sound); - uint32 GetWhiteFatFemaleTalkSfx(int16 sound); - uint32 GetBlackFemaleProstituteTalkSfx(int16 sound); - uint32 GetWhiteFemaleProstituteTalkSfx(int16 sound); - uint32 GetBlackProjectFemaleOldTalkSfx(int16 sound); - uint32 GetBlackProjectFemaleYoungTalkSfx(int16 sound); - uint32 GetChinatownMaleOldTalkSfx(int16 sound); - uint32 GetChinatownMaleYoungTalkSfx(int16 sound); - uint32 GetChinatownFemaleOldTalkSfx(int16 sound); - uint32 GetChinatownFemaleYoungTalkSfx(int16 sound); - uint32 GetLittleItalyMaleTalkSfx(int16 sound); - uint32 GetLittleItalyFemaleOldTalkSfx(int16 sound); - uint32 GetLittleItalyFemaleYoungTalkSfx(int16 sound); - uint32 GetWhiteDockerMaleTalkSfx(int16 sound); - uint32 GetBlackDockerMaleTalkSfx(int16 sound); - uint32 GetScumMaleTalkSfx(int16 sound); - uint32 GetScumFemaleTalkSfx(int16 sound); - uint32 GetWhiteWorkerMaleTalkSfx(int16 sound); - uint32 GetBlackWorkerMaleTalkSfx(int16 sound); - uint32 GetBusinessMaleYoungTalkSfx(int16 sound, int32 model); - uint32 GetBusinessMaleOldTalkSfx(int16 sound); - uint32 GetWhiteBusinessFemaleTalkSfx(int16 sound, int32 model); - uint32 GetBlackBusinessFemaleTalkSfx(int16 sound); - uint32 GetSupermodelMaleTalkSfx(int16 sound); - uint32 GetSupermodelFemaleTalkSfx(int16 sound); - uint32 GetStewardMaleTalkSfx(int16 sound); - uint32 GetStewardFemaleTalkSfx(int16 sound); - uint32 GetFanMaleTalkSfx(int16 sound, int32 model); - uint32 GetFanFemaleTalkSfx(int16 sound); - uint32 GetHospitalMaleTalkSfx(int16 sound); - uint32 GetHospitalFemaleTalkSfx(int16 sound); - uint32 GetWhiteConstructionWorkerTalkSfx(int16 sound); - uint32 GetBlackConstructionWorkerTalkSfx(int16 sound); - uint32 GetShopperFemaleTalkSfx(int16 sound, int32 model); - uint32 GetStudentMaleTalkSfx(int16 sound); - uint32 GetStudentFemaleTalkSfx(int16 sound); - uint32 GetCasualMaleOldTalkSfx(int16 sound); - - uint32 GetSpecialCharacterTalkSfx(int32 modelIndex, int32 sound); - uint32 GetEightTalkSfx(int16 sound); - uint32 GetFrankieTalkSfx(int16 sound); - uint32 GetMistyTalkSfx(int16 sound); - uint32 GetOJGTalkSfx(int16 sound); - uint32 GetCatatalinaTalkSfx(int16 sound); - uint32 GetBomberTalkSfx(int16 sound); - uint32 GetSecurityGuardTalkSfx(int16 sound); - uint32 GetChunkyTalkSfx(int16 sound); - - uint32 GetGenericMaleTalkSfx(int16 sound); - uint32 GetGenericFemaleTalkSfx(int16 sound); + // TODO: miami // end of functions returning talk sfx void GenerateIntegerRandomNumberTable(); @@ -397,7 +322,6 @@ public: void ProcessModelCarEngine(cVehicleParams *params); void ProcessOneShotScriptObject(uint8 sound); void ProcessPed(CPhysical *ped); - void ProcessPedHeadphones(cPedParams *params); void ProcessPedOneShots(cPedParams *params); void ProcessPhysical(int32 id); void ProcessPlane(cVehicleParams *params); From 72ccf9a0db8a1429da7a0da041f97b993cfc3622 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 14:21:09 +0200 Subject: [PATCH 027/148] revert accidental commit; also update librw --- librw | 2 +- src/control/Script.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/librw b/librw index 661feeab..3971dda0 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 661feeabf4a4f0a8b0bee23b53ba557a14352d00 +Subproject commit 3971dda001cba9c7dc67e86bc0b54a2c7568578f diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 631ca436..357436c6 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -506,7 +506,7 @@ void CRunningScript::Init() #ifdef USE_DEBUG_SCRIPT_LOADER int open_script() { - static int scriptToLoad = 1; + static int scriptToLoad = 0; #ifdef _WIN32 if (GetAsyncKeyState('G') & 0x8000) From 964acba08382cd0748cd46f4676a7b4e9025957a Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 15:16:12 +0200 Subject: [PATCH 028/148] fix head/hand atomics --- src/modelinfo/PedModelInfo.cpp | 3 +++ src/modelinfo/PedModelInfo.h | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 0cb0fc36..473e8b63 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -21,16 +21,19 @@ CPedModelInfo::DeleteRwObject(void) frame = RpAtomicGetFrame(m_head); RpAtomicDestroy(m_head); RwFrameDestroy(frame); + m_head = nil; } if(m_lhand){ frame = RpAtomicGetFrame(m_lhand); RpAtomicDestroy(m_lhand); RwFrameDestroy(frame); + m_lhand = nil; } if(m_rhand){ frame = RpAtomicGetFrame(m_rhand); RpAtomicDestroy(m_rhand); RwFrameDestroy(frame); + m_rhand = nil; } #endif CClumpModelInfo::DeleteRwObject(); // PC calls this first diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h index 52f75894..d73d3646 100644 --- a/src/modelinfo/PedModelInfo.h +++ b/src/modelinfo/PedModelInfo.h @@ -36,7 +36,14 @@ public: static RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX]; - CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { m_hitColModel = nil; } + CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { + m_hitColModel = nil; +#ifdef PED_SKIN + m_head = nil; + m_lhand = nil; + m_rhand = nil; +#endif + } ~CPedModelInfo(void) { delete m_hitColModel; } void DeleteRwObject(void); void SetClump(RpClump *); From 4ab49780b52a78da981136f849862d3bb2b0e577 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 15:33:44 +0200 Subject: [PATCH 029/148] collect HUD colors at top of file --- src/render/Hud.cpp | 62 ++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index c3fcb7bf..8c7904ef 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -21,6 +21,26 @@ #include "User.h" #include "World.h" +// Game has colors inlined in code. +// For easier modification we collect them here: +CRGBA MONEY_COLOR(89, 115, 150, 255); +CRGBA AMMO_COLOR(0, 0, 0, 255); +CRGBA HEALTH_COLOR(186, 101, 50, 255); +CRGBA ARMOUR_COLOR(124, 140, 95, 255); +CRGBA WANTED_COLOR(193, 164, 120, 255); +CRGBA ZONE_COLOR(152, 154, 82, 255); +CRGBA VEHICLE_COLOR(194, 165, 120, 255); +CRGBA CLOCK_COLOR(194, 165, 120, 255); +CRGBA TIMER_COLOR(186, 101, 50, 255); +CRGBA COUNTER_COLOR(0, 106, 164, 255); +CRGBA PAGER_COLOR(32, 162, 66, 205); +CRGBA RADARDISC_COLOR(0, 0, 0, 255); +CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255); +CRGBA WASTEDBUSTED_COLOR(170, 123, 87, 255); +CRGBA ODDJOB_COLOR(89, 115, 150, 255); +CRGBA ODDJOB2_COLOR(156, 91, 40, 255); +CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); + wchar CHud::m_HelpMessage[256]; wchar CHud::m_LastHelpMessage[256]; uint32 CHud::m_HelpMessageState; @@ -252,7 +272,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(43.0f + 2.0f), sPrint); - CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::SetColor(MONEY_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); /* @@ -312,7 +332,7 @@ void CHud::Draw() CFont::SetFontStyle(FONT_BANK); if (!CDarkel::FrenzyOnGoing() && WeaponType != WEAPONTYPE_UNARMED && WeaponType != WEAPONTYPE_BASEBALLBAT) { - CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(AMMO_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(73.0f), sPrint); } @@ -349,7 +369,7 @@ void CHud::Draw() if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(164.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon); } - CFont::SetColor(CRGBA(186, 101, 50, 255)); + CFont::SetColor(HEALTH_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint); @@ -380,7 +400,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(234.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon); } - CFont::SetColor(CRGBA(124, 140, 95, 255)); + CFont::SetColor(ARMOUR_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); @@ -410,7 +430,7 @@ void CHud::Draw() && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange + 2000 || CTimer::GetFrameCounter() & 4)) { - CFont::SetColor(CRGBA(193, 164, 120, 255)); + CFont::SetColor(WANTED_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(60.0f + 24.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); } } @@ -504,7 +524,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint); - CFont::SetColor(CRGBA(152, 154, 82, fZoneAlpha)); + CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint); } } @@ -598,7 +618,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint); - CFont::SetColor(CRGBA(194, 165, 120, fVehicleAlpha)); + CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint); } } @@ -630,7 +650,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), sPrint); - CFont::SetColor(CRGBA(194, 165, 120, 255)); + CFont::SetColor(CLOCK_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint); /* @@ -674,7 +694,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer); CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetColor(CRGBA(186, 101, 50, 255)); + CFont::SetColor(TIMER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer); if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) { @@ -683,7 +703,7 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(0.64f), SCREEN_SCALE_Y(1.35f)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); - CFont::SetColor(CRGBA(186, 101, 50, 255)); + CFont::SetColor(TIMER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); } } @@ -718,7 +738,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), sTimer); - CFont::SetColor(CRGBA(0, 106, 164, 255)); + CFont::SetColor(COUNTER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(132.0f), sTimer); } else { int counter = atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer); @@ -735,7 +755,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); - CFont::SetColor(CRGBA(0, 106, 164, 255)); + CFont::SetColor(COUNTER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); } } @@ -782,7 +802,7 @@ void CHud::Draw() CFont::SetBackgroundOff(); CFont::SetScale(SCREEN_SCALE_X(0.84f), SCREEN_SCALE_Y(1.0f)); - CFont::SetColor(CRGBA(32, 162, 66, 205)); + CFont::SetColor(PAGER_COLOR); CFont::SetRightJustifyOff(); CFont::SetBackgroundOff(); CFont::SetCentreOff(); @@ -804,7 +824,7 @@ void CHud::Draw() rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #endif rect.Grow(4.0f); - Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); + Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); CRadar::DrawBlips(); } } @@ -959,7 +979,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]); #endif - CFont::SetColor(CRGBA(85, 119, 133, BigMessageAlpha[0])); + CFont::SetColor(CRGBA(BIGMESSAGE_COLOR.r, BIGMESSAGE_COLOR.g, BIGMESSAGE_COLOR.b, BigMessageAlpha[0])); CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]); } else { @@ -994,7 +1014,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f - 4.0f), SCREEN_SCALE_FROM_BOTTOM(78.0f), m_BigMessage[2]); - CFont::SetColor(CRGBA(170, 123, 87, BigMessageAlpha[2])); + CFont::SetColor(CRGBA(WASTEDBUSTED_COLOR.r, WASTEDBUSTED_COLOR.g, WASTEDBUSTED_COLOR.b, BigMessageAlpha[2])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]); } else { @@ -1186,7 +1206,7 @@ void CHud::DrawAfterFade() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[3]); - CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::SetColor(ODDJOB_COLOR); CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[3]); } @@ -1202,7 +1222,7 @@ void CHud::DrawAfterFade() CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[4]); - CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::SetColor(ODDJOB_COLOR); CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[4]); } @@ -1260,12 +1280,12 @@ void CHud::DrawAfterFade() #ifdef BETA_SLIDING_TEXT CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f) - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); - CFont::SetColor(CRGBA(156, 91, 40, 255)); + CFont::SetColor(ODDJOB2_COLOR); CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); #else CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); - CFont::SetColor(CRGBA(156, 91, 40, 255)); + CFont::SetColor(ODDJOB2_COLOR); CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); #endif } @@ -1310,7 +1330,7 @@ void CHud::DrawAfterFade() CFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[1]); - CFont::SetColor(CRGBA(220, 172, 2, BigMessageAlpha[1])); + CFont::SetColor(CRGBA(MISSIONTITLE_COLOR.r, MISSIONTITLE_COLOR.g, MISSIONTITLE_COLOR.b, BigMessageAlpha[1])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), m_BigMessage[1]); } else { From 3f2bdc096dcc6c4593e2825b64a47a9682927bfa Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 15:33:44 +0200 Subject: [PATCH 030/148] some HUD colors --- src/render/Hud.cpp | 67 +++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index e06cc143..6a8e6f9a 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -21,6 +21,28 @@ #include "User.h" #include "World.h" +// Game has colors inlined in code. +// For easier modification we collect them here: +CRGBA MONEY_COLOR(0, 207, 133, 255); +CRGBA AMMO_COLOR(255, 150, 225, 255); +CRGBA HEALTH_COLOR(255, 150, 225, 255); +CRGBA ARMOUR_COLOR(185, 185, 185, 255); +CRGBA NOTWANTED_COLOR(27, 89, 130, 255); +CRGBA WANTED_COLOR_FLASH(62, 141, 181, 255); +CRGBA WANTED_COLOR(97, 194, 247, 255); +CRGBA ZONE_COLOR(45, 155, 90, 255); +CRGBA VEHICLE_COLOR(97, 194, 247, 255); +CRGBA CLOCK_COLOR(97, 194, 247, 255); +CRGBA TIMER_COLOR(97, 194, 247, 255); +CRGBA COUNTER_COLOR(97, 194, 247, 255); +CRGBA PAGER_COLOR(32, 162, 66, 205); +CRGBA RADARDISC_COLOR(255, 255, 255, 255); +CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255); +CRGBA WASTEDBUSTED_COLOR(170, 123, 87, 255); +CRGBA ODDJOB_COLOR(89, 115, 150, 255); +CRGBA ODDJOB2_COLOR(156, 91, 40, 255); +CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); + wchar CHud::m_HelpMessage[256]; wchar CHud::m_LastHelpMessage[256]; uint32 CHud::m_HelpMessageState; @@ -252,7 +274,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(43.0f + 2.0f), sPrint); - CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::SetColor(MONEY_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); /* @@ -335,7 +357,7 @@ void CHud::Draw() if (!CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { CFont::SetDropShadowPosition(2); CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::SetColor(CRGBA(255, 150, 225, 255)); + CFont::SetColor(AMMO_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint); CFont::SetDropShadowPosition(0); } @@ -373,7 +395,7 @@ void CHud::Draw() if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(164.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon); } - CFont::SetColor(CRGBA(186, 101, 50, 255)); + CFont::SetColor(HEALTH_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint); @@ -404,7 +426,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(234.0f - 2.0f), SCREEN_SCALE_Y(65.0f + 2.0f), sPrintIcon); } - CFont::SetColor(CRGBA(124, 140, 95, 255)); + CFont::SetColor(ARMOUR_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); @@ -434,7 +456,10 @@ void CHud::Draw() && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange + 2000 || CTimer::GetFrameCounter() & 4)) { - CFont::SetColor(CRGBA(193, 164, 120, 255)); + CFont::SetColor(WANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + }else{ + CFont::SetColor(NOTWANTED_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); } } @@ -528,7 +553,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint); - CFont::SetColor(CRGBA(152, 154, 82, fZoneAlpha)); + CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint); } } @@ -622,7 +647,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint); - CFont::SetColor(CRGBA(194, 165, 120, fVehicleAlpha)); + CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint); } } @@ -654,7 +679,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), sPrint); - CFont::SetColor(CRGBA(194, 165, 120, 255)); + CFont::SetColor(CLOCK_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint); /* @@ -698,7 +723,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer); CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetColor(CRGBA(186, 101, 50, 255)); + CFont::SetColor(TIMER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer); if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) { @@ -707,7 +732,7 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(0.64f), SCREEN_SCALE_Y(1.35f)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); - CFont::SetColor(CRGBA(186, 101, 50, 255)); + CFont::SetColor(TIMER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); } } @@ -742,7 +767,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), sTimer); - CFont::SetColor(CRGBA(0, 106, 164, 255)); + CFont::SetColor(COUNTER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(132.0f), sTimer); } else { int counter = atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer); @@ -759,7 +784,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); - CFont::SetColor(CRGBA(0, 106, 164, 255)); + CFont::SetColor(COUNTER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); } } @@ -806,7 +831,7 @@ void CHud::Draw() CFont::SetBackgroundOff(); CFont::SetScale(SCREEN_SCALE_X(0.84f), SCREEN_SCALE_Y(1.0f)); - CFont::SetColor(CRGBA(32, 162, 66, 205)); + CFont::SetColor(PAGER_COLOR); CFont::SetRightJustifyOff(); CFont::SetBackgroundOff(); CFont::SetCentreOff(); @@ -828,7 +853,7 @@ void CHud::Draw() rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #endif rect.Grow(4.0f); - Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); + Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); CRadar::DrawBlips(); } } @@ -983,7 +1008,7 @@ void CHud::Draw() CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]); #endif - CFont::SetColor(CRGBA(85, 119, 133, BigMessageAlpha[0])); + CFont::SetColor(CRGBA(BIGMESSAGE_COLOR.r, BIGMESSAGE_COLOR.g, BIGMESSAGE_COLOR.b, BigMessageAlpha[0])); CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]); } else { @@ -1018,7 +1043,7 @@ void CHud::Draw() CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f - 4.0f), SCREEN_SCALE_FROM_BOTTOM(78.0f), m_BigMessage[2]); - CFont::SetColor(CRGBA(170, 123, 87, BigMessageAlpha[2])); + CFont::SetColor(CRGBA(WASTEDBUSTED_COLOR.r, WASTEDBUSTED_COLOR.g, WASTEDBUSTED_COLOR.b, BigMessageAlpha[2])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]); } else { @@ -1210,7 +1235,7 @@ void CHud::DrawAfterFade() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[3]); - CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::SetColor(ODDJOB_COLOR); CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[3]); } @@ -1226,7 +1251,7 @@ void CHud::DrawAfterFade() CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[4]); - CFont::SetColor(CRGBA(89, 115, 150, 255)); + CFont::SetColor(ODDJOB_COLOR); CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[4]); } @@ -1284,12 +1309,12 @@ void CHud::DrawAfterFade() #ifdef BETA_SLIDING_TEXT CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f) - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); - CFont::SetColor(CRGBA(156, 91, 40, 255)); + CFont::SetColor(ODDJOB2_COLOR); CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); #else CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); - CFont::SetColor(CRGBA(156, 91, 40, 255)); + CFont::SetColor(ODDJOB2_COLOR); CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); #endif } @@ -1334,7 +1359,7 @@ void CHud::DrawAfterFade() CFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[1]); - CFont::SetColor(CRGBA(220, 172, 2, BigMessageAlpha[1])); + CFont::SetColor(CRGBA(MISSIONTITLE_COLOR.r, MISSIONTITLE_COLOR.g, MISSIONTITLE_COLOR.b, BigMessageAlpha[1])); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), m_BigMessage[1]); } else { From a0703fd9e1617b6841d8b491503dc0242c32b717 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 19:45:21 +0200 Subject: [PATCH 031/148] loading screens --- src/core/main.cpp | 58 +++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index dc61f03f..fa1f87b9 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -81,7 +81,7 @@ RwRGBA gColourTop; bool gameAlreadyInitialised; float NumberOfChunksLoaded; -#define TOTALNUMCHUNKS 73.0f +#define TOTALNUMCHUNKS 95.0f bool g_SlowMode = false; char version_name[64]; @@ -356,6 +356,7 @@ Terminate3D(void) CSprite2d splash; int splashTxdId = -1; +//--MIAMI: done CSprite2d* LoadSplash(const char *name) { @@ -401,22 +402,23 @@ DestroySplashScreen(void) splashTxdId = -1; } +//--MIAMI: done Const char* GetRandomSplashScreen(void) { int index; static int index2 = 0; static char splashName[128]; - static int splashIndex[24] = { - 25, 22, 4, 13, - 1, 21, 14, 16, - 10, 12, 5, 9, - 11, 18, 3, 2, - 19, 23, 7, 17, - 15, 6, 8, 20 + static int splashIndex[12] = { + 1, 2, + 3, 4, + 5, 11, + 6, 8, + 9, 10, + 7, 12 }; - index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)]; + index = splashIndex[2*index2 + CGeneral::GetRandomNumberInRange(0, 2)]; index2++; if(index2 == 6) index2 = 0; @@ -444,16 +446,14 @@ ResetLoadingScreenBar() } // TODO: compare with PS2 +//--MIAMI: done void LoadingScreen(const char *str1, const char *str2, const char *splashscreen) { CSprite2d *splash; #ifndef RANDOMSPLASH - if(CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - splashscreen = "mainsc2"; - else - splashscreen = "mainsc1"; + splashscreen = "LOADSC0"; #endif splash = LoadSplash(splashscreen); @@ -474,36 +474,50 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) if(str1){ NumberOfChunksLoaded += 1; +#ifndef RANDOMSPLASH float hpos = SCREEN_SCALE_X(40); - float length = SCREEN_WIDTH - SCREEN_SCALE_X(100); - float vpos = SCREEN_HEIGHT - SCREEN_SCALE_Y(13); - float height = SCREEN_SCALE_Y(7); - CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(40, 53, 68, 255)); + float length = SCREEN_WIDTH - SCREEN_SCALE_X(80); + float top = SCREEN_HEIGHT - SCREEN_SCALE_Y(14); + float bottom = top + SCREEN_SCALE_Y(5); +#else + float hpos = SCREEN_STRETCH_X(40); + float length = SCREEN_STRETCH_X(440); + // this is rather weird + float top = SCREEN_STRETCH_Y(407.4f - 7.0f/3.0f); + float bottom = SCREEN_STRETCH_Y(407.4f + 7.0f/3.0f); +#endif + + CSprite2d::DrawRect(CRect(hpos-1.0f, top-1.0f, hpos+length+1.0f, bottom+1.0f), CRGBA(40, 53, 68, 255)); + + CSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(155, 50, 125, 255)); length *= NumberOfChunksLoaded/TOTALNUMCHUNKS; - CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(81, 106, 137, 255)); + CSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(255, 150, 225, 255)); // this is done by the game but is unused + CFont::SetBackgroundOff(); CFont::SetScale(SCREEN_SCALE_X(2), SCREEN_SCALE_Y(2)); CFont::SetPropOn(); CFont::SetRightJustifyOn(); + CFont::SetDropShadowPosition(1); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_HEADING); #ifdef CHATTYSPLASH // my attempt static wchar tmpstr[80]; float yscale = SCREEN_SCALE_Y(0.9f); - vpos -= 45*yscale; + top -= 45*yscale; CFont::SetScale(SCREEN_SCALE_X(0.75f), yscale); CFont::SetPropOn(); CFont::SetRightJustifyOff(); CFont::SetFontStyle(FONT_BANK); CFont::SetColor(CRGBA(255, 255, 255, 255)); AsciiToUnicode(str1, tmpstr); - CFont::PrintString(hpos, vpos, tmpstr); - vpos += 22*yscale; + CFont::PrintString(hpos, top, tmpstr); + top += 22*yscale; AsciiToUnicode(str2, tmpstr); - CFont::PrintString(hpos, vpos, tmpstr); + CFont::PrintString(hpos, top, tmpstr); #endif } From 84f8312b8666b2774eafbbb0e6d034ba598fd69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 17 May 2020 20:36:48 +0300 Subject: [PATCH 032/148] Weapon fixes and thingies --- gamefiles/models/menu.txd | Bin 10244648 -> 8475176 bytes src/animation/AnimBlendAssociation.h | 3 +- src/animation/AnimManager.cpp | 6 +- src/animation/AnimationId.h | 6 +- src/control/CarCtrl.h | 1 + src/control/Pickups.cpp | 120 +++++---- src/control/Pickups.h | 5 +- src/control/Script.cpp | 31 ++- src/core/Frontend.cpp | 12 +- src/core/PlayerInfo.cpp | 1 + src/core/PlayerInfo.h | 1 + src/core/Radar.cpp | 18 +- src/core/Radar.h | 9 +- src/core/Stats.cpp | 8 + src/core/Stats.h | 1 + src/core/World.cpp | 15 -- src/entities/Entity.cpp | 33 ++- src/modelinfo/ModelIndices.h | 25 +- src/peds/CivilianPed.cpp | 2 +- src/peds/CopPed.cpp | 2 +- src/peds/EmergencyPed.cpp | 2 +- src/peds/Ped.cpp | 378 ++++++++++++++++++--------- src/peds/Ped.h | 24 +- src/peds/PlayerPed.cpp | 8 +- src/peds/Population.cpp | 26 +- src/peds/Population.h | 2 +- src/vehicles/Automobile.cpp | 41 +-- src/vehicles/Boat.cpp | 68 +++++ src/vehicles/Boat.h | 1 + src/vehicles/Vehicle.cpp | 4 +- src/vehicles/Vehicle.h | 1 - src/weapons/Weapon.cpp | 156 +++++++---- src/weapons/Weapon.h | 9 +- src/weapons/WeaponInfo.cpp | 12 +- src/weapons/WeaponType.h | 13 +- 35 files changed, 639 insertions(+), 405 deletions(-) diff --git a/gamefiles/models/menu.txd b/gamefiles/models/menu.txd index f617bcf80d98d50da75c36d48150a91b3eb65082..1ffe750e19af95facced8d79af0325af5523be46 100644 GIT binary patch delta 289578 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
n9)agwjbb75^~5@L>~H?yya&27TU-=f9xa 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Ñ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

%#kIEDAYXwov_5bbLxBE@5 zNcneJ|HJv8Wbgmiqcj}vt&rKOziVdAQV-I-2fP8reF4s8La!4lg56jRS~>U@I_H5^ zdMH92TE48hZT&jJwx5DVop88cfBsp$xcMp7y<>Y-&b>W5@>ru{IrY>d57L?SV0Tp# z&RE3bGmk$)-^M=8kq71#)QTmt)Me*SQ}1ls>Nn~@{@;G{b#=q?CH7fsnHSRIJ>P*u z@)tG#|NIO8-%$>f*)$9UdFt7|tzMr6f&XQwQWg?9-drKGotN%iI;$lM7pg_{%~PnL zrHd9>>axX))pA-dfEl!i?nPcl^G~RtC9se9S+R7f<##3B!L-A0)FvrauFA-UJ{ zHhj*VYTb$@>c*8zNhTIs>iSj7)H*V6SWRxE!VPvC)=(bSuB0$j79yBIa6?$c zbN#YK7Oh#j&{8K)7;o2&p1y8wRHv3&IR9F;X7K{Go_KW6rrRi;RhF!-TTb~Q{xF{` z6+DaZ2K)iperz}JIhQt&`x2_ddWTkzl_#wI;X7aQcP<$mVXnC3Vud{2uxu%nbBUD( z>I>;}UhH%ud4wDMtRuR9>0&D^;y`%Vv0isWJejt$|@nXd!PYOc*Q6~oz;hTe=eE_-1d}Xr!XX3@3L|Y0QPjCNf!~}-8#I@ z^a_!zFQa$z<9Xtbo9vTyR@D7p!^^0)R1oifpf32weZXI2VcN2j2Y9RMVj^C{E=KxZ zMA)NAHLoxxxq_%4(HbJh_p`}d(D?(eZX&8n5H%^z+)>Y1jRHYx*v%79a-u^|@mdGn_RmrV4(JZ13 zMC&zz-3>&D3-Rk|a2YrcQoWk|V;+P&fG#0Iy&Ow~bp8BJCeO%+OrP_^c3vvyk=t(N}$^LYe^DX_eAKa6=hUgF?^D`VU955U(955U(955U(955U(955U(955U( z955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U( z955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U( z955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U( z955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U( z955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(955U(90BK_!g#~wSE)W^xJ+O}@3NUx6T&_Q)**X||K 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

ZIaVI?Kdia;_{vWgfki}hY#P8l) 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%0D?H!DeKJ3~k@?HZ(NnU(muC0q3)$kM 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�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

S6) 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
vL|d`giq)l{Kw~9J>?lc`l5CiS28f!7JV{z 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 z zulF8XK0+Q<9bwv;BW1;+WfA`i^Z~%@_=||gH-7Zx9Od}qH|1LJ7l-|YVY_e~EN4E}Fgxj|;1 zIYK_TrXTwsR2%(Wb|}{S=MU=dwBudmQ+#)+l?_tr<@oj0BjozaM#wp%PL24l@3$yl z1N;vDZ}a%kR=7xiADCGHQtW{jV$Tf8}4L=cNW7)UWOI{q`@VYyZ1si_TZ_ z-WcCZ{6`-^7fAGh!Qg-Q*l}{GPi=q2$z`1z8~Nr z)d3z`F+!G(duzo10_}g(UG}IfTA?wxp^QU@AuGY@YB3lcp1jDfEFS>ZS!1`4Jx)|E z8$TQVyZ!&QUF-y_&+-g5b-Il9k7pljU9o(N>mvG&4Rc6spGy2%A*~nr8@^$Wi)*)R z5$5~B{u2JH|NnN?37GE&1GD;q-tA)IJ^i@d=?&h4pNX$Q|Ht;{U>t}EVE(XLInzpG z(YI*5bbsL|()$gy|0`klSAQwJzb(?IzJk<4F}?SjS`Yd`UR`>x_f?U}&;3BA&t2kV z8DocBEA#&w?wdZ4q=T{lFFEr>xqD&%ynM;m@7e7SF4B2{D_$?p+_PCe^ziNSzPk>~ z2ktpiI)440qw>Uk*UBgE-zy(KGELsK=vM@NA+0X1f&bY5tGgop8)g@k!bjA_{yoS* z^FMNK_;0cL)$klN2#ymAYdU@?TOIy`@96xVd^7ytgpH>1!R^1Rbyd@DHF=Ofw8y*y zd%f`7)s%~QS{&!~eTMIdcg*`Hc7^y6Xv%0hq{pIu!#nT{*bOb;rnWxw{f7Uf{Ko&! zeQ2EgVf&^Z?^hk6S$kiF8!9S8oAN~{R{?d=7_cygJmp{9{-mi(~{b%V}zSE5v zV^^~O6F+}x4*-69$6)Y(>{%zvU23xvmzRdw52$YNp)I521NYw`Q|7LguHISFGi{!9 zPnj#-Q|C&L9@AznlC>Lm$on6>T|RnnlH9L;fV8@N{9iRO;(t-NZ}q?voTtSAV4FDI zTyYvXggmW=hb-SJ^(myuHg!`b)!^8^_>0QgV4%XSRJ|G?h2d4JOf27~{X zo^^`csd$}*|6uti4or|ct~(@eIpu6Q@x-^wNhhB!C!KPZoOJ5ha>9wH>F?9zO>Z3~ zbC+zCrytm_{{1%zeuFd}!0i8(5&xY$Gwd!hMb`wR(Kn z%Qa%0%J4tY1!#|ZJYOO5KJB|K) zS}fw++JNSX_rHZWe?5HccYXl9hF);J&JDP=hdKC9Oq}l@OMBLKyXO3F`d-TLUu6V5 z*}nLHWxpL>0sry)PkQQ)<-9Xamvi1cLe4$ujdHH0=e$V|exLBGdc0oFeZvU3Wc^XK z|JAl<9YK~)p=AGGnU4RV55Ut28jb(YTt8cm9NZ_TjyhY;KI>e$Ok*TgEY*4DrORcu z?um54`4`Ekx1S-WpL?l1c*_BK>dLbOzkyp15X1vU{4Xx%KTBsoC+Ay0;d~^%NEZVL z7S~{lxOqOUGjk3=@gH3j`DGaIQf+6WVm~ne{=ItToaqo?J^PFybGa6=zx{B%8XCaY zkFHnRk6P)h2z;+p2Yh1s>@mf5{QTzoHyyxy0JrKr&Y^$4ah+B-d_#<2r{TZT_w^mI zu88MGZz2v7e(!kv*EM?+9{!q~cjg%~`kZs*yz?%Q^UfWu$9Xb(v>xZ2E9YG>Mn<3U zc9*B?$v^F%2dEeSJ-j!&-_l0n|GRW9|Cw8t$fnKP<>XUNle5nrBahsDv%K)=5&4YT z`k#FC7Fnjcz}rqeL(Up~iQI8?k9>I7MRI?{|AyK3S-4-it~_b+QD(~+f1;~9S;QQG z;%GH;7+<^d^QjyQbqeY=U#Y|RM6aL>{lWexHUL>(ZF^aLLZ%R7xK?!=*S%|!SX;W(K64%GZCX^@`V)H)6w{^bNSf+<8FFdMvpp0MxTAAoIiH5j6L{> zjJx4U8F%bMa?zr#di`uU4_!d>Onl^bYQlfU7Wp|K{x8%6)GyE|{AWGiBUg-+kKevd z7A#sNC%olk88>mNeC(dx^7xWpm3ya-kT2ePncR8X&GOb0PL;FH8!LBTulRq}1^xK% z#Sz+Ez;XNkgrUPn9oG_8cHlWOf^|9OmkVX1`$nhISG7KXiukX3zpX9s?SJC(umxPq zp|)qS1og-;`ie|Jp8yN^&Pcn;n0lUnxRik}p&`EE$J$eD=a7CI_1oF6iv948o2%Ep zKx4Mok72$a2LS#P0{~st5+BnE@6+&~Zvdc=n{B|J+m1JN?Aq-)dzM$>|9@HI{xzoW zlAU+S=(nFFqfZ|t7tUHKec#n}0RLWO${%Vh|0n;OoPY5+Iq&SV`tkqW-zoA9+j+HggAQc9@f! zDyRK@KfrqWKzttQV6Y!KbG6!G_z`#(Fadu=r^QpZo2)FnzX{%gy>4H5eb;I97SeMO zzm0~?cMZ)Ea{!Orux(ra96)0G`}of}_)n|=b!7Dy{lNLlwcf(VO?ho7>NNbv-nY3y z^Z@J&?o}&ahNACTZB~Q-y~3|IE|ml3nlAxWS*wM#(5}V%xjn2BofZ6t2Cvf?K*N9V-sS-;y+iSzZ{GPnaKE3_ z&wLfUVDn?0Kxc;kZhsI@_i^6<)@Q9swrIXq8jGs%|5c6s|JZ+(^Dmv)Z{O=2{{>xB zWz4MQdMuL*`sQjp;CX8IpX*`)$KUz9^!}Fa7x2{#+aH~vmiT|AC5!zdZJ7P9`2W%U zW99m5u9mltI!i7%Z;YJ!_A})zC!Z~EKIv?E>s#L@r)k{(1s9H!54`sgdEt&L`Oc26f(OA|{QJ(&r{%*ssgE@W zzWp>9zDBmtH~jp_lLdW!rMRq!{jDW4i+In(q_R&0bLik@NMDWkO*_ynbEsf5F$ey$ zz(?qq*KXeI{QtKk_P*%=ma+#Rw3@XSvBk$yUpxB5{W0;+osCbNhWg`>3ydZ2iM7Y> zUSJFOWn1;UTKw;N-yg{6v(D6be~t4WJz7TVJb+vC_qG!>-v4wrCvg5H<7L8~&q~iL z|CGP>uNM3du)k6B|HS@1p!ol(8|KK4oxA0P6HZZ`=0dr0+jhC@mh0rEV@GAdg2lQX zV6>ce`e@m=XOBE{(|mbAzab39^Butu`=kBe9PD>;OXV3h$@*jtAe5=_D(mOm9H(L} zc$>$Q$Tw%>WcX!?eWpJ6zEWLz?bto!BsvGNM95EUf94sTj7Bb3p|iw1t*s|u3!}>s zZ-*!@_&dMg;`*GOueSdA7mkdSp1Wg}y!V|)W$gGK-4ke(EMBrgo_@z#dC!txk^9yDzjx6{rw4>O zK(zmxrvo6r(9OYRlX;dRlkfw8sfUz@E6FAJ96znwgGI}QbF(EIM`c_Q_)mNGZIP0$ zqII{UPqE!(U^DuQe#g5c#-F%Shy6-dMxTvNP0wJj8gxoW|AAf!|8TIs-%a4Zw+0aG zw*&mYUSkB{Gx#9vyTgCg4LT10(cknPy8RivXJ^ilacf6jt%(1u{d@J7a_Qa&bngFT zhxKD-ERwGGeOF`reqScs^+h>NQ5JqQU&0yX8|M>Xt>j0_?6o&ua z{J-1xU$Oj?_wIIc{n-C=7Os#_-?v@Y{{4#l#;P~TXCK-l(`PQ!Jpf0^(&cO9Q+IBV zUtj)u*)@5D?9p!uz9(f*;fVju!++#B{&VKc(_)j5fwsSSC0<27I(uB>n6YI{ewwU9 z?jir!lh?^o&0jB$xH$wZ&s;FLfczvboA&W9)LU;X*BWETd*mGxGwMX6&C*v{^8${s_Qc13v-|M_a1Q=+j^8^M|JBdHb9V|IGH#5YeFMmz9bbUMf7Pqn z?O7}1zpnjz^k_V?0;;J@zs^Z3d)%5U6#Kt`W`sbc)wWZn8L^65KP z%DppnUjVi7KYHgTnK4W8|D;i}YV`(r?#|Wn-X$aD;uA;6l8Z;`+QEU}6pr}cT>OU* zk+W{zUUAfyr-tFoy;hP-4*!*(@h7D1D**3v-F*j0Wx@fDI(gX2&S?{@CjJ##%NlFLfBNjOUhRLg`E3q>lSyo?K@p>8lE9Tp?+xI~6;k9DF^ZHZ~|M@P^SAHgAW-M{|KKit`$ynX* z$9?CIeE}5z#~yjV^9zhV?PR%V#Xjl#cY5vd-&LJquUj8jGyWUa`*y$i1N2@a@ZWv+ zXX|Mi`+r#8a?{ z=oK9RJ<5-LL_YAI^K`3Lea?#buWSD%e_Ge}kDsh_{kr$B?)@|2p;!CY_A@u|TOyb4 zy3bud@3d3p(rvfOxNrVa7Txl=tlPR%CVt^H=}r3%K%V`dhySVv6o&uan!Wqx>UVz* zcFDW$zegr^PnRjPm&!x$yj?!FZ@k>A_a0aL|L8q?WTt+v__Wi`QTu__d0)fKGO4 zy~yqX^(1nSH2}nP(PphYZnAN;?k8@3f97ZLzhXPqT3^gRwAk>wHuiuf{sRYG@SvhmPz!KtA@{Jb=T0^#QOBF60ZI$FAXr>ohuM z42cW&V;?#e|G)CDZV$h%$A3@GJyrMpIrRjG^OK(XGmY_AzkuxvxbBFYJL*(9^W?Y6 z1siUV(;xeD`Hd$(Do=jm({k<;|3xN!Q}++h{JpwYP{|h%;J+JJrM=Yse|>$RNc{Ka z|H1gD_Dz)Me*K;D_+8h?haS2^o_o&`d35y&!oC0xtFG{|Ti3{uYj2Qs8@9-S1Bd12 z{o7>smd*0Lzx|Oco-$r`Uphi=oBevZY0gNwP1gmmrT|~SqpAr=|nIg{~ou+#Mog?>aT)>0m)BEq+e5UN%vO;$5J|OS7;~lbT z%XWG0`7a26dv@qIv1Uw^E2dr|myCM7Z0_n`7Z~xsdAJYemk!kdwyO-zl27>W4yYcV zC!gST>^LwwZ4SWAbE+JudS4;!6LJs#Dtr79N6g$I^&m6BjCS-PwyP{JvfqwY6!)PQ zVmY$b#--6?Bd$SH_@H5BK{a?xdulP?4Aa?K)<)cu?w%_al=;pDs z&LYQpDC=SzSvSd?is3(FK&(SM@@_8vgVQf5Ucc}&>Hgf`>+yGb{#rkVI~?!#|Brj% z>oR`)MA^A*tE}0uNgjF6WAd;6@-OnA{^U<&>(Sfg(ET5f8Ot`x*gIcvYXj2oAO1mh zJNqBJ4=~^D|C3y6g#Vv!_dcLlf7guu*f5DN6PiY3~HI^|MxICku4>RZs2cZ1Uw0! zhVm7x<-kAb?|&A`6=)LK8OHlsebj-RzlwRzYGtfGGxnjILrmrskk!tQP(dFF`xk$= zhW&5)9I+g3{|UAGjYftdg`V(Fvlb>#zs;f__|x_P@@;=R$1lJh!0=Am+8CahJ}|FU zwcerpn$@3Hx<35yUv&WX|JRs)cc?$0WWziC;FmI4?{yvfpnUTc4HiuK`~9zeUZ!t6 zAY-5W3+d5#f;9YxPT8A<*sK!PXXpS8!T-b;;Ntcax6uc{Zht+$+v7)dgr%3BEFbyU zC(EAn7yt6V<)L@KR~AnkC3k5Yz~j0WAnyM&G}w>)LS`WU@Ij`1PZiyreLJvE@?<3Z zen{&hZ%N-z$5>i_wRGF<$Y>I74F+$0xi3}K(n74&HSiuj*~`xgIS z^S2owG;K`&W;U!(Ag~vG(Jy|K^9KXZ_5xUy!M1zeR4JIa1!I*l)T+wEu@z z2jH8$%-`$*eBTT?B(Trlv%h7X6rrn`ge7Bww=|-_duPmK=C^d_plGiw~@NE zZTdjUzQnX)@ql@C#Cxq{C-Tm09>>iGd-P>=*38s&N&H&)qUm2f^nxy9djML@pPxGX zSNs2HvIn5?f&Z-N%8Utf1f7om=s@@Yog8UVy(NndD*OL4aNpMn6w@ca@=H1Q#!t&< zKmL&tCjRtCKa{11?vV4J{-28d!9D;%{2#Phvj2Vj_s$LS(*lO&- zJ^;J*-T3?hZ88S{pF7OS2=}58%Fus29-VXBtVE+>%2*&5(Kl5Cj zhX3pf3g4PPkU0>(71oaayJGPF-(>vPejzije_USs;rHdoKlq;f!}tED{QMtZla04O zF6V##=hElL{-Zloi~pY8@8$)D(Ehg=fQ^$+k(XZiwtW4!zAX#p&y!Dm=5z7~fBdJi za@-r`(PZwx^oof8&B6Fex)k3!b-3$ex8kq!l~(Y*BTLZ{*q0|w);ay3Iy6rjHd7Wm z5v(vQK#!mtF^b4*@}!lG*M=DDLwgSF$F|mky&vp-4s{A$uGRT=*EeWM`&lpTz)R4i z{|$fv_^6viZPu@}s}}GkNESJ|ky+{0Gu!^Zw>HXfyn04Zx$irvFZj37pqA zL9V{>E?F~kf~>o6ge;qKkz9ZKgR;E)40(uk1kwI)Dc=Ti5FY^k{xn(TzJsp3o9TZ? z=Ii|(9)26&lj27pZUxzZZ4k;`>_q23P+Q6T2gpbK2KYzQ%7k^q-vh_B*<*ricXqYD zGh*A9sQgc(C!aQ&aZVqIaoG!QtDZR+>}O2Df1dNE?c3cN0E_!G+n*Hs{|3EJj9*&J z19a|UV>JfX^yg;3uST@z@L%~ETflgk@ps=-MlaNH8_=$f=YVS|a$+d*6oLOeIknE)77T^_X_q#^ep|Nz<~hAj-(g4#L-JeoTK1vF$5e=~UFjSg1K<5U z089^X^Z$zfH>w^0?xl@|(@F4esm|O<_z%6p(|-K!u*QF|T(N!Z_FJT9*IhE^$^R^q zbUgsa#Si|bpkH)7@rV8U1zYT&;s2L^uJ?C3-3b0d#-{H7gFXQMCpy5O=Ks$;QSR3L zd>sCVcpv`uVgvB~^L?N76GzIzF(c$1>IYz-Klb)v&%d3z-hbgm`W?W_N6I59_Wznm zasS^&;d?dpA{Vj2S12u|$!O#he4XaMLw8^w70M%LLwRSi&h06vep6(GvlH~3zJV9$ z2;{S}=p9ZrYMbqXfy1?*;1}4>9c)x;Z37Um|uhVb* z`S|b80o=ykz~`|tOyd&O1K z{i5Qq`s2&&bKh34bgp{=bba6tW$b6Z@74nLzWi@)zJH?DdC7ZzS0+FGKXi?N#{c>F zuS*5H75{0U{=j3U_`f{+Uv+@N;QxhZoFsRF|BBnJ@hjQ)V13SS)&(*LaO3QeE}vW9 zms~?Pcuai*)O#P_0ru*_{(o%wNLe;M;(s+b-Kad!7!{tHbI$bHGU@66CcVF{IQ?Q3YyCp( zx8Ljs=-cuUFZHCX$n?eyxmgC{-ppJd@Q-G?>Nn+Dkb;C+fNFc|xP$vpjL)#wrO z#M*&a?c;gsIr@Me?CYO)AOC=l|L6-JSUEy&*13Xn-*!sGf0Y$Osi#0^w9k5d!(o$C z;5Rz_)r!d>roq!-y6x@8zP;ErejTPyfa`pFh`D|0{7sFZ6ZqtsWDTIr`Kn>?>(r+;@z#&K@A&qp-#!(?4a@?L@gC0p=JU*JJiM zx@X{mD~1&Nh7xyMrEQA?#C~_aTu+`mnW{GZUX`h7I=s#Q!teN_nAcp!Jc3sT_rP}i z1YGz110|WL_u2CYe*$*VQ1X6kJ6*rvU89@vjvclI@7UhuP^HioeFOW`XtjvG92*Vt>tM${AYiLY5J|($)El!>B9$*eAma>?AYx^9{Rl?x0mp@ z^qaz;_%AYJ#(cL&EA*P`{}1s$(E}>s|2wa})~$m<#)jC#9&9U@u9EIizasZ7)R;cS ze{_H%590qgsB`1E5i;(=i{;v#{l2oWKk;|-eFD(iW|g02v-@(Kz4^@V>&sC$53IC< z4**=p*N@*b#DD6-H=A~yd$ftKkh&xOr{k|b?oB&a*^Lb1oxqdM?$`I5=D+djrP=3; zm9|)G+Hm^OF+jg?Hos!M+5R>cKuQdt+XIMk(td?w!Pv1bk@4&#UzhLy=b3po)IojJ`^wK{@^k;6bZOk* z=7f&vZyEk4c78bTZ*u{a@c*tOM>6r>(c7 z18{#~ioEmdNjpa;;NUxd_z9u;T6s0*uU)=X95bZ{Y*g0H6SGO&2C-|cg#FMB7`sCC zPHZ-ZrwybZcm2D|Lx{M2PKALHAne@c}C6hn&f6L@2{zkzYO}yh->ArluY)Jh6 z_I&35XWrCszJ&jQK9Gn1i}ZcmxMz=}UFgnaewglEyH4h6?86yvJ4Mbq`OR|9DQ_w8 zc(a^-(p#i^!erTa#j?ykgnf#?o1+sL&9PUi$tqHZ&ziC>&-s7@UWP`&ZDN|7??ChV zhi(&@pZd z_5i@{H(vnw&u<&Ea6A}Ci&JnuwHC&|TId?tVEB(50ROT7p`TQ~2KzZ${Q3Eg+1x2p zrF+g5(ld9N^vqdW+@bY#YkhNjd*w=PCmaiCjeSV6q)(^V>tF?Y3FgH-hxPH>bPHn1oh;OP{JP_L1MK<= z@)nxqo$?(!{6WNoAV1RH-%wtIc8D3-hTkZl$wtwQjScp_?E&CpKRSS01E_NY%$cR> zOospN+m<@Uo#OAp{wIdmy_W?4kq4Q2eH&nZqv)vGdJV7HSGf%T1MKHsmi<3ZbqoBm zn>7B~wX5UaZnzZt+njd>uQJyDdO%;svlbAV4Cxm?F$Zz}wfKk0yGm)<=@3aBVcqd} z6LkQ6_sDTeuMq`4$<%U9wT%8Y45F7t`RRvU(r>XGCoT4@H1_(2LNmRZ_>lZe)j&oMX~>O z{SJ`xhvneEi+9n!cMSfk4#qPMs9)tB9~D;>8ZHpM$3w|x&yzvn%5$}={44E_4iZTUtDZuW_k7H1m2<-s_L6e?N)xf)WHY>MYXGtJvH$Hb{3iww`HlS>&Yu|l6Dvm^ z4y(JJ(=`0&`6K?<$=``Cjt)ueRT}2IYt`ESeSI!QV710}?N*(v9Wg2Pxp_JZvIzat zx95>%Zch)rmu9mwcg#C-a{#IDU4e!Mf@bNIem>9^62 zvzxWgLxq)$6}pFg2iUORd;t6g|Jf%HUSW+w+BmM&`3rm(ox%el{`0=TF8qj5$FH8x z;YnzW80>|L+3d>>Z~9oDrVC`*{r+`g0r|aFbx(8v$3xl{?ZqRGK}ZA82eJ9^F*3|# z@Rb?g1%!5qX<{EXKflSpWlGC#9id^r(%n$W@!{Ss?+Sg*?fayd##Cxl`;Xmp>?Lb;R`ecosbt zyc@?dA}_p&6h)p%E}b~xQr>B#KmYoMJWq#O9b+5d^1&m4eT^QWnuGyhK<0CTor zeK@9$A9Sq2f45(;$3I2C?`GAeP&If4I!YtUM=`q8fKfWi1%iLvIp8u(D% zoWI%rDRcfMKY-@R!~F1``2iMd8?4#FUPBik7MnC4aSWgVY(wHj*b|7kSLkwq`j1GN zzhrL@4)oR1k;IqaH@KYqtUuM1bG{E`bY9BumyPGg$FV_UfxeHN;ae@(7;b%V@=keA zt#;5qFcjGY?F=>D;Lm3K&||OHeE?VsXvg(>&T*q&XOAG_Dds2i?~g0?7h}&F0d#<& zex@SYC*BbpaXhc|WO9OQ+$*Auj;jM&g3mQ|{(hwi0z!OedET-#4%%Jf*unuyij^Bz0}Q3u?~y1sii~herR%)UY|B$ zf{ahfP_9?&ARqTi`Ter-yrJV_?`lp@k91vpv5Y_eeD_XypRIU6J6#uDaY&@?$GkAg?)Ctd6_%rDHr%wDN=I0{TuQcDU_YB`t!z~n|0mKmzF2(nqQ_}&nr9^as?SPW8y@olkrY?kF9*r z$C*lZ$T(zVCaqL>_5tO{Uu&79eZ~;qEcP0)h#Y)3i^I-I(E;YEOy(KFv4)4xZLsxt zwgLU4tvdUcT36oKRdX+`FTpi<8efO;yFD}50_~;tE2twiPo@6VTSujGmF`#SS2g#O zHkc1$jL^^BUcZLx;J<&K_M2;Z)Pwz2249WY|1s_NgT!$N#zAQWdmg)Sk{;;!)Acv| zoO7&F8pH-bcje$3HXC?D{)uYuOx6@0FXg8U2W9+oey7w~)`r(s>AGJB=YAfm&*~2E z*>x+&eJf)rc{nT&sr|N;YvFxs%j)s(TYf7~>Ys;Y?Os?1`7E!0PxG7Yj2`FSg}yt| zRz9#FFH`JCCenZ8pc_|GJJOz+Yxewp8M|g<y)!|QoHZx<=nqV8M|*~llGx4cj)g@YUg?PG>>6@GOSq7Hl!vxRK`^|@0qS=I2k!|cbL0;$c)D(GuOb_$A-;^_Yx75F8=ixnm z``428%i8eohxya)*|oI1;Wg`*wd>#a&+UGg-~a9B&pNmK+_!U5JCf_jH{JoZGyWT7 zviY7lZ^Z*2IoQwq68)zC1D?@;ZaWXh!N2a0i+`PS|M2VZuiLraHy<$H8+Mqla{#3H z{{4fv8Rja|#vJ|uC$am8!!CPov}OJ9+AUqgTum{W9TwD;r+-fBWS% zKRnGE4W8HLIe5;wDl;6v`*r&DSbyxk{kA-I-ES}J+{*f8{A+%lR)^isy64xGmdC&5 z=MC%i^Kov6<+IfCS?bqmWx{)!C*oH=e#P+_-1vb1_%r*)jxFIo{LQ|SS@_R&=)7BP z9h2+R)E}@qxn9ETEZR4E_wU;^OSAaHzi;QHeqH{#<*{pFYWK71u>5x4ep~97w>)-@ zJZbsD>;CWX-0DhFWG;L8vF38x`0*u~+=`g*_X+(3?8lbG?nj47#k&g6Um8y1O2dEV|H1Z2O8aR#7x>S2Ssjn~`fysG>{?p?xK`=D>af(mXXnYih;M_#w>W;4$B%g;Vgm4AIvro_v?+=$<_j#z zgM>EWd;Eef-b`h|IL$v&&3;>I`ACCnS@_SKlf!?%Y|UO$hWTWWdy)W2uvmiqZP53h&6!~DVTh+mcQD~{3N#t0t(YXPPxrl12L z*O&vab)?K|`E>03&uS+zM}Qo3_^}KX+c|Tykk2$S;4sA@)xh2;4K^tIf>0SHJY1jQRvf+emneEzBb>W;s0fd|0TKLx9!&xp7Yzk7M2U|+3!l_!g}m^ti0W~ z-&yt9ear8s;l1#;wdtpR`S3ie4?(_&UzPDIj?v)92p<43e8d63>FeQJ_5_nx`%&8vnyO!r!!4 z%{9vtreS~c?q}t->sB_cPyW3yzumLc%KN|lGHKVXjGtPWFxB!A+XjzqaSW>;L*f9C z*=E!G>wKL2fu@tg`8f3)odI7c>j;q-sdCTgow7#f{<&SV)b5e`=iz<(?WdOCzZRZb z9!taf{0{F``t8?Yc`Z%5XKh#>OZ7T9Wb^$F`xC#bkFBkI4i4fIqVLX!KkA_BiH`dx*Q(_b(d&A>`z|4q+g}7 zmY38&_w)JJ?L55imk;kHzlrJP9r7-Dr_dbf^kj~stWRNme!F(hu3750n{}R-*X~(L z9sar1Y1b^Z>wfCr^#%DNc2$pEajc3NE8+l{w}sD{=LCyN zJ^+tC9Y!hM+xj5vQ{;im>*Y(85#0BWkT3k-R+pbzS<7el?6;rVJxjChrQHwn`g#0w zKc9b|mM85RWs>V|ymefOlP6}*t<6kiZ!2TI_06y!ejMNr;u*u|x8Ii9_=Ugix~1F? z^Hln6Wl62PmC=;3U!SZ2G#$WCi3`}NYXDduV|ZxKO^Qy?t$e_Ihg%P0bz8gsZ_fSS zmZ#d(%IDQ#d8pI!`KfiDfPq8=jAQQ z3;({IXQgTNrsd6Rhx~Tmug|Xe_tWYQucejquT`o~^Zv?+{y&k|y>*nH-aO*u5uA_I z^Bu|g8}g$g6PU$aI{<5YwmI&$N>#=*s=vHfc#?T#8$0~W$Ub7s;Zw$v zbgRyHlArO!#%J7-3;x(sM|e;dzJ#f|mY~(>DE6lqT``Vh9LGolkp`MU1FWmT&kPQM zOML6Z#~|>Z@18LaZTL?a_NyH%j`Do2j=Z|^?pgV2(xU3gX^ZD!tiXSF=-8qAg8AIT z?q>|y?-TzY*X%d=&sc-^rhECRorC|_3HTEzACEW&kp?0SL>h=RP!A1&>);VMgpJB! zHYb<^j)7^|{D%Jy`v-%kT9&?|M+{1bsJ9RGmeW4x^_OR29XVr$E`^T-JKetXL5%sO zI?gtZ{yDb)2GzaL0SxQIl=p&uMxDe5)bqY$nJ6bB4MZAxZ7J4siEBu{?@73g?oaRHHVQjGNS@#D{qc>syqgR3N z9N;+n{P0~M8&hI`z<%=`q+!3|KkJ0q_bu{pj1<23T_n_G6p+_;2_F z9{Kn`PIZM${134*{H-`i>=l@Z58Ks~lBXujA4GY^EVr#1>gL;!b9DbsQoehJ{SVeN zreMFrcJMvHc&=~O@1nA<*>nKr_1OcIvW&aE15!K3{zrFUE}`Cc9?L~}5osXOK%{|4 z1K6G5KX~Hs-@_U(C&YhZarqW!E^ZpG2KWiRx!7yPIrg}zx*n^qpp-s<)A%%8pMrko zK3hs&>cE#l$}@#Fyg#2(!t%u5Pk!(p-2pudy@+?QM12UR1C+|>`(XZ``4{#PpuKp+ zF^Dt}X&}--q=9;903S8@!`}4ZzuB3VVy_a@ZvOw8@ISz7u#WGPvc{*{_(8Cma(w^8 z9eR%6fb#zH`j~CkOV^1NdHe z2aG>H17Zm1qwfc>vaBayJXkwy&l%Im`;i7B4MZA#>2sdgi++gARg!oIG4-y&`!ysE=!;X$SW>=m*$J9mM4^PtWhP zz6`jgWd~dfbOGvRtu3~@Z};1|r6oMqeBeB5Feqz27|Ta$c}c;4o|`qBjAh?QO9vm{<2X8oc_^Fux7Xb07M{9(Q)U;y&062KqRUU2N+U{p;19qa$D|qvtT!!92V3 z0VMd3o>6+98g&}~8SR{B0-p{48N=`}EVr?C|n{}_u!#j7%f$iI6|JJRtck^c1vuRV^$0D`uXDaTj(0S*>S6=Dr zqfU-}dhFk_MRsr8C@b|o`R1vex@FZW*`)ob_Sm+1wJc;00WH5-_xaq!q2;;Gv0CHc zXDjw{pJTS_7fV#BDhKlldyMhMq9*68;{ma8v(vG#wyVkZ5Xt9k|Jm#h7K zg~r#dM4!=oYxUcslv%IksfV_=tXwGz6sK2d9?q+MmP+}kfBTv>Zrp4fEoD4yT>X?W z-l}8DSRBxIx=(+T*YaC=Qr`Kl4I5nFcdlPw_j?}<&BU_x^IIIdIChZ++K&dnz+EbD zcdlC}YZb4Wt#93U=#ael+;j58Ll4P*@TH)GwQ9_P<^@%IB-;CRVD&Nszr7NC=?*i>sUF49`Soj|7_d&hK z`=IZ;RFAUjF)fZK;#kJ9j5H8wAd3cW+_g)NU3HagQ2E~sJ>bLdf4_YA(MKC1>zAnw z4E{R&SGzKN<^zgj`xI}O2OwXq_z$kJet@#zEV#RY7&gUvSD#`Y-@^qrxknzu=mFT8 zqH|bYQp#3ap0@bL4mt>Bs%fjLJjru_{fu2Wo@u|q|GjGeGaejyWx;>ypznM)Ev>$I zEy}J)1Ca(I4K$Vp4y)gNJKwERo48TOlaD_xPd@TU!{q#O^~-}fVDym`{Kt+3|FO#* zUe{p%n|(|<=Erxa?GJ{s*DZ78q2axrVen@mgc~K8|l3-$(0EB=R=W%fV&&N%#6dmY=^Ffb1n$ww?azYrhdQtbE^;hM+ZUYC=~w_odkQ{Z1rkn1#>UpIb+2f ziIq)zAKU}~$yZI?F;A3Lkp?0SL>g!e4eV1}ZH?k%kvafzeos97aKq)h;Xk+o{)cv_ z;SWChTJax@wQmJprOyNQqer;)dDg91iB8L(DS#$4^flV$^*5KMNPZTyT~3c9i8Do7LJPCH4-? zYZUI&w>0eMI&JdoV6EYQR^F^<%)G910L12nV;PQp_#6F;elaeT1^dyPc6)VkjrYV@ z(%-O-_&ds@NCS}uA`LX323F~Ob`jXWLjBE zF?fc{V2G z=O4^DZP5>GYrkFpyzct7Ui=@7o%v5}JS(NwDCRRx_)9n^jsRPqy3oZ8|Jef&-$14M z;{E3FejMvK){zE=Hw_@G4ae(E@4xxxrpa|%*AGTxvton#G;H_}E|Q0MzP$N=aNYMQ zu)h%X8up`am0@e#K?~e}#|372BN3kD$3_l8S z0H&Mqj)>dj-Gz0<-@{w}#P=WHf24t-qXF=)Ufj2G58Zle)8smP&4V=@;AOZ60QkiL zu9GJ({twLa;|a+RZrL6~#QI|w57x%^%lqez#QU1sQT!)ASZ?ztc{~ZOU!&{)m=}S5 zcn4rU{t0{l#3*uZx)~{Y6l0xNZ@f2jav+X<9Q#NE!;c2A%M8csP4B<)#-_=2{NINE z%!g;~X zpt@6@902=?mB4Rg_HbWjPYp*8y0*g4}SbK{0H~IBy8A{Ukf?}V@tfB+5hMa+=tfq7J&b*;`z|=ejNKa_K^mLHx0BK{(~d4 zleKxonS(L@oHggw;J@KB_C0z8hac~cO>24DCG~CjTKkOd!`w%n|DQeo{QZ}F{726s z9upmbv14w)y$k&f{-aAVM}U41WzO)HIr06+_aAAXHE5vS@SoT`Tbplt0Ed{xZ@y^< zK4sbe;G^LsI)M2LD8u!%c>h{4wVm>V|M>O8u{1u#&w_uz$Ncadf66hwzpVMde^RiY z1Kq-|S)DO$4H*#MLwpaB28JgMv>X1jZz1yzU=OkVV2i(Rjr$gj+MIm5hdg=sZ#n?> zs_7KWTeqX_KUiG@{Lk70fbqrl$G;z9e)t>ACk7C#r%wDc>=Q(6A?4#YfQP4?iTD!V zd!&KZqk(qAe`v_xr^oQ#r!DXbTec$pD?Wksi~)IxU*os=1qO?$Ls_0@sO34pYMz~O z^ygFf4fbQ(hghHWoBYK3Et)pX;lJr<=veGC=)bFY-g+`2zLWS)A`J`=8fZuS_vfIA zCrh*c@i!YjWySHCkDq+_3Gf*-D&D`@x&U~dhW}~TT;DW5;{o6M_|JR*_-$jEm9h@d z?y(;Lbuy;ZMR}{kbc`rphKGEK?>WBbNCT})1MP_a{vJTslVFR{nE3UxO31q)N?0t&?pdRJ~ zwy0iU?<%IPD;MIsiSH)TKF*Y}ro()n^FzT^0gBMr1Z4YVWv6Q^c41I7)&f1Urw?zB9i{SRIeA7C+m`25o_G!G}M zxz~s~)7lN&;Wzv3p##)9pW(g(tT+zu67!FKW#gEZ65Gf4<2S&@N00LJ(FenS=51JK z8RbIj%Z2!k;ya2o(D^jbj`$BonN5lfpN9XeGdCOx@gIz`?+BG_|AKAuG@KsnwGijC z>f?F&9v}M{gWuJbLzg0M!sbxGb{oUA6dj6h{$cl<&w$@xyya&fAcy~|8}P1JUlHX> z=gXD&j^jIyG|>7q(2n>Iwi8T#Am=czJ73@{OD<1vp52L0RFp*=dCXz z;ya4(DAGV@(m*@nKfY$-%fJ`rpVRDr@|67h9{ywd^URb5!E zLzRa8;WwC1yd8cH=G?&Vk;5?|_u=16dhl2iJ%# zAO;}HlFpPR@x8|P8fl=tXrLYO9~v{;)cngn-GNQ~=G#ADkYODd$YHnyE{1aheqK8- zDyut~KCk4OJZ+O4#Yhd^My15n}`1Jj?lQvdCP72j8+fzF_TcEx{--N(iqVE-q+Xuj#=@L&Df;2bt8 z-}>Vkz5(_KPQyhXBb#|%YhUv6o1X(*wz&In9)RDb|1h5T<{3{P>(kC{Z6)7du=~XM zF&E?F2NSHv=g&Ssw81+!9K%raK&G)3O(m?0YK)d2U^Y*p|0J^mJ zb9bKDpN3=L61WE@8s3Gze{5m$*|z{gTiI~6+H^43T}>O6>UaHDzlV(heh>T|TsIxa z?p2%O8(>|fjTLhR?3cv5z`q}U+ZVhiFLO19|L6}qUz8=CCrjcxjqfzlKzq?ZyW&57 zX7lfZNoMmye_#!B%!X@V4mgC}YH@>LJ=aVx0F&^QgK_x5(G|F7$NypP-kW70h&U zo~rKZefBV4o?M)wW=bruPy@?ur#Bbj| zd-$>6J10oT=Q{7F-|O$6OvWC-K45&LSErxrZvZ^#r`l)je_iWmk5`Y^Yn}tImH!xo zN!S(rGvk0m_4_|;{r3Lxo?jYzKE|^H*dHe&R1S(yzZFOR&c$QbQTD!sc0gqlR(#gx%tW^WKZYFERu>f_~WJp>qWGyXo#^fop94m^%KY zx@a#s2b&*j^VcWjAnewM_VXimt^H*`2Iu`3fH7c$nKppY&%VdZPaYtH_3!=D{NB6Y zyWe{b^c=_>c+LE0SH>V`+wdlB;;;ID&Y<{`yQ> z`vB^Bw0+m&=}&zu-d`EElYjQ@Z@>G;-~8q||Gamh9^MOBWi$O}%rai>ewyEY_j~ty z&w=}%1FxC?`OZ9!uZ*$J9FDQwul&!m$GZ4M2CyH%&R&`O)cz0Qzq+X7W9higfAsEmzwwQEZ{Nl9>=9tSGXXglz%HQQ*c8O=_2<6VpC11n z|DFS%ZVtR={wyK??7&pyOeuKfh>)nRO8jHl**^1CJn_DaMNZvUU{ z-x&b;>pSvW|MoxKZ@>G#`@ZMEeb0f{%zvDVt(jhlE#`AL6J}uz4$@^GqX#FSJy-tp zT)b6=>!>WC4eSR;;#aOmCa7+n$4z~_*O)Z^dd z-*e#8%z@X;e>!)*0W{B=pV)&z_~Tp}{&2%&@1BK8&*5S#Spb70b8y3V;jS=0;q&`^ zBVJ{9W&30N%J83lX{R%Q-g%&l=l_qt{pBy8IUn9{x#WZ7v*kL^7aPCdvhgqm-v3X0 zb#YF^_;7`*NB!;F6PW))IP$CE?f*3EL-%|4d(VNlI|p7f|9^3?ER4q)yvba}qOdRf z*w~t|FzLBmWwMb^yTIU{vLgp@>A!gVQ$rqchE6^5O@gpKvOwH~Uvg_)GLQcNN*k3& z*B3{aI&QIE7`y+!`mNuZdjP*NWCZX1C7-x#{$vd2`s?}2i~(18>flU(d-3P@f=8Yi z8*%kZ&ScuN$#;foe(is|Yf+DFk8RI^k2?omGymC+*^u!F*D8Y|3xrkJf}41iu#f4I zQ^*6}MbzhE;#voGfXeVotiSY(e6gPSCyO|nmv0~{`?r7b7vKHwzx~^j_y6bb{_eYf z`J2D_?hk(XmnWmM$6xE1ZzIy-=U)Giv+M!v{cep3IV5>Vmoosq6(HQ+0ojBska%3} z+sn7ZKkhow{oVcDbKvdGf!EA`XZ*9bjWLz~(MiLT@ISh5!e5$e|3F(VvAsUqlNIWj z|MU@CyS$xO$hisa_kAFJCru4c-}s+Das!zvXZtQO-#Xz;02lB1lUMd>jF0>hzUB6J z0^i7R%=Y*nosvH6$~%Kwym<*>Z0eC!D(7$U=WK!Yu%}DQ z@64aPm4Ws77SdL`>Hhi@qwS^q+K>;h{K#(?@9|yS==zZ>*z}VRnZvh&w#pYqZeb%h zQf9|_IcrLfMUO?#f!8qy-U|Qmtm^;fpZn;(n22YW&i`W+?%|_%*Vv?es}4hR&R~yK z9~w?hu_vHRb-ji6Yh3Nr26eKZkoW(v*0bbK7I0~+y@7dFVaN)?$V$%QMSs8L_biS5 z7-tRn$qwmvvO(qlC3}oM?{5UWj&VW)^UvJE9qq$GJj1>{ zPGev6=I}4~(&Ch}gX{Vo?|IH16hNgjvc%9%B~~#zxkD~ob}?w zr;Foot;4N;ZJ}@58&OYfl0W-`eo9*}<%|E~`8~&$f8@7q43wj9@;+eFf4;oyA6vj) z9}4gP33y%W$&oqIae7R94!n#x@K*T0zW--_vH#QSu@48c7ZBERorRCBpAL+b;^xBp z@KRp57F%}BC;pr_$UQgj_v!23`s!ED_4)UI@CWby&F}oqd?!FWHU;^s$0asjdZzyB zi~Z`U9qwy=*cj;OX;;nfEdLDttA~C(Y6H;U%2QU(`AHvp|JHAwyudC{>sS5ixs|TN zUdH;-dFTkPw{PtU|ctie2-cd;F8$qY#s z7qk5ad=vj)jQ8hO86f{f;D3hkPCEPA-m~{@J$iE92gK|xE>}ih^Gh#3@&q2U<8LvR zP2Tgp{PY=)AK|~g*EVg}cl`Q9I2*os7Ja|27vklA9MhlGC4bfU?SH*%O^;oVUC)7+ zH3!}b|Es>4IfgBGjwj>*T(k#{*I1uDe9Wy3y7qs!-b=&uKm3(ndH2u9f8YJ<@&5e( zJ-(NdZ|Owls2p4U-n;*2zy9mkU;vW&LZ zvy9&TyR_dh&+DJg@~2-{S3m#ym%cP*40+S{WAn%V^fSM!rk7UT*8a)8y4U#ae_88C zk4KM3&w_X7Um*S_}dfB3au zd-uPM@8bDBUUbr$qQU^1^z$Q{vY{3JM+#$&h&Za(ti1C zqq3BnbnnR&qn`Hcb6#)#oeTF3Am0Ygo=Dw?(f{lmX}dAP`Q>{o|Mjjl zJ$5~IJqKRa9C$PQFXzfL$M7lV%h~&@t(!l3C;LD4x##}G>79Yfq5p0$edYYtJ-L94 z5PiPpp&X274<~=n&-FjX;jr>?dzZ(fZtpRABMjs1U65YrG?mml&3?>i#c(|L6^b3StIL-*vSUNc_Sn$hFY*TXo&%qD4!jlqujk4#uh<3f%elVr-(GvZg@;L%Ic)E1SbZM<Z~AHiQL2{fa7%jmFMaA zxW*;#Hmb`SpM2m-f2^*tN?z@L+O?wlzx%)Ez}uPwZ-M_9g)>|4sSBt3)7dNkV-HyM zec{-*awzv$W>1`cADjM}_d9&{9E0WSqEpLHUg~s-!;gI?Uwb2y|D*iJp!*?vP6w1UvcVL!t^zl%uwUE|KqL?-QV5cJqOgr%PkU9{<^vamPD-;VpRpTiiSEx9)5E7LYhO$4>{fC&0zeOAO8PFy9_J`C=_Y zov!KrYdP!vC5|g!owX%(x)lG?vm@UC+FK)xOU_g(WBr~0TYx=*RR)U;K=#_pyTjk^ zy3}LaW7~7!`RBl^=l|H3CIhVd%9%U#OYfJ_L2(fCv%jBx>9B?yPS1VrkuKlvchBZu z8NB-4v-3N{=Uc;DHf=gN?yJWo=03$UGJySzynC2D)w9+;;hXMgi~f78{%@Z^d-W}u zO23fFGCuZfjGca|;}HK}8{_L8g2Zq4`PYQ*vj zss9h|uDT{2*|&JYsIUjiaq@gW{8(1m8J33UYy^oPmwdwZFV32Nles(R2(HDg^%58V z$vxy8<+~S7AJ6k^d9qVD@AsknCs$=3;PapU=?7;3j9uP`NT0?1v9Y(q{?O~ueXK`4 z&OOdO2R_~$c+LFJH)ynBkN@-C^}!E1KOH_?i7T95AO5g6+cWpv`*Y6qSKX97A7`;V z7ltNH^5xodh@D^DmCw>`gU&S?xc5dobjMUK2jvn$UgSecf~5KIXt{=0CmA-oG5tr*6J^LulBb3tVjJ z(hAS>$8b93JhiJXuAEE2VC~mF_7DA_9qPYX_Gqj4=E`GafP8;R`LQ{eb9KD<$tack z@#DWem|m}Xz3Ms8bD-zI)6Rj{z<=M_p?hQ3FBV15hw9*y@YRZe=BUw^GKXE&Cz>#8)N4mwaxj4)Lr|8k%RQXnrG@o zuFdk)<19C*q6#{_5Z z@M-dSu)v->mSoOiigR|AC!XOBu7o4v*z3nK{7X37a?bbB<0A*);jT{n2;2P@Tf^6_ zXOAg+D?efS&$&fyc5XrYh1Y(V=M_fSS{L`?I&1k@{w9|n77vCvmrtL?YvJp8GIPX#)na{^=RNZ_0d3h!+TQom6{7X8_N?6i9#tlc4*1fj4ww^hE$Rqi*yNp|xYXA94ZzWd>Eoj=xyv~XZPl;Fua1>`j1AjD`u%}B z#why_N6YMZy{`2f=sD1H;QAbRY5d3jtp9XiXZPvl7-%n_zD`$79PY{#e2Knk55XBg za>eB6$g^@U`GkGgm~-kmAMhdkUHP57oH3Yo@e_-~@>%|{ZQyj`#!Z}CT>Zd4LY~kb zZsmV$EZp?LR{r`Cr*HjD(eu6EPrlIC@fn@s!mClq(kEw_Q%#d_30D;!z1bK zjfaU?BmZzwJm=50nE045Z6Uv4o%FM9!{t}DI%7Y*oX-51GHM!mM*n9gk!Q-(=InRq z_g(&vJ|lxYYX5(X1>VPQqs%&1)*tzb6I;Xs{*Up|o?fT!d!6d>@A2z7adPcY>sFI=v2i9P%50VK|2Tsk-IbL+VR<^SyIy#Q_1Kk0)9<%~X?-vEAu{*Ud( zCVgofRy#s$1d+KCH?BHoF0}jfYe4sD_i4|8`M1% zIU#)DPR@+DNf-9JpZqWR;2fKQbodwfqOwmpc$_luus(ml$MNjwy?mqR%0Id|ca>}O zMe24m|E+lHJ?lO=TAvH6-#t*b%{Gp7Y$A`+{|EbXwokk51#IPGpJ)BXV)|YkGp_C4 z=Q`En-s9eL;OXbUOX0t7ys-PTjo1BQtiT>RAa-GtI)@E$r(Rk3U*`%LV&*e+`jvU~ z>oB;okw5ydGQ2W^(!;?>BGn)2|xG8=zB8Q7Po6Z zZ~5)tupKCaJp<>B)f!j0J)6{}y3T~G@%#S$KI}f}KIu8obKsUa@Y48C2c#pW4VZ%; zmH*yhuYBOAW7c=dlRhq+GZ_Qpd;>7)<-5m!{KIGZr+VSydu$wW&YV2pmtXe6>%Icc zNB@m&;`|+=Q@(52>-{bDNLp_CBJExC(MRg7FUeBr(<3fBjQo_LpQ~(F)8l`&MWjw# zazTyT{$AsH4)h%8Iq>0g;HB~3{x?S8e)RUQkG+9v|F3L_-`Ti7s(uhgZw($%=_|M1^^_hI*8&w-u;FNObX{PbSBJ;vqy z9^QOD*dG2@eYG+I+pqE883P=P{w@91J9y#bbGZ1Lb8h;+@;}^nPEQ@3&EMp4kq1&o z{gNwTTQ0`Z=hXq1opa27MBbUG>Ex;Jxoj-A@}DdhyM}iUaemAGZ|vA->X^n)PU*F( z*Q%ZaJqLOYJnbBKG5jAK!hc)}kFbwj*qCDy2JP(;W5-4Q4>^L3KpxH+hAs7d_{zQK z@@rH6cL(F6-%tJjv@hYTzIx`WbxBxU&oEuTkQ*W=t!WZZIoV&3hTP@7K>bnALe}*B z%A4N+y3zj6?vi&5ouM#BTYCuhZj4XHrMl#l{@p+A@4ox9`?Kdj&w-c1|D6BBMmlEJ zfA7lC7jX;c@*UeekL&r~-m-a)L->Vd%80IwNk?_;EhesE*Y4RLVh{HX0QC;bo&Wbt z9@=Ve0;8o7M;O<0I=tsD_hg#NacOE@v{9P$7niJ{{PYD*yO%EIobwoQ*flx0c!Qdu{7E&~u>Yz~wpcQuvP%^nPdFy!-E)v0)W`75nI_ z>lyjP!MnY^Wpe;?*ssG{Hf3pj8z;;=vu^P3x%}aJ>W#}`ZR)0M;kc)M>;dEg`aRi2 zI93}w?O*_r^zZoc@3{M?`={qX&w*R#z)Rsjw*1)859x{Ycvoc>4&c!m7Ea*VCH~_O{^Kv^ zi7zdgdyx6UcK1=v7L^O``C=Ro|9MDK7`u?!Ro{_hWHwO>m$rh+QYaUp|6GS@!z;tJ4WiIeKo)K-}W2t{_6hf zInZ-pYYw~={WVekk^im_4=^(RxZ>oj;8r`sf2RrW`lYD`TD^+}T4g?pxn>VAI&jx5Ii(>p9SKpy$Bj z=fF$hKQ7Sy*|@`hZiM2;=jCb3&SSo2K$m8yV=xA>heNM2j*#eZd|A8+~1;eTu%m(CE1 zmwu^rC(GPYUdMg>deD8>eb;l~e&)bS;lI6k_UoJxuQq1<|K_k;S6#L8f!`kSrTu?% z8vpD2cFDuu!BKW^u`yvs^N776F_{%ieby@qbJHA@|%;UdO$k^{dCa$GYdhy~=RS{71Mlv=3kD*!Bi4)mdEQP{(Gk zuWLB|)BDv^eJ=6eSk!j$t5eOd{g3~>ci(m2^&IFqkU8*@_-~&V=Wx0*#yJ4z*06&e zdgX(Aas&PG()o1xvYF!;9)_uOPI=$T`fIGb^c;KDA?MxLz3IkDqdxAPi`4e5c1xqq zcy13Nd=KO0p&WT8-}pUqP1#_ikK*rVm)c*&U=o$SS6pL7KEQo_aZ5Sk zuJXsN>FMt5Cy(O)==&cXHX8bU>;daI89)7z_HvzRbT(v-+xNZZ^&IFq&~xC!=D3M&)5h9%HleM!9rj_r`|iK)zn%j< z2VN5Y*@mtC^Bu9ljLc860Jg7t!+2F$A^s))%f~)~ba=1r(m%KUue@ER4q3!AG64O$ zwuc}8?0-L2J_*xTx1I~|%zX`u|3SS+{nWF{W*MVPuK4z5az=5F|Hhboq4q)l_iwLJ zm*!SK>-o`h;PG?dCGj6?eq@~Y!lTNF@MGNv#|rEYFYHa%bnCp34?BYV@ihNSD?NL< z@CUp*vH8}p$L6C>X$#jrKlVR1ztmg$@H~03Cph;{rt;2!y%&29$`tOoxQRdW8e#fr z?bmDf`rWq~jGr@$dt=0|Q2+PATzE`**Xq;HAHQC7-*w;h9C$l(;3e^&Zpqed51hW3 zc}6dEzuNxsvdRR`%hz;CA2;6=z%*RRc>}BsAH&Q&_W=)2^1)WvUiwSn>f}9r7yi0` zOx{Vu#dh!i>nGnWtamhP_=lj8?OZ?AV!c|xOFJb%d z&+!d_OT6EDhS}P6X6}v+B8=b4BVqEO%cp-HtOUbYJVg^ZwBj_w;{Us^{df=^Fnr2FtLK zZXDL&B$*)W{8X+sY_VOKdgmgm?8U2f*QV8Ok~ZJsvdJi0nUDDf5dJ&g$rfQe_tp~6 zVxM52*^AfVZ*MK?G3_z!Iq-4kz)RzQ&cWkzWw~$r<@*5P7M|2IfzA)sG+T3t-sM}O-(0LD-K zeYg0M?SP#p{{f`_TVvQ^A9s!D{_g(nIq){;z)Rylw)~iH*$&Rt|MSIld=2}#?8EiU zJidsReg3UEi(8nu^50$n{r0IC9tM9%epu^$xOz^Zwx3@)+EU9ArY+LyqczQk+_Sgn z*PHo2^ndae8R8oM)!9B!@BP2cHD~L0*Q~I5SWaGc~zlY=&?I8nTzI6FcK-K%%48$c%=qHS& zXUEo_emLSfr*X-Kzx6w&|LafXdA=tD7(aVJ{hz-de=XP=w+`!Z=sECq=fF$kKfRBg z*#3TO0J!bly>$;j{lhFg!;ee4sb~2Q0K80E@1;GZ{{L9nfjoof*#}AeF1gMw*we^) zh?VK~Nn#UVQ^+;#2BVMZ<@P`Php_&Q{e7=Y`RV6d)&;U0xkTNZAJ`is@zlY4h_~e5 zao_G5)nnUZ+jHP~=DMy< zqxlWtoiUOx`J&JMJY^?*d{})%jO8na7uG z)9lXj!9olq2PBX6TRSVS*Zc4^c~!SQ+w5 zdk#GP9C)exrz__F`HVX*O#Oez1(n&AN&NN*_ShmH{FhG{h>zJP=f}Ru%aeQ%|4}#j zUW`9j9KD;KoAdl@Th@Df_R`^}x^k6=m-Kb}0P3ITse>@_>s8yCc&nTE8HZXQd?uG& zI%`>fujDtEbA9sN8zbXP79!i!^zDE8-+uRL_i4|8`N836g} zBkl0a^gDY3pdwck?7uw$v<3uYFD|DX;#*+_ukhd&&;|O)~l0x*KYu71N*-;bZ4B+JATS@ zt?vcsKde1s^KdTFT&Z=$>ODLD*7`zT(8ta%?42EuCp(6+w({t(UblJ<^c?6p@HBJa zrSso7V+QWvAp1Vnh2ND&{A~GqY^if5I&C;AEnYq+|J6C~HLUfn_gIa~WSmtePkp&; zAlduJRNU7FV@eKS1CWn4$t!0K*$2E|sZ3?5*ILdh_asiOr~bSoYt{bdH!j{W)CYU% z@Zb9Z>>g|SzJHqEeD`DbW6yz}1LnYM;D7$-7qjp`Y{Iq5BYxc2V~h6E|6O!U9K=2O zIOk43=D)_mlz)pWPYhk_yWZ2=vyZ>#FAuu9cl9%Fc+Z}W_2Mf-8(i4Gw#B_?`ZWK4 ztk1&twanaa)!#YFOMShrG5D|Um-x?~z}BE$_I%bn`o7n#o&!AxdJa6z90*6S^|9AK z{RjWx+1F`|%Q-l#!X+Hb*}ZU78|aXG^TT;{{HG7IBP1WZ!T)Mg5BuV-EKT?kS6y?? zAaz|`Iy@bHtDNvRwh(E_3K*|H!uqYWd-Zc>&{;rvVX`{z#TD+k^ZThcPT$IZeZWq! zm#+2yr}!3*m%aNiiR(SH?DMCc)t&qw?5h07 zUU?_qOB~#Kc8$AOd+A%gba8RE@)3r;xS4jc`wQEOzg54zFnPodfX(hN#U*p34rGoa zdoAhvY5yPZAY9@<{hw{ZyiB@wd%fy8&~u>Yz|+rx*TR2e&&G{CSRGE$eb?{R`tRUN z=hDar7!&?aoBH7CkB;+jd53Sr>u2|A&w-u;bq>5H{<8r%uZEv= z&s=oj%2b@%voC8q{`&^7{eQfaPtL^Afgi)xOWakT$S$>>@vHwE}0r#-0M5zS`}RC)YFe6Q5t0Gx}S7 zp!~!Uk1VF2_2-e_CH|8+e1~XneC+=lS2DtpJUhwf^?8|Kh$+2Z%u zS~+-&UmbJCE_LL3S7GbSpSoyM;*t^E@0BUOd~l!Nm?mvp_I`cxyWjZ6yWjZom*0CA zAu@on$N>6as~^O3P9ph|$8P1nJoeJ4qj6v_={4ZvtO4E6-OoJ-?sE>jM*f?tUl~kw zUf=s`-b2IKFo}yJd;8MDaclDJr2k`Uy6VHnd}Je?S`X z@=YId3%$Mefqi~${cr!y-+A{he)Biq{rf-ogLnV&kN#+0|N6Io``v%@%fI~KzlQCH zsE>M)1Gd_(%v#RZhb(sKeapJ87!&&|#_JOQ*$A}1rfvUyu1`JgJ?=dRo^KAkR{on4 z7=?HAMK*!TCFlF_W^3+5E}$#t3;>?uU6{AJE2D3@$IPw&D-b^GFv_m^VQ|{w9fh0) zNF4Y1PQaF~kFS6DxBvFLe>uL(@E`v056{dG`>RV1&`*&YYS79dLT9{mQQA3dB3gf8SmrS6uq8pRv(4?cN%@4!gfKs>i&?yyw94 z%z@X=e|kTC5d-VDfauSA|4&c%bWPj)&@(Gv`EhTHeQUg1?v<5q?WwDG=Vtk%yqb@4 z$ubzY6$gLG1@a)fe0%KWSN{KlU-*TK`hIx7<;u&u73?bHD*3Pdz+Mr%i*mK;DF6M2 zwR!KiOm;Dz_B@==*o)WU&$AYEzjnX&9JsGJ@Y?xrzE0c!INw$|$dB<`Y@&zKGwGQ5 z22f>i{44ts{umdxrAr;_H;ih2DU*G`nSrDe2RpMb@Q*+L{LJ~B6_EG0KKtw(zQy=! zVfsUUZ2aD-cyI6FBpan2@BZjle&yXi{OVVyt4#KN{3oNN z+_Y8y2upcf{i{#ce%`v@+xHjOSlRdJz5io2`~UdHzHLtd^P-Qh{_yaqyYk-|_dWhA9|y@H(y4>EYy$3A9iILj z9{>F>esP}p!+2-={?#}G_|L!n?RWpvx4!l6pA4IUJrO#%?{P=0_B3$XuST#lyec)iy39OyaFbKr4v;4Sgr9Kie^84STO45d?U zu}PT!0NCO`#^JxbR{eM7eU%T^XZ3#NKO6VTR`J;!*xl7#-Q0^OKAXV*@jJgW`Tzfp zclrL^@BjY0|7&nwyTfhuaRz{G!*}*_HX_gC;;ior(erVhu1_9t<{)vTUF#@+`zG0k z5LcXA_5ikitK<^xoqPX74%mv*VUPQbcfWPN^&IFqur&wX8vp6Gbss>Rx86^m{2zMj z%6|;Te7yC|+-v-=jKAc^O)@~(x^=csdhy5|I4HjIbKZ{a{9panZ@v4&lf7OWoPEf5 z0+aWii}A|9YZs2Ya?d3<*h?XQIA^GQb*gO>ubyROr}z;5YZp5WnSursF*A zI?(;u{n>Ni{^r12uJS>zbyRJ(!i{>qCyqr8>nwe0xCA@|Vnx8$G52kB$7%2ppA zT~F-MC|f@Mm*Hr-j(30SRgZa(dC!5Tn*(o=|7_Y}6Fqo~P0s(>E7;><_PCuVq%((& zx41QL{;K~w%eTjW_6sZ|f7pYUE_yq*^G`SaaWDT|siXTD_v9x0h%2pg2=*TMYZ_%| zPa^%yo}y20{cTEv|6~-h+O6q3{?n}m-Iv{$JqPY<4!lMF)9djwZ2ElMuWZVDXnSnO z=6RNI>><#vR|ZxdUh>y;@=TrbpMLeZe6Ze_h)2J7U*qtvS1rHB6`r^?&QZVj@YeSu zrNw{wrY&6S1{vVi^+TFz`yY82i(Auo{QFw3dc1qQdk#F^9C(ZTH$T|W!zWzXvH^H! zed^$Yb1M_0H_Jm_IK0NW^@8?hV+wZ>YzU(=0-*e!t@*k_hC;R4G-vM9~aMpcG$CW<3wudm~ zgb^lukBi~so+}SF{nQIXSNj9q+8+Pj`M{d@W9w1#c#L1U&Q(@fMqAkNZ(UFD-(HA) zj!XXwaBIFD|Gw9?9{(Qyo&(qCz+2@%U9z5m$C=ptGcWMpw`Rism8WU%vrhk7P^6N?&ie-pjOCqd$IboHf{r(_zT%TWe)m(M(LcfG(NYa?YO<(^&IFq&~xC!=D=I# zKW2vi?90B5U*`+{vpMgvE*wlATlV@RTu%Pgo*+-*RmV>}dCq6!`H}n|6DRp=lX|)A zg}BH$Tw!~8OBdNlTi7+||ErCq_ILHO$NZ9a{zqExFxF@7|FGY5_h0v4&w-u;N9Mp= z=D+v*>U#j#ggdogoB_nLJ;pR603b+&F{$l z%K5N8eD~a51Dk_$65c%|E7{w32ElXJS{AuQ9knAD`^wRG0LWtcLOH%USjVLOy>|5+ z=sD1H;Q8mkTjsy{;~lpA9{_#T|KrwqMJAYf?#4R+;j{1CVVrmNK4cGIg~_wVx1WE6|MM)y7#nHL zzd9c6fBxTm_i^`e&w-u;=D=I$zc%`&d^m+Yl~L;%z%8y~VA7K(aBq!wxZwaLhM_qD4@>}cZUU@Yydnv1Z zWow;rP9Wb_(6+5O9oFkp&w-u;JqMn54%`F(%^}~?!7AKx?kw|ao&oefKqGwb!ntWj z80o#6?|v`trEvTX_teGr_4e`-mz+U%@jd{S3lkrcBMVfWUfsM)SDE}+Kihykf|Rq> zE_JE@wd8+*ukoMkWzQw`l7Ggc-RJ$ScmH<(_8jOrQ0KtC@Zb6J*t@kq{|Siym%alW z?%AWx{|fom{+3NVara!T!~C$1EU?Fad5BL2aL(S|!~B0dd-UVIhR5pkDf^PEoGN4N zwMX5Z6-Zv*rCi^!sB?|qbNMBW{#fJmeXmhH2YL?l9C-dYa4-Bfm%cFeznwSppE&f; zsf(W80hoI3;QAix@ZNqp9h*)*M`ZzN*yY1M@4j8)zq-hq9!}3sy61MCcf|i| z?GncxLF%I|m-tWbXCJ6G3i3mL_wV_C=e?G8ANL&SIk3)wd*Z*gM_9+6GRGxZ%nd-<36kNw)a*4rHH|NZN= zX48-eucMtE{0d#e=puvxU|X$|HvY23R`j4 zFx+JKPuk~potL;Ko2>GT{fxbD0Mh;Sb-sV7AL{pm?Q!@XK>yyK_xIlY+x^>fpyxp5 zz&-JQe(R_3pPidd>MVfs0Y~`1a`~2fymWRT?8d@d_@Dm;O8Vz?uboZMZtZcU9_$ks zkM)^farLu4PF!+AWPyY!Gx6JfzYn`lx=(rz^c;A~Iq=r`Z*Q5-k1h1)dR`rOaLoGv z^E4@aH=o00n^68W8$kUAfV$y)_Ea)YePh8p zf3aV9ukqKv^rZ*q0JMQUp#KM;*SE}@c6%=L9C+S2@YeW`_qb($f4&bl-eaTZyQ;mp zGBfAWqLX13BU5?5V)B33Q|j+l z7~4zgXaB_a|F+s;oLUBW-rsy3oA!5K_Z+z2Iq(+vZ{OHCG`zlt}Nzvv(Tx#QZ3w}#Dc5A4VQ z`0qQx(#SvWRn#@bHy7oReAx%s1ClP`aidjSt*sM??Hzu)z`$G*q@Dd)gz=fAV~ zI5K%Z7!-y)#>KMF$N$mZA_G)5U-M6Sq3r*w(G-2GNt?X9!3JIAk&rd?x8 zwi#i*ZA2~+52vM*K7GnxZ2(p75nlfX(A*>gWR5ypQFVW1I3wW7yBJ&bSGM;olTW+7 z?)4n#InZ<9Y3IOe7*0B;RvCAV>qnn&@n6_2?-Std*T){m zdUg&k@zgm7^2^M3#APdZ?>d#K-1D>ei>qDsD=>SnKcrV?`p@q(-&W$sc{0fQT)6ii z6Tan68DOOC-~7}5=DR<;KYI@J954r78~^E&bkyuQZ*fBy-iw2Y-eq$(y?%RtFP(5a z^S!_DI(*+_V4h!dlV2@+{-3~L?zOa-&OYI)`{rS!yvYWhbFp36t#wWsTu*+Ny*%4t@ft~|TI|p7H|LcGGtjsv` zew_1XlXm$&-Moe$M~>PH$PK=^gMrx(xP_&O8@KYk)|-BPiLcVhgUz2?(`uKn%KTbR z^>5XqK2JGo*tL84)_VC5fbgG=FMaAvc5@ccZ@9h>kmr|NZI!-%|4;k-@BZxm>^X41 zbKo`ce{yE%gDWR6osLhxue`^9djGtJOyJoyyFtyH43PiNy~e@yd3YPwbN<*}!x0==$o%ZZ4cma4GFpeoq~yJ!}Q(H}7BM9YF8+C)^p0=>Cu4zkG}z z`$Df*_q$&8*!S4?9C*4p@LKqfE7k5Du6XA>%s=yfu>Q>b%KzcV^rSuFIx~Qox3IP{ zzw&mna`3X2tIm52Pd?)KX1+atwsw0HdueKUm;A~5Qk)~tj2L5BevwkZhupbZb-?wGnWB%aF8pcKt zR;~G6x>rV6cf?-5$4-2-r=7C2Ymep1vp*mX{r|DHh^@LjHUD$AQr{-;w2|xkO0oT0 zYw*9m6IkP3^Z)GV3;Fe$b)Rcik9&`M&w;0z123Kb)_HYYneY>X_t-ym{)6l%BjC8R zfopz8?s41MK)l{#_7-bv*m{1CP2*Bt^nLP%bm3~v?}-1g>5k^DZr8p`=-UeQy+C^d z^}mph^nZ})hdk%cq9C*q6x97gv>hW^g``Px7>iwsE0O@Wy|943?P%pOm$N)$A zNnTjL0l3HHYuvr%dFtnV!}#OglFwG$)uyrb8`;3S0QI-Z{_nd2YusD!<=ryChphp1 zT-x7#*>m82=DYBW_TK{wtHL*zX4RI{4Uiu+#P2xyL#1Qu)8N?~nVF{bQ}) z)bn>_f@v>!2Hk&UopNy2b%~wxdHH6Zd@g+lFpRyF=cQ*@uWqR?xvJJt{p) zHjH{4A9>Q>UI1c*YR$1&-=&BftSdC`~K^9`h4>SXKvws z;!5||PXAFCRy>!Bt+55{oejiOOs;jX7hajXa`v(J^Sr?#YuGb?sM**nDkq5rWDNFO@^ zm+rgnCDi<%!=Ly1_U!CaCog)lJ#sPto%oWzeXAUR|7+Wwo8PO~E%|TB7F&Jk|C#IA z|L|W~Tk$_6j0`~TySLwQx3}5VbD-zIt#ja|@gEcF_i?bmxxMf_I{l_Q;^C-o%|-^0 z?kV2+dn}XioIPVb;~)Jy`C_u~+W5Y}9{=~k_1WGt;p=yH^ij&ch4*V*?Yj2fpY~zD z_y6nM^!}f^rTxBdcfCN6&$t122jH&Tp-DdbZ_5y8qz3 z{a^nvhe`P^F#aE5)HSAj$a8GRTi?UYo&fgI!K0gVoq1rZ*kk$1-)r$aS6<~myM(Z7 zY1gvWd*?Ilb6o2eouT zX+JV_w=jW=-&6O;_ej14wYYVk zoh*X0kwaFl@7>oj)Vt<+sn5tfd;FJA($fEpzq+wcTsu>cbeCK*MSmxF`*+{#VfRbV zft~{|h5y#+_1ir3b}YEa{m2CPKm2r3_J3T!I=b&uu;dbFZh1y8oqGaUv>ZFOFp=!pWnjo*!#&rWFz|w*YdB-kALoA9NhEQmT-RScZdJp3rL%d6}bfe zjUgF;tB*WOyjxvqzcS>NtvYnr`|CmXN%u+5f%};QFMhslcZP_cf`ikAH$4aa!Hua&1F2v04{A<<-|H~F8Srx>%jgx(0$W=({ted=D?@sKTfP`I*w1f|54pP z{2%s$mH)W1eoN>QCtk`kyu;i*E^mcz@jvluKV#vgxYBr@z5Xwbvjffz9PJzN?Jqdf zaf$!m9OoZup5EOcqZq^RpX**YIYykLa!Acv{ri7{?r(i-ruCTj9N3=&pOXK+3sZG< z>or^LwEJWFEf@VC{|6`5JSzuYi{E+pyeANbKi19uzqZq%ujMN~d4apyX0G+0`6TUU zLk5`qAA0~>zd!bW&uf0l^-G*#EaDU-LAEVy^Kk*+6=!S2F|KYFi7h@r|hu4t<_S`B5tZ`}{?DY7Gw;%eQ z1hxu!D_g$y+b{9o{!iM-%^6Pa^ba{s-NOC2RUWui24GX^wd`%KWj(Gvu002Cn**PM z|8&Ghf9DVDx30mA@PGZ5KxNEp_S+xPcFeIe9QfG$$BFfQ zznuGeH2Vi5Vml5eZh2qrsW^DA`Oy7iTfqMC-(LHk{XcR+?K9sfn(uuY&s;;U6E@|V zA=6auSAS#x^PuLr`pHf9DSC}KzD9Ikbzk)yc$;(JWAop-Uf1Na?w|GkvF?czm_YaS zjk{V-`+w+J`osL$`c8rUf8Y1t`u4xI1pmnfbzImoCjZA+p80P+jC*#0==zoW)gRgK znw`V^==JPvu4g^2J+3_mj?aOQ$^R|g-+t_SI^PG#0Nx*;``g2OZm%Ag{GPegFO#b)R&f z^c;BGbKqn0f7Qu-=l6ro{I7DtSl8znz>^I?+bUn$|FklIeff3YzuN!(U%(dottngl z_lXHF2{ZB!k0eIVMS~IK1x97mIIqjJU*smIod$4>-et@9VyQiSb^-4I)H&fCVfeo%0~lZ9 z8s0|^s4n{tIdE@$m8ovMMjTrsx}UnAdJeqJIq)&~?;P0r4Ss7qd+q}}FNS}}HTX}S z2n)yn&W%0hJ9c~Q=|{Q={L{oVz9PX=HUAmg3J zcuxipP6oL2exrHOYuejf(|TNcTzd{2n*$$%|JL!9o7VBE`&-jLg!vn3tBrV`1sHbf zs%Nfs>HFL40Jv&zKdj$!?f>7(e|GusUm516c`~nz^SJkHz7u$|@tozo!Tqy;JTnjW z#+H21Ys9fNqWh`)spr7koCD9zfA-<^TR+~-d(wUXuz@@HknaFtL3BYn;~on-{5JmQ zn?qaNPZ<6?8))6wdk292U(f3M&!frz!RE>T@eYUaoOXcI7<(Q&0og7#fVdfRuIDxX zI?nRw?*P2bHLY3IHFK*@4L-=Xa2(e>Ei#8{VwtU?|$J656)+h3-R5Yv}a?Um=|>Q*Z@4obaBG}%KplK z`#*bQt}Ndt>UHASI??^q{nT^d?ahJb-du~e;=gr&ecvzZFz!Dq|A(G0|9mqpeBibWaGmoRr`4tRUpn*m z;9Y>hfA`n;Po_vY&H~z}q4x``=Kv%ghzayY?;iA-z~iz2mQTC?;CgiY2fROh z_czbJc#!{<&Bnvojf7p|zqpa_!u-g2x#!~l-q{cPME5H9ce`8X?K#kM;JNsZv0;97 ze{|@0&#L>^y?`MDSmP%Lc4UAp8Ku^@{Xg^$%Mb1OuQI^6cLwB={r|_8^C9+z@~&vk z`9=57Il$NqoJGL*b$nO;yWbjT_9_2C-0NVkgFOd&4&37$crO0a!ME5s&;D0NKevC# z0Qn|h^uxI9$8<<~=2l(rJ&cXr8NSD|pDp0?Yy3ai`nUQT=gp&)|FI8{?Tq0A-WNG9 zase5^d4aVIMJYzE;7p(lR zvOxUeZ0!MPYrg}~Yhl*Hc6%<|+Z=c<{_pA3p9SKz#Mok{_pAk^z2W;e=@+j4^SBqS-{zZl|%P%&!+Co=EXC8kI?_|-+%qA>&^WC z-{t@R)_$JnM8>$S{LgzOY)O&b@O>T6+)w#n$N*b1>6b>E*1Gk5uZ=widJf#f9QfG$ ze@^|Mj_;a#3xgXE_83n0^UTj?(*O7 zYh`}!ofFMC?(skG0Fdj98ChV@4&Xd$qEM_v8wFnH!j9F>5Qd#*q*(BjAwP{8GzBwq>C&4`kUzcUMG7F z^c=W{Iq+Qk-#Tw?&9!Iy)cnVH49K}~?-<}jr;Kd%l~ptgYHi*sAmD@7%pc5j3?Hw-+WNUJ^aqQ zjm@*313d@UIq)3(SH|9Xdh7ag@!wi*PdH5B7dH0<1|!aL!0?j|>bbGiZXDU5=9hfm zifinhe>=qTN9_Hx|NHOfb^qW00e@@opX{;Mm+EG`Hue9)fAPqD>;=*P*Redy149N_ z&!tG${{z(P;<_&Oeb0$|m;=wje|xQ4-&?WPKNtUF1HgLvf4HI^d4@Mr2H=h>-;b$s zK(z&s0lYW3>WsnzqjX^t!mNi+$g7;vVL}Q}F)}e*M?q{ru4N_H6!jy``sN@tMO|{KS|1 zS3S@9FgE|Q4M3SEd111?=!s!J7cchCj@5R(7QepnAAV2uet-1;%{_!MC%!uN7b^ex z?ftJZTJ68{*}tKyuQGr!tNMS^vGde%<6p1H0@Xewy|XI!@LTUTHq&|z^c<*j;6wQT zUyU{Q&wu~-zx(>o=VFJ=dc5aar>*@@&HOb#tY6RXh4-rrAns(xi5bx$$qef1o(v$~ z-oD0OdtXwxK4PPJYW9->w)oHfzw)2$-~7AOFZw;4-{QY#Tj?*^av}>DOZnII#*{sx z{w~_z>txS?o&#@v4m_6sfB8@U>32W)UElTYyT9W*-u=v2|Lb~s&2LSARvF-wKVH}K zUfwBp_V7X3BQBoM^K%XW>&Xtzl~tzL3vmBe${E9JZT-~G@ec1@^!_bQM~8oE7ys=u zRQ=yK|CDp7U-sB<-gvghf9E-jU0A>6>W{5G0O4=_x8Ch*p7k8)IZ)@ot^EIyabD`r zec$)J`<}sl?0*dZpYsgh*$yx`f%AA@Z4;RO-u}ahDbD)E)}MWfl_&1W0Qrx)OC0;u z&v1@ji@|&E_&v8gu%4}B`(N!cwV(96Fs<6{m(i-&j3F28GtDV46e_!0E@jB zL#7P?_eXteTx_@hj8RyUJ>$v|;beuCA!*-BaJA95cb;0Om)|WiL*+l)|1XdK+r893 zFE9rh9%Jv;IZfCqN^aQYE0E>wLzy8W5`r##gO_sKEU?qAs-e>j6z zVaQ8zWAlFw{;zrN$^*mx&+cHZ`33;pUmsuUr%QYPxPM9imv_b`;}o~bapIU;wI1fA z{gM1G+U+&6=RnVaw>}4s@W0yn!~D44|HuFMyKjv1e|U-i_S}DV@PE~>>RQXM+-ov` zHTo%J0Q_IyP4HiLvwTcRIVZi+v)G9%H>w|3#KDsKJ=(RMpWovB^vRU-v0e5HHupj-hz+0aKkKzBH9%lgl;t%}5JMRGC z|2KzSH|(eXv;TAJxx2c~#&0d(vH?_Hv)gaQ*^(PBh2cBBK4o)r7SOYtS63Lmu#d#c%yL-|cIz^&IFqU=G~M|35e0_s9Hty~lrh07HMS@7`sNuCDbSd$+hP z+&;bd*7X^0to>VYkA}%(OXm}=oOymR^%-ShSCs*xSH@kLBK%XH2f(x=cK_#+4{(3l z9)_;J%35{Y_x$GK5&oMGTX~QR^g$h$J-@vhGU|hT#{NT}0qAwH+1PX7Ugp42{{P^2 ze&@TtFm(RP{rK_UT3Rps-_z5w=CTh&*RBi~=DzOPZ^f%=j`(N3gX`5UK^_RR^~IDk zPUTPg#E=ItWM#hltuXS!Dr2O*&*{>Sui5>dL+>X`DA#v>+4$3!k7=v^HjdHtw_ML- zt69r1UvNF+5_d}m5YJfExgbB`_ww8Cb~fjF4&3(~IKuxQ{+{o7_m{@If8qV~=YF`( z|5f($J6~lzU)SjM{;b=Fxx)?rD@XYsu(`xP!v4gO_iFc5r``NV8|-aVu59rnVc|-x z``YHGzIT=(_V&jz9>=fQ1rkSDm`_*c(z&nMdXBVtj?w7vE$$~woIM$XT%azOxPKle z^4o~Jj+5U*uZj1)CieLE_}|MMIKqG2&tCrnIlw-^9{-1KCGTtN{(KiOHuu8x$?1{4 z>Syx%P#HkJ@>m%{Rw1`U2aUXtd-BYl3{ZK)|FLBNdhAo_{$YIf@T1#feR%JgHtNed zKG(+j(sSQtlwUZ%=Ngxl*~!Lbnh|AG(bm>)|9pm%?H=;OEQ{WxD4AI|%K0JePh;^3vRF;6f${q@wY zc1-?{aw_}DUk~obIOJT&S_g9@{8#TP161zEZ;ZBN)X&Cy5cj$sbi12{JqPY*4jkft zZ2il*zg_+hUD;ZER5#qT0i2kNJ@vd7d0_ zTlF*7GA?2NCH}`wQ{~Il*WBne@P5|79_t?Kdz}L}^M92EHthdL_x`iqa;?MG-Pqfs zdt))?*6#@k+lresM_qZWXUVqCBb@Uad{jT>pKSp{&kS#(S5_BWUGk{yeM&!e+mny( z&c*r3_>(S=^ZHR-?Z)||^4U|?buTZBuev_JIln%4nfT??9!Qkb* zPQ1mg=zTLT89meYpkVy-^XU)rPY z_FvQw-=3??^w)>Fsr#zulg-#on^YWer(H$RL)<-dDuUiJUI?+S>&?)_K$fAwcv z#Fzh8f3xr0>zdH*ZXWg=xQ{t-6aP2Z&ld22|6|=;*J!q8Ywi&nxH#7Gsry$KtB2jX zzPoqn`$6xeuX$Df$d??k+9&9oo3hA~R=lG!fIf&FfX=(coqG(U=Nqq;|Kvq7K=gm^ zI!@^?W5AvtwjXiDuQF+s1=xg~tLSy`KGwk==N{*KoCAmXkNw&Ek9(2_>i2)x{_8qw zeYU4gpW50N$od^u+DqKU>Uw5N{m*uQ!H2`#FB~Ut$fMRfHt9=snPn;SBm=BAXAD~P zPWQ0`v<&b=QwB1Ill>=Gf4cM!TMWPF+&cD|GhAo?YJYEyMU@HiJhqt3BjqGt<9m;5 zLbthD*mK}M=D=b87kmGC|9{~>9SkqCe#W(qdPWAo+Jx`9>a=MC7-{8&)!Db5oE~fT zrTCN6r?i{?k>37-tJcZ;ZkUt3ht0I|9dTURR~fYWD}TrU_UPBM2etfr@JG(7y1#zL zd2BWp^evl`aPq*~FLZc)InVzO`6~ThWv}?deY(H+@>0%}^F}%5QI!L~)b9ee4AkF3 z=sEC4=fGk9pICpk0pxzT(f{f9>$`5&_sRajY}~d^D|21L>%BDA;XS4cmzRCxq?6}W zU45jx#Bk}?x;>CDaDFcj&&H)*;ZJxU_T)Zp&a3a~v}xO0cIWxN(WjOFmBEp%Jg?!k zPsoDiUgdxKc*~tKz~Fym)hdIeyyUNb{XL-j(1lv(?Qy=hIdBvItKC2T;pYE;=)b<7 zmbH^>Z5ED;F0ud_pt8HhkN?_xcvD|5wgx(!wfm~BzQ^xVI3~olkh-YrA=%<2185`e z>~TL#3Wvx6>zRp^{np)S-!J?(hB$9L=a?Fo5r+R{uPuAY++VuT=Ud}Y`@Hf$az=eG zRDJx1@x84L-QMP5&w;l+2OiD;qW?SpNB^=;ue_3f<^PlcM%?ILYy8|>ld;^|yQy=J zvgA>9=g0uNY4-9e;nFHs`Kb%{qC8U4>jM`VVDkNBj}G&z8!mD2XsiEf9p0kfc~0$) z{y+UE`w&^u*w<(4xabpU%mp_6^l9zq)t~;(_bFHY%g;P8pXBfPSH`!JdM$k0YhjOX zkMF(Bft&bWm|xET(EsW5Sx+mctjjC^$pGS4cGooVtDE%J<4qZ0tkIs={o3e^QwF$@ zZZALK@~rO}q&{@?S)UQ-Qu@ddh z9Oon#)c(Nc*n;$*{#<2%+@IZ3ynN4i<-hWjyZ-;=y{!%1-sWM?fww&eo{Ill+_J7> zpv&`mCA_|WRo8WX`XAm-mhUjvGgnQU|B^Yg`bIfGe$rOCLjJg%@-Fhf)RkRivVFr2 zu!iSe-`s-?Fl9Akv+zGQel{2V93F4Ui}q$RUg3Xasy&yj#kge7Z1I2AsmL4Z>OT>B zJ$&2iVUKT*?>)_doA{qS|HTgQ`DdTK$6#x#wVCd}#ecGZXV%%Q!&~kVyF2|)JJ$5V zlyjCLZjb{o1$)*!vFW@oaV@{`Ts~|al}+LN7N6#`!KZtW0my#g`&s`l^I_UiM*p$9 z=*Oy$XI$ntAjUIusrKcJp6@sD zANQ*aaPs4SY_?fbxz-rJ>UHmVcK_9nao0F! z-Mz+J3?KvSy;q=qGtP*2lMJx251^gShil6bIU?n0C$5J{Vf`utL{Al$o%*fH0A#DP z{(sW(Gk)vdzdl^&m;2aus_viu-R#%Vr+M!``H?HkjmRN!mARe+F&B;dy{r%2&SqiH zfwwyc9>xD+|NqOw|J9%Sx%bv)ytOvddspVK_ZVmW&3e4$;=wiE%EMJ{wl%M5yB~F$ zc7PG@2)mPK%_n|*(8eSAoMixZ>ctMQ#i@j4ulmwCiPYz{x#^QLZ_6CW_kPaq2LH`5 zbHW%^{-^J%n?4uM_}9KNFXWMW#7+HH+1C9R#`l|gU3|OiVvlW)?LEwa!~9=#{(1g? zgyH{Z<2&hfJ!LbUd;eo?rt_}6-@0cfunJG*KGe)4j?Ds;?_E!yvY>OSd%YZc!2Xsx4NE*6aHMvE6l_v&yb~vxW z7;*ItW?>TMhgb2hZe)Nx+s4|)mwr!{(GTG)fBJW|$9q=y;nOzrj4nUrslxflP_<9f zpZYv|49SPG~9^3ykwukv&*7zXib(U_ZI$RC>g-Dwbm#9^E>z_oiTi_E?(dQStRLJ7i$i4`^0QA!&aVT zmcx0CdSQw>t};Nl6*sa$?#TekS=;g&@Abbvz}cyLm+>My8qcj~wXJiU$C$8nDS z`g7g;Pkxv9ubi!Mm)3anTGE{8InZ<9HO_%Y^Z#V~|FhrseP{mDP4U}$>EgFO-g439 zoEgZvyt>Y6W4rvrjmrM%A56h&&)4+zo?TbnF6O12Q(5xVUp0^T$pEv=#J}cN8Q`S< zUt(9D<^O|I?rU}DcmGBoZSC*ZZvq-aa==zQjh#7`zTrk@iu)jJ$WQCufAS@-M&^j_ zAJ_c2B$Ki!yvE;t*SVS1bKt(`z@zxj7I5PK4}RBoo%vsN{>QLCasnMq`mD{XOLsiN zT5;5AO<(WB?I{BsV75H>_9$>m8{U&g_VPW+09)?{R;E=yu0;me(@AUlUaEh}ZYQ?u z`})28aF?quxB6S#^;>lR@P5yoa=_s9);B8k(fTgpxei0#Q^se1^{?*EBXaN0kLSIX z-uGJC~cu4_V&0u_>GE)l>MmrVKFn6n<6aul~pY_77g;c>r~;y0$(|f8u&{etlV= z)v+T3uKjZ9o{nx#)jX=7El62s?vJwBCfqyc_syUBsogz*na^m`mwx=mTL$Q}06hnK z4!oKf6n`TDEngrhzzjxO&{wmhFGs%QYp-zI3sRN_u#&kaf&z31MJwax7g-9fPSiFzXrdt&@cLF z_Q`M~$B+Z^Y(5|Hs+}W#SMgl+#mg^T=N+F zzlQ&V>t7pofLfO=zd7`IzZ1|hQ0u@w2VTJ(xQYLH2Vm&`|HTjf;JY9Gp6{9b_x@kC z`&&2b^&zqVnZmlhwblwd#O$%2lM}?<%O~OZ9Q}Te{b9H~!=t2+iz%MJXHOXUC;fZ* zk7weqc7V#Y)sJ&HSQ(l+yi}Lm6vlJw**asSf3TRl%2;8z`4#eX8~79{1NY2X5xSJ%AJc z|ICU1UmSa*Rrjy#-}2vL2asOgxLDWN_}N@>_C1!4_-mMW*8HU1a%X-c?R(tb$Zy6O z+}O%T*!*vrgLOOCb>t`CTkHTh=vrC1SFcYUzA`>GeeUdsuz2)C9WUPuaF#m+V1am^%N^{js0!&lcc60F#fr?fK_EE_)T(;We!TUDxJT z&w=}!12^#>`%g9i-~Ic6Kk+A~{{OY{{oimtx_<8CuHiS!0K+cMHk>uKx<@%{t#@I3 zO~3jvCvneQ9_hCHxN?cRIahGjGk5ZNkoVw^@}~?i*j4q}J%3oZ*GFp`Kh-@phOyk* zcWf!z9Xq@}@xEv3Dz32>FYVpykAz46moE8m*&JNPTAz_C+e?!~Vzt!XjglDeMWj)Tfp~Mo_0- zXPPZN2YL>?)H!gN|7Gu=?*He%|NAHVzi+(%=l}n+AY8L`H$v@Ogo8K%Nc7hL*0g4^q67z5f@2=T6_UiiF;q>e& z2aWz;#{lmq|A(uu>X`<6_vQfpbHo2#?w@2P@g6G=kxjll?EBv&1Dy5&>;VYVPx=`9 zg>lW5+JAZeQh)nhujW$Ef%~2VH}ik6AOHXC_kQo>zde9G{#Vvlf4DC!{xOb(_t=Fs-KH4$fdhGbG7P@ zVMxy1KVay}?h}9HRnML$kLr>U)aPP;BOi4YZ|{8odCH5Nb1kp;o>v*5aBr9Ybl)KZ zD66*RQ~SwNvu&sL)IFFyGp;WES@#BFGth_8`L)0HLBiwe1L^kKjo-$ro-x>qt6Z#S z3$Q2f<#E1GT;B!6eb2bg{Z)BGyM({g-+$Mu+0=93e&@hV{6C!mp#T5S;J&?oc7R*? zU-f$Yw?^YT+pzVxa$#>hz7&4zS%6h%t9h%-A)WoiEPSi!SO45o7;)ZX{I#%=KluXN zE-~-SzLN|<##!s|sqX3S`qE|I)q0S_gk!(?z#opr_AiZRYx~#x^b!7V$z#IgmHejv zwAUkze%_iB<^tQ3Gk-31R^RZS48Ts1{eiTP9M)^>{jRY+_C5A5bq-kj=vkMpdFFpP z|3~k~|3CBH-~I0M&pw;F=Cs|9wXV9>zTER;KbMWy`KhgSHtXhxxYls&!;4F-opDCI zOEL%D505V8GoOvJlw0?$*EV39GG~5Q>h_>KamS@EF)Ex7>*{^{xR`g}F12s1<8$3l zwx8O*ayflm&j6$zp6OTVXZuIH_Szj;K)c0F9;>S_8t6m1}z)wT@5iH|A-NIk)CNWrNW^t~S=XW(?15KecbG zz1p2N8@IKbde0UkPygMM_x&cz?d1VXiwvM|@{AmnzULlkH{IWSOdj%g{xbJ*h1;*k zdCbl`esReHu?gTg&aXBFXHmqNx_@i{MFudoDUV$864!vPQ?se(zx`Jj~64H^QKef47jxR3?9oZ`AmN7@igHl9&hQU z>WN9=*HvDRxMUqy+PJ#(Vfh`ZTk071R98IN(}A}*$!36!`ed!obKldo({HQ&C+7mD z?SHgQ+|);!+3zFVoVwKB$Uxc{8KU;{Dt9OYzkRR&fert}adJQ|e8+!sfc<^rW`CgS z{%5)2lzz$%BMmu2S=|1Ap!-~Bo3B0YFL4eW;{UMs=evK{AO6?>|Fh1@%X*F3)@tjv zwLI%z*7U4})??3ca>@&X^N}IAWCyZD&I?xiYt8GDpKPHXVMrLX=UUgdWDRwl`ufOg zFYSYHGQh~|(pdogGUbF3??KvYWsJP>P5)ey0k&9424D-&mi2r1m-_KTpUw7-I&aBW zQ#KgSrv5+L9$j7is(fTlWZz?}-7{>oPn_6{Uo~!J#PF7>%)06fXlP>A_I7~m1iw`%db9_BiC4~?3GjG2&@iEuH}*E%H5KG zQcs*Z%O}^kU!M{LdJZ!{)ecw6)4M z5B!7u#!ubklktje!Tr{FNQ3XwmcO+ZFj&6o_v?MQzq+v*q`%lFdab>`wYJB+$NZ(u zfy4Z#_b+w;{AUAT|IgZX$+gah`CF_H`{TYR0}TDo`hBU4y=U4PmW0iFt}>Lp+Q}ok z?4{cZ$LQFi_v(g6%5-hzu^TqHsIR8pJD9%5`-E3c3Zo~x^v&Mh%wC;u31Y-f4yJX zpL=@@=DxCwH`~EWTMN2A&8MCN_caF&^S`p6|FjQ42Ka^XE>zagEf-rb(E1m)b1z*h z`*Sak%80Gx-+=lzxgZA{y>rJlK;V|~iI z$^fzBY_-Wa%{~2%Gksxsb;JL-_1Wsj{It)U=>G`5ueG+>+T;Dw=D?%*9~oe{-v76z zu69*>tJXUl%{jnuoO_M`kriqh{>RDy*#|fz1Dv=Un?YDHWts6TY&j$YjQGjtlAisj zy@0_tc~?F72={9o{A82H&+MD0y&vk5yY!VScKzgOe$4(mF`7TRd(w~%v`-zw`C9k* z=krnjq$kVBqjEof-|(@2zka7D_0kvhTpx~y?{QbQAGy!oLgv6{qaH79J?Q#0qk0b9 z&m8z5{-0!k`ToEC`Eglu=bAlS{GNOJ!(Dlw`?%L+0rBcZ2Do&#E^GPfl1FaR-$y&b z?&L+zi4J*`|KS)n`E0p2+W|&?^3?bE9UjKL#LUErEB&?lZPocw7!K>Jt+8ScsEk%N z`D3OT%y)lo+rs~~UFvR}QWtu>v|)Z+@xpfcxbOESOc*cq)!lqH z_7%tgdG|v5UfP<_^=VG^9Jr4;aESlw**|)Jx$^zL%IDR;$M;L&^2qZwzdXa!)vjFE z@-6?P^!Kq&9M$J* zeI9eK4QrnzAFS5Cu$f<kSodTmeM^St5ck2C+rnDNi|{KotE7#%j_{4b1i z|4GYLxB4z%WqS1|j~Z6(IoEZh1^bFYzwrIk|pN29UQhuF3#|Z{j$| zx5xLDqxHU~!6tbf>BmcP=3dLFJEpJk%sYJ)M)R|&=-cy{j5^GHjbW2WT~p8Ms&CFN zu4f7&U+9sP%${^Hfqy)c@1DIp%*4{_4_o7UhN+QrF7@HwvrD=^xkCl0V>Dkv)(7~ zxb=DUvoAP@n0lK-y%yj1THNE`ZW{7e4F<1!JBYk&&4%u4jUhEztjy!#S0%R)8jwl;;MMpBIN7|ulECPS1h+oCAmXkNM&LA`j&JpLMhHd%gE; zE3Ags=kdo~^A^5dbVl*$qFGaqxcWg}_;HxsCw57fvs}tL=XK)I(fp|uQrUU+5onAzlLowcCvTyDQE0AWq`qSb|{fw=mkhw9=f<{++_q zXRl7FPx?su2Xe(2Pjg{?-!I$^mvO%GSAOQt5&kESnrHlRtDI27l9p`ZEI`gk>R<9m zugCYf9{0HSxPQz!a1;N-eQsod;fDX=GY;^_P555eUU<@T<4;}*+j4OaQ^JNLu60)$ z{Muxy@U080M!0&^y>2WM7M*l6?M8m;AkF$M#kCE2Pfi&#?@^BjWtT0s5`VL2JARj2?U@186V3Upnd2U$On~)dl~nE#8;Ki~a3*#MrB|681o46x;Hu|HvC0J>#3 zQC+;)(pAGD&yTSB9A|I~M^>35I`1x{x5_!?g|l0AtnJ{(3i+SqjO01;QNOtlFqjsW zUgH1OGhqqmk^$tq*5lHBm4o!H%iJR`W$%9W`KYtFwai*?wt839{ij?t(pBC6OM|bt z8t#U}+!}_z($%_a-%b1<)9XH|CmG_s&S%2f^Y@&NMfb|@Lc7M#Zpv!9Z^c=Xa zIq)d{FZ%$i{Xd+xj>pek@9VRp{xuKxdzU=P02o}?cf1kqdDXcRCpM!>r-t!o|2^mL zYF$>py8EV%ad2r*O^4rMzkZ%|Eiy-~hjOdz5&5d>{?cQ=y?-1Ii{q{=UgyUbcg_sf zbZ7qs_CF}E#FG~9{r1Q)IitW9QRP*0=qp1$=r#Gi*5n@V9`BDe2X5kj<$m!WegAKZ z-Ie?6^E_L_>plOa%liPUerLU>6MN>Wx@6deCsUu_&WJ{;6Y+e18`CHGh*rjf3TWh^8`DcAkb`ySmH+B5M z|CE_}aIrnIkbUwg?~HWO{nZ6`C;x|g=Jd(`fXO3_?w#)kq@Laf+)IDX?<8NiU-LZ2 zIh85D*du0qI{#pOzB^1FazAYj<5}v#CD(oa(?8uZKz|>%=RnVaC!Yg1^Z#V?ulE0{ z|69NDDsC9Qy4Rks@h{!WYwJpym77@TnKby%zuEz$!IJO=n;tNAJlnm;+wolfD_i7? zRflB&<%mD(tUl_w*0u6N{^E;!uHU#9rk$8t<$(CZ*f4j`O}y%o0We#8kN$TMdw}}j zdB#E;*S(5b4`qmCc)Vm@2+bvk;|Y`JUxxhF^1 z>o?xgxz95;fY?Fip2N5oR@3H z*(rJ#!jED^sue zM|^Bj4*jmyfj@TZ2b{i?=P5t+!AXqRlLKy*0U{Gr*4D7f`Wl}2p1UFk=uh=y6Ce-h zb9$_P(1-dzaii-ekCc_X>vFy$$)#bXRzv z^wnL<^GyEqd~MHpKjGq%J#asBLzr`bYy}CM?vP1@^&0vz*U%o99+%fT2M+On<$kpR z6#j?BE1T>68poQwK0g{~D_*!h^BkO68Hu;#g2am(nc%^?J2)NA9Og78EmzguYyS8s z?&R2#X3Zn_>fw^7YfH9JhIS`z(oT2qQk$_f%nf6?D}UGf8aMtLCwWe;pX>r#{-lkY zJmMytD~!BQ_vzE7s{2>IhOw2;5Bw*-<8x$+jLoI*1wP1Q@OrPDvn(+3SB7yi@96h6 zk6OOpBL0&Ls!XC@=3##uusQQuIn(uinREA1{IBxBkOiv!KP(SdS4QXg5x3@XOML0@ zoNkykeKK+IHu)s)>Tacxj;$JN!<@&sli7pYvG>+`VMAnuTl0<%yp?b40PofPWJ|!K z@U?Q6zuvDbuJ>F1nl}ELXTrA9ZiQjLaZ8_Jq5iDwH+EQ>Gk<$ruI!z0hi;zp1j*n3 z0i5mq@;q_=9OnL1)>=-u&y9cD^hckwfna;h$1`J?vh81Z@2|=_d1f4Y9etVWXpc*e z%WIqihxuQ1{_0=!|L~QIty}kNc#ZQ^em3ZJ?;S6q=U47mKPHNoH8-wv*=LT9=eKfN z{Kx>_F-*R3!!%`xM|L?{M)D;`$R~Nm#gg~(J>@U_EC!nbAZN6`QATR zZ4#c5Q~KM0&6(H8nXdE8oVSPgAKu4}{(rh(-~T_t@W=phrK$d{Jhq;1g<*WvsjQvs z;mK2)y=%r9=~vruHZmkIQSC1BdvJ_hEnB5|;CS;p?6o z=I%XT!^KZn^LJulF_X>aTIvyw>~VjoVxHbzH-e#JlFo zUtU{#0a?c}7EhB`*hICEo8nv+u9%sk=U!^&54Z{2%?Me)zhldsoh`{w@BSJBRqc z$_M0u5?1wl`v`P=@|U*cd_n3Q`Cw}fr0vxekKEF0>dRbHdt7>4UdtSKD*j`|)`g7; zul|I^&9k@(ukMj&l^1o*bQS>r$N(q4V=2~F znLu1&X&;`gXTIf49~Do1C#O$*J~Mkf+w_lkv&>NkF1@+(MSsltZOInOIF%!g^8pw= z?E%BBI(qeo<1?=K7p|Ia%OBgrI)>U3_G@?c)5G2{)%^no7d9s@&XX}}8Ga8p^M7G~ z@~?Hk|HzWstBhJ#XZy)zwJw+Zy${fgc`c0TdcNGb`e^>!2RQ8oRQrGBYSfzx6bj4YY$u- z$q-@lCigvGt|@nnytQB5Q%Cg>H*Je&IX|JtV=#@Kz$OI>^?sJ8c--(2tS z0=?X|wYk@0^U~+QVg481pTGTgf&VL~S6+KAEZ0{2nr8La`{Xsx{BP{1*L4)zj-CT} zP`ANn>0HXgYI)%hJN;v20(HY-c_@z@U`#N-)|-Fo?4!(-edhECyXY^vytMN7-+{@0 zzTY_VP(J3qm)A)SkXGCE0Xb^Q0O9(H^%$2vO8;>)zHy}&_beCu|LnbK@HNME-UnrI ztXNAVTdONYk(2-uAVJ^-2#^3tkQBIz1PKx=Ne~McfB;vKlt>UHxLUHLiY!G^B3Y8P z*ilNGCE1K+mt>hvq)H+=`4Fcnl@IxrDpxs?9lMfLHck51?>xijo`3gD&;8#GeEUP! z>E-n4(>;C9b9$M%DK7jck9E0!OOU;htXtBBF-I5n&2>j#`0tpy6ffaFdda6)s(+?@ zW*;D)@w0Cc+aawp0zI20%2=Pejp_Pz9PD%8H0Qw9_;2?BeEl!`E}Jh5U=NuxY`Dru zPvs*<)Y7qz+S#C~4ehbc*-fwmoK;(EXl^gn6$XMA1p0?u`iBmz*THl!oAn-N1Yp?Q zzJdGz+CUa{Vn4t{*1_m3JUoNfB@8Do)zkR1&P6}z17$r~m7D5ne*hWi2d~CKSPo@8 z&h2MG@tvYHoWiXN*%Bt8LX8fexAYO!k)kLP(SYf^FBb98?ij5 zOR^)6rRA%rPxQI82Y^o{o)*e;>+b}frfuz**PqL&&w(cVAJ_TX@Aq&2`uBewi@^rc znSz%oV8g*h@rg%i@sqDI#g%s67>7sg%-K$GIM+=&x%_S8lO9PParpt@l?U?k{(Z`4 z9Jp)d`|;8l{lH3OmCiHR8(=K6Jn%KiYYrm@3xClEA4P5Bt5BA48@cei{IR}poHBSd z_QG;-m32I6`C7DvZ0gcK`2*CaulNnx5Ad}=x``M3NA`KKA3vak|NJlS*7zTN0>l5@ zp4|bYKM#y&0MnU8;>St*2&hZ9O{8O zwKC^hifdh4v!URe)~MU!eyk^*$j>-0oEz7y;GX;e$`!zZlD^Q7UPI(SA;lJ(m=RE-J2aNgJ|HrNi1EJV*@BmxK8U-6A%oSg(qx|zw+5jt->?SGiv1SWijQ)|oswTGgHL6ms_XT@9kpGvm)QF(W7JjkcR{6-^aa01~ zMm*sf<*a|fx{|(Nf2~aC0mx9;#s{DdeMb-41EVtbCY`sDM<3?zqv&jaVw zHuZKLBpV98X`Q=)|M&z6--MNUFCgKb>)8@#p9P%W+6Nf*qdw!n+>qZv-fACUlt;gE zNNM`Ux*y!n=L3o6J%L2YkLUh;4_Wv>o%@&YmAq2^%(@+{L{F<*PU2BwQ*53&{9sAm`u0M-Yo&&qWfAB(BhmF_T8#^ZK zcOLON^>U9pkH^IWjd9ZW04;Wudw5_EvL$QRRC*&f<0zP43E&;R0(f4t^R;}|%lKQ! z*c!7_-Rz5udgOIHdFKuC0}`cwjEVLGz;?za_DjA4I+Wg-n=pS4hYMw#^Mn74k=n!u z%Xji4|5CaE`?C*#oD{US$M4DQh5F>J{T6`w0PWuf?3i=PnA3GTo%z{}|KZHv-vQA1 zKNyNVm3;%h*oPOcItIo(m5B;}mEM-pzTaT8Up@dd<=vF* z%)PhWHrXI-j_%Tx@Y``-@kmuq`AVOgCLaJSiFPuk*>`4bMSJLQh~RB$KRo&Y8Lz?Y z6yjNV>_aWhx|(NBpTO5i=8=2=`buzpS-YZ_`~v)zGq?=aM!b#b3MR9*X8o_TDz&XU zfyMQENjCChSl|Qy{oKL-!zju^$2d09RrIkt?ie1s^UjU&QyKl^9fNLfPsiT&XVIU< zDb0Z<{CDgpKBjL@*ni!#o;BPyu4k~*!p$YD7N$l%@`Z&?V?5TIOHXZ$`})!D%U(KV zT+|oUKLk}j^BO&2VDfu7d{>z{Cvebp^Dv$LNKkeXm(Qn3mqs>%Kn){BN4e%`> zzKt+9M*L?HdjOw)*SqpQK;&hf-`&3r+y$VFUxl@Ew3VeaICY5k0?|7L=?evi8Ryzw0A*l! zsSj)Nzzci{FcJU9_Xp5n@(0)xP)Kdl{+fVKgZw$&_&?kU|JP!zWA9iOY%T4Rql^BJ zXYv`SKi4K@bLHN?;)x&pXAISE*7?X`&!4vGFaJXf5BkDC=d0pFd@8N|KlRRcW_`O_l zVWiTcrF^yHRB?1(!XIojwijEB&!9FAO}&pBdjYl|0QL$~=kP+f(@L{Hkj~^^k-pEv zK122gQd=5>$sb60*&l#5guHJtp7Gao$$Q{>??2764Qv*sLg&h?oIU>1dYWf@2LI<| zQZ`p^ZDyT~7d&?z!20Z$jQ!F51omS14&Z}n55WC}(pY`y-g`6lKbiIb9)IA0$+vJ` z=KHDGovug6z&;0#KL?udf5d+7{ayL=r*B|C>;L<1zkPaVUN{96&U&85yAg z)Fv3Ekab(|0i=Ja4f0smPG|ClpG6;_u^jBxy+Uud_$}U&Oy!A=n7ycz@w2}7{{dhQ zZtQU+Uefrc+UW?)GQUpTQ~2ffoE{&mZi+ z>KV^CgZ<<^nBG4UE;$v(DsL`bDvNoNQ=)5lRbO?mzb)SgW)GFRzSn__LkH;(1#ekv zPiF$-egN1?Xz5qPiM46&&M`Ll17IuufZ7+G_5*ZYkSMy(`Ci~3c)hsJp2J`(V~vfh z(%wk(w|@-BieTdpwU*usdCcj(>d)9Dfe9;6La6CG2PIf8Dd6J@Ea1VW6-{*s3(Nl;`E*5ud2@ zl=4*WWgb^~iNXh-6H52cWurwoU(d3Sybs|0BaU4MNAg|(K7iKc31f+uFi(BjHI+ZW z9XHMkqzn4xfUYT^^W5Eb&i*G{jJUcIhxI<4@4I`yS&wJ`Ahx6QTzizwl}m;I95H244beWDj>?gYBdF|IQJ-UIk-x(`Ub$V0k+6X5uEw_{&_2B$CwTJS%f z_k;Tce1aFI_W?@yFRT?#i7LN^st#0fuctgwFC$*cujPUN?CsCtk!&ezUCDtSGkBlT zWAXz=UjV$-eF65<)rUh;`~iF`y zu0zMcJ_n9B2U_r7cpoWif6fN-|NkWHsbOx!s1l#>w8ZOqins8WcvK(i@E^(&qU;1>|UlZYFqmq2rfiKci4@b=x(aLO%Gb{{dk9 z^S6f+zI%J<#Pfm={i%bWT6;n+S^8kDR;&bcBxjrANjCl#(HSeoO>{fcD5pTU8j8ASWV6`Dd@oAA!o6v~;Mn%3x8E_a z&w=C3fo<_$d;c%6{eQ=vrFg{N5`PO1^;-G74dJx%Bmv5q3;xOe}Ou+GYrY0FYNt;{RGYf9(mK7iv4DfsN3G-+1@_(ee91t2e!rk zYc9V$@BQ;$fX@FNbA+eLgKm>os^c;}F3j~j#arZvC)2bK!1}q_2N?Gaq{Ast^&N^n zdF^j|0oeaTydNNJT0^xTu5aQrt-l>_Ev~)u+WiOC-r(wa+E`sTVL5tfezDJ={hi<= z=s$|N`^Wx(`vkS|{Mh~X=kEb&{m;7qrSC$~Ha^L*ZBTE&<6xfy$C(4$;{WrnyfW|o z3;%^R89Ni!2y>Jl)8Z3OI$vwtWq2LWS3I^aelHh~=Yg3uJL~z}b3fL1g3)&=sBig9 zAoYnoVfF&>0p{Mp^FAIb4laR>gp8}AhUrasJJw_G9DkywKl|`gTWj0cl0UzXko403 zIMQdZ-Sr^OU48Us9^xOsQ@h8Y{$WdX4-g-KcLB&#xl`svx4p-)y?xyKxF35CY=i$- zf7f?S*suM6;c29frNSWbc$wmniZ|Bve2-IKGGe}`i925{&i*UsjS=l@6B(twXN?_(k0~O^L_I# z^^W4y{@6Bp;~#+k_yqU>+zF`l2S1d%e|`o~dl!IvE{xBy?ND#OV_}~Iho1wo`@El3 z3x4mPbAK>DhqU)!!hgq7>~1MIkK&>w{+L(dE#*r5$@}3oLgL^<`K`VYa< zGhnYk-viF~0Mebn+W!LZtRGCi!Le;oZ@=SVp96=T18eaA`tf~#;l6wTfB#>&TEfy& z9{jZ+eyHM+cWr*Gzm)d2@c|gGlD&<2(FdR%$vP#f{!1s}KlB)T0jza1_HTiwj;)Hb zR;F+9`6x{v;Sqn8MtzhPo!g73@sOW_birrL_;38ArN93l0)BzNKPVZZ_y+n0o0acof>uhxEGN9fJ8aZD19?;!j2ukAIN;%$$A_-PB@CJx$ipX z_FC{i;=5t=UY{`~-9{05TEI@MA)~QkSL#OFX0AC;l-Bb6z?IX@u?F#?n{(4DY ze4TT(=a}zt@H?i3{VE$VTzC2OUEaL^A^cDNi=Po>eMf%vvKN34klz(Zbf4z|V4dUNguCFKW2fSx!b3|VXX$?rSw9!?UvfmfedRfg z1L$JZTy?<+ix@!+&{#>Zj)l;#|H?Dy+?z&ZoK2jE%8I?U1jp8$uoza8)T zcpq~PwBY}Q{aW*b{}zP*!VKY?($LntQk_y==Zoo|puGVyOEUn4P z`Hgr!$!O%KzrMad^DV+8hxy^}V=&*yqpdtviKo^-{0Y4Ws67DA1m1u5-Dm5hy#;hR zrakIycRcKK;Ba%G3I7f29rqOn|AkkM7p1sxk21w0jrHcrRTk?=zLzU5TB}paR~~g$ zUlbpJJ^q>v_I&mW@;-p%r2PPFxYl!=_40pjuD{wmCiVWy4`}@^lJ|cu&bNs5jhhKa z1FjeM)FalWG;)~RbL~+!-KUG~>@pqoGue9f`Zh7xzVSXnsteZp{9-R)@{`8$+F2Cm z`gz@-&i;k}oCok90i`F($;ajCa`nDO5l|2Yd7 z&jYmoFDw*3I9{xYyPQ~Wu577Y)fJU&rJ;(eY>tXwb+Ql8u;v7pz)ipZ$G+>dwl!Y> z%(yGrdiD&wy<^5TCenfZ0NYXnK*VC`LuKFz}R@-Nw?mGbZqiCeuOY>752Ihkj4xd_)9Lk6z3T*z7cP?Zrk-( z5l3I{f=b7D2NHj#^#4Wq{ee`5zQ~As1d<2+c=}I3-2>D)0Pg~_|KWVZc@D?4Nxkik ziG2*v(5ze{QE;${4&@2Q_#;c%*ljFxv4 zI2&iooA7^Ied2R0q}lKHcl_DQpL9y?YF@~SDqIM%WG#I*wgqe0Q`aPealzDXFPw_}= z`hbNk{}+J01~c&iSc^?|zkm}H9wto4e2G#AyZ{T(1^td0=m%#T+~tdSwUqYttoJp? z=kV9cz{=8^w$wKF7K-?9@+Ljzp2s=MBECmokh6a7g2es(s6V~{bD-2$&I|Y+u@dQ>NhmvRSB1r zSNitdG!EYH+E|P{tfh69F4;BuiW_dockMKO#rC}Ix%h%!bFyh4A3$q&<_uU)zMdui zWNA->bAjwXpj+af^L;*e@4eIafOQ7Iy#Va&#uz1^l=FygfA?>H`xy5zKIR-)h5v^6 z)BgVg{tJgPE+kCY1r^4+tWsX7yp>ONo!{ds7p;~hyWR3$0JeYH&uzgHc*Li;Xu<+; zfI9`;{X$3dJ5S!-}4l8HNQvbn1)~}^DVjkZ#7S7Jfox}Yd zl!5c;q48q>op15-4E4;|6DWOyne!umUx0XRzHw#*-fP{D55RuF_rLw^XU2=Yt7F=w z-gd{uJ_q(c2b%G}g8jb!7Y2$78-+hgd%5hJ%9d!X8~JPUyk4wRN=JUlRlX>76&IDf zoK85{x*p~3H}}!G51#P|Jl_UiQavz*z+Hi9Um&gNq%XSdE6_%5y&5rCY4$A~$IkS- zVJztH+A3fNkmu{rl^Vc&1|4a8Pbq1jE!vFER1d<2k ze}bok&G^q9fRYc8@>=%)Wyge# zCA!2zxz|%#)XRw1@|_PJ@hR?U=k>UFJdb!SpK*3uT#IKPAmPL014OJ?N;_5&PXS!a zdj*N&3xJXA?{Ze}ecn}^aae=@x`#jQXDs!xQl8(VOY7m<*v5RV|Igd5u=hL^yl4ES zW4zzVozmLfN}eaUuXjk1RXQs`HuwGFyMW+7{}rgVq3lQ9lg<{7X`6c69UJ=`*zX)T zH~u&5|3{3B=^AD_Ux~-_JWjosc3CQ4;)!))dagcYUJf3%`T*b|IQ`)3U;pJj{tD); z!5r-gh`KL;e$x58G>=n~r~kEeTq(tM-ktk`ucE$sTzNH`c)>lLp_kf;d0-?yL-vm( zx721SPy9Qg=Dr z2Xh5kgpx1B+~W+u?*QNf@NVE^>38gM@sF5)$Fxtq?T(Lq4(x9Z>=OTlbB>3er?_b3 z^L)icBd@1x@lsv!wvFUG{BR!GHqR4ptxUYxMkc$cw9{Id z%bw$})mNQT`BEO`tgi{J@5qCrtPQ!31=cm;i?C`9|A;~I2ZW9I1DrAYel-241;z(I zr{$Z#jKS=^KlMYj&>#FG-klU?wNmhrx@XS+X`|3ibDne+Ey+@uQFQS;{;y5?$zRNK zF8Knry(7*5#LGSovhd+bW5GE>yaRwAz_|c*y$AZ7!lI8rdE!7uwUge2;na3&5>14|}Uv1q7U|q;s9J^k` zEa6DRnz{5`8S+wjUR#g*$;82jma_q{$g#{Z#pCh)wPxQ&x+j`(bBpf{aZf&vWo_(~ zFRC_`o}=)JU)1?S9zGVj_?n&f_=M@qnYld`=8^knoT;z}Q1dar@4oxa_yG6>@jrp^ z;oi~z52*V<{r`ZzBIiI8{s+8|?*Rz^g?$soC7b1Wt#QZ8825CGyz}r=cdq`LGM6>Q z6aHhfOYe0#MtU5)WG?`$V10fDF9WX3mPg*0cDzb)`2tYZ+j`FGk5h1~rC;20FZLs} zUF!#R*SzzmvE*!A{h4IX^?$Ccrt4gtPzL_f7rp@@9l>sVM2$1}@9zkT56ZrP^YSbh z7oLOjDb9J)XVZTGYX3j~M{qg=_{iJdw!zOhp<7>r?Qad%$F`5{vF5-k{KpT7zCgJD zFAQ*OCQmj@H0C+K;^I-dM8zWtkH<^tlAM-2$rY7sPe(akMqEL4q4)qi2ifK&%6%{P z0y2Kp{D6o_0dFSEi+oDY@C!FN8%B5aS$%_oJ1yTnL=WUO=~Ljt4`QEuY0P3d_b@ls z{_1y)s%_C4U(8>@&p7yd_&jGHTkw5up5Pn$-i+#&?g8fS0VllY++RKbcLE8~Z{rys z%RcpXJ2v(?u)jIbg#WttFX}!(itGMAb|0G~D*IES!ird?x}r<+TKT*kuT#n|m6!5V z*UN}2Eh;`}%u^a03nrCpb;K^EvD2)>*=J_$Sj17sACE_znoF1JS)2Mst@;85hidPu zOMl)EsOpVAv|DO>)Rq3SHeEAjYMXP6rh5l7?JxQ)b7NX68~f{b0Ks&hH-0{#zKHT$ z#_tlponfNuf#yMSOnX8`^l0Fu*Y{ z#>FEV%RMa~(NdZ6N<1nn(H4I3h`O9oo|l*6)KR@ivEAhHU3%H{7Ros>d%fVHLJ>C| z%RFAfBJ!4a#`eH)uu%U&l>43VAMBdbpT6cb_)jJY;SW%vv9t>`Zm+M30A z=`PwbZnZX&493#&8Xt;vzt5FYpUC5^9>0t6hdM6fQB~#@}Lp{&q&QpuS zAM4cernZv3&U*pLX0Kh>g13CLO+G-zH^-$K?wkj+Mwx08KSbj}Uwthbaf`G6jXn5Q zT~nLF?zLlt4jX&_E83j(1LnqdMHzb%exAWTz2iS)TN_i}-Se@Z=3bgpd`}>bKmHnc z@81F-9lr%gJ_84(}y^cvLS^ zuUCt!PAq3XmVJ0a-m4wgUy)B~NKMRenahUTO5;^=DcE~UA42K{i)BYTcUIFN@Xbz zz3~5}Gw)DD{4ZfS{5*S~Q;IWA@k}3n_Vu~<_oUqc;QxTgi}wt%6UVSmz0Hn`eGcqz z4y?j|_5h*}kn$q_%kGE@3u0RNHCp3WzNptP<*g}q-WW$V0c-|ic`rZON$uChx}>F> zQ^m!vG!*;?=XjT^X7hy;CCdFfWPtw}?@E{xajV3mJkeMuq*PH z{`(Ki*BwB82jJareB-18y6}HM%*Aet_h*ay*!HnK^c+}?|9%cI#%uU5OcNEhDP5z^ z=kdrtR~C6mi(k}vJdgDf!Ry4hu!r%JtrlhfRyH`+^EN&1?JIw})$1Pk|i=Lpf{C zzCZzo7BRn6$MTR1j@7V=eUki5W3Vs=2o1dF# zo@AQl)!dm7cSj@sQ;)e_Is?GIg7>WZ{d>UN3*?-{$CPxp$NRO%eSG`)9&!$>#(!V` z;|rv4|C`^ufnknkipz#6-9o*N;-b{|_*|NGDCPNlK2fD({nA?1*HhBjzrhN=mEOrB z58oiRAsHooOJx&YjhF~NfZwctqu=4SdM*yOa3`Ga-yshi22+ceYuMyCJR2W%Wi4CV zcjinZx49B`sl&L=^{-aOv&w7#QlDD$q;H8|W!unE9?ye5`hO?sOexQ$)c4w$(r@NO z3ICZ}rFuLEu%0`B!hb051wI=74~RK^NZZug>R8z4z<%dI6aH(>FX}!(inIS8aW1AE z+gjsuGGdvhi7Tyj54K-t(ZsozW+L<@Wgb%r1PP~Nww1J-?Jych1iF&!` zDWCPe)`S^z6Fz`p1n$qVCZnyWQ)`-aG`PT>J^X;J{$rqkclapiSo=>t{F;o#stf*& z7+CWy7zgUL_AT<^?`*WGwp-|eZhAH~-Iw|{)l2Pw|Blsp4u-kp`vcxj^5Z;WE)kf= z?pII`pO^RjvInadv!utjM7iP)+M7mV&{54+X zgRR2l91r#pKCoZdh~0DBhuu?swac0~+Ew`Q6U2jDx3|POBXB!O9`A5#pTX-Y4pm=b z+AMpEs zj%ki#rMP%S-DZh@vR%oJDGytS9Yc5UnZSBUcuO64d|i$oK)z!Hm;j&J#SZ$nSK!4y zI{w2OeFWNe--3GRgg)LkwWEI2sMpcGy$yVEJW5y-{Q%xg(EUX3Z)=>f!tcQ6U_Sud zY+k>bZs>)a*e>rfto1GAFKpYdGy4suXK`#D!#%!KZ`*Qf1N`@Wj<}|0&dRTiV@sOf z1->ow$b;sak0E|5`LxG-0RAoj@ki6yp10A@0QPH-JKpv2J>(o{#{bgVf6Vjqf5$G_ zn;I3bY!rOhEpQVXr+m>|Znn=c7n_D{5}reSjRZ!6rQovcS+=XGJ>=2`ZO3o#`8U{e zKN64IUhF6Jye;JO-u5>5?|r2`WK8R1!-x`QxgVf!^P^YvSJeL{>e!&O0pT|L`-C~a z0N%KMq)nay7%j-Zh!XxQ5A1Nf#us264lZot3s48W z_@)rD!BX&>_?%AQ7~doG@g~j~Z{YtzztooFVU#(SM#ssAlFzcx<}~Il7~UdlNseSd zQ()i4{af%}n9h9ly{*`H=Aw9cZXWO<_${c8<~KaF3I6MQfKc`T{5MBE=2N%F`?1G; zT>H2lat<`(f7tVX0qMg2zc37YLL57kX|g+tt4tUNR-*@d@48!`*Pf}4crs0CfA0%9 zV7gX!SI;^^z`iBFXJibEA7*ULSR zxbEo-->Xy@Vpt=*#Sxy zwo%DOU~8~pU@vQRsIYC~Nwz4i$z{)+7o2r_sC5fAF|NI_XYn0*+JLvTZklvS`j*Pc zb6qC>q~|-@Yj9h01?qlp9D|JMHV2to3jCJb&-MF)@m&D$KYj}cAG@Cc?8hE= zoa^Iy$T_eY|FsWbwDkTTwn`Z6XX^L?zBVCV!~cwjqYVS2Bu};u8<+FbnpAmE@E059 zd9({JGCiL-d-blxD%L z-@sO#6L8-j%mHiZYxJq&n0Oj|$G78r06ix^V2sCS!JMP5S>3_k6yS?@GQI7&IC?Qh z^bTeAIYzk~ZIh>QX{FoLsmU(L%6?BcJIQk-Jsai*zb`)@h~wbrTAHh(n(Nw^k$+1$ zQWcG{4w!A_AD zo?>&rWj~XYEyH$e%>$-J9Kmi;H=fzER*LuqhQNz{aovP(pmr#CU9-N)pOC(k6VRJH z*E^pjjBVudk$0m`CC~YZE2u7O>@#}+1>9JTW5T2)3(Ud(=d*%DX_GsXjBgwhJ)=nR z<+$_5IRpBFxttj|AM!H(FX)dxV7J%ZHqM+wmi!ZRTfHZsu_{sTi^og6rMyr_&)WNo zkEMCa?;*}{=XHNqbIB>c1^HF%t7%U2J&DI3d~mu0zAFZ;if1zCdf%lJoqMO!WI&+o2_yvq@tfTP}^>UA^T(tQPKnYtsFW^kg zUl4Zd-T=7Cxj$p>cQE2JQ<^;y_<26c6XnbRY>)d9w2}3JrT~w|S9Mz`&p!Hus>eLU zKf$-5jh*-b(tGVVm+DEz*njs`H4m8+%w^%X`sS4JXY83%rNBJZZxV`3%|G4)@I3&| z0QjGvD4(;HL)xm|R>#IZ2X;FLn($xieZzd;577EQ+mB>dkSSZ?>k#EZwH{X;sC)+T zVV5#yWABpOcwdcnuyObasw3)llRR()S&rG_Rhe{&n8UdP^>X=WCrPW_jQ!}CsA!D_Kf=c_~l-=Uc<;o#fBp(X=;^*7JE?o-mYkWAw8$rX|Yr#gC!>g!RI^ zK-nL_e<;aW%440+c?NsdaZaf&dh=`;SM60S>C`mFGh^6P-^PKx6JO&KXWh;GI4}O^ z`NnT5jRU_U%{k^J|NRH%Pu~Je{|`)>-?GM!IgkI=?eT8yaUah@Q@%xM??84+6yE{e2=N?2WwME}9AAZcj@hK~ z3+Ny1QznY88UuU;(yA+}K0BqXRt~0Z;O2R7Ms-DnIWb+y&wB$2!@+2D;#~m7V{Sdl za{!Cs&;5{Wr)ob@WNQrd3|lBZqs|sIUX1ZvU3@j}L1z3%2kBwDX|DpRcr%_C_-TINW6q5?_2$<9$l;ms8{*7HbCi7cMn07=U+)3tGk}L5&d<%q@y+SK0}g4c zdRrYE`yANq9B9UWo&Sr<4@ha@zp%`4JnyY1JA>-T&|XLn2AAKl22Yo}JszZ_ieuKxV(@GilX+M7)ldM~k zhmXQspOb~}fd1e=^(KEHjIa9uv%UZ_s4MDnN_kd}T%Nb~n54I`dI|sK8*831uZVjf zk3Ag5#ql56+yRJZ03W*d-i`5Ny!siyZtZc$w?3YSoC8hxFU%M9bAS|g{EusK_7|}& z;Ag}H`3BgbQn~LPP#*W?wQo=TxHlks=@i?CZHw<4fE&ojA?X^+@mn0j#TWbIZ4vkN zn&i7ZR^Aeo-V-JnP89KF0b8or8|Bv0Q9kK02!FvZur&HojQ^Y;qx$Yc#c{2rr?Z8q zchXH`$39BL)F@B$igN+&aWH0%^&X!cPmPr*x_P{ytK>0G_)@MPbBf;dpy0G(^m7Jf13EQhpLy{(RqeGcqy4m9Dv*7{D( z7XbgU9oUU%TZOIIt266vaCNL#D$ncgaqSHL$NgaT1F~H!??qk`<@{n_2 zHU1m!>l=U*{wG{4VJG$k-1W7CY>4bqsodAyl*jkTw7#Y+uEpV{T?5yBL6XpbraXj0qew1fvt>yhW zFeYd4f9wzZ;Bp+tr8LhP?5F->9}ANBzz{7-fy;y<F>?~ND*YK%4*45qt_KEtX^^Ro6y#>;7zkt4G{7?G0 zt%MJp7T!X=oH#mCmoo4_wio&H-bCURu8XP-rRQkmrTvU?!a321DYbm@EtQLJ2NbOL zdmoJT8T?P}fT8i5w{c8sY32}X^R;Vm#!~(i*j}1nu}$ur$Y=8Q6o-0z5#u$+rDsB3 z3h~|x{uDlI)XmfQS`Q6wj19sT70c3^JmY`D)KYnto65jv?hDH9h*AgH@ys4uPT#}_ zl}$vZpD&XSrmGLM<>k~RjejCvMQbno0NQ4Ks5(d!x&{ujC={dOKV+!eziEyIq&^%ITqOuNbQ5Q_yMkOsZDsO<5=%FFZ@?t zOqcpEpF(v+89&F{l0Kz8&2=bauDQgVYYFgw@Sc0l+yUSWfU#Da$j0|Nq|NGWb&TwD zU^jDMHU1a&0(|`+_tvo!v;n5FR+rrnr7Yv*h`-7g&HI+%XbPqJ+S8AF2iQI8NDdS` zimw3H`@7Rq(I5Vg!1=`ALZ>~2nx3BT@!&6@2UrH>e7&~D=GpsxgYZ4l zmhsu(Dd@)d;Xk*GgYz(!tl{;Jpyn8Jt2JO_`S!2&|DoXjhtu6aZ;NjRc6+=Vd)&vd zkK-Zdz-s*0`rrHj$A4^#+Xmv`q%bm;P57VcVWa%47+!2`_7757#BIu1dzbbWv@hUm zC)O%akG%IEuv)$Wx=;rkfX{Ww_SEa8II^?+F+bw?Qrc}a@yJge=hYei3s|v)B^%`d z`)13Q+M1EY`W3zP+)MZm#%;UyM=mn)C-S(IbaDMX9(Xf;r*d@WyNAeRZk7Ci?7xh% zYPhfb*|C)l$QtE2KV#$H-q$!TQGOTTzvi<1Xy#OF;C%`(-|qnEy8!%dr31dkA#GM~ zt7BxJ1G||6Tj4+0AMk&|tAu^BIkFF|K{7TL%4i>4r+y9J!GCNP6SwZG&dleX6CSLIK7$q#_?-k_fg=q@1jYdBxaFSc2E z7PP(1ok->{zYC2IbD7_d=4T6K-hJe4Z`(Kn;0^%)2f+XTNj5$*&$HX)-Pq(lj(r>t zH3wGXf53j;0bu=)t-z*WW86++Becc_Lmi7L6aMGAg>ufOAY@in};e`7nPdgQSdbnMJnQo)W5oGI}v z<*8hB2InVVA@G7|rfBFxgg#Uj34;vHLa^N+70a&W@NZBRMHf5Je z}r?!h{Js0_HmYOz{?;5$`6s!lahE;t?I|f}P;Ko;P&b!$>@oZ~L8pm&ra3?+;A< zmF}YG<+^!XJPVX@rw#cTj_tG?@n7Z27v0cNdWgCXDUUW8Blmf|-?cb%oS<^eGoRBf zamI}I{&WWb{MR0U?=SG1@81I4jZN;@*2nQsb6{)yH(vn!pKvSTbKHw(e~@zU*7x4A zO}_t*J&E`D`8H4H8L?S%{9QuUW3rFfA=;5`gFoB8q!;oD@!ftS?_fI|m_>V8Z8320&YMXZy8J9!Zt=>+@$UXfXHBC$ zc5lQ?h5-g zzU~7M_cS~)t$HO&pVs~#l782W5B{-!Cz|7H=tH;Nb_W0P0k{{y?^@4*Hv1Vs$F4(R zS8wP1b4_*vJ6j9-&aa>Om+t=y$DrWx#+|$I93NYRy};gQ{=|nZf}cHo^1%u)f;9}d z@7V8c%*9LCS>l%+R9S01@z2pHtCo)W$c%YPi*DSZ-v;jvR0n(qyZyX|=bQ0AmB~Md z-?-xrC;nny)2I3w7m=0L_?kn)9Z}{R<=Lk=Z~szTOFlsf*M;B0_c2GIWx zpySpdaI3emn|Zbh|Dz8uo(K5%e}sVJyc5Wp z2D^qV{0iF9K0%g=->?)G+Ed%2$n|(k$1?S;MkD`H+U2kho^ejN1y#I&A!qO=@_O3i zEwUDPz^=G|jjp~BxKzTEVqOEr73(#$ z1#ZVXep=&Cm`M8yE_2ii8Li*JDV~kg`lozRZ+j*_>795yt}*gFkEn8p|ch??>~eWv-QY*uMeqbq7H20mlCW;Q7$c zZkx|YyXaq%f%c84@r3N5`4xMc4RQ4W^zZ305v zYhaH-0l$H74e4w`dl~W-YIO1;*q6}WL+}|`51$L?gssAvm{$H;>T*&X9a+D-4@bYj zv?}hojIn*r5&RBG?Kv}V;C1XR?kyl!?TD`J>&WkIDIRIHuXAmVdNEdvS*_1=`I>wB zeQitm=AVBHQ2qdC0Qk((fwQT7+pR9YV`HBK=br<+!hd17(}?e07USZ@#({UNS#)ne zcBO?#sW;5#s7j_e2Dm8 z0+Q!+x*JiDv8%BH+lBAQR9rN+6ZySP z3kaRnCUd#l=JVU;K8Ae^_dN%|zS?_#%Fp-yb>?4L|AXhUGZEY8(yEhjKVd%@NV~En ztrT3PFIwxwJ$JP;N9uJGXAg8XXKq5OZJPZYyFmf zuF+?dr!f~T;Wv5i1Bh3&R!932JX`*QNaNQ^8T0d={cFyn1M7d*`{2F;KEVg?y?4@$ z-y;3lx9#fkJ3jU~aK1Uvg#QK1pS}e!bN_F`+=P`S|3KwnKRD{^!&dtSA9zUpyk`!c zkL_*HT7HQ)<>3eT9(?v2;FZ5H#xtMuvVWm4^3qRy1Oom|_7TRt2kk*{M^XC<+85A% zL*8RZK7`I0pxGZtb`~Dwvo0>;-WGUP#iADcEbs{b{Vaz*fd7ZbHu8*^o9r-etnj8nWr+437gS6+t0IA_+L2#@bCY~w#e>4 zl_x6PV}G6f@fKU=JbAA_*%$B<{8Ss>=3E|nL|*ZGnc||cPAQ+f))3`Y)2W}@cfcoL zZN;94j|p+GZ(~jEm?hkcc`+@%HPmHz++?5^y1UNcD|qhswt;z8f67mFIO|})#ASK> zo_H^^qSGX^)K1KE86F?`N?5KuQQ9N!>1G{LoA@=%eedgB91P~S);b?s_#V6S&NFua z@dLO6fE|`T^6$EB-rhF%vFl^E?>W$f|61?+K7hsb|9{bb2+x$C*SEdjj|J@@cPpG#`-OIESY2wz^J3i7 z@(GHvU56B>PpxNU)7syDBR+?=jX#wBgDJiP0REHrA-e;>^XUHv)bVTI_|@f~Z;q|P zfBXRL0aWl`7>9i!o@uf{T8Gfynl%h|1b%Rz{bTK$PqMw8F)kfisPtUoo#UG;o0IGH zh)k$|&p!9@>*Kf2Ina#%hW8uy08+m1{|mQ-S6~%+?De;A< zl5A16xkQ)vw=JjMQeElR$|wF3Wla4nUE_tH1Qt*DAMm4y(~-w;smSl;jdAb|zl42x z=?di=K-=OpSXjFc$2_CGCjIC7@BMQ=k2}v87oJBde_^eEpnCMVaq!~ zlywB_xV+v^cqiLc!oyZfo#U&OdA`S`hw?;~4{gm;omPJEpRtK!$@vKXl{?{o#HIz@ z63$fVT>ZJSqz5`hyyn@0Y1Q_k{z@lVU@Ln7Z%Te)90$^rSI0qeoG$3UR!3pK>ebTZ zD~NZZK_|wFIa2Dc=YhMN{rkM4-mb!XD|Y}m1BmY^zOjD`sQW+ZUP#C2(;S0l{EzE@ z(sTHq>`m)lrQ0sPr^nis^^5inA}%T&X$^B_2Srs+X;JcPW#VxvUQsWL@fIG{sqvEU zWu(uDzccIkRFC}w#zZnj^VtG>0CRnc?Z$Mh zTPYW|i;n>f;jSUDJJ>0dTLsb_W0*T`%rw_V)lz)An~v?$4zO z|AqCUVJ{$l{};RN=YVbx=Hgnj)No(;Sfh@Ok;lu3dph#YrBzSVd6g&XWvy|q>v7fh zJl1(}JZIPc5zh{p20K&my&(L;ND&S-C4xsJ;_Ruyv)Ky&-+t+{Jvts zv?Bh`=n4M=NtX7Q7(@E(V}Wk~{;!pNuD%DIh3zi0mKXC&Y5Ef1q3}M};`m(ni<+y3N9=!L+8cQ2uDh~rso9@WKK7Y4 zzt$#>gN~but30Na53QBe^1ZI&Yk24CtdX*d4=;J>e>HO8y(e+H`^vo_)_bt*jZ z{u+D3tns(OXz*X}K(LR%8GxUM5XUFjM)pR31Ex=9l|Bl$Bc1Av@>H(;m?q!zay+#e z@7L+M&r$p&?X7A4oR_{ot@A(o@Wa!80I&xD{OoGuRZXLD&jn`ZnE zYyO+AzIq_saMe}AJ?Xbyx{Fq_Nvv71+rrNCP;6MO{#=>Ysqraa)az^$cR3z+S+)Gg z10VLBcf8{mvkzWf|3}PPN(=iUpYol;v%rU5oXbmR<_tKufzb;xgqO(Td-Rfp-@|=3 zrJ>EfP-B~FyF?wURZgDrMJe-mDXsdkjB%R#?veN1<9ruFel~Mw7XiHBo4>jPApGYH zfVN`$^tofqrHL{9xu5QHUxok42N3Q*|H>Jf7_QMthb9zj){0b%u8X|BZi=Q^?D8l05mH+%tE7fHrssV7dcs)Wzxf>95;SK=%0v!uZ7Yq8cx%8e*3;uJ) zf6e8W7qQ>h|JWt$%yh4B#C_Qt;g`}-C#JS zsK+T+nmd&IW@BHM(!2+_k2`?zJ3ypAoW2hn_2C)an|!~HF_#|3^k;s$&%6cyuNe3F zwcd}E^MCw%aGy1X+Zk}HgoBd^M{2rSdg$O7&}b zE|)bJ@6freJu3c3%=GjaXZ@=8_Rw4Z)h7&GOXC@Uj|FkCKl>N1i*UG6E)H~zzBHdr z3;svE_wsI@20exv&|5M-PjeTN0 zOrJ}bM;`CXohtq>j%Vq)r7_@4W1H`6<@uC+M$Mn|Ql5u@2T=b5%(+16d7yLu7VxEs zGu^*9&F6j|{J-XkEAoE;@cut%{Mo)Fd+s>p*cJ1gUu7l!n5VStm)G??@i~ocdRZ;L zO&w%;y_#OmqxMU@k&iU^&%UnPT6{1taVuls|Nk$&8(94R-wNIdCq;#8 zqROA6t-P&#b8UH9i#+j&QlGe|U8c%o-dz4vmhhkF=XRDm7!%$JLk@{o3vGe1=qR1p zznJu0s9VETVYvUdpyY!&6NV$-$0WshpN>5f0zL$5THc}L{q~Hx@TY)|rGV^7{>Z!0 zMoXWl*TR>0(1`&4v;U)hwot|$pHcI17xbg|-M8@#0L}yO0ZQ+tq9gkj9S2Si2l_L) zG@nT;{y*zGz9Zv4m_K1Z{|hwYzidef$70?Z-dJ}jjqDOnEgxRj$Kxs!jWSB?=t=;jIH9y3aly05XOO5QC3XD69O0t)(Wrq52GUf&&dj9;2~@H_-!Gz z0p^_1HPwl_h@Z7G?+)<&3eG3^jqra$tatgpLB2D@9XxylWaC31U%mh|`U+lF^cO;( z;C{v~G&oN4e(@NKw{h%bVVpuL3bgQ%ZLm*@|a(i{C7^`81L z%0Pz}UEx7b*8iG|=zHFPO)ufU`*^M&K2*nn)5C%OOfJo5(t`h-@e^3-fC@t?J^_EUuIoKFzIdG-XzXMe!Qd@c?@ zdmQ*B+DG8|`d)&cIrx4;_K8AYh5u0W_q!BxdQgV`np@19T?BO0H-NbV$h(02FFZi%0wwsTy%-QRPK3-Bk!F*`+HM( zOGjeP`#4>b4HuGi|fqsAN*Z*Yr_;37^DSYBL z|C`~1|H&T}`^~s~=vV%zhdu^<4jf?)@Vk8MZ~oEnj$itt;cY+rkB8U%=&T37n-@-L(| zN@GGE^H#jX(M5FEdg(WUK5BE0!iNqe-Cegi8L><{?2_L2oBv{X!QcLu8{zrC@u$T; z=4X-0DDR<;ru44?F(v(w?rB<#>|qYr+i2hf|C@ zF129Xnm$Bar>zo(Mn1+}d28C+mY4SY+4-1wd~STu_k#H_Uau6Vy|wdeiGMx*C!eO{ ze;Hp{x5a>U$T+=EO!ifD&T*{EL#IJHso!Kqp{vaSzlh) zgM*Prm`dBiNsS$OCH{TpxgOHTsq~FH(ATB9E@vP3e?wvYe?zkE-mb@UU%Kr-y6x{i z*m2k1r!f9k{_r2P;lI}WktY1V|MxonV}p+sI{t6^4)P_=U{3HcBHuCbU${Pp+Se2A0X@jbo@Ww+8p9Sj|H6E&|1I6|e|NTYTbnG~3Z282Qz*NLU0=q3VcITrqYdP0Tyh(~QT8#! zqp{O7aE#rhZmqJ^KKi(h^aUB&7C=)V?L13y^>G&zJtF>dC$Of&#b?oN`L1nwm)Gai z+BwjK|6sl0eSROn(jEUh{!o(7<*E>W! z>pc1`t|xKyM2Cw!f4Z>`6nSG>ecT15{f_?~d)8u4=Rf|O*&6?~50Gfb|BnA_uu!<_ zn6##T3omVeZLtlt?J^<{_4eVDc$;hE(i^>8U*gEZmR|qsoBfS^o<`0tupb$;e+K{4 zU4W9V=s>=7?ig@<4Cv3`(tQTa_-}Z>@jZZ!|2wmz=ds6b+t*^tq4|Yn`_#GChVs>C z(vDN)3;)G)DimF%zw696qBCVargL%XpJ%>#UB)NkKWTVsI#8$M&ZUbx{n?+!vv0!x z8SKXw=Xpg)I8_c=7K&G--2+nql@1L*kQ@qaDOMck$SuCX?^k@mTTL121pgEUwq9^pUfedx4yoR;|2 zAL$Rj;!BkAkk4>ls&4?hAAoK(9cZuH{o~pFKK6a=nFFivU*`bw14i2MzvKTBPQ~&P z?h4By@3!gK23QnjMINpD;msJ8Ff7(NwKTtDbXEW8Lk)Lh{&{g<^@ac1`-h@eY)|R@ zKUIDG-+iDy2aY-iR^h*JUw%N}|KHjANp^Hw>fZo5HGC@R6LFV*p9=n?2ROA4ol0YI z-aL()bVhIC>=NB}zQuYa{Ga;BSzpGfePXR+Abk^FD(-lhaVhaY_o>q^$5{QLpXiNj@AF(-{fv0NHtqPYGk}i& z9bdYSaoTg>T=?Jj|4(N9?--WvRwoSDCC2PpmSYz9v`?&c{EK4~^>F-GeAj*7wY=B| zH#l#=(A6qb~TQYgU;%w$CWon8I$vd68^I%P-|CX`;~5Ad;dDVpYj}7h5zmYSiJB5 zpWl9-*ZxvpwpO-P*l@~p-#QD+Ywb|Z_^2F8`ocJ#r#yD9n`3^~KlQ`=G#B5++*^zP z8s}5Cja|2n-CyZ*pc()D>>up!_X7yB?*R070Qwv_+8k)Ye__6@`SacXj{oOgH_2A-in@)>?^uHk={s>b zoR}{V*XEALyNWw5YHS#5_ce&C3<~zs{>AuHV;{x)N&lq3_iHYG-ucH}e}DI1?*JgT z)^2_d-S!{N_Mh^)wCi@5eUm2q_q~6`%@^qF|I=9i*KDo6^9m-Mk}u$xwJ)p{&N~KW z+%aDW9$%+YF8qwVn0<&OW{7nE+!cgk^%8~uB#;D7%Ha9_*raxL3st)EX#_z%`= z-EX+xzyEi9+y_4$yM%A8l=}O^-6gzq%tGIN>5=i>{EXO^uwG-vc#^B_9DEVTji~L|l5));@HQOtk~`{!&g_nSZfj>_J-4k|Pw_4`_BaRPV;Zc9@4|ciec|sC z#z}{LwO_)2y&K_ex*kh9pK7`Kz&%gJTWOqIYtl9RXYS3lpU1!3{-fCbue7yn@6Y=E zjE?`u$M7|F)_HwR53XZ_`3=BB8G$%?lRuE+*xZs$hW{A2CSBsU`FE*H2@mBLh@wXx zuQWcpZ2OS1G?w(&=ZEs=sNNItIo2AF_^`Zoa9+vJX8easFu2b%C-`~ITgK0x39 zKfDhSZ9DS?oT=G&$~31~lht^Sfq&}DKHJWC_-kMO)*$1Q$Aobi@!s<&dnyJ!|E=(U z^nY40-}xf`>;69!KIs){eg#qW+&2c&j&w(#eYK0+*x!sjDPL`B?3CVj-}fP3^8yV1VHPpW55ALizY_?)W$+sw;3{AbR2J08!^ zps)YC57g(tQRcw8@PG6RI{qIH|J`Gl;d%&FXzdptvH5~r!w_d`A;RP zKJfgAqq{%LmN@<2CSb1}^F7X8z&P&GCBJJK=3=+~hq3*AoclPp;QtL*T{Y-kzx*8_ z&i?!P|5kQ#8{4WnvYAlURKBj#f7X=ns`SoZ{Oz-UJBJsPfhoe3Qajt^A&>s4Z`;Ud ztwURJEU2q~QHCz9@=lE}_ixK#3>rqtHjJjqcTYwNG!r>!^^)F)qM_yB8Uo)Ry8&^lXsXWe4sUR6JF+# zulZxVwg=Gh|Lkut{w906kI}y7Knwm~^^9i>H(h=8#+qN)5AFEBU;LL%mksCry_I_I#{c94$fh!ub*wsz|JY&Y_us?PSpao~le}jR z&InswW^3GWiaO_!)zYS85aTBOiK|~Na!!qhe$WR!TOU{N^IV+%BV%n~{=_wZDb1L9 z`?TkCug5z!_c?I5IdJ(CzdF41y6a{G_|F+YZ4clLU);`SthF(hBEQ>8;$X9|ANs=I zYB>Wa<3Ho+7?yD`$>;Y+J79ZkKc*$)V%_b00qTMS$VMO1uGg;P-Us}vtb1>zH9vV?*Pgl;CZ?Z7w695Y+lEgKGuB>T$}^n^?koQi~aZp;6G;oweJAD z>No!9)$4^z5zE*1xn#Ri~X( z{{QQ|&V#4+4gg~(8BXUgEn{M`$!mN7$#!2L+xDclV{B~q3~nX<$g``owaQHp0u^ z`&WlofA4>ACfxGa4`jY)-}`;TwGTWoJn#Nb49|P}#c)lEUwz->8*(I?X(5HqQ-uda_!h@eI%8;xYMW^T9_wn2gx*uoUZjDzPrmEt^4o(1F1v*UMIdp5Ovp22g{99;7ozCN|}qW65^Vt6Fcxsdp7 zdie8`URS2}(6xs?27M0fc@8|7Z1CF>PTc*0;p*2vI9zetyB6{P!WCBx&w1uE2k?Jm z{XgRW19#jp-1g!ZSHtT=nbJ^&x%#y-ms8`3`KlB1JuMzl$~<1;^}JHNR$si76W(yk zEyJr{@Pgq*&wJiRxc#Ls9e&}-Cx>79^rz2+zwyaW4lliMA@kq+%2y8eyy6wZUANwv z1Mxdv{_+i3$bR|t*AH)b)vG2x@lW)-zk9edg|{Z2hhG2s;k|d>IlS`?Zx~*D%{6Ca zMO{m2>fL(74a4hR^rGQSFMCKDFnc>DK!&+xWa zzj{9*wfR7j&sa-O+C~?`%hGw*9jV{MrNdiCT_RO^iPm^MpSaSJp|n%Q#UmQ?(V6E@ zzivtM;lcFW-jwEz`q@f(25)%DOQzqZ=H?uISDG82dgnWH_~bj@G1S5n4?UE5KJ)H( zPxJg`X)ZFym|s2gG3ayPaC3m)`qKTso02`@?%$2zz1{oQJAjV=*a$F9w!-mE`O1q_ zbz{EQi*if6o)`IJ8!@f6O8JsIS0)~(;urNY#dFzcb4zymkvF~R4DP!x@Q&MV%XS`o z1p|cRU>or$6AX4f@ka_4l6QZ?%*T?ShaM&WB+73|zw*W#^ISpxo0C4&A@70Y58xLN z9EXK_=b{NC@h{vb0wdMlcR&C688bmn!0Qe7|0JoqdrFpl_J z_&NA+EziPvcn0{P%*ob(&HhxveSClt_JjML|JjEhp62CCuDv$*vD^K_+5JA&eXN-S zE%;x;d|^NI{x`pQTKg|z+-OsTd)v^KHg+Lb?TAL1bNRJ0mmwZe)?BR1-4-kUxnwUL z?_>N29(!!62d)eEp;{A47L+{SCy2Q3X?y^11Z;Wu_S=WY(p~`b#^voQ4i?ZJx`Aon zzk+b@ycGOr??XB>{u%#Me#XA^9EAUly)jNY=DBWjWzMI#^T#|d^EiB-MsMxWFm8;a z`q@gEgUm(dDr3_UGX6KL|K$UGHm(2h^Q05cykk%YH0_?^Y$RX(<+*_i;Lh*t1uNn6+ zz&qrU_u89o%7K14-gJAq6{dsP#7k!Y$Oiks zyt@*v!z0WW-N61NYf2}6;@mOAZbyuHZSrRxP4@+miT{BP++n0G;ghgt4W&MKH~9hX z1K<~Udc@6$pQOQh-8rCr{0Z`SPW&c>|B@H+SNSDc;#FRx)K{Kl#kBHEyk16}KA=B+ z;`xxiB|YOcV+=3;=oKmP~+ zm$32mx4d+?H z{HozqH@ClsfUQSw=`I?vTKS@_<&j@$(JW_S?T;<~@ehBv3IBig6Q7vQ5aRtlFt~QU zAZ)`k9z^U13)|e3_2!tOuAI&zAuukHVT8RK3uyym-KJv{yE{_WxM zTP_=Z=rxxOfA!U4@VN5k=nVf4rFuW`%FBk=Jma$A%FC}D-txNFZ(zGH`^$QL`8`F) zXpcu;$q-L0UrMW<2M*nch4(sJ@flojsJ!9KllG?*!R{q+&(<>+rDx5&XuvJL!q{S+4!9!Grkbc}o5QvFh%>Ois0 zEm-_R?|a`W{O1e+{KBSU!&&1B|G{f~0CbbhT|>E#PhGGX-$MR?$-akiTD(>c@8%Bs)^pxnQ5p^6>>68$Ax5f|c4E2YbMO#)@&v_X`3Z zM-29Us|>1mY|qnPSNWML z;d@-~$28vx_};g?WtxkOJNs8l^Q4z|f8eP)2Uy$OeB+CU=lw_jWVrAThvCBS4#Txy z{Ik6UnEQ?c1yMlS_-bW%1e1FgU0fh zj=Z@%?dh|xAMa&-@ZNhTTZnDO9)jm{>-|z0_wHodS(p3XJw55x>$lk(mTV~a z$@&{v_yfrIa^m0!^Pal^toK@eyZ8b5>>yF<>TE#k_1K1|*%RPg8GXQXoec;lg}vl! zZOj=Ayo?p&p7#&NJp}4`UE#6vL?zd0|JT0%HoGVuu_E_)g%NB!;to4qh0nch~KJ>DV`%mRLaLWxh4Ojp5 z|1Ph|+pz!tOa4JEBy4Z-9}>@X|7aMV`xF0l{sy~`Uo-w2-cNV`$GkcGf7&;F?eO?Z zFYe9P@c(n)ecABW?)cW>mmYoo@QaUJJN&}KV<7&>h2a<8eeLj5cYXWt`6TBvFPq;7 z_$$c=_>u3qY`FD`ubym|aMx{_=gq}yK7rQ}kEoZOi6@&H_hZ2u*7=`*DFwFedl{ z>=Sba!9I0tBc{=r_Yw1cK*D(1#}^=Y-!rZz{NZ`9hR#@;`Yntt(GnJy_>?D{Ryxv} zyrq1VqceUD{tSMd_B7&{w4^zo!UveceUq(Edujc@gx!DV&xQ-XKMdEUy@Fy$n112+k{tYlIa#Uf!rvc;=l#k* z8*X^XD>r^$&G^s0fAj%JrvU!fudrnB;8+f+ySN<*EeRPMaQS&zp1{(QR^EXPjD4nkQg)i8c8pZ5j8e92;s3!Vw{ zBLzFqUHnejL*~0eeDfFVWiMX*=kWzN>u)^^h`)303u+&MGXij3=lHIBjH9paGcq3F zKUgU~#*8%hkH6&jFMJhVllI{G#8pe zeAOJEqpbg#ufG59YyFxJz&iju3+cmeBtGw+?pXhoG6$abJ#Qbb`K|wJxc2XY+cW$A ze}^^y|1(_uGynZ?^?&$ZrStng*$hAN$HUb>{ofAP{N}$HF8qTeEA!XoUHIaVc>j;# zn%Ca9@%uU#{*OMv9R7dTw|?F5L|U_RFRz5zpG&^MPu=}Z!;gLTL&Nnixovpvg`07vEi@3`|9DdX&;~@YXkqEeG&g7{(9Q+ zI>u$|O8k)*9?$bSic^j)_4l2zdGEjb?g`_um$HLU)<<(VKUenngAY!!SO)3a#VJP^b{dfKYh_edq;Zu)wIGE|WFU7fc0EV-s-}bl7-UND~6LRQB^sQ=ous&ul zg8TmRV~Dd~j*q}P6kkA?Tf%eY34fKQPAx8ZqFz^dP9;ZtlzF_A2LE-h10RM!e`{k= z%jaH4GybPN72!WV0HGECdH&LYd9>|(==HjvaO!j5+Sj~oxaM#FpXt8e0{*9ad)NG@ z|7`fqSKK>1{puTsXFUI9DZG4m#tmb*{+8kCDev+-zjt`vFaA$?eSh(spyC67|Eb+; zQu{teE%=}R^Ea;j?H-`^|Alo%KXqzj^rTulc6oC9k|=_=V5CGwttx_3-($Z&309wEllh z!vBcLN<$Twu1jh0L0jrae%+-K)?n{A-**g;>wj#hm#>Nc z8VnyncG#)Tk=f&A{jYoa@&)7%umKlKxwLkf+|NnpX-UZI8;>s7^fF@0}la2|##RJmV zpa`fPlW1bMgNh_37;P{HT zAzZz;Tzk30J`%XGU%N!c|L;X>2y*EZQsaM=ujx|^{@0HmAG_~A=L33+{|`5xOALtG^>_~U(q6^)Rzj3gG-XL5L z;MoHfga5fOTw``2zb`K^&s@&|>oMMBKL_{T=H@JXM}MjBqi-w)^L1Lx0bp#-{9x0b zPY1yDe5fa%(JrtW`f=!zfs2?|hAaSH(&KQ*0+0(hR{(56xx^!#C;Z3*n5}uTH-5+g zr~@uwIr!TzGhZ0%7lD<)e_$H&z&rRC@tH2~Bg{CuarYRfU7cS0bsFuDOM|#j{t+1l z?}=}QZ&j>bMAHUxU$HiTY5W(S#X6Qt1=F#B!6V1IYcHAS{>Pj#?&c!!zYr#~j>K#o)_(s!?(yQid@gjT zJ`P>^jc;_rcHq74f6;$xOfS{1_W~jo01vXp{<0oGhk@199qYP4F2J+UkwX@Mt{rJ1 zV`Rw!sWtq-VaNa&-xH7HWDAV7k*?hB74rd*LoiPPeFgLzkb(3&vqayrQc7&V@$c+C#maY%$;=8%(tmE}Fx#E!~?p_!tws*cR8vC-uo#%V2 zI==_~FUCiuV!lp~GPK-*GXQ~u8t;8S_6Gv)`PcxQM!ZfBIRN+q-2tA%SQ$9Lb_U#~ zA9xHbjH+llAN_;I%zXHNi_GDF z?@Lwghu6(=$A0FEZum#{btj)P&8=y<(k=hyvF`8YPjpY-HP@X#YnJ=i@Q=I1*kj#& z*I(>f&iQoCH2@m_{kpJTjQ3skb4*vr<@0&d3I6+-2irW2)AVCLfPF7qjEi`$r!M+s z=7~Pm$8e43^aD>YhtKEW#^FEH!-Xt>3x1B9xtAN|0F3h?Bj|kL2UY>2E8RCi7Jv)@ zeFS6<=w<&jb1j)EDmpEX8~}_c@4r zzkG3cp6vqsp6k-%fAB5#dcZe@J^(s^T=M|92blpfB|3e3W`TkG`z1+9sYe^-Oqh*@rACoZnCS9 zG5(2i4$_bBxyAit*){IRcV6ojHDBUt$JDuxRMof{vo3Ux-h7_B^VFf?UO?fPKhONX zUmx~ejL(JNemui;`FuV%Oe@&WGv?X1VLbMCH{1}5>-SxDS-KBIdW@rbiu-&H<13bp z@f^ngz*~*oz8`6z=jU^9F%Mjf>_Ax{)C;6!0obFF=O6?4YxaS|m6!uynQ<;`4j>EQ z9_IRU?SVuZa1BK`7m$(xH2%WRu=W$13%UB)d})~uX>$2lN7Nm19LE2cyWzW(;zDLD zW)A?4|AF_wbCd_U_nJ9#!ZrT6@E`G*r-F>adcg(|`Ne%Vi!5BI*44%80D%8KHX@8G3;#W=zFF1p? zj&+ldKgk_if08?FoEFm$N=n*;bQK- z(AOb%q;t+!w_j z@NgOT9~RmIj=yfDJNBPszksK6jQt@K^uqrCc$xdh_&;_IKy&~c|7-k%A6FLsdzcOU zf8d*SuKC;Fa-SY?up4#wXt&>|4|4m|9O6Fqi9_7J`+mypFLwWSD(6NTcP3p5lKf2MDf0c0e13PFT-LpkCIoS*6SGl$~AeTQan&B{!jS+zqpYHA0+nvV&^|{ zq#G&o0O6XyPgRS({{i8gKtj&BJ?gr@cawj)BmdgJUgG}=qW1^>-z|dw%P;$an>Bl`tFHc}$TUZ|Z+!hccm1ME-4)-x#5FdaD(eA8y8RCr=`O&W z`4tWB7CA#07>{!VeeCzg|GFN;X1ciN`*m198<*C8{?~c{%$)<{G1kYpQezHm?D|Uwz_tz<0CmtZ z80x6$pz9251@=+~$cNSX9{qGR=KC10)A;vthK0_+eAF8<9Ap8?1G@gj_+gh{D*glO zAp_8c1oVy50Z=D^dzdHC^)VYj!(g_{J;^PM|6=AZz|07s$N-_-lXWjum@=%ozbWbO5~=|6{-Zaid0s_&@o`BfG5w!1=$q@Guwt z-y--QuKm02EO+YEuZVqLwHqfojvwECnOk|ysqWEh&vf6r@e)@zezNQdG{T*F+Lzoz zi>JH0P8;TKmhu16DMLazz?T6^9slRT{9N&I@9D>ddVlFR*`HxP^RKVGvM4MEUh+Bg z{XNBe{T$>DjN_Ou>YESCp|b`4Gd*0?3-QErxcOuVolg5PPK2%(c%<_O=5jv1KifNG zF32gmZdgZnrP!dx$pMf7pwGx<7fAf3n-jBB`U2d~mp1NRTpZ?GuzwG17hw+oc>sK< z->Vou_Hil(|3L%j^fCVDoIc7$8L)YQj$iBiiT!Z#3@*J!5jG;QTj)<-u(C}CDK`%k z#DA>)`&H5%IsX=!`>zSHe)MOjxC!6?wb=Omvpeeg$6ey+!_KcmHeo8K(Cq4;03KS^M{^58aq)^927t9?Ae?o0{Em z|15U@IPXWs`nBgYi~j%9q93SnM>L%6j+3>56MwPOjr+lRcdV=(jFka;iT|_##9F}g z`G3HFnFHYbKl=&o=EVQM3f#S4u5$O^aG@KSI8reFQ|_#<&2%fS{jyv7dD$00QP$z`Yt_qlxux{{F_G5irn~0f^1SaJqgx z!*rRBF5`=JL1WYjIErULTi+f<(>|ZSm^FaNUyuJ`2e?RdCd~H=+3yM%uQ6Zyp&!sZ zhv&d&{mlzjzR3&aZ`imR=+0#ONAG!ahT%GLq6Q1*jeE|gj>lWS@>IFvb zU*pDn=>m7$ZzS&C7e!{6AFdCq1pd^J7d~(_r#JfyKhep+>y0) z?(_*YA^yV-;11C%+@8`cWbi+8{*PZL)~#5#(DS^H@rysEC2quFa$FqdpV?<(FWMhn zeRWyJ|G+Ke$Go9i$fW~7KdiAipR7<6=F40`I$cT!K%8fN;NsjJU@zw3%h~2i%?ouy z9dzCFIZgO(_sBX9@Q+RdoW#6FoDAUOxF3$gb)820k(OcKWj?@v*lYm*@tuLszDvYxe~$4(zl1RdfxNNz)GZfZoSq-h*bhJOAM%r~2XtwremhHVcs-DL zpdkLs+P{e_WNrWWi89wOd;cCV!X0({ucEd6m>c*f=Z>6nQy72v{`8-((o}c*jn}xpy)sC&lVLYG63)bIsm=K0Pl^q+uw5lr~`D@ z`g?*N{#?utuDBv=o&fcS3o^u@P;{vPrh@V}>f z0O1?qS@L?Ei}IlJ*LMC0YfOh+g*`55BcNpf=mv0K^FH>@;29GGxlgycnaoiv59G!F zr#izu{3hJH)*ZH=?EAA{b%^uF{P;h_#$WUT+!yeyh3>Es`?-T^_I0DqzRVqP&&%%q zA3flH^mi-VVJ&}f$F$1+0g@hj1*LTXy}*Cy`!VM~K4k+qVa%9l9{^?lk3NC82$$h3 z{8#h;!1y0uaI|~$uWxksUjJ?P!`rWQkKVP=-TjqnhjoE>h^+9pSBWn6JD0h$&YtNm zyl{cL@|$0Gb7#(QZ~W;Uck1!u-P|JsclAkoxhuXf#9b}x0Ds4T_5^c zFS?8`#*KRhap)WIyk1|0J~!7sKR#vyn~5#xGj$($&!v}^1^-c|UXz6~AP=CP#BAtW zaRKj%%g_@b4*CFGT+h#Edg5}QK&-XX_712M%A#(d*fv#(bf^O`Q-6!^#e9p~y*-i;!9(w~L@YW#nz z%!Am%WKb?B!-mh}H$h;Xmu*_gxzEbs9gO_jJ7WW9+Zb_Jht7 z`gR}ZbA^HbxNsjBqxjQIw_Iso(ysE4*mhh8F%zW&-Z&=~duz+5c@5U+vH z8ms-VzDGY@UlxdqC;p>s=>LKHz){Fu`ui8_hYqL^{-cdxzbfE3@t=Bq&`pwX@t4d^xg%QzqS zf1K?9$9({fmotIGbpXo#&&NrGbKyVE?!85@{`${G*L5cZ?#7d%F+A4v0mttY8Q}DT z12<`coC6@T%?rQ&wfoDv?}qsQe>QJ+PyF&Zchad}bBUTEt{FCi@{HF1qkR7YZtHsL z`}!W!t^2JzzWwc3oQT5?KMwQ#`Ybf)q5U+y3G2Q0Fvj-I6uED;8t(&8FL1@uLRci zCO`jKjJI_k3oHgMP>-+iALBlZfq}=sLcH5Tbs-L8Iq30`hIV_96M#3seT+FlPwYdB zeSRS;`8JZeKJdfV40-dS{Lvrn6?MQEnso$L`7}is-%Z;KAU*g3GzfJlg7I;Q8$il}W@L%J-@5dfN_kAUB3nmP4 zr;2U$Ykzzz{jNXz`_-=gkbT@WpC97BFW67nL684+pGAK$F5iJ^bA>S`(t3ZSD`l-; z9F8DP&(i`wbEWG^JnYtWKa6oW`fZK>zzOIep!){q1J^kRfcjwG04~P*&~xKi;u!M6 zcpjMJ_vO0WLVoBbP!F_0$QZ!k{*VLk{`!01{c_RWr!C$QGz1poB8`aE+9hr?&JQEr zf1YXRG7Vjx$fh87Fq*<_JFw%=<>B~AME`g1K@d`KXfCA2lhj* zg5O`GfPH`}(GOdmhVT8s1HHz7$OeMx6Mva>hh4tHJ@V6^q%rZo-+9YTz4%&}c<8?b z`@J;)y|n+sI)9A!xepNZ0GIz-~{Kr(MEv1cwda)`CMPQkRc#%z>XaFk1NzUD1AdE z+cC<5K7;RzvG7l>y*B4}jypd9^bU0ZDH$LR4@h#jlP%VPstjf8TVL*3;=x$ zp67d%>OzJn#s&a-eU9lV0}$JB&o38y1VCOu8a$`xr;rx97tpSf-`MgtS)i|Ypgj2B z<;Fkrf%|;(z3$I%ZFL=QzTvjN@n3G|yMK1)Tyw8WtlH_0)3*PR8OntJ+6EAQ;J+UK z`&gQV|M{>#<{oVT&YAd0_lsXX@BZf z*9T!A%j44IjgxT-+G-zO)kG*77vm?`t0DHU6jc|Fz5CaQFP^LASN-cdlu{m2Sp` zm%4X0|A)Krhd*-%|MX3F9OwNxmrw@$hYf(<2MBWkm;ZVOP(A_RJf_LN@|7#rAxUc;>O;LWqA&m#@ul^=x ztv=WFY5XnZzjeWatUeH!Qs|jd?%(yD@1*m`+AQeVHU2}#t!>3X6SNb`0oV_p@&K?G zx@DxtTmZ&zxaf!d7Uu&nmkW6VSc3TlU=imTfKj+0?|`;?%^2xR7h^(vKVSvQhb&Mj z836g>UG=yW7?y9I=eC$Nfw02^T_L|v28hG+T-fi&`(d3Iupat)(hD@k7#f$qZz0nZ za`9a-{s%AQ!+-EX-1>gV0Kj+9K$ivELaY(Q902qH_?G%U{CJnX?x(FhlMO1t1LeT~ z$uh4${_>x=%f2z)opbf~-RS%O)s4Dmt-I*5Yu&fMbE&I+@D(@tS1G%{a^Sz{{yEpL z&jQ38z-MG%ARqrVwqpDb`#fMd$LMJ{M&GaRLH9p<(hxUdzfZX{CLR#({f9LH3yuxk z(W4G=6Ar6(w~38_J`0fJ|7qhR{eM0@XFb`U`DuASD_*caP7jVWBn44I2Vwz2jm!@cutq`xm-V;4g>$8 zpMnep7nl#31M%8kg>@>%MP9|M0RSIyyzjfY#`l=-!aeL4;GYAGx;K~>Py2?O(DJ)zzhK(_QUCwMPB&@V z?5sW#<1vg6@?Dtw5Ak2za33H!1BmMYFb6PC)~ID+r1aSgk2zppcZ2Nb6XL&*_kLK- z0YLYU^L@T{^bmK-=)f%&JplIk!`?pF^KZ7S_djKfoCEk*L)@~M@&A{O8XjT?>ygim z#d-A(cvh#;`{-i+9OGE%c1sz9=SvGcg4WZbZ_JmzC-<=T9{YW~pRWS|)+5fx3xx5` z)WMh1el8T*0T-X)m_6;{zQSW?|8a(z$BC({Ov7JW;LiC;S3 zO?q-?I3FL{<#T*qiYt2oO!&d?T;0#MhHC+jUDFlL_a7}f{;_wx=q5h2Mb-$2{h!8v zSt>XQ_%G$_Z(bDsi;kZ%0Pz19wGR;X1myUi{ei~XQTtcB>w*7*+gRh59^V7&^MtW3 z5OV;RpEM*)7q0J1#X&Z>M|1YJtn$J5|DI_>+-Y^0{r_~m;MaW^{kqQd`)Q&7 z^yj^~UoX}-^#q6Gp23+vwB17ghce>Q^(GE`6tJI1S-uSb@D^iLt@mbnxahMv2cY?> zTz<+4z+TD$a50YcWfIm4YZ*`{K3lH3ARpkr)?GsuD0DUx_QPS_w2L+u>Hs_$fVfYW zn66#z_hkS+hrA(s;M+llgUo^N3;fqIjIL8L{;)lW48Zo3%f0-(^U`zr8vo(P+<;zB z!E!+>=v1)ZRh+)Z_5tWyoGNGAvAia==t?CnDd7|Kx04dBmQo||A_~EG+igw1uik2 zejR3*JpNA7aC<&$H*8KX6}Ph=<(6 zx@Z^uIP?gpU)in{-iKp(_~p_v0OtxIo9Md04?S_E<^iCG(CYwDUZHsz*llPU>-u8O zCA7(l(E$MCiSxwtd@j?{g^dC7#|7Mn?jGL}_z!;8^(e)Uxr9P%0MVWxD?w-FV?V-( zM_cjB1uunb0YyHD(@|hwNW+l~juX?r+~g?Xhg5%q)K8W-vS7x{4RL665-C)f-C ztIOR#LZ<-PLgP8cxw+`ec0*}M@SMN)lCzd0u{c-nonlP=<5#xSbpc~{O z$dmXkxxORomCuFlfbE>^B+kWrKCm2k5BV4uWdYdv;U4Dm{j#uk0CWJz)4vCu5BRIx z-_`QlJ#ln*{ch7wJjoq>)lb87d?$i2iCyNcj^4-?}^LuATRj3Vqjb)@E`pRWIa8nkMZ?GH{O`{+dLrq z1(Qy`3wolyzTD$ud>sBWjmG}0ILJ#W*#W!@9zt2U=5zeI#f2gB>UJK7{fGlyXwR>) zpE3aE`Eg&*aiKi4H>{liJ^b=v4}f!~4uprK!fV#CO%82m>cfV2Ftjukjh+}AGV z0Wg2&myPBOt;Xm3AbO0Kk3fTbQ+x+mVtI{+kt?5E` z!aPW*1Aq*GIgperKuo90c({ICTo`f%WL1o_v4$SB!S`j^rMl3;qdlLO{aEd#A z;_>d&H6M2ee!R*Z^oikRysF%YeTTboW5>BuKQA^)(l68@de!jC8XZ|ri?P3j}?i;bUyuM#9KhE=EIq2VkBXL+u+{QiN59J;{3tAPD9he8* zeC04rJ{R(a*2kkRnE$UN{=)`9V<_y_i}@Cq=O?Xv7w-U^4)MJJ{^R=)>$RV<0pd^= z>Ie*m3;>%w$N<29-1onoU!PoI$STMSZG>$npNsE<^?Y0l2weci{kMvaKbM__L-xsiUR?6|qW;oxv zf8OKXKXifr`Yhm+W#2X*|IsfHOLc!yC{EwcbEWg+{q#BvKf`o=n?GQS?(2d1 z?62;;;(-6SV6O_y z#{3n&4`d9)`!*AC^@)pv9*k{@?WK^5`6B4~Z;|)MoEC5&GEbQLIemWgyUUc=n zQvCXP?MEKypR}GA@ArVL%h!E9?3ma;K^LI!_12I1etixw)>QR2&s@*zz8HT0JRl#- zfxB^b02p)j3e#is{(jjy46M^M!nXj)&P8aVR=SLjxg|1*c))r`-2X;djfGgkL%6`3c7<~oX3EW~Xv?c6~alPO^X!m8$ zUPI?!j2}E!?r&=O8U7De9srK#!hObP;lGUiG5*&!fH({Ii)w5@3}#=!a4D{SmVUZA zpSU=EU;A}h?PnUsVchSJE3t10`*OOppGV)?B6GZqFNce{dD<4DU&Pq39QnrOq1ULv zz5)2Ian|=kuN$}i9_b3n4t`$6gdtO)Ow@}PaL)fm#1GgZLI%)#36`^cL%*Q+*Vl7G zar9*zY~onQI2Z4jo(E7^Pt4aY@t)YP!;m46561p12iOfBLcG70g=va$!INk&Xe;?H zqzP>Wq%C2sAN!!OiS0l9~X{Gi@3OWJkNMwk{+vJ%)vffyWHOmKgRyRf4vVN&H_9`+GZ&8 z3zlj;&49tH7{@fe%lmL~kM|J<_V{C!A6$NUEdFzk9>`GlUwLJ0nx5b> zpFv;E{t$ME7djo#h~G5M#rtYI0N}ij^~89%x$Xo1ecM%h zGps+>dZoBJS` zOw4B(bO$y9n}8jD-mF_GF7OXyb<8`Lvwg$10DQr^lrlF{%$hgIKiUo;AO2Go&}rZY z{)4AkN4TIl~84LIyXS=D><@4iP`S>5U zCFuL*o1(wa&%-tb-yUoKfcvnS#TvlHvR}5JRzH`^4<4N<^53Lq+f#!KwO1OKXErMj`w`mf7ZXxu%FHkGo5zRX{7)1 zaR}>{bM@)y?=c^ZeyURQ|JYw%_k-9sC0BjQ5wGVPfNA;W@-hA={;`h0cHk6c2jC5` zf_qG8`GU`s;sQ%Bjzs>jV~5MR3SZaFd@Z=P`La0rhjRsTAKw7${($@32MB8c z^HyGJG8jJb?B%;fN!OviZ}pK^p&Mys!PhdVLn~F(OxlYXd|s_`LLs zSZ4%Vqcp}!Ul5DEUc64@`~AG~h4nq{_w&R!33^T42Z0}O4qvYR9CPu=6VCwu|GEP6 z|2$ie^}=2%x$0Anc#O$d7Ig6W<^XU{+rZ;F%;^H#e7S&m=5s+qJc~SmtH3{$fpIV} z3m3i#=Gt*#Ob-{>jtk>)=!N|eQs*pKml$_7B&07AAP{!>oC z`ohnModC`ZguMXjFi@`Jr7rbSzwx6-yU~XnlD>|ut8+_bzmhve-=6EbS@t$RTHY7W zjXCTvcdd+Xa;5EQ{CDLHAYCu$RC=0MG0$Bi@1V;&S^9CIIzyWGdzbcaqG{ohC9CXs+W+ z^+V5xwv0B-Ho!dC&-iWpY?&LnSY)R8BEx+XvYYtl$=u9QUfW|n`COF2{>5BnmxX@W zE~7yTpV7CVjef33J3o#2+8^?ikN+t?)B6C8lQjTo{$qN&sXFDo@AEF7g-buv_+iHT zZjN-&U7+shzqAbl{0pRSx~I80?{(Y4g>GVPZTKwuFwAQfdZyI-w}@_7>sNqd%LFS* z&8OJ(cgvXrz+ut@_yHWjcurs74a5V#nO3{NchCg%0S?g4lsJ#^8?ZWD%coq#g_mF} zUFc?b0dsL7tX;+fV_>tP>jFRO!o21S-z2gn*30l& zjE%8>q?V<55ATEd6X@F@Cfe==YEx)8jla z)IY18vfYY{axW2G$9Lp{9Uypt&z9<>b?Y+8tMSp z_I*6|pVxV5f82A7%a=FP_~od0;1T2^;FRC@pijG9_Vq2)mt#LyZToPI=*|m0Q|f)- zF))~Q#Ml;cN2&Rgk{+@T%Y*EJemWd`dNKfPJRlP=EnL)<<9J{^Fq62O59>9)5_^f$ z`W`XZPs1?gnc>%Uq93^VHNkAAg{$+6^Xsyip6M_LjkyZuKUeJPilsBYD{M{pEbK_| zENluGM;G!F_wUV;0X)3-?*aeu&YH)8o4{e@r+JrUmEwXInI7YDwEHaCo^3Scf>$6T z;a#=N4LMSeA(&@A7v(`8W&M3+`g^0R(N*(6x?K}fiPPc&>vemkUN?M(=@j;M%Zqtx zH&=Sb7s{9Ew2Nm_^+kW9`$gT?pkFSgAHP9t1NC!@WNyBg=Soe3{#uuFV+HgKx=xTU zG;J{c1Wok#pMHOQiM}1<;4l~|&Sr@zy{QNesMbvaG_(QRX+yG9IW552P_W26xd8wH^@T0>l->|CqeedIkTUAJ+Nvp6?=!j)Pw=)Gc4% zhd#Yf-;MiN8=(8D%fwc{nCD7OgFaH1Qz5vETA9MJ+jGp*WuM>QIU#gv< zt%2sie(;EvDIp6${<&nvj1d2!7l18JDRqF|j`jDI>Fv4(shmNZ!QvBa`wadT+HF3|6?A_V*iydeNXQJPgw?B ztl#cwUd29lh0I5@OyCE``QQhR`{`m10OM+=#heN;7_tEHQDbNvjuMCcbh*OBYvx59 z4)qLz$(VP5eY&2LLjAy#z<s0<@xuK4|E(HUqjbkEPas3J&4$A-r<9XOkma21S9@@oxKkAjMtwA=> zU?$drUlmRsELmu$M5(k?2HigIo@1`^MGux=ySq; zLEZ0`hxdH?KAz!ox%|2wI<1ZuKk9(-{;^UY^gmh$$+~J6<13EA3iac#5!8LF*54L- zwv_w+d@ywJr99u$wCI;f8|ZIy=>UMYSR=@^+6CP~Q`iB}9*`KSah7=NyG%>04_(1s zCJ_g>^(7Ad7MS12nknyWcJ8+raK$ z(+f1$-|M>h^Rsvscnh6=XxkTq_r6>J`uKZvgEqi_ZC9%6P>LUIUbkDcH(a`1U|j(C zAe6&JR{(t$=KMAO!w=iXg%Uqo=03nLusNY_C0CtLPEYzXd&Y3kc%XP5NVjom+o7MB zn+l`Na~y=W3amw38pm@ySMa{hL(2j>Kh}l!#YNe`1h~2Sj=1>d66Wx+W?Sn$u&zn> z-R1IMC3~dkx?O$LatCZ!z}FrBB8<4gI;+yT{>c8drhua%GM4 zQ%j*W9+rVx&ps_`4em9cpols6f!`1yf4p$xbM62O@RMsWBPf}2QnGfbm;h= z`0;JoH-zn7+8fuzB0sFV#2g3o0Z0cwz7=FzjQ4#R0CCU{;GAT%C)fyJ&1&K2?Gjtz#$vvV^EKuZ?=|Mr9szs}?DxmEz@c2a ze`0#BI_df`4dd`md}r`ospEfq5A1PBT7d_#uay2y_%3)arhy9`KK4q?k^!I(;FXdE zASd|viM)XSaWaxFqZogP|I+T*)-|7k=4c<`J+@D@QMoX0;_Cp=et1zXfGhyL0OY=0 z^)VfQ;aRD8X6Z}gnKUM&9miZ~=UAuAHVV5q#HG`wusI#ZJsn3s-CXyXC)2^@mAVI9 z(BpE}3H8xy^skildb|f0&&6S&?u)hm4#7-qzg5cmZ=FveKQIOQQ(f1~?`a(CFtd2TlDp`gY(;++F}^Pl$(n5XxSn3-{-7p)aRBAn_9} zt`PTAZm8Rru{y9T9Op~k#Qd-vl;vHFN7<+Y^iP^z&|8FS|D_Hr)5mf@%yioI(*Xa0 zZzv1$BzQv8uNXhRrLHT+!2WaBcxwfqb4cp|fcYHzdw$4GzAS`!3gADU(dG8U4|#>{ zTw_1=f8jm0PvxRcu(SP^U^}s%*bkR+aDo5ePrPqj9U+659YAUQx#6GDs}vp>7DPYi zhVDB;yjKQ$1@I3M|E!e1O8i4V83f;%*L=>U&66faPxRow6o!0*p~29aA$v(^uXHBP zrM;oY!bT5G0pkZvjX>I{g*63?9-10`&mY;PTc{r?&=CASc!A|NbhJ497~a0!b+~r7 z@i&WupslT~{y(>Gb6xVcY~7pm&f*ZgYbk@Asi^e}p83K&0VYMA_8h##`4 zWubnfKo9ZXAOGjVYmV^^|Fgevq4r_-jb54p#t)hrhOfIjKV*MR3-ucX4F5yY@9yo% z>Yv?$j2=c0O#$NvO^yDSpR#LXp?;%4k@)|Tr~kL{fA$x%{>A8_DPa7dsnP#&52J^sfboN-hRGudAxD#R_N0o1`-vVY{3rd1 zzx*y-|5qyhm&@Ld^`ShFu2-6KqL>UPSr`;BdPID{|3(i|B65u$Mh{JazUGI76fS*x z6YF5%exe8P|M}o~(w}(C??U|d=l=_>|1WyFYj?EQn^vUOWmcXoEB_y6Je zJiICYdW-+^{F+s(R=t(UuL@zYLX3X>&A(PYzl41cP{8=X_(4;^_(4;nd;7?~YoY$4 zzUi z%=}fdzcA@!?TeI%T%(84LsP)`K~tkU{uq7wmp%z8zR5ME`*RET4?W&<@3|fB{Rsc( z%;|>z9i8o+xUjo#b#?V{;&EMT)tc2ZAZNI@_+Qr=;{9CaSJygv@+&)&&oTV1wPWTt zJp;X{TDV|pL&{cs`uKjeqEl>9KY^*4*>%8&W~_T?$_pQ)9@TT{Q4FE3knep7~C z*50H6sh`n95ktI252J^sfboN-M*p{uQF2Hux^~ve!hJ-K*Me8^M|u-q`5hR(=|GXs zWWxU)w=Mjey7t0_Lxv6=%KJXv`{82nU#9od`hyhyzry_gv}wxx+S+H@82;_cb*&;U ztjyGtzR1mRl7&G5qesLC{BQIiB_h}8Vf4@x=xcs>4fvw$|1I1{^Z@$rtm%3Y^k1^1 z+ju`Z?bmIDHoi^pAE*5$|7v8J}Rx|;Vxdp|MwW7x-QKipgV_w!?zlp1LKZ1v%niCm+H(L+AO>~A7lDPvA>u(V`jJUe|uMZCv5&?{9jc)e0b6Je#B?W z2ZsOF-ZcfR|JT&8{@?gvaPvd<+gqq&6qp;}Z+b!s5OseW@i`Tq$#7`z*VHy*y)5?M z>^j}l))i-nxqs32em?$JDoi?A|3OMbuF=Ejp($Yeps8W<)G0Z{hOO zsrjet zZS$QZMd%K+_HFga`aEWzVC^-FAqIQg$&dJ4NS|Nme!1iaHlo4ae(e3p36X2`FnVYT7(Zxg z3_Se@=AT6$oi^#VaAoK*-TglNi|9LZ2JxKSAv8*9YeKfT`$?EM}qVSiu4 ze^NAZt^YB4XbKoVXle{RJhJc8x8DbNv`X#gX5q@v;|;ef{Db|UZ130I-mi0G7yhQM zO$1`^r}p=)%e%j?Kb|-I@7wlc{gu&MQ^5E^Q^VwofzA)vU&}&eqrmjwpm$o2ZiQeU!exYRxLOzmMTRDHgfb-i;ob0>%%T8ixPI52f)#c4`ZiNCBD6kABnL z@^HM*a5ub1M2FkB^5sO8EdOtLHo3{YEqnS;ZM~&&$WXM~=;!O(4gX2e$hG!u^w1PA ze$dn~{5O6mjUTd8Tc~IXG{|`W^gkk z#``$IFWk>B&v@U)|Jh%_+OyF^Q^5E^Q^WAy_@Q_Fko~lUa#ElnST6hb6+hmW`TdQZ z8k&$pO5c_!iN8(aO7J1 zHhO3Z7(Zxg82%eSl*SL)sV$VIKuyq$zl21HyQ|v^WqtDTwhLmejncpg$@5n@yNCIZS>F-Fn-X~F#I=uD2*So zQ(K4>XmFFF-Fn-X~F#I=uD2*SoQxED;gY4LUUqVPA@{r8; zM?-j0#Ml4hte*ABO-|11sTw|f*ihd0@w>NS!+(B($hG!u^w1PAe$dn~{5O6mjUTd8 z58}|1!F$2`!TSjzf#Cll;yEcI;SSgC+F!?ff7^%=o86{RKd^G$Zx%0K(R2I$Lh^y( zKfgfaTKhJ7XbKoVXlfY#8$XoB4+%-$YD2s+)bgrziG)0-OlF~?B9UD zI$7V>QeR(>wSD+4So`MFnc05V>-m0P9x(hTXGX5IZ=;8%fboN-hT*^QLuvewkmSz8 z|3MT^@crL)f06zBqxt?OneY$6UH*}p*uB?vws%flJFlizCj5Ed$Ln&34gdKCA~*9z zEDQ=5Jt98ff1?K}5xGVWqlcz|&kqT?=>+YVX3&HaK~1nUcs_jJwk0x}k1Y5Ro;kBS z{>yxSa-*#Ao7#HQfy0LkN$=-ZZoK#NGyIniqJ9}pjUp|qh$CL3htWe*!1zH^!`g?> z4+$a9ptS#gKKKtgt@p#!`!C^mp4<|KWyb&YuP1~)Z6h|xeE&9)5yJiaR;+l8>3zH| zci8ZsUnFvU{L z4F8QEO5=y@)O&O&5ljlE^9^^nXh(mBef;m}Z137A3IN&Pr>c5*-_7?M{_~4OuC-^Q zho*q>gQkYzz41fu_#q*Wi?v(!`oBFf{OjPg;J<=b`My5hGd!12^DPa7dsWI^I z#lFwL{yqt*o(zVw#{YXlxFPwZtnS;DTHimj+jw7A_hY_){npj8pZ|zxKY!>47OdU+ z^iH+FzpwG$FVFCQV7DLZ-|YKn3K&0VYM4AS(D@-DpKDLR`(SSHZt%gR2=C`CS&|yQ z=U(40bNw4TpA~(75Y$!=Pw(f8_5G_>uUf_DeLU{#u;IV;Cz=8Sy+5(~>91w@XZ$d* z`60V@yIE*ba35>D+^U2 zx2;`9`|D+XKL}*FpI*-|_$vGP4V>}5;Xl7vV%Jjl@3iNe(+%%a5wF(aeVSU@J2%Q` zf1B*zd((l{Lxv3)dw#=za$4kOIM2eMfYBr31O7L9kP?w=^e}p83iOsA5|Y^fUGJX= znxp-CU0YMr`{C;S)cSo{z~2r3G1}kU(OI=d?D^|!t2;w$0Oy9k@#u;q4Es~RQt`LH z)7$u8bGzYVZ`->)Z~UYwVEmw|G5GqIguMQM9RKgE>B@}vn`RQf`L$Bv_Se6T`nQdc zy?a87zPi@Ns^P=%9iv}=<9Bb%H~i-pk6i1oj2@Z-#t)hrgAc##`}gkqC*<)RJG}k> zTvHo!#eLZxAZves3WYP{eJO8eYW$A!sQu^J*~OhwVRp*sotr@4MdO zZ+|~;_%95ge%9U1FnVYT7(ZxgSof&bKa|HZS042@)rJrVDHdByM_T$B0v{A=M1 zZQwI{7(Fxvj2|>LtbO?WkWHQP;J?5>@xLJ<1rev2}u(q-4nF&J!uFqev_RXhv?#BD^`S@Jvu;D*BEOLGR zwXo4gQ^5E^Q^Vv#tOchFU2+_s8?u;SKHEwyuVK{xiedH?0@@ zd?)Mimmer_pEaKUxsB&Z&XU(B8vf_x-|$9;W21ByHhO6a7(Zxglt&(zF2C$tGogfd zmHl_-M#_iv;D3-GZ@l!m{OOslzubfr+$BGjkFd6nd+|WoZ(e@9kN3;>{!B;r=9(Zl zSAGopZbBmR<%j$JdVGI9Uif@X%`^A84?_LD+;56z>ocu`043RlKZgIfIMm;_NjTKs zPnGe!OxF*K(B8@UI=3|X`uo8=Utey0fZ;zml6+}lO@T}cHu``9Mi0#$m7#~>e`bHY z0fzre6Y}{({J(G12k#4LBMkf}o=Y(N#fD{${*DJy`uh;=y9D18vi@#p5Y5)h_+Iwg z`ERx1PPy^U@@xDFzYSc&e{wAO*20~btp8QS5Uqv%IxS z;rC5H!7w_~|Ici?`RYg`&-BFHgha%if0M#zrcVXa`KQ7i7cNZM-#f9$Ten{J(~Tq}9X?+wK3V$S;d>$a8UB;QBeyU5H(jEYr>SA`hVjE78vi#0 zuO)>2Q}h4x?)oqqZ@0C{d3ZG!{Ub2*HO&7@c*@fef=2k?)YOpzRJNW}(8uS3;e^-| z$Z&o~^nAzmz0M26D-rJ4vT4i3p}zh(83%N1*(Umd1#9QkG_{NmI@WIvP44T~B&uMK zM|lF{`Bxc`JPP5D-LEXZ7oxA>KU+}bTK{YG&=fF!(A4M~`D~9J|4#~DBQ+b6uRFkG zLLzPug*xySKi-c*rG`7U>@`0DJUDt& z?CE!iK7Rf72(+iRPFc88DnSTeAb9>TGE4oiU(QmqwrmwXvqD zYiQ81eO-vyRWkm@;(<+DBE(*>_O$zd8mwAH{9gHTUF(e^5HNq6Z|~pncA@cjU*9+U zXA7)cf2K>QM1N`dXDDFw&CmkA-H{%91pedv*_}aWLcW2(?@Zz`z6pNB<0vHIaCiES zPV7%F+tXKX3s<{4xANt!t9L1Tc#OXX)A=-gjfaD+Ji~vsz{uSl`%C=>R)0;6-4p-x z8w|$pxtrpDO|U$8H6b5Q@P5&gu895W+ug>~?nnBT`i)7fc<++^Z5pbEtNm>T8y?yF z_N{)x@L%_~h8KeoZ!`zk`)g|SPkZP~{7=a1igLV(Z{5RiTcYzJ_Zs)Fmji0Ljqg(t zw?+2yZ4Rf;%9-;E*4}hrZT0Y>OfUWMnpNt28pFfB#lyiyZ^M7K{K&Qb-{_$!VEmw| z(KqryU*doE+ePQo$oM^LKRyZ1@zdeF`RVT8Li;_~>l443u3LDcd$wa+d#K-Ukpt(u zLhC>0e*5xEt2;S4AP)^T{IU1#U-`!HpDi|Wt-m*VXbKoVXle`&{P*|cog+V?LUZtb zbBOmlb}U--UJBqzoo;w9279jEt>3y@^b0bfzahCTMEtten-0|b*&6=!Fa8a7`WybU z1xK#+_eKv*0pkZvjX{O~&rEkaLc9n5zn>bflNvF2kEr(BF2{K_O(QxwH+Er0f2y26 zFY5iYz29IzZ+@`j?Ld2f!+*Bu$hH37=%FcK{Gh3^=i&c_<3fAAwn(3UU$|eM;P))z zdqQ46&;EGr(fM?8{`~s(&JgcqKl@q_@9lg#Qq$%)4F8MM_psNo{+E=9T%(84LsMW+ zJFopAW zX3d%tKc6r9{7b_1_-)TP+5Zm9@~|GiR_$kx^XJuczRl;qUtE7r31Oh&FTWzx$A{cXyK)4FB0x(DCp-GFAg`W zmHss$)yboe_x8{2*nH6g39QGTfWCSA_HDAh9`o}qoR8nW&TWs*r+Xp{uUof$`^s>? z+*RrDvUPZVRRHW?CpG|YcinX0f`M0mD~KjlRIw zfnOf*zrjU+38`+=4KwG2U?cxn`!L+@wk=yH=gl>>)w=ffb?B!2d4U3m0~D33-P&egDSfcK43#pZBj_L&vRLxl+!@ ziGGF;<;4f1=blZ^frkI0k82fm+<5d|`0ZBxm(|z4S6V|IvaivjSb97eJSnH+e&AeV zIR8&PkEj^x?>n%gPIx|jTib|Dp?uKgmaQ9m_wp4h9%FjLt34a9?E9AY`}Q~fOZjUA z@84qkt!o{7cMvR{n`!s-MXt#MMh{H^;|EQRzLA&DksnJBvJJhY2vT*LXvt}}U+rlXeVYw^aK={k}EDQ=5Jt98ff1?K}5xIRq z4~_rXrI!%;aH;IL^IkaKUnC3k*#4PA818Tz|MWWa3vDeM+_u#DxGT;WV&~(MT)SQW zzq{d;)wg%@7S`8bKA#MW@%_^0o6lwV!i8hz|ARX3^5gBnB;3pN1N231=8lCy0i#F6 z2mEjJASEKV67=X1{wIRp2k!>ybM?5MpS5LwkPff!=xXoUBKzmhtH~bkSFL$W^%vGZ z_pX07`WgM$_TZMAAL?2!To^2UrI}^i@xYXY=P3Oi@t*e~55OKE-4CQCfy(t~EDLTW z`b*0{Ljj|2h8FPcj`S!2|L5{;=ej4|PHE%}v%RaZjP~8LQ`gFPzpbTyliL+q_$^p_ z+WpHPdd%$mQUoh^|7`gg{wUF!vnJF$=__4D!G4?|vPYOAl! z^b7PwZl(vZFeqU3i1>j2jUJ>#2=|2RJ_g-mEpO20C z`kyO%9DjWO$l?`eWaIsX3u~*h^?Sg3zrC|x$n-2xjD<-VqX#Hp{LuIOP!#^Bszv;N zP3Hd}ay4BEiJuv_zJHr+=C|EFw_t6ftnaHI5%mYy&;O1Ut5(_kzu!MvIHG{bCzX{? z>RQLl*Y`9$o2i$t6Bd}N<^;F!|0(Y z&>#Gu@joGzaWbH1opOb1x`OwEKL>xt{kZ*nIUjJ_ zd$(Oad|2st@ADt~flQAO#aNh>F?xUk#t(hX583vAu7tVZqu*Wj<}yLefz7<5}2z?u<0v7qZvC;9&f*z1Sq=aPTJ{r8@q zdkw>H+`QL$dF}TupE6(4E@Ar6eoqYc8OC`%syUVo@0ma8m+2?yi`>E3-)aij`)g{L z{Lvr$pzuE&--r1BLQN;}-YuC^81Ef+`|H?LC;R<0iGgsm-yhENll}fgf#~-K7LF*u z{?X`R^Z*5XeyD4GBy0aY?8l?FKsC^V_|~n?C+nxNpDTZ#VsBvBvK=pO*RjS(*8K;CsIPcrgDj^KJE+_9ymx zsy+7C_ay2J^8VK3kMxXj#1Y01Y#Dt_kEeqFlJk2+br|74`wP}4CcM#Y+Ss)~&hKez zsU5y98O<{K<9oyVzQv3F>d(m^R(|ikcWOVLyGT#qx9q={p3lFn!2WxWu2^w~Jo_A< zkM`dirsQuqUrPiE-tVvPmFZXL>*M||RjlES(O*+w(DFlP&{@-UpL7d3@gL{+Yzgi6 z+D6FvJ#UBO`(^9K-o5-`+rOv3`%^1FqCkJ)Sx@O7;eF=(T-fjV=jZ->Wd^T(`@LvC zp10C?4*h<8?Qk`p|K`(uF`r-R`?Jp-wEeBgA0Y+o`?DoPZhz6^A=$kTe>w4glY6JV ztG#o<+6LLbuR1+{i2iG}+8=ax>wm4jy&JC@{dz~g=sdmW=Mq1+uAZ`RR^Ib-r-bL{ zGJRd^sSD*ez4ZPWu-E@U0scV!KJ4}StG~1I`xkGF{sW8th48<smi@_mBZFpU?UfOCRh12Uh=Y-(zrp58(e&7sw=jbp9{fbDA&K%ba4nbC)C= zYo3w)d!4M^@02-!-@g3PYL`rY!1Tqo|2-u=>>EV>`H=6E3U6l^>l?+N*3V*mCgIcw zEh+Yq2tSre-o9DRN5y`~uS5}>B@BD-pd|_?!}SwV9v|ptA3oUVzq`FJ^z%!fpL=fV zgFDRU=R05LkFuUm(mu!Z^1PgAlbfQu z&TU;SUo+X%6y0_1wEN}0&~tN2Vt8~#qH3{(x3`BSI-HJhvV^y}4apAqH&y0ef??IE z@n15MztZwV_w{1zZ=>AoeqYn0uJz&vgkKs+f6VXC%CrA&YQ5gVO!`y1ov*Ve?3ckl ztz!LIssPKMl#X1ZhtWe*Ak7bn41Zw#pOdqE-*xvz`};IC&1QeZXWe?Y0s4TWlZ{mw zeZV%sqeoY`WasXw59n~~Wc=MI@A$mDZ~ON3o4cll;k!iMiFQ?4`SQFP*-lmPKKiBU zQR#3;RKVR`k^GgG2U<-YNRd8t`WoN;^19peow`tl`?FZb-z?6*A0Om{rZ%nLAG=%X z_xZj)eHhNP8~P$Q-5;f*Eo}7B6fl0!)TqpU4Z!~f7km)B7Cf1d;$|Kg$-yq{}hQ0T1 z*Wry9)-ou1t0(TCwOXU## z_ky{MgA4lQl?S#7x#fL;|FyLvMj$=jXTjP#9uRYZfhm7U9S00QfMD_~wLboMziQ2x z`E$jfFUrk1tk280KM%(HGTcwgYmxna$~>e8^(nRf{gs})ZT&kb5xGVWqlczIfAB+y z|EWrh5`02mCV2ED5Gf(?OO|l|@Z9J9$XvC+ziY>SfYr6nv_<`4m*5fX-ID1JuCM!_ zRDYce(SJk7wz}3+WIjJ=h|u4;3q<>W&N<=!YEQTa-Gg#3{0*n4M7PKI@0atwSZB=5 z$OI8RGu#nLU(S7VVGxXHYijCr+b~5V=PSNi7X-tGFn#L%)B1o^II?e$4-?rd^8A;M zlzrmj^!W77wOe7&$n>Hw3Dhwl!fQyUB5SG{;Id$ zO4AeefHK@4%IC{nzk!+`**n9*QH+I28KVa%VEoYc{GjnatMr=SDTa5r-#Zw+CnQ3S z|LLwD?~wg~J6!v1my7XwTU&jn=mYSF@r__@-{8OONF1GqI)0jLPrOB@^IhGVgh(_y zXKYArlhHBk^@5;T7F@Ic<@*8qHU2ZcRJS<%zbdU)Kzf0Xrf%f``=@7Oqxyc3bAAA} zf{+Pt{z7$qo5){D*{^BS<^^j{yMNVV0p7RWZP>gC`ew0DyLA2LZJ`As>>GB9eZ%H$ z$t@`3ZLwc`Vu#oxCO5B_?+JUxVAXS2|M5;};TYLFIteG;rY%^%014`0=yZmX8#D9qzhQ&YxJd>Y-G9K%dg=Ra5eg!f)))SNwP%`}t*!_eFl%r6vdl zDqiDz;#aQvk&~@|CnX}+=wbBG6zC6r(D+uDXz4%06NA>RQLlAB^LDzCY=k;UoGY zH^YGz1_g{B5g+is(SwwT+)B_R#Q%oidHf}$7$<;{f{SkW!rF*FeM1M%16Y>`TIweZ z?@Tp#=#%yNWNiO_f6(hNv<>n@fBwY8=LGqa(%o-!Tc1t@GiIDKi}|PPi--rG`*b?o z-Z5<^1LE$b{N?nP3;+E(z2U@S^Yx&C@zMLvNb3=za7GR(Cj8u0pJ8^w10Bhkw?_7h zO*fo@J?7mVF6dSM;42mo)#tWlke5VUSQdrvWO!i|_S1I@?-~_7zbHzdX&s^s5e{`5 zx2|resvi;AM<5O4#bjqE*|p&K7W4bEe!rRdhx7Z&KF_!BgMMGz^G{tX=k2X}Y!#oc zSbInnFi`W)e0TaHH}l0T3U4k9b zpNf86?u$YDhGcZ!pVHT?;pSB0=>-I5F z%1eKj^oSygsYHLqvfx_&ni@tAT|6SoL z{(St0{hv&Kjo^LRpZAs_!-n>oJnX;EKnarztp6n?BG>3)^w1RO4}J*ozgcQgBY&wM z?7Q%n4!1`=9QLP!y?K|6wl~SO66>E=tXR(euh06McDGsn)~|f|k;SW~O`DcXRRHtb zV$RkSN-H8Cu>Sq!M)=>B)_Wri`^o;QPpRdiz5{an@4d(evVRr+7%keW@b8azi9Lk; zH2w?xr}5vn@2isWzS#Gr_v`iX-VZ}RAj|o(*7Ieo3(99d*XQjkRbaW=bNaiazfcs@ zAN?Kc0@upd)G&GsMt%tKKZX1WVFyvB%KZOM_hHWX&j&a8@Y;Mme(AW5Xv+&_t3m2bXYHf4i zzxyj$?b#ydS48;V<)*!}*Liw>3gG|v@#E9;^Wk}X(jdrxKHf+A{0s{Yv#8%%9`64atpei|8N1^?cJa>#e-mNtL z!~SoG=xazwgrUD-xLCIv{-+q`rURq#e>6MP<;K79&4nxFr}^ow-~DbH!(;D%@vKfU z5MbEHf9&V$o;&$u-e39hNA6y!>;Wsy|GR7c{Eh>mzhhnCT75J%j2?rLAL8(Tx|@^~ zi-7mZ9qjMY;gmwPYR$Zwz2(RI73`lnM5n)T**fe;^W4eXT&K*+CLQb%W}P!LZJ(8{ z->~lobAn45G`EKo03KsMUh~WFX@4ojQ`Ps++H=n*x*7MVz zFj{}IOUVlrW&Druk|i&4t)b4M5S{Y#(E*k@tAIrh(Ce=XGwf0v4_|L|aM2F=~WDG=fR&TjguLgRnz z7lri(tj3DrTLQ!PsU-qM|I)6rHJvOP+F~kk+7`lW(a|a#;E>G#XBg}K@{Rwe zuAQ<_<9}KCT`IAs=9l?y^hIvw3tAWyFnUCM!2d=MQX+E8Mvp`=34h2B_|Fy2ERFqP zIxK+S(JA}=$^N?a-u@c;x!{iBZv2&sz<$CqokMmEgzKZ^ z+ty{H~f#r^Q2F)@(T6{!_T>)`;HLzO4)G}elXOmlwUr5F!Yl_@SS?ehVj5;(JS~FxX3GEed|LJAxs@62Ea!nSFzF=R|1N+0a1*;tCzhLc{`PVdGa}C3o zf9o2$`ngP4>}?=)V;xGt6#g?0UL-w!{xgy~cDYhyTi zexiE+xaS}8?sv3jKYy23pYdM$HzhiyBUk#WH7}lZP4g?NKX_#E%HjKrXZmUH zjG2GF{1^tmee16p8yWuN&12@boY2z3@XD9BuD)T#2OlsTz0b4h`bS}(KlJyFt-tk8 zsq+H2=LUA@Y&r`D`Cp(XPC+=}9WA`@ z(P#(fe`dIf(slhK=@lJ;VD9sr-bDJ-v6cq)zIA&jqL5`3aXRW-ST>>3BSXj95^e2n ze0ZGSmsb~l?X*e{p?uGIw{#+ILdR>rn419UMR zq5O@FW9s=x`uwJWvLc1|?Zd}Y*<^Tx^Pf0X6{~5eSNQPE@RoQ{nf5mV{!@H=h5tBz zwY;cE;S2EgOK+`S&E)}q>Q9gCWx9R%KyyJ*+dtcf^XeMt12{c0wEXdMx|jz3VLi-r z`|!@@=mA}yrlA!b?ZHrp(=k7&sn_w-zT?MFvae25R4D)I2=Smr6era{GL3lTqq!6G%E!SjucEvmk-ADH}U8als;;NQUi1FZ!A3jb+-`S>JV z{JsxHY5h+Z)0nSh=wcfD*nch-V;bkZ)$A=*_35GWXA2B@LH^pt)ha*ntFCMS@syn_ zg7ayvURCGE%_OgqF5@xF4(=ikA`kOf9%jaWTK{+bt2g-@fd5xN{^%p7L+Jx|75{1c zruBP3;UUKJz_?zo5}wvg)r?f=`sCHoY3N3N!W#oWf&YOqz5eexMfQ%(dcPXhvsU!F zn$KJ$eBT`1tndx^Tt*ka59xmVC-_(RkNH4?F3#URToR-3q)H#rKHM~v?Cw_U%l6^5 ztIYf>Iw(KIOXugu4_C!%>0-KR$Xg%a)e*Wl-H)F=r^sGo#9N8j_^#(0_@0sI_A!2b z*S?Zi+{Z zh5wOs(1ZU?L+3(mbn)}YQD3^4#(XM97t_!;T#sH?_z#-oL%kpMGii!97u&lxqtd}o z1O8<^|72l}=dS)n={H@vljTG3d11AuwAY<&ug`-2Z>Dln++TqIAAR)S-eCIfqwoR`$;}cb$^*`ymV=eXd#(I;|i;D;J^H1%| z4J3^62yg3a4BCsgH^Bc@Ui?3X`X{)2tp6)UM&4$+efa5pWIj>lr>>X8vf0+noDP4C zfr<)+w;L{1dDj0}-xt%x`Dem^%zt(qJ-UPQWBwE#89Bprg!BhvMt$0cx5hWu)^6tX z!V5M(dzp6hDUD-HqkW>+uaoDQbHQFg?%ry?W1qj;l~nVcnegAQ|M#!|9sU195Apk4 z{6EKZDE;+Sd7_aAMjw=~Td2|tFA#o?Sjs-oGkl;m7CWbCq(`HhmA^pPrmw5{ zPMGkPv;!(X^xMV7x_syh>g&7J`(UpxrUfq72Y6hWVal?o{;~RPTAvR5jz$~Qd<5(1 z=twHaPeju9b&$SVm52H@G+b5nA^UcX!jpi5XJ223v-iQ3@BU36r{QtHY{D6N(L4hux zp7+&%1?m4kRONyHBO}@#6dAghdj5<0`y%NlS4~Z7ejiWmAbFYceP6Gkuc7uc&Wl6; zpzY-9eM@b8Sm@sy8QL1B<0u+g;9!q3=gYP}pu1a*ACRA9GOYARn6D<2ID*5uAitJ% zP5Hmr&(j3Lo1XcOrv1-@P7H9m^L$D@KNG*5_gfi$-l<=q^4Gd?eW!T4$29#FJKUH|>tpD$&{y)DzYmC2;f31uGd)ARe=_~Tr<(nB9l z)fSr1kEaTZ_#sVHo*Mk!=l$g?@St?$*XTCg{)hT0W4>LU|NZ&>KQ;FCe(9)9Ha=NR?Dei4Jb!FV#A-(v>9Z&W`IKj?dv^1$V{ z`Muyr$j6U_Q9jcB-{&cxzONx@^7CS<*l2G&|Ef{GzrI4>-SOy7^Ox|y`BwOkc!SBT zK5qd2qJyocSF%Wj(nHmzeTe46b-BH#mHrO>$NEjzk2yciGsw0!C_KEFI={($emr$_ zeffZ;x(WS^qdN%bB+0M`!Ma#9n=0x@SiCzUHK)> zzl-)OeSt2fr{lj*|3dmYQ~$Em<#VpT|Fhu#{*>O|hxPxDXafMZcPJgZtNZ`vnm_V> z!BduX+(jN1mORXi|G~${=;Ahpze}{YK&^oC34H?`8mbUW=2rsviB+lSkSO#MUq@WC$fUs}!ikEhO8e~B)p zcacAn7yoU4*%nSG{(I~%`TgfYrhn8-{mJ>B4z>Pt^da49e)HL$&t!CcV85AE`iYsI zzuW1~_jP^9^>e;Y>woU{`)`2%b>{kiC+!bQeV9`Gx9$H|Kl%~Z7xwWKT};omzD>}d zX>%6o^Fd!#D(2aiC;1oF_$=)u?ZsmU?sr-q{P+*NHP@fePj4Gb1h@{s=hD43YCkXG zeQO|?QtN%-`B=-_O1}?%e1Wl_1^%(gjMkUi&j*s~dH5gGcGwzzAN1|yFQn!V7>~Qj z0HxERpG_+Le}w#tYPV_qKm3t$i%KUrf8m9l&B<)5dLO>`$jbu?-zi>V%=}*X_n60w@qhgFao?xv@20Ew!#^x*%tx_bE$G=lXUhk_ zj{N8H(XU&!(YW zU2z%!`IRBE2egjq@_^Ug`jS7b;XnKW+2=F-Fx@f#@qMr7dD#C4%C)~U>id!5po9Gs zxB6bpH@^2_o8kxTEhhglp9%!R16-x1p-_77-k1KG>G8vPbp-zk|IvQI;8-1}hiHE= zJ)dD3_6O_g*t<*v|4sW3{3U4q*URbfS0-+%`3lvK;;rfZ&G=qxYU(=Y2VN5U)qKo} z&z5N9^bNK@hgseZ+HVpp;&hZp@UPyF`6j`?#($e1uQzah%N}?V zKSLzH=KdDD{#K@3=RaB<2y`ocHrf8IspmNz@#0#H`6>DTQT(4bUgvb+|KHLEK&IO% zo=Q)9K@ZcI&rVKG1!H^Mn7UK8o76uArd(15U^O?|=^PL;dSLDqr){X^+qD zKRZ+ZlJup857OR?yS*_!gtI1I=J$6R_~~zdJHL?*I$(L9H~mXL&-3K2tnl0a{A}qP z*4OjBw02+dzif5nRwf0g2^D7>P0 zs@0o&wf+J7y`$NLnqNTQQC_-I5VH4r>f62w{GX>JFb)c?0S!y5BTf9q9d>Fp^BC2d+|Qg{s#ZU?~PO# z{LZU0+ZXf2vVqfQ_mPZ(+RRV! zKxn_Wjt2&PjA{RAAAVt&!apc{?K$;+o2f5o8ai5S#(RUmr@3B5JePu~jz9lXir-@C zaB_CM@x~~f5aC{NioZ(kqDub{yffGT_@1j*KUMmF(B+1`0PiFADE^>4vp$6Xk50pX z!=5q|{x{tK|C7POLasmN1A# zqx2&fFDt2m`FZ%Cn(d4Ix+D(D9wg((y&XSXdrp|!hvxUN&vY{FZx1)Wl85Q(_VfPo zlt0u>@)z>^u)d)8tMSC2e34|BNTzG1cGj zr_3@^fJ@-{KwcI=GIrW zpTB-H(eCrAelz8l^m{u#%*1ctGlh3;WchIL?d1xl{rFGu*}HOcgE^eubE?yPv=)Ee~k9wV}$>!RehZJs--GF%BT6k7{4z<`#}l{^!`fN zFQV2)Wxs$uo4!xyCw&6x=hgbZo%9c8yw;vm5$aFfYW)oS@9Qg%^ZQ);+=Z&)4Tp(w`Wa0g`-vd$zJ~_JJs``X*^K&d+0A7dT{S^Tz-7w0M1V_ z>W}Y9e(w5XJfZ1DC6_~qfd==VF%2UR?4r@k7WBldW7MB#J9uD{9u9cu!Cwhy_!@rk@T(k2`B zQp8g<`3w809?ua!`U_t;t@1}~`({|}S9jhwSeijj#w<@~^3!@NxKTTq{gUQQ1o{#s71@^?hMh`6!868-D6$6i43 z7E)RPa6Hwue)3F4^*_jW`;HyEx%?aH|8skz4V-SrgWYa^U)TC_BfcE$>8Ah1iBpJo zSEHVXJ>BFFzW?;dX=NYr>;Kp7S?$CBE%83XegyshkN)=mQT~5quc>ZsKBxGD_RQ_k z@2B>u8*J6>i}&x{`|_>y7t`$*2L9hje>i|JkgzCq~F0nWn=Dt^xW3#s7be zY4n%3HoUc#Y1n_x)J&=MCY_J8C)e1&jOQC0w<-Aqz84f|dmrcoIV5v=IA5`b9Fm#F zco1zJRQed0o8Z~ z`yhp5QT{iuA8t45gYm_*FOolWJQ~&h(y&j`^1q$mkNQm3jw=2EAIG&w`{4tZM)ame_H_zL8ubSNF)%XMazm8Z^!`8KDIxKZ57StWTJv=P4e7k)NLL z_)~+%^HJk@#FH;JXj`60ptwNjFKPHQ=)AgwQ6APG(|xw`C;4x0Jctng@9)$08O*<5`r+#;K177@nBtAZxQTFn z(FwYk2AEbMQd=#U<^bEh> zmSdDh_OD?xz82=o=Kk7eNdMVR7nkQRAKzbp?V73*#;-=BzkoLFZRn3P;XlE@!hdId zZs0SWuVnh;ki9eR)hCW0HqX=Y>*LyoFQz`Ai@(P|zwpP0!T4l;&q0cxQ~rf7O!D(R zG@g*VwUQUu6KHy5%-6{OIHm0q(w}dyKMVhs7XL6GF~=vYpUm+C`uHYsr6kjX);SQzW!2HJ>FQ5E72f}JShV@sOXZ(_QtIS*67h3;wT{0MvEDcBcffx-AE1lVdrobQCrIJIG{sj1{+BWB z$N%=>3lxtfr-0K>IQB&*Nxx|0zbem<|KQKcl@)6J4}0Rqjo(ah0i@3(`+}*T$Nm_- zA7&c<+vh3h`e45H^B3=5&E-M=_z`*qdU5t)_l#IpUit{V?`Vf9Hj;5>YB| zlWD&reSpV)XP=)uW$vFP`=ha++Fu|0eCPpvo>Y&|zKHd0ea+@(?k|4*JoG1{wUcUo zg!vHJ6Kgm>>=6w$+Mb5``RcRD2if;ce`5GMo9ln{ zXAk~&dG`~!>wl$^1Af0u4CeAtpFmije{K6a82gQ|pE#D)=aIl4Ji1x?bD=!1J;-}L zhKwf*dpwc$ySMG<$A5SIuk4w?d)lw4?28Wmf2{m3{PBOJ{qAl1%{P7nA1X6E+S~TK z9j5&b=}I|F*`U9E+0X|eT`7Ml-T!^l%U{t!_9lgwIPaIX^C}wqLw;e{2d2+g&TmQ> z`3X-w&!c{&o^-Fis)_1rd@k7w*6nHWyzf}6<#~QZ2PrI6{X*%d_IdU9-t(P8w0@uR zrPX-`l4TYz6-R?MIV;$LWIqv*WkOr|^sW4(>}$ z9xy*J{YSAM#Ej2}_-TIoq3I8f=esGO4fAlR@lU>2#t)YL&oh2t{X_mVSuO+md)ls} z=HE~4Ia;l~jVufL|JS<{ZJht;7}`B_@>W9uKY zT7Ln1fC6_CARF(E{YN4nOG`eaz3*&$qdyV+t1jk`kBs#_xg)Fi3c&whQRWFA(~qaB z$X-~X@E`qkk}gh{_PVp}CHxeAa^J#TsNUi@7e@)i^%sr9s`6k~|AHg5pJEeb0e~|uQ_6O|uH_y`zQ+%%mx;PK;zB3#i z(=?s0G}yG7>F|ZB_y8#gn8tiU_Tw@)WW15_M#dZ68>Bx-e~|t#pZbFx?u%Ov8R~jV`98 zJ?FMPh5y2T?u)pKJcvAqJZKIq_5RRAcum~MFh@e^Ep*<-wtA-F@1L97m0%k40rPx- z$k5JaI&NE?w{7G96z7)lW~s}Ue81q09t~tXkp3Y3VLtT-;B{qXc{$e!@q6m&VtOap z`)RSS5FPe_?c29kayriAEGQ_*Wg7neq%KhV0Y%wnl{kQR%Pg78tZ?-f9A&Ax2KFRGQMbO6nT{X zApJr5gXVz0KLEcol`B<-@x!+MU&Z@_{r?jyqwN3d_8hGyb3r9PAowr+i)8_KzkCTT z@*(n}IUxN(`h%8+xgReh>H9hcR}T(yo#5Z!-P?DFX{`VE2ZPH0U)KL3zbqTL%XlX8 zAo8F&ApJr5gO-N*H$K|u`x*Xwk)gc0v6hw=t~23%?0?AJzu%zayLZ3kiT5+Ix3rkk zVL$lz>XgzCi2RHEvuxll@*wgc@}M~&{XzPJmWF#jJ_7&4NqxTGGeadYf`1eL<6T`l zc5ofB{%?!NvrIS9e4&gkrh)%cbTKXRE%ME>fV;?p$b-m(=797E=?_{O?)~@(ytb}f zQStlQhpXZ(4K+1fC*b{cD^sNDl2}{z@BWTy#0M@e(&ziw=lgZ*^8iG?MZQ^9a2I(H zc@TNf9FYDX{Xt8^y&oTe|9y0E9oFqx^FTLUOauReg&iv1?}fIK*yhcfD>*$x{sK8U zIqH1BP&y>>ewaCQm;NpN+YkqlhfhQvL>@E;WPF_4{xBW?zda5Ale-To|3Ab7sGy5m zu!-gmqoZd;-|sR+8jY?fimy;e%F-xU+_Ten?GP#!Cl5f84pDsGzX+VNPp1MaPP;*rlIk} z1pgVXLnOU+)g)a^W4+&*)aUsC|9>*5;{ip|Utd*37v~pw7I|h_z+L1)rzAEw-V|5))5`__nHhAK{w@965C@S5(SM2l z%jgg?KF+W4F*0;Km3(W%25zF`T~)E#jo$tK$+rA3rypo8iCK^Q(?^)5{r=TtA5i{) z(!TSneWg95J-DypF7hDqAo8F&u+;kl@P7kc%#mZQC9z-8#WeK)g@wsxrs@2@_(*g_ z?f1j;ue|a~lGB$uKjr&neC57?yU2scgUEyCfb@s?)gK~52fN;)i(BYM_`g4ye1p?N zQ`dWXnBGG6|713+?EA9*m+^#U1NWug zpXB?cKS+Pj9FYDnzx#s|@29eoTP(l7D!#4$oApeSzh5jjnV-+}PKy6W_@8AulHS=| zQBdHC_cLW(=VZYH+3zI#om6j-`H|qk{Kf-mpQY74J*U>~NoM159-_t%SHQKVlmGfZOR}I+8xnOz^Mp-#y@8L%a6%bapCx zz+8WyykEu}mQCD69z-5Q9yAA}KP>J30RKG8>U)tTqJ6k3*3!~Y!}LzF?|=B|rwY$8 zAJ`r2{1K;z(s^}d#YJjqgTjI%7O5r*1|3|OCuJr%mOI5KHU7UZezenCL;|t3o?jjE&4$p}$|d%8b_oeSc`|T$Z1)@&AoCln+;k&I8V+i_=BEM7~%S za2I(Hc@TNf9FYDX{Xt8^+>ehT^4ALtHm>G6t?0zZ=@nA(U)9u5d^u~=fYJb2&B&#%Gpg z+(jNl9z-5A2j+W!aQxS-4A(d^R22&(#+3j1e6Rn#t{>({8SA@$#QbU+s*2Y(X#57= zC;R?#H>YENKW*<<`u`1=N@BfqaXS3{Qc3amV}9K0_LTPtUa{=qF7hDqu$bk+AD^yi z=;?jQ!rd|c=3V=$V)e8jWqPUi2YY{CG8txmgwiFk#8~4trV-DtKc(aO+4z6;YLe5j zzu)?czo=xI>;z+EPe)-L3zb=}>x0d~a#7+7F2G zI=f$emDBz26I#Y+mJQrR9z-5Q9yAA}Kg_N_V7;HoTv738$UiMsOAczxQQ*~%qC-!Z z^r39_|6{smxGEkU87O0VvGbqsIZgJEB!6#&_TvQtiAJWM-beBKzqwKQ=YxNJ$+iwo z-`ZS7z7uCRGaX8w-&9tl^qy1qb@Zf?D*oSM=bwC^j8`oC zxQjf9JcvAK4&3Sffc0cDtnKqSU!L$@>Fd|+S)EVIO|_l{UIp6rd+4cbQu+VEpWR&V zhtf~&$;s7tcc<$=*X7y#^Z4^u#S@L%pC9&-U;E^`FT`F(tWPKSKcq_?qb)5S&^!s$&jM7gZ zXswE=;B%A-_}{%hsPG@_doSJ}Xe|gXUcC3qH~Hgrg~PkoGXL`XOFaJk;Fp!u`VZ(w z!r`%T&VM6+{>fiy#P`2X=!Mn4q`joQxUb_b@*wgsm-67~_bZh>Ka&3Xs)Vs&kM^I} z_0o<$t|Rd4NHSc`H2l%6?N%kz*neI?3w%wJecE__vB`TVeIMEL1B3j%5%SM#tTpZV zWbatswwu$zzhGhN2-7P%-t+tOcbWeD&?gZ46#o|+|KxjQ{NuiWyU2scgUEyCz@6?7 zHr{6{zsqmH{(KYfu^#;wJ^MR39eA}nnaOCH&X+a({hjk=i`9NLl>d(54{)dJKiB0s z^CdmsiKMs2S2woQGJmkYp|`hB;Wha8SkgSNuO!x;*!Dkh{z!VqnoPNQKJWP9&Q6_w zuD@5_FXJ)GD()f=A`c=DngjE_KQs-EAEw%7xW=?UKTg}t)qXR?m;0-~JoF}~1F!m$ zN7VY%)=!64tNne@@00t!f%nH#uXJ`RyqoX*m~H*sc!pu-Pbj^!+4SEJ_0#?b!#)E3 z-Ji^! z_lExdygI`BF{a_qX!=8dUw?gd@(`zk?(96I=0oH^f&GpZoDTnht}gN4XMV_dE#o!I z0`4LYA`c=DngcWS2S472(p~Gx9-ZJ4B18W8yH)Yt%+ys*2VNyZogGZ)_dmIY)CJ1E zA0mH%BEx?V_-Ok7&s4wpo<7}Q-?zTM0p9=O+&QKH0RQ?@NrnGU(fJ0^=!n95((kV) z^?rc)>+mn7<_GhgKTiM1{bG%^^$q+3^!Ma{ z-=^uR*jS+OF{Yva?|bv_o?sgK?c!YRpT5}e-rru(zh^S#|5|@Powrw8ui_cOo^Sf! z0q=|MFHdp)o>R*or@u2yBR&GD_Z7aQd_%o2!+dLH|^0+t}>3-v(MK{bte>_1HY2ltg`Pz zKQJ<)?fFfFSO4)h8u9(_U+6TxkGPv*4#R#w=!>`iTcq&dbnq(?E?4#s%m)g?P495} zGZYWO=l=+EzFO}ubbd+wWjtnC$6e$>O{v|1p_7m*xC6-WO&+VjA&}OuWZ_iVutl*WH!}DPP84mPOn}9z-5Q9yA9QdVlb* z@7sqjrmRfrJN$)Bq@SnbbQRv)=jR#mbg*8X`tU;q;lQuN{{Q#)`FZl+uQSh!0X{0{ zKgzVw`Iny#^;5WAh2MxrKzQHC-%ofyZNEcj((2=M@Na*x-81Ncn#kk$PC*uP+eFSP9;xt*QMI34_J zOSY-`0rp3j`yC1|>})pU9WHkNM;R|=yyU)tyU2scgUEyC!0q-22k$GDJ(=R~#7G_8 zz;D2LFsDu{cRf3vetABvP~8i7)jj!I|P_N;9p@d(aH3Rj;h$^kp~}S`i6LK=vQvH{pEQXPg&M*7kLnQ5P8rXSZw{l z!Ta*Z_zQ1{_u4(*#{2Qk*Of{hcy%D0jPvtkzxV7XhyUK*$GrCYUl}d`fECk_4oU2d3B@ubvE9QO=^E}XFZ=Z?AN4^ zCIvn}g8lgA6wrrh%r6%6esaS59i-16)Ze@O@v$+*9$TNElM@VaI`BTx*%@XU`V?#X z=9Ns-{3~waJ@{udkBo=1AL|D!E4a^gJdpf?ry@U^0}HJ`IO}!G(9e^yAaaztQyvKe3Gycp%gM-Jyo$mDuAEg z8qcdMGuGQS-XyXfdwg5R{rBtqgzx*ceg3|VJYZ1;r|0(*zE6~?`2h6yf0L`%^Z1^R zIWygtx_o2*LP0R((dTEUlAX+=3vISOzmjRp7rgVQr#$ngrOr?J{-r%$O8ZOu^H_=d zT+4&A9#0y0IDVMyk9 z_Tf}8pw|Du^Gq_|gD-tY!U-%x7e6J2|s0gGv(z@%cGPh^0k=d zYdRk1Q~Z>q!po+igIz?oG7l)8%D<=OvBF2kAG=enpCjpGw0~XuzX1=uH0jp^S5I)ApCkaAoN3$BUV08{d=3DK6py`Qy>w%HE&fzlHE-!0@-D z^Vxf~e|`J#x;?$b5Plx~OL*u|zqvnO#*f*JANO_qVi~bBtoggMxwIhHm|w~KiFt#& z$k*)TOZc_8`Q^q-HO7zM0-hP;$MF>5m-62VrFV4^y_x%zyWTWt#ACTRo)wV47NLQ{ zGw7E|yQ^thAI>YYx_!WKWBX&_2GH1(f&J|qaHk8(J^4u4|pDw{a?(^dyX%N zXIxQQ?6Kc3=KT$VM~fSeqe$!({VqDs@|BJSR8|z=_3udB6%=|GzGn1z0Ykah)Jb!*aP0w%E&)e%~T|V}& zQCoz$J+NP${#N#Y5XDm^T0Q^NzHb1Z)p&i}w%1yUM*LOEZqQ`Uod_%1#`8Ws-iOG3 z&})qUSdZrz>v7OxKj+qw`HbMn(!vvI@A=i<7>{ZBtMH=d)O{U9xAF*Oug}LC)C&7J z;dzVqyscOtJ;3>Ai{HS1dOXX|yY}4)rXBsTw(q{*27jVxA*bKhaV|v9D?Hk@5BA@v z`X1=>X*Qzp5A&7iM3KsG;}=;JxIEz3gl9c^zB=i_vlShdht8`r(?1y9*=*{|VQ-Ea z{PCyzX@7n{?az<>XXg8{|IAyz}1zs7TE z4`~lQI!zy+9J~*2;5;_ICt5Z#jrIEN;QJPPzqH2lW37JwEa3Nq$3H7NVy-85HjfaX zaeWXUe8TX@4y6xvUH9PG_~BkdUySdY3Ew&myp#SS{e@)>caaB?2ayNO0qGA5yFXz4 zNN^YD7R7m(gDrYJ4}JHmq=4u2nbz;Fe*6v2KYrM@?<#vQ%8&j{p@HA`bqsj$JHJ1d z0GOW#Udwutxgq!?0UC{q$%i+e4p-P%m*bfv$CzI&VJJgur& zkFoysEo#aV?BPizgNna@r7j*caaB?2ayNO0qGBm zyFX0#uix4nNNiL7^zh%RH|+C%eD~9?e^`bk$hLdKDpU-JYRp6%2(k`SIOvkH1koE`obQU!UK<-_Q@t z_4mvBWjtcp$6e$>tu_*MFM*we>+_WE1-+fUculRbWuBkZ>xGY%{Ro|Ai? z@|W|k?;X6)evO}peqdxk$KTpL@$^1pyS=QR#1B})kQe-D(I=a1(1chQ2L(?xz3w){x@N&9hM#$Dt= z@E;=39So&zm#s_k{Nw_4zga_55_aNBo? zCFh5Kep!LuZ$IC^U+O3070WK}A`c=DA`hAa(jOLge}Fxn_UDapi$A^Z==y6$z#YGS z-@pGJ`hmTr#p=8p=ntlh=S6-NxBN)^O8fHIfxF0q$b-m(=D>XG525tabiRFJHPBUkCGriqe8ye%{vaGeLLh57HkD zaS(Zs_=^&M(dZB|KFauLh{IhUA4BPl{iS>=OMxb3^7k zGM>qJrh9|*2k8&eALg<@*!%S;pbpmo>-Dj1waS10Kyyh(pSNpY*Lr%qQa^v7 zxj^*$%#OQ0Uz71e#t$WI^oPiU$b-m(=798vTlWV#@2;8r`39L|ySl1kGpzSxbo|~` z&Ts4Y%d~zU{sONW=kW;tZ_R(+msaxS&oA`SmM3X{ zX@ABZ+(jN{ClAxt`-soCO|SPUK3^)8>}DSO{rREaH`n`-q2sAnlHJO`U)p1K?Xl4L zMeW~3=AA-YUe2Bz4PPiBdr-2K=(D54m#2Pv>Xl`5x^mRA-lfa3{_m+kz@aZ$C*QR$ z|MRKmA9m;~*1N-(FNf0KejpGCkD$CumruSMO0QkT;UF$sCx=7n^P7lv{YfufZXZ6L zvaBSPkL$A4K75hrtGy0wSufbMrR39<|5rKPr4vjq^!AYYFRlJ3?Je!iV;Al-$piWG z?=j=`z(4<1_I)QlpLhSBf4$!=_I=d^Gx2|+r91whXJ52G@Z`zS_{8~Y8{bc!ymX0v zym)w7eqgL2ddXekm&5{rmYS%G$CgD{ZC}iw+0w5(90;VMRNiH$gdG%JvYcqlC2$>U zU6!9D`sAo}2K2?$>inXKX!MLd+pw$+muS9WMWdIk;diglGcOEN4U*T@e57fJ=rHCd zmyqLfB>m%Ml)8oVVZxuS4~fV1U-uRFwyROQUjh4haJ!a>E8=rmS&shhb`Vf!d%Gu%J>ye>zA(|hyS}wjH zPZ7EizK^=OuFM_sQeC$cC$p;;E<4gVZZO0K%_zkdzsKPqkhj=p>5-N+F1AI^N_UCI%$^&!rD#Ii|JXcx`*!i_|q zIXU`E;`j3;@#785;F-#k^t+3Xi=Dra$8b3L7Rwv(y#AZ|{5?P3yX*Zd=f{43S?@D9 z=Kp*>--*}sHMhn;bH@M7{Y0Pr+3=|K;dSWSvkipx_OS{VQ_J!bv|#52C{AyvC;Z|s zo&g_CeE;DO^Ku=0pO~2VVQwBj>bVn~2EIiX|M(%{=LlU)|K;O(U%WyW)4>0YbUm<( ze{t?FbO#701A#XBcVzG0y+57$;#Sb#cr*~$+}zx3SsVX5DntJdM5%ntF1}GkgnJP^ zRrQ~o=jl9Yd;anI$z}g6?~9mkG}!xHr>wt9FQfd#j_*1Ac=JvDJbroenma$4_>BCT z_520z|CZ4nUF*H`kpr#HeB{iqbp>@e(7Y^=JA(O$Gh;bM>6ow#Uw+rl@xM+v^N-6@ zBmndT+MmoV)ZV|eXDCHTx9v5swpeHK`zbw8WPcwlIFTXLz?qL+nmRcgNgpLT*z0`% zyYDs)J++V28&n>yOJt7;rK$QKJG5mr4cT;@X=nba?K3V7`;mR!WIjSR9_PB(o4zHTJwoe zdPPSfF}T_mM*8O%;`RM%>N?YY{C{d6#pfMy#zW)@rPu9|^*(cJ?(yFp5B>PwK{fo@ z&;I`Jr;4V&{Q&U&XQO{lD{PGKw3;V;=P&pMX{*ig$BSn^ef{OkH@;}Ezk#3D51-2m z1{{3c+yJb{wT%9Y*3{JCZ(PghKZ5@W{C%Tq8U6Tq@c%|-;Wywv!T(-PhyGw2T}&^d zKg{_B|IT;J7tC~gUp-w9{H~K@8Qs1|*YCPCKli(|OBPp*-d{>r@_JwgXw>J~lP75< z|H2EP`69Z7|Hhqs6s+o}T>fp|yczA&ed2+~OQ}B5=%sehmoHbT84Kts>-+C6qh|>| z-1*46m!0;BqJ8WO^`Z35E;;M@2I_{3pNDp0#K5cPseI@^tg}uIXeY{uW_!%>E+?I) znzqK|z78sk^dBeRbu=chw}dnFg=9;)LOCL&AED_4$>;Fs=#7N~L|?v)9KUVL zGwd_4wp=EE5a_3JC-C;mmq$qBZKwo-J$q@alZi-i6uHt@@Y0y#$Y!79QX0_J)0OaIlf)r_P1- zeGfVKG403y{QfQR2P;a|c|4epo9Fl4>-sP0_g%4uKN#KFO!{1`mrf4<@)C_dG{Pjt z2;Uuzyo2w0J%Q*Aw;F#iw&SwfKXc^4W%Rc_ydOF8;Dhux=n3w@2eDJ~l^3%X_{DS#RU2Sdcn^XVf0O&Q;e$i*2eHJzV(0md7 z(*VtNj>7&j^5BEO*Z=F!0s-3|Q}fMlLO!Oftxq|4Ra0Zji}e)ESe(nD|MyGFh$Q)O z=Oa^=OMlBr_su8iN9SohznCrkV|u}eEwIiTpiTc8(T=snSziZ<=K07@(ucqvGYi_b z-(c>H3;MAC(|F&k>ifr-Iyl$Qo_i<_R(&v6Xv82aWYJ|o1{qFiO%<=_$ zKW*nX{QK!VKEvKm`}yLupHJ!IFkdJwE-ui|hx%ndKXc>m%ZuH9*<|?2FV9~8+0;qG z`#`|-*KmguwLZHgeI(=J`^bdVm$@mv{pW9~{{b9~Wj??K}_h&YEpWprOz4JN9gE_xb&;M`EUr0xNo*fPR&-exUlkYwA%ro!4 z`v>-nWf}d3=ij~b2mcZ2d||!6e62hGh}!lUE7}uy;2V!FqxnQD*>5mo`CS_`@eJrs zt^d%zjQ%D#cIOu_{1o#aq6d&pWex*hiFWrdDcW7{48Q57Uv=`o$@yJ-!tgNkM;h+a z?QZ@CC;toohx>k-Pgz%9{o|Y*hbDiPIwGiUe3^gqZ@8m8f`7q(hoOrOf9HBW5lUY? z94_4bmdjr2c#8b{XSVmd{R8@~1FZ!Gx$1nLx&EFd^!_W>S&QuTySm6$*YC^d2U8z^BYa0${M?Pw1^)&ASw8%C#((}D_)qZv z4AaZ#j~mV(+zik^_~$R=zTsL|xD*jy&;cw>`(8c*nAARrP=RSPyxqspmZ|g_Q`P4G{-JDN> zHtktN-trRs7kxitGwyd9-+}<}fdo`I-{xW`j|1Prkk9h3;2gSdinRgf3 z$KT$rz9ws(v_`S!52c@fn9f(+##Q+7G8#X5L2}mmw?x|hY-jWSO#l{no2CJl{=DI} zjD8jT*ZzfmCf&^b&-uVVbG^;K^F2oEIoSW1#`u0W^#5G`GWx@;&z!CQ-3rYa{=4sI z{C7!(|4bkJTJQn%C8inwnJ)Qa?15gon6~l%x#yl^8uJsue;$qQJYM<7L!oCkKe~aw zKfcX4uV+hq3-%`~eX*_YCkHWZQTX?hxxbic*!ykAaQ6pkkJ+`yZ24vT=VvN2KfnGn z>s^cX2a&#iTT8tj~@MTL0sfyk+#m2v`uTi_-&=8X#0O|{Vd{~x3u~i>HFbxglICP?; z=g{Bv?%(8E5eSmq;!nQ4?VI1-_7&To!q5NDMAOSqZXg&4K9GZrJ9z<)XVE^K-yfy@ zo^Ab_d#66}zR&->rk&@HoaOwHp^{h&?O)UM);R2wO#AEO zJfBhgzA=CH`|6iDt;<7w$F^(wM*KJ1??&l;>itfA#*Ok&zMnt-@7MKn`CG&F@$*|~ z;-`$)QIU^X;?)_74?+K<_}GWP_miJ~*LnILu6NuQ-m~@9B7Gn9^?^iUjN5PBp64Gn z{!CrF_8U!K zB<_aeOym2y>+5xXIu9ur{E4#PA5WFUx;I9Z|HZmJ6d^aNzdwA5&QnVD4sdy-zlpVM z+}OhOx;^Ksi_V@cVjBK|saIZkjOh^KuO!A){)5C{+V76r$9JL|MO9EUuNL|ZvM0{IRWl`-wgmpYGPw(=?YZ%@A{{97dav(X>;pWpu{baDTZ z_MPADYsb$Tsd$##3;5d7p!NIM&z~DCEaY_Hf8peKfN2^}V`~k*1-Y8SXwj8=RKk$U$U(H8={{v;k#hi}ybSRu*lI$TR zvHJQJouBAnut?>P3_ZPX?b@Hj_<;zeoBMeP|FHd9;c*jvUv6$j%{OpfO*WZS`=fDw z;>#iJpMm%$V|1zVhn)34({{YE!PTpoK5?ofR%5hp`|y1`3WB;k@TX-g5#am>yYlLa z2VVMfrqNz2&(y2^p(jq=wN8V1>Pzrn$?r!zu2H&}ZXd>aSdaH7PBjgYze0x7 zv0g;HHKrp&D>`y>cYK}cxT;W*{;a{{t;}87j&G*rK$%Fsl zOL=wh_vP}y55i-`Kk%z@P~+!CdVfLrSHH^nF@M;$twpV;kstbbPRIU>#)N(z`hk(w zF;(A-gr`=PSY1&^to!?-rw@;j^ioyS!^Y;w550gKD8?VK( zdQPEitP{cBf|xKeK9m7D``e3k1#aF+}qLy&r9<%bSh&mX+c059@VPpL?OLBzEeQy%pTf zg7y8E^ZWWZKj_ZR505g9^ZY0ty21mDw>{l=?|fbd|M~6kC#)ho*X!-};k>${;$nrj z?ZfZ4QAFD9`~>i*-q8Oe{mCbvd{3nlz7xDDd}$w!QN$B+5O6PN{jco@e*6c%nd|=> z;eR(>TpsZ2ik_a>`iV2fdj7s0=QpJ*D<9$fh>u)A6=FI<^MOF8UjK(LP<*9i>bg$P zt0VJ`>K|B-uUxsZOr;OydGX&_|EuS*{$D*9Q0r$KFGp(Bd<6U;{kg$!dLJ23xO~Jj zJv~sS>-ieBcYNjjdVT!V zKjNzj{xi45{<_r1|9kfRH^F}gzr!0?B5|I3GMP~81&0o(^@Kxr9?*t4)Kdi<}qA9*}ryAe<`R6+wa?WQ7D}LGWr90Jn z594Wlz1C*~-;a!Uzrp!I(|J<6nT9=|rVna827N)1q5nnun*ITInm_*eUxe_9@I>J$ z@GshMRpE7n?9Emttnd=+|C)ySGyFYd|KFFB^ZX8`p`YHkv0LTeaEaFYQGH$r@G1Ia zLZyQ)DAoD_=<^#JJB@VP9%0bLA7T){5B31!r?RgD&j$xvlztrZo4uu_243g)e@gL2 z`1uW_UoiCvm=8y5rd0XU>%U`-x4m|(A$7f~-}LqN;%K7TiQQdyd`d`PN4yEtw z7#uX)5B8KVtMXCawcGGdxzqA4!{FS~mpy&S=51-#O zRb#332FBC!ff2(W=m4EC6;%4qi{!twv1X$hFQGrpoX+HO`T6}_>nGot9Ag^ebugG) z%ryGDwcW}nn#P|oa&Tull&100uqQkCrpL4S)_yMDXLbF*j`eFo)1-f`)%(2;G!Ipq z@pggt-Mb5SbAFuPvwi#KN0^RaeO6Flw9nnedq01j@xGF)L+4>YUq7kFZ^%n9rS;LI z@2*Q^^?4;&AFiy>c-@5dH^zIE-=Ru(&Qn*+px@E{UpDmj$p4XjUJ_$5~MS+J>mo&%?i~^Jp4PV+C_xo#``qH`X-_T!@x;D)9M?AMgVo=%hZM^?PuWy0(`;&#s zIX~!RVL;(O{I8;W_4!cG3_Z1{XTSDOgZ_3teg9nZU*0d{JNG5rMIJ;RL>@E;RDZZ7 z{%id+*6S533l$y%uTB4(Q2P9)ZRBvoZ$SP6asblwj`gNLQq$1+>Jclc(ox<&{Kiry z*`8A?I>O0#jGx~{{?MbNFRS&w?O$#9v#IZKAGp`Fi}zpS`i3uTjZ--NR;J;9r+4ci zo@-V7H>usqI;yzYb_~J$j>b3O}pL1HL83^#1hYsq>o>R+L{y z_E+p@F7Vh3w6_1=k9YVUs(zL$2!BPK$gb(HPs4lKZ?~V*f%l<6r~3X~`;M+Be}GC( z_v1a@*J<#}&wrt1{AJm}UF1RJLF7SmK>EW?`om4||6cPeGITN3N)rxlG3@W7c<%pocU*7cR?fK13^ZTElE$!#$O!d3{@@;ErKl_^Iue_qsmvKDYnO6a1fV?ct8^H`V8lAFhgxZ`1+jf%jhucLrF# z?e%@(e&rHw$LC9|ewfok>9wo;c>fDyf7?v_zw$! z@n6E14t7ypjQBAWABGe#x_(EiDPD})e|e|-EBX6FU$WZszCgLM?>OUy*6_^44}ZEH z4>zI9hdw1xSf|z*Y|vNATU|Ww7owtp!wZI`&Uf<`_r-iJrL0G zf1UC_RsJvj_X|B2c(46;us?18Sd37moe9Cmv(8s#tl^TCsI>F`n>vMzmqdve6D!ti*?y7Ho0-(MuWuidEQ9{}I??@#V#d9v5{q@dR{{Pkl$WIB}o`ZT=% zM`MBSf4`r$@gZ~NMJ^Bf<;Pmiyv#J>w@s89{uwl0MUw&5Kajq;w$bRHI3K6f@GtPj z!waQwj?VqYYHQDi^+D>!2^Sl|~X+_8C1RVh9UfBOh z)h|>u`Gcs%4*lpnU#P~9o76{bL5ID_jE9T;7G^wL@RP#xD1D4up3>jA^oUuXjAdPA z8sk@Or{-^D$j@&&zo0?K3ur=mO2<1Uf6&$uqkX_n^8ZxxxoO|$#J4iy3xWSPkALN~ zM^?2*#MTG3eSz!m%s1?#h3%i{eKemeY}M%~zq{8*b5VlOvfka zJWgZ2zF}f(ytVbY?{PZLV>0_A;v>=Xt2rIDWUi7;)44)4|E{go`caHW!C=bM zzbxz1k2$}?zj8JHhSDg%TMY^R@5T97$>e@xJi`3ijGspHwLqIH&;Pu`Pd$Hg=SOOM znD6rXx$7tRZ;PBgeuWFyYWb_e`Em*m?DKMs`8M#rJZZ+;C%oU?`se(-e|>-AR4Dze z8m%vwsl6Qe%Vu?Xi2vKD#tZbHm&3lt-{~k|;^9$AaI=lAe)&1cqjei#pA6-A$ zV5#wA{BYO$j`j{+9{d}Pc=cFsnd2kkK}dSim3;tiLxt^=j^Xke6POJSnj=o9b#Z2-(-_q&4 zqYmmmasEE&kKTUiWhH+&FZJt*gpxnRBU!ofh?1xF;ivXd{Ky`D-tiC8c#rZnpI%wa z>FvY8N68&pmDe=1e3dn&*`p7%WEI5igonr{YsGU z8sj_;)OW#L zdOnMIsHAY^^6mN>--q(3f2rp&p3;2eQ_er%A{QLd-{MoGU{p|_-&(g*3i=?-B@Hu?p{3dfeKz=h`y}vv^ zjrE9Ge#lpTg!(@nho{CT^oP}zD>Gc5d>X%Kd8@_)oX?k{i_?MsqksPAYChCN=i?RZ z-@l*J5zoId7SsH<{X6w}HCSKKd_;{WJ=8yod-ePY>+L`=SJ^KjL-%!1d>*5JA5Y~3 z@|8ZdX(*I_WA9!yUqSo`s(uUCr)Rh-9!#0@nRR;-fn_Rxg!ZGZ^u_xzrdxLWK!X2D zE)V-PZ-xIDU&oB|d~jY4#cxvM8_q-OF<#I<+_j$0>r?!|_;}qo50B2{sixzI{*d2~ z`4Vk6Rr^hkr*<}f>)UH6CbV;rze=3KYpV9ec>|N*|Gx43x;^b}i8juU{WpL0Rej!3 z6U|?8x+j%BI702!LJh|G5f8+>UY(tM`sMX*)4(6nS7&tnOAwE%mTA~?ipwUVOrJRA zwXc0JO6yzWyb9t+JeL$~oF91CN*B}Z!$0xp*Z$5L`){0vJMhz-kNf9$&_{#6u--S@3;n%frRE3hSKjj)j;C;71DEHV zf2q%F!uOizHFjL5@q#YSk9gANc!BxUcj@AE`o2wOygBF-a*h6Xg3hmcmJYPy{Dj|i zG`&#mh59zr#pw|`AJiLANj|b5{Nm!GEWJ>-~j@ zKcA%uCbuu_^QC{P_2Q5;D7yo$Y&d;^+-&nsxU)M+n z&~bf$AH~JxFEb5!wX7*M9yt1g=U zE-ru9zVn+1{uTb?`G25`(}C|E{XESl{QCKy9h&+w=O?^xu8HgQ2=s|jTA*+`;!78d znDKO?E08^8-45evHcp9Vj=~GsJHSIK}BR@yEaZ zNBjBL+vfPxPUrQ}aHs0iKK%4P;@4{RKKg#|`NB`Gd3~})tv_KeZhh`K6))>x*Vg!& zHEWLY^ZEVDA1~_Y=wKT2-*V6S1;+ul! zoJ{7*&-r_>KCi9S_BGqS(-Tzf0eLj-Yp`EMV_H5PynXF$E-yae#oN?%uf7I&X22Qa zzv|Dh518|P$YaY7_4>c()G?2}uYLGJ+uGHu8~Ocy{Kxv;T>ty+3x0WqzQ>RM=6Oxf z_ax}z_sxX=J;Uqv^z`&7{Sy4YDcro0w{gV(Uiq3DpWBC5kiA3e=b@jX?xEg?^*-4b z6n;;`e`+7If8qNG{`*vY1^@g1gf8aCz3zW^`h93$)BnUiZ_U8_6&)ncpD4Jp_v3eV zA5!*8;D4rXcbxfw@xauN!G3G{_hUV6?svQ!-}B;?3|Gg(dgSFZEo1xx@FY-JI>EHP zJ`N<+{21wpvD(c#o#yAI`nc2&^!m_09!y`~QapdUxO~F@>RaPKt*_|f{NS&N z|F*t#Ot1eV_`agDPdI-QjlY3FR(;<^(ofen=y(Z;2c2WYE}6=D>Na0 z6_VGtr?mbB`j*CXy1a|29qY?qn^N-ML;3)HdZk7EdoA`4tNA{kVVqKQsP&&+mr4)GN>Lx0(GJ{4~#l20tjAt7p6-^Zy9f z5Au|G^J8WIM|~!Z{sH}b@qnJ+KSSR))*4mML;r8aKX>*2Evoz(@INvXeDnxiod1Pk zve(kZ^qn5h=S_KwWc?5Mp|;9!d*M7F)4scI&$k~i@frBO{Eg1toPXN-p4Kxa-ou~V zhxci-yu00=)5n|RskMdSB-bDKQ8Q(pr*^)Y?12V8bgl0#((6gAN1so2tLN?Yo6+Aw z>G!JXI3@Kw_*<#C3;zMa+fltD@^X)UbK6swuJE;r&Ts>&4mw^9eTK|Il zzw?C3PWXC$Q-iTSNBk)B`y$j{{`g4O^y5@tvUeEzly+Kwki(Sve%Nno=s*H~1p3tx zI*@>AtiRih{Qma#^9TA%I_^k4@2vmz`|SK&INdS-A^pC}KkfU7p94PrnCCm7{8-qO z2hwL6{BI(Du75_q5c8YUuZ7k7U=K6TgKj6h)7n`0UzWsP_T&ft>+&EEjYj?9zhKIb zga7*b{rsD28s|GS8u}K@KdHMY{>)TA$XD2q51gO8&3N8_9(4Qgu6?Hb5niq$^S^o@ zo`2Fqd+Rg3{9~<_kstD1?5WRv9d8@y=zn7#`he$qA)guDywrd0>lpRqA3ywxF@E5E zS>t_(-!@>-@XzypulKwUyiY0H>Aj%KJ?~$)XQSu+EB1^SH1hxBlzss9_45Czedc-G zXs<$}e(*Os;w#Ur&rI#VVAB^U{^vXUXRdOKM`-_z=`VJ$t82X(pAdLo6x=_?`KRN( ze|_)8`}y9!kmsOBp7Z<7_)18>Rs5jooYw)?8`q>{k-p+{(a{A zXWL%*em}oV`ty|Mt*`g{{pH<=|K|H=YQGzmXY&6>=?R1XH%bp1>3IK4`MuwJYx(iN zPw0EQzft%t{I;=hf#N^xw+|K5z*wj=e!}z~zU)OpHw^zyZ zjr95E{#xlT(qC9sa2I(Hc@TNf9FYF7K>Ncy#ee_$9{Q?V;XTgNxvs_0w&(9pmMi@( z<^##`KYNF>!2hkhNZYHSKQh!uGQLYZ{U5Nb;4b6a0v+GnMwIrG_LKgsIiUK(JjMS| z`oDYh`P0|;Rq>v4V;}JsLBAgkU%kS#quEWX=@0V+|FQngWXfM;34_0EOKoip(^$Xvc543^;C)+XXTnSmhqG$G z4E(8lc%OQ{)AV->_0#r#r5_M^UL^AD3WT($v?q@ZxQjf9JcvAK4ygVxNB9qaqGZ;L zf4w!HXlzvbHGud3qURO0Uf)7^Z{qc|_5C!wC;xWAd)45oz1?4gmhn&t2mK-PAo3vc zpgFK)`okRIe-rIjqV@U)=6F8EqnI={*xLU3MTLc&j`=`gU_8z==?AdBH}+$D@qWp) zpUV*WUKzi+Z{RNSAo3vcpgAD@;U@jz9^t>e-cK6)lWD!4pa7`cLcsU``fBPiO;^PW z3lp78Uues#+n#yk5vD^FufD+8&yM}YrhY)$`zGz}GEn#<{NcWYyU2scgUEyCz>?_? z_Xz)C-?uD%o)*^c+gch_{4rYZ#~$nIRPisc{wMQ5Bew|r0R}wrNhw~$uYb+SGJc7_ zzWD2_-XM6sWX5l|&E_7Mr$c`*d393l=M(uB`DWR`UF1RJLF7SmK>CC9 z2Q3Y^7$5H${=c%!JRb`9e}7@2f&ZlM|G7So3Fo<$6<6%#Z*b!CTvZXrMZQJ8SvGJN zc@TLJdC(k?{viE9OT#V3$GOD+`^(F@j;_5w$u#2g(s{Eg9r%A$*8j{N!8`GH5Pt{N z8*VYaxp@Q+1rH5zk@1tq&pE{Z^1c^6>;JcYQW)ko8b4eWD=st7FU5K5S4ICX39(to5sNPm$2KpePB_#dJ8ex$#zWFBL`UoBlsL*KuD z|HtZxW#In{gUQ{T4uAh*x-^~N-%S_O(toA@vMk^(@*wgc@}M~&{XzPJmWEr5k9Q0I z?Rfr~D_n=j(AGG?zY)(L`}>n^oDTfo{gto$KGQb-8|U*Oe$efl?=Jm8`UA@r?jjE& z4CgRrZUOSVj2A3RxQjf9JcvAK4oH7kqW$3>;s5c}jx|$svBUxYDLi17>0_-W zv9okBogF>anxczokioX@9Q(gv@2`q4PbQ7? z{_^VnKyck$b-m($b;s< zXYLPo3I8MMoy~sy@5;^1;TrBF|353!r}P29e}aF7|A_Z@jV{jrnZL(n5T(jT-m%wl}JNB9r@f9{SVwV!Wib4eWn0CJsAoZ1?1?;Y@*_iI_Q z{%8J3|CavEvVgnDgUEx(gXVzrhtJs`?kxT*JfCU(kNy7CdfT}Lao$fwMVW8?ufhe$ zcqi+BS^slqp}UNCpL4u(c_{o7{u$kA>Gr2Pg#Xajo9F$IK0jVtUtiBWM!cV3;G;=R zm&6(y*REwcGPGk&5nW7UKS7EN1WZeRmHx`IfV;?p$b-m(=797E=?_{OW-&hAA^eBG zemJ>d1J|Kxs48CHP!nYu_BY@L%MaWdU~?-$Win9yAA}KS+Pj(r^dI$IprXcD%oEGR$=frSs|% ziLq@=WBvc?p``Nnx9$Jk-APX0wXbV^CX*>=+Qokr4@l%)w#`t&}_#dW=>kz(B5^JT4Y3%pwO6v3bfd9YKS*ZN`BI&AlDP5euiS+;G`G6wd zBHt_FH8m$B|UVBFevnS@6BT`s~1Yn9uNY2cOn*t<(%R{RHBpG0w6E)DZOo|i) zptG@HQ53pszgzWgz3SHh8cqBV1grW0uW#3T_3GVstG-*eZruX@?=tZ}0)KxS?~l1P zi}&dkVfzQ$KX}q)<;k`O+a7Ft@Hn8`!<^y&{TnVI@f~RV|6J?-fJbkRwYPtu$N#k6 z-^71A{uM_{tUk|Ux@ZTf+-@AifnT+?l zY?(3sU$ZNC!P^f|&i}9X<_D;}tQYRj_J6kjv;7}8CLC@5H&6Ya%VW!5%U`3p-8${< zI`KaoKilXyT~*ApCk|eGI5{CQOcVY)O~;NgeF^IU_wC!ak!iC3!#zOj2jO`56!r(w z{sFc<+V;q@LPskPRvxT8cpR|p!L|oa8fMWy&Jh3QdcXFHFY!IY@yB9aU3Ilg6W*^{ zwbJou#QO{XPkR5}7Y=TYtzNxa@9$gRedXk}tJkja`Bt8-JhLp&(aM9B2P+RA2W)$= z?ZK0VIqV;&z<(N#V|!jb9*@ZJep4OSA%gh6wZ8bihuUA$>j58wKG4;*|9gCX81wz> zSFJL}`@vHP2cXNh@@?gtWrdDb9;`fAdGI)3+k}6*^jZu<~H#!Q+5!54Jsc(lC$x;}rORw6*oY3Bw8mp31P@qXpn^?H53oZmMb`mH=$d1l$6qm>6M4^|#L4%qf!+k+d1hImqm>6M z4^|#L4%qf!+k+tX<>(0Yzz^m;FTFX8<^8V-C`ey#j23i)*_ zVdc@vqm@UG1GYWb_TWjwH2TF9_#ck1J5UmEwEw=9Co4}gk|*~hD=$`Fth{&}u z;DBw3jBhZjt#rw|(39ZQr*m3bsE32X6KD;KzGEKXksuf7@Pc zd%5NN3xEG$X{%4jj?w*RMS+xPEj8@7MA(d|Lwwfj>1bg}i**IWFz_;2yw z>Oa>1&-(uvfL|=0*z@OCU(|T*zN0zgx5od+Uw-MOml|0F=B)g=uCFama=^Zy`E75O zzm~t;7t+zngO!Jcl!tl4d-oy2@!+XpB#}-hQbRrI`fkTLbm(d=Kckg*EAK1|bhPqd z<-y8>#{t_OY6M4^|#L4%qf!+k+?jLU${-=QdV`3y6zkfqlRaYG-`Jvc= zl=vB}JX?8YS)ikp2P+R&9y|`%_F&tCCk?aj9~Vj=NM-xvfIre53N|#<)>`~mZ_&1A z+n(pLJzIIQ@?_=7-!k*_c`=g3BP~GxebXqeyj7_KELgMxh>Gq%7c{$D-RwA zYHBn>oNaIR{dm2v)kkc5 zulnvWL$ZF^!_p`-0ztvpzH z@Hk-GgKZCtNcXvpiuQ`w1nm9f9VdhzqM7li z{@vRD?fzdZEI8W!&h~ePI9PeG`y<-^(P$8hrhiO|WO^c%k@kKV{JDxAuFGFeF#W5} z?am4&jH4a@+y0(qhmMOzzTHaM`dIn2^67EFwg=lDNE%X^A<=_ReWEIeaDICKK8AL2 z0xSGJB|gRUR7Z>dR-U}x#p1v1Uu}D^?ZM-KZ4Zm2JcrZ2NMVV4vT%2iqPz z4%qgvINC#cqA!!mrVzh>Q?L#j`0yKIbO-&4*e8C6>B7jb&b0WyINmS6Put$?`(Rn1 zqm>6M4^|#L4%|}h0T%zZ{&O9ovvXq)hW``z)bsv5E=w5iVeMbm=ji4A{Byyh#edts zc&*Fg%`Mfx;KkeLwe8=we~$x;rajQ^J-s3s>0Z9gX=oWbzit1X^jkbwH0|GgDYibgecJZvabQWehdzpb z@q1m4yuxt4+zH@Qe6sj&`xmcuS^Qtp{R>{SeLmaXZF~1Pa6{Vz@V;Vnvmft+)8IX# z^{6C%2fO#Jc#6sEK3e>@{ejmSEI!=O{=nk1)lY1^p`{yd2zVckuh|8#uHy0iznOk~ z@8P`=Pnmc>SuCIHQ35RfTl}~9?{UE5zikhmG+2Guwuf1?2Z{IhZvZZLG2Z`4)|t+p zKks<&*AXoK&*J^s@tPg4+40)a9k1E;ZQFM-?Rye?ezD{G5CD1riO2Uu*C63AFUjJ+ z#eX~A@i<_|JGMP|(qPB`wmnSK9wxzi`0LGV{(cI3eh4T}_|ITZw8ej~MOt~BMjpW? z%OA@hueDftu1s?#n0fy`Aa$?khR8d%l~W9*e}!bpQ@0 z)cIpB&DANI?os76{hBH-IT(&_CjZy%iXH_0=qAvTOeKhx{;@Kibwbk8e@5mL?XHhC z^6$DA*YBefkUbWTKU?lNhjtPT(xuz!{M2C2ST-Dg1o=b{4vvfo#M65A4(AxHucfnH zx}D-_PfpW*o48!(Q#{UGTICOoB@$GJ7ZaQ0`C~3!-;LVhdOtmsO(e0yhiFb1fWc`Kc$qo%h;(^aOPQVQhGC1n;Zx!8Jh_P%WeiZMs>25^}#1ED7ae--9 zzFuY8;>oSm|J-Wt+m&~%f4l8rrIi1^G5F_ij-iEW|NK9h zC{A3)eo#)+KH$sXAl)-I4zv)!o5UbWr~RTrRD3j%pu182BjtdjXmSu2BUOxsf?3e& zY9Zd+A0oIao*tFOiL;IBdR4j*gw_)%Pvr{nZdg`F(^WvXzccbfpm!QHafcFLuc%v> zhPL3WCH}~_EyTr#9cLBj!5-2kgb1Dr1@9gpeFMKBUG4x!H%6mbF_Ik{6zNDD91NZq zpu9oo6VQ+DfIe}YX!-^E6lh2Hm#+SJP2~&W+EY51zSZ!=KJWbMOMZJ@1ok?}noplS z(WvB)#t#?24tc#w^pG46Q2$H)?bw*o_aXnsveB`jr0k(Cp9DQo6HU4u)Y(SIsh=di zo+_WbN-0byn$J@ic_kY5r)AiCGHTro; zrw4o7csL{<7|{%7Nq?mQjYtp4Axbz7`og|wuRB0lnXL+5!vJAaj%I|o9p~>b`d89k z=cvD(7rf{8%Eu7C*zrG0%lzZNPd?KM-~Y=2S%co5(MbF)jHsF##bA#_^a%D}Xu7f^ zngG^QqVa9R%=AThKEG#4jHT9@^!CkO1V_r>yqR+qUS1C!LJ@$I0g?WCbqT(c^>|?Q z>eWB|;b%TWr7yqpkzn-Lv13fXb;q4S0+rd&`?|WiUVM>C_tJ|Gs_!8j#*w_7`TZ8W z-*Jv3@m-eRd1tT+iRs0545311`zQRbMDo{jzsp}be<#vWQT{lcL-eIuhNAsL|-qO&5It?z!}V0-(ae?c@Q zSKl`LC#3(z>neBt`-htye`i~Ncl^!l=J&z#iDPa3;W%Em(jLc#-f`#mVz@veHjRHA z0Jac7Y@GEe;B`9ydvH)8HtlC~41hhVx>G^3gQk6Ort-%X^qrqO-bg1mQ2&Sej??+0 z|LP06!$oy#sJkTzN4_IodYrmTP4jv@&iC%4&cB)I+itrJ&#BUEzEG2T(>QABTOfIzrpq5d%K$pNl-CGtzM|Barm z6sf*{N?;$tUljTR8C4e|g>VxSPkxFUoAmNK-@2n3iR(gmW2WNiJA;7#F0%~tdkDlr z;{O$3;8MhY<|*-$@ZY2f|CuKF`x+9{A$<7;Qu(v$7ovZR)RA%iJ^ey-^y#Oc7UE;^ z5TruVIG^NyLfrq~B^|B#v1$)Ph1x^Gd_w;Lw67uQ{UF4;1CI0Qak4k`z}tcB1)ItP z9n}6{f#?xKk@#Uq=-mT!fBb^|(4{}g^Qt~$IG^mpA01XS=^xU+^Op5*aG$?|`QhqQ zcPkqHKHW!K+uO_jj_7oX{BxxLO*P0~_{)HQWU++53>njb(UETGZ|ybF!Gs!c)BAGv z(fd+q%{IihG5Sjyy_@54oGp`kdI9-J59Xf#`qmJBaP4EMum8^_NRgB)%mvy&F^Ee;di0>eqNe?F2X*P4xw;}H}yZM)P@a8{-RHRE4|@MQo>}u5wC&p_B0YMyCErr zyP9}!@qcNI|5=#m{az3Lo7WTmn>676X_F>>!MR8M62gJbzwbwmmUlWoBToI$LCd53 zC@Mtl>xBvD-%2`K^9<2K{2y6GN1s--*SpS?rt1d?UtD_w=?~=ZkQh`J2=Z?UWXQiE zIhgKo{U^&#%l6)r83Vonznrq;>V65>8wmeiBA-~96h3DDk?Do@Z*cpwVZQ$q{<`~B z{@9SJZxi)LnD9;}U3=v|P}0FQLjD^~u_(Naq=!#iKe-$2j4DdmW3FO6;ts#Xnq8q_ zHSyO?V7E-yN%v8IgW^>E#1sEJ;V)>iH@$w~_5k;vPm7+vTF&>P<9EIw&6E14Uw6NS za5Vd~$!Jr4-OKdB;=g8v{K74e-)|wjUFdvQUsdx(a=u;qi(kO(P){O5`Y6eFW3(p& z0*U4;O?)T)6XHEHc}|Pp3xO+AUeoFS<@eCTN&4w$o*9kY2TIX{Nc5dj2!G~yi)b@m zgT;R^#7H50pHBZaPMwplcKkp2_@9{@!j~E0zk9(<&iCsh&mfh%b6Ipf_0Pkj_x`U` zB+=AfuzDl=3;)$^Z#B40WAB^b; z?cV_Z*5KzsV=f{==Sckk4wJAhWP4zfkn_!f0}{V50>=1)Mhs=AsqDeQM4~xyc0asW zo>p`c<7ry2a*Xf|`M~FR;9fa?hW}X)oXq6-*%?MY^&-+A6ZM0?@7N$z82115{C6*R zKwrsv{<{ar{{rJ}_Rn2+05t0FPJc`P+HZrV`%`isU)y(!qz}0E@~=@@sUJS*?1zqr z`J-=wO#IO=I4=FoZ>C58&o6*f{U!9pudZDtZ}n$*dK0gyysb!Fj}X30hu3@_AL)Fv zyvgY4%Cq>-oK#1a5PH9q<{RIA`mO8#@saZX=;^`wrRO$b_`X-9dXh9JB<)WC^dx2n zDG|QIJbzvColbn~PLdZik8hx;-#Zid1u3s2PurXl$q>r-<2&_VG86wM%eVN?+;JT8 zAF%d+j~~T;Bl$A>x3_>-lg=#AjA(pQ1tBm8)WB$e<)rirpY?qGk18K zSHAy##nGK_hj0O^H$e66J-+%ETpIev&>wz5L9{GVys~w*{Nnyov)_(G#vpmlh|6P1vsme@tZz=`8tWd<)@^`qL8mtD;T$l8q;j*ZT zx-=9f>R%Tsa{_cIhWR|~`>jME0qOW}|OyG}W{2a}+wIPH@J9+Hx{v2q07vkSNLw%a8 zPfc}o=bx&skM94C-~HX+{S_Q3h45#}6Vax=1#;R%{IK}%v1qa4H`nlb>qqiRsQ~`F z{_*0w@?_ZKD=sbHhWKfX@b*m58cJ!8KLr2yv5Y*0{6kE8JlWrhm|seH&n5m-dilRp z?H2-l=Iv!@4PGLwpDcy&qhJ30{fR%{;=jj9>R-%Mn6~(D@~hbIAzWa}Bk|jg|Gn`f z@n=T(kMk&n@K@-3(_TV&XO3^F3^UPsQq!Mj`JK3;qN0M&q4!mX#B{O85H2v^|8m@~ z6p71Ob7$)v!$?dM-kbJxq5=QE%lRREG0P*`;{Vj^kFFO#!B&}W*6Sr$V~R)3w|}t} zG`#5&nXsI{YHCcwHcvjD=P14m03B0TGST`s)8Er&!_4NJ(tlKIoZs{PUv%|xtWQdP zG3=CZrg046yD85`)}&wk=M!!5-`iip`u|TVHaF}?l2224^ZZ+9N`J{hNhV965DBqMH`prxs5N7{q=1un9e?HM>`IF__ z@jsa4Cc+;x6{hX@-{e=Z-$S^-ly8gw`R%n3p8MN(q4O>NPc5ZCMfY8udPx3pfo=h{rCy^f0{WM!k6jnPn2)AUywN| z1j_6mb229({O1#GmOoj(zy5xIB!9lye^7bm^HKXT#|y|_&=kVmOny;)OxlkB7xZ-$ zyqW)fS^Up$uZ8g3-@Xf-Z?<1*AJf_Y?f5^JKQ!N9@{8ox@>;EAZGKKKpuK!cKnCw6C$828~ z|8wz#_)`eaP5hb3`4<1d)F~3_Lw5Y{F=w&jH`nlb>!((?yYUXWFdV5oxTWf3>0-)`hd5F)fTi^Ax$HgXpbIqT*F0T;3 z{Q1l8%zZ!m=UDz*eeLsNDEEGM`sBl3zuEG~UtY2I^IsqG^*^(%U$NI0zQ57jB>q|2 zp9z^7J&#s8bL9KMf% zPf?tn?e2Fh^>YGL7>g!CnnT-Dva02Be%RzZtKhD+jaLsIa%n5b0 z{IL8mIWU<#$au2%V8>tjxM|Y(AZgKez90V7(Sep;krWfygC`PieXt}z{jy30;)xfE zH$HX#NIKJ(No8n1@2a|n2EL!JZ>M-gJSA2#E&CfL>~Z!SC@5Az?suj0LP z!HV*vEARcdKk)gJ=J$zYbK;TmXtZT*8rvgMnUU_h?v1vqHRg0pB!2$}N%ss=cv|ci zcmIaUGRH}bsQu!a6YCCC9-{pcRC==e^2uS9C4Zp(YB~_Wp7Z_k8tFdQ5kunq=l3k% z_5&oQ|4GWZhriP?(!Dvh7Kwjz_rp2Hw7+~yZ~8v*#*+j7rjA~YrHKQUA4(4RzvTyW zLLKLV9}@pVPL=Z)&QC%p7R@ut{g=86e(MuMVoVH{U3#RvrKP1Z>+a8azW-cDHtTh; zbKSqG{f!(Q4ytf98HHm`mw)5}xND_q^BatxUd@`d}}NtpC~_a&yMe=+eb z^ZcT|mpkg?UX+2ZM;|UDkN@h2^x6GbpXcsBD295Hv2miuX+L*RgV+x)6pW4^a0CE8 z2?Ve2K72>?c$w3iNy-vvzvWUxpDcveb1iR0<9|FK|BoRtf9AS=OQk$dj`*88&P9J_ zmT1c}xncDQD-ZedAo2ev&QF}H&O`{=(S7^!@qbXrPkp!J_{Tfbji+YYUs3;0@%9P( z=@S9|1OD^y|DQWgIjIuyE4fd1(@}`7=cd0X|Ku;lwL*A1Oxa>u$0oqD`Y`_23v8w-$6@At$sUe|9QEEGsg(~RQ^d~TXF6TCH^ z4`0*iL~rK(i=~+} zmLJ3cD-ZK84>Q64R3^^5KAnKPCj!~rW0^DhsK|DnwHbZg}PobN8tKa+wzm+-$7 z<4u*OYTt97pF)X1xO&)+#l}wf9!>z^dN7~tIMrLX=gkLfbav8w0A`YJl2i!)Ul+sy zQE@30tQ?3&3EyAOrr|Faf}8fTRp3o;I@yE~V*&5<_d3Z5|0VaJS@w@IVEh#DC{(iRoZIRcf>$_iQ#c;P` zNTf2aXWoWBu&KPZp&<|d(J_L9c4z0as8;xnG{(=X)aFL!?1NiP>) zM+qEW@pR*WqhvUyZSh8$cU_tu#w0NDylVab-Ph)gDk;snV z{uu9eHB^te71*@_<6Bga>%&h+=q~~(ZyDf2&L!uQI{kck_H4HRzFv_-nddgi=il!y zUya5+XbpafiZZcd#+56C|C#gzeQ17R?OJa>Nc!t9fIkR7-(2e#7XK~&n{C8v;p$gQ zo7}Pb(M>B44>|Hf^(Xx2{*>P??8)@$I}3an7-(5d_Vx@Ai17H@$Dd5_`LpeR2`@07 zAC~3yrW5D;&o*LsA4?~Df%aL6_gxL!YZ$Lvu}OK&BzTYO)8e<&Ih1Q2RU_j6K;qh7hV$dn^+bNCr-|*o*pU1~S_%CNS zfbVVncioHW4ej69oTyKBLdvUOQ0#yPqVbaMdzA!bxz_kBZJRQ9jqJFis$sNm|n^qov=Ex7#e^UGhme5DeFZ<$~9h=GguCgDb!|}%tI!#?o zi3F_(&kE8f4(+I^VL({3YjXR29^SY=u=M@w^6$tshfJ3^8%p|qMZCha|ETcav;XIn ze+KA<)RPT4r-5f#kw^?-l7Z|2kn*U=j*RuZosOS}eZ8yefQHi640X?$Ii=U<<` zP3+9q2WD=5_t!s^4P~64VQi$R+RF1+ypLCiw_ycU8Bwj+^_3DT8 zyJ2ZBIIYOBp*7nieYd33iNxavp-)5yq&_z|m>m2R_yui^-bJb>F_?{XZwf{SKJAe9 zK{lH<*mDjaZrAZ}TzwGzs!CJPO}>08N+$RGdGjx@_;2x_+ZY{h+WuYl6Xw&{=dth8 zm4`z3PyS{2oa?}P|JAEk6L!-_`rpkYz8S{ClxV)7Q|zO~dq5|O_p+&c`-LXi|0lD9 ziEz9Mc=GKR)!BnRtq&5OL|y-ajBsgRxr zv*JByKPvgJ&!gS-bsZV3cSi-^&c;W2p${AwKYT~+u4b(dkiY#D`oJGjnS4Jwu5j}7 zfsmPBe)?2K(^vlt_4TgLs~^2B=v>W-O~KVI1JR-E;KWE~qKEXihPpb1r-;CJYRMW#nTnRqPb9P;8xMY?y#aJjzTPlw~s2+O?qlaY9C`QbROH|`&f zzqj9U%5-_*`15BCXF9^*?2 z2tf9348QaI|2I1O91#$_%}Fj3LDglQKQn(6;!poHm(F0e9cQ^o)z0HSZY?#OqpiyR zJ(WIiWorAtx2a4n-}%evCnn7d=KQ?-s~^&YUQkCW3HvcT$9xL-F|a;>Pz~S^jlYAZ z-n=VN=du^?@5r7q=g>|rudN?=dc|As5j?dy*0j^Z=lAxn*>ypqp%A-cYjz3Ae^o+Z zdh@PM96Zvk&}`>;rFvJo~^0nE#mEK9EkGXXAyAMq)oi^(_xthl!{Wcif3q{O_+)Zp z7Wm{AWBEBh{4CFgvgPeK5$7iO|1{SuIvNSe{vuiO=OcJy*;TB znxEf$;W_DF2>*exb4njbf|any_l#7GDts4b&LEyXtv@)7c=}CO=mbjV`!PP>>y6jf z9q4}es>+i8$zDAjp3`_2!|MvZg!BQ>*K+B`N~X^?V!SVSK1PTq4sMQtzh#_H{(rb$ zkLUgL121nXH}k{sM>pYGt$+CG+fU`@7oz>w7osEGU*2HeKj^#PS=c*-7}(3t=eJK- z{J%cDXMS@3z)i{a@5~8xwEVFAFgY+^^3WjuT7LZaPtoLPyqO+BJekqd4+;Mf?$3?) zH|qLxBUFH!xINz}n)H#4xcP`cFdWzf5RVrAZV% z8}MzX#Iz*x>9oRkjNjo5pF#u!nqR-|wpD@Ngq+TYeg4RvB-TF=)>CTh-@MDjcfzCX z<0_B-7s8|6d)90N-VXB>WWN_;r^fT<1mX8-jo*?!6VUkGoOo~lY0Urg^=ZHeYYv_0C%*Tet6<0=xSU&)Ja#F| z@dZUMoP7XW1JD$BhWzgyLI51TKTD%nrany1;854^lNX2vg~@p&5nob&y7b7T+UIUFk8bgos7$Ja9rJl}=s z0gd0yi6f2c4Lm>J-<DWnY(e7slK%B`B&PlE!`lC^Paoj+w^;i}TR+7C z`+iswmKHzm5#{HdkkZe1{y!uBR^TV{U$5c*PCd0Z9`w`8u|ACSh2FOXMX1O6?@(}A z<-mYieNOAYA9#5o_Cr(A=+f{9s0!90<<+0?KPc|z`cHBUId6F5`x)VVpGcMs!rw01 zvNrWjBBT86-VCh@I9+`I_mi7rdv|#FSjax_+T(}$`pX^9k-c24zr&X{_|yCFeGj(V z)p*~A@%c4z_mBAcX7ayxF6{7V%pWv*^&$OZFWw*L)BWKtr}Yn_bN%-=?=tu6_2VJ= z*TrJP`ua%s=2&Uzab3Rh&o3M2`-S5Vyo~CfW?Jcw!)>{=vX#(ph46c}`4<1L56}61 z&6NM#{w%&QC)CmM!}7!Az(U9a;r~4YnBNXL_k?isAOF~!U*@`S`}Wa&v>FTWQHkhz zBNVZZ*7G5J9`=h>BVOuHk1a$z*evaiCk7+kfqUyFi_den_)VJD?NJo zHWS}z{9Y3sIO65!<2&5{jQg+I^`YVK=fD3P)9Kv#iL4<1ft_OKr@6k*!+!CR$msQ) zXB(GqgL1>}i|~)!9J?C|C7(~@YiH$YgO=<2mT~?}@n)vyTl}~9Z}bt+t4+$h*qg4FxTz`Zc%U*JcK`0$?W_tW{` z(fA*Dul?<4{+;3tb9tC=kGCH4#^23}vsmBWRLA*rewX3@N9Dzf!1pQq|E_TP%Kp$O z;~CIzM_VzU5RGd4Lu~xb5PsIKy%_J~{C!OcgiE69FC%_L*>S>i ztl%7?{Rk2NiQ*}Vu`#UiguUq5JKCLP19Wb3Y%me&UcN1Qt<2SLGUCcfD!=+6%BMu{ zcRd0$DT?ArkUkL5`%%*R5STBnJ3f%be~bUzN6^vhG1RY?Ho0T@vlQfEM);pp<7Khm8$zAuFL3QvDzj_-5up8V-PX5|Stq47WM-^=%-c*IwY{KsIA zpH9EX9e=C!`p`H2BbNuf20jlM_JuX@7brtNrxNsy#$5luNc{96Pah%s!x>|~fa))m z0nGj24W!@4j>JzPUX+UdJAv^(?aw^P{u1u}^!rGwA85a&(kD-^6Rb{aoR_=YQV}|GCb)R|XiNXny`@S)mcDIe~b02Hq3CVfsLiZ~f)_ zY4?8Go=`8x-=}l%9qxb{-`fyzvGh=TnXC`u38?tSzVF`6D!0Re}T z5R&$t(LvC3&HIu@ynjE9%PGI?5}hB7s^~*PtT+Jqs`j3TWR4P@E5zg49;0Zlb^7VP z34ni}nr~@d+amcxKh=}JV|DGnPJgK9&SDlS2=I=ec z@5rp#HE{a4wm-M^N8+y<_I&9d-*iE*FNb}*D7=3{t+%gWd?R~73npNgru#j6Os?;z z2)`p_|3JEsKGP%P2}l|a0=(Yv$!^DiyMV?^ZrxnooY5)ql-MbLmCFnKn7mKDl*N+L zZ+_w&=3ffkANl~rlTOuRJ!SLS$`*A#_NSKijcV;*5J9})(p76Kxje#m%n#`O2<8d@ z_56sxd`m0+!h6sBO&ym)e`-FFeIAn=R$o|*@^DMy{|Bjw*D>CIAN%>NT~(^b`!s)D zyS-Y^7vzt(W&E6B#uMOqY@lWBDv$Qh-_!az&tIU}@x2>A$H05oyI1P<`aPwC(jTx= z^rhZ8lcDt%RY9kzp_=i%4e-hh+*cwFrGAN~k2?6;)-CFpt^|DU;^&tK-Z_a6D1Ixfck(X64ZpUDl2 z=Sx8zZV~*K6Z z)7)Amofdy=(0}j;ff6R2KMvp_7E}6OZe@h{So}}w8ejG|2HLXDfI95c{~o-_v!J1z7aoWjQ?jur|bVG z$5XV%pZx96cWMtce}B4QbfNkGk<>)zB;)-j3y=3HKCT|`lfAtX1_Q>6Hh8SVysz~I z%E$D9o*jl+nj{% z6rVkz0scUV{>qo!RL3geTyuWv{5e-T?|FN$;W0j8_zRljeZ)7|RRae^K0h44w13&M zWhG4e<lebz6#+TT8FM|mDuTy{PEL&Bn`cv9Z z_6F$#g#QQuNb!a$ut5-f|5KUQ6CY4Kpqd|lvFsh5-=B26@8P!}kB_!K_n;7+8yPQN z8b8|z^MJ;C@`ndI1~{L_>$TgrYkc;X=ck|Fvw4@;x9`{Z`nJUG7>4@+JWC=q(U-yg zy|nzVffcNa55u2+^6~u%@!3w@SpS)GbK|}HApb=_(BC}#2{x;ma{RB*Ukt4{5DH@X z!D{9w#rK~;V)}gld;8mvm@b6>6mRiEBtGB&{;d7~`t${UuihI~zgU_%WBEZGu<|hf z^5Eis$h;GUWVtBrnR@?QS05n%u>s)Gi0BF0JmgrVe0n$h2kzGSGQQ7`TUu!KA+`(v~##&Iq>Rpw8m4|HdpasG|_FF(!kfZq|XXR(7&CIbB+u#EQ) zn%W-d?8r>%SKl z{*v?PNcq@KM(YDJp_|nCQlldLZ)q7AAnYH(pqBPC*t&IlE#HIr{R;Loq|cH`KP&&_ zkof7;<9n9@?}lZ($pJ(g=%E=AvOf*1Ee#|xO5r=-f41@2;h2uM5InVJ*B95W(()kv z^Njc7m$zc^pX6n@eOSM5=|3{uuI)kV5MQ~}u-8BziIt6e{u%HGjX5UU>>uCz>GRT`zonAze;(zvU)ihi zgzO84v^9h99ubF^mFW3ozdleb-HiS7h~2#is7D`KZ(obV^`SgU3jJ?3{4f7?ReSso zIe&XkW?0J)0~qJ~pI4+rPkOj7)125;-U5e6Ht5U!1&#MXc-l}~tJnX9Y5kv}zZI6J z-2HzFjsMC1e>%ti|7>Hl$+It@KD(l@qVe-cy5^Xsubia)9fmdSuJ6?JiUZ_t8r{p+ zlYa5}_7hD^Q#|FDgwXz<>u~-`L*JnIQ5xKF(a~1KL*R>XBz*+xhSo14-S=;Bj0>o~ zPQ|#+mvoMPa@W1kPjrdlIIhp3{rO72@!m6kQ^$qq@60>e``AG_apOVc`ENB+f6?{}!7s?fsn_H*)zEm!3EXcfAbGx8(`kh_T6If-hX~`;>iSxuORHl zeui>=;!TVHP0ru2JT#@R%2&cPzn^L76n2zKlKmqJz^B;|(h-^y>s~&5?3m_1y$|yD z;PPmF#&!ra)8Y8VuLqErE+k)6p1J>DA^Zm(7PbD5$}cnICmg^1lxZ)b@wg7=gi43w z=Q?(PNnC&0FKMSipYK1?7|ki~u~_t)cRtxaqG+Yw^}C@@c;owuOURFU@tpm%)K^dd zU+>SqUfO%_{7oHih5pujV*9)%H?00~BjjN|@jp1v_)qvu@qW2~YD+x7r>o1`|BvG1 z!ycgV!H@rl=eKJZiLY`qO;Anji4`*L?a(%pV+* z{b_ozH@Ri>z5SR^*g@A1B2`=>+KCeO55foFeDZLpw)P>JPv>xJS@h%okDX8C$E`5c zof6kyQ9`^ClJ`A6+eM9hc<=VAu{|CQL{)|t?(a&!` z?Z^KEnawdX-ZSkFR8r#EXZ+XuX)3Rn@qZ-#=%%}oxXN_B8UKf9!0VSdzghaH3O&U4 z-~U#jJ-Og->NpqunOUMO&*X;HC#*c=%fo!&Kj#1C2i|a)|DSpPTWtSF_Wz9=H+FLW z+SdPA4EA!3r~dK2pC*4m!2d??di3azKKlDiQ~y1e`x{Vsuvb^O+bLW({)?daF4fU| zn?dKhCV6AOcR3$TH~vp&)F;v%3i{*c6~k}h=Swe@Rq*?w`SV=-h5wx~|K#ousO{PL zbaD7Uh5cWve5B8q`#+rT51wiq_ViKG53xK(O^)Cpik1Jxc76o!1COzh-v`Z)MWf^T z{SZHBJq)K@3AXrT`N5K*j+P(u&yVZH|L=*PX#C;!&b1}q{~>G$8;(Cx4tx5H?XSi5 zXVm|Hslw||sXyMn)mty;$9q5hz{?jO2L5+){i(dB)>c}xC{wZZDRe%SkLl`mvh8EV zB;wW3`2Qc8)ZG%Jt?f*vpY}Lm8NtD0pi0R*k^RYh>Uypdt)6%s6 z!-qfTv-9_Vh{*MSUi{yB*mpX=_{EKU16+Z$Yc=LDDU(i)%h^`UTq{SsvUYg``Lx8RPmk!d`C0@ERR&#&cH_aN#Q+ut*1 zEI)_?RvzYG9!&fXNuEceeAmh8f#_c&IsmOvqx@)1jqXqRI@%1L#<=i~zZcW#dOp2S ze^qS0?B6h+=KkjWWFTk$*N^vpdNTY6{LdNwyZx`OUpP(?l$x|Zx5S@gHPNv#^#rtD z;SlhNY1)q<;H*5|EBY{E7DEx}Q?(6MUHrU=_78m_S_5|hnVA2dbvjGLXGJH|>bP(* zfxZXqrw`ws>&tWs@p_>Fuz%>3^Fy>=p8_E9^|YS9&WNW>{_w{EaGdXdzjIB~{rvjJ zDvr;LN=W?U%HT-jT_>d+khK4MisH{BJpSsW$VmO5IkDov;Z{%oFBabmov+5z z9{$sMuWBUjZwmGQD-K-zx@rHX@>*LDzslDay1zf)kN0KpuWlc1)c$+tIyUdBjt)qF zH@XMaH@aT$=L3I#(8FH;8;(D^L5Qmt5D!qMNc_ti04JRp*bmNRQzNwgy?XmY7gVk% zEq;3WX9fr9H-2BA@zW)PUp4a`=L^3+2AzV>r{e?A@=TgW(IyQ&MUw^bpM(XUuVzER z<49azKmUSQe^%Gv&F7H6rs@CZf4}7KVZfUxmZtJ?eU|H^@P7E8G98Y8B^Di6yOQbp z?iX4Q8#naJ1Lap3`Nir3YQA8&k?$w@)8V<4`0wYZ$)2zhiLdwT8?&X)_g_9~`p;7R zKEMPH-;d}M#`BYX;lwp)0B*{aAUoc({9wsYN6U}-=ZA^^xpy-tV88RdY2vR_XO2Z{ zv|g*FrLt1(rYq!rE2jUQzkix7P5p`4ztVVdM^{r5_dn9VFZ**HzxBn$mw~6Iz5lrf z@AmnZoALaMtskw=!g#fc@BhNV)(5eCU?bBJ_@g0Q4Rk1#3Y8z}KH9nk56I`ko=yAR z*NM1E@U;T22!fqMqO zalYS7=@X9l6S{`aC;TV>eWv~8DfCZeznZPe!+-LR;PbbPz8g0E`TclL_W9iR3I23= z>;1^yg5_?S-%_8-p>y*igzq`|XB*GpA-Fy?zAwf<(f@ww`i){A7YF+QW`K13Y~?Qs z`MJO+5Po0P+DP&K0aX5~Ro{W8rc%WvjOU@iPel`+8*nZBG>!j}udk=_>*`{fCcFpy zYkBoQKhvIE@HchzB*xOj0m~012mIgigE^s&bHR@p;r~bQ=laOG%6I4fL({!5_G3aI z(!Hs?5&`%)pZbH@;3@YPTwWoX?zd&QUE{|K2j6-)n-l;2t_}YAe$!v9Q2B-O!|~V7`hjS|r6V*y?yMXb9a1v{ z5$H!Sz7Eh@L%QO8|MG2Q@6BXKDd2#J#Gkz*dW`y=M1syB{{)4HS<#b8_gp?13Px+{ zkWVQqZhKDZ58B?Mu8IElfZ^EEwTfYB# z(wDP2@)ORP4!f|ok;;Ns)Dx}{?;??54gP9o{#vaC(ZHWdBi_6$B&@r8UN2VR#kO1@$*pp zm9>>E15DR?0M2EfWp+5vl*Rp>>TmR*bPGlyteIH;2Uz*nEZ?97K%VNYY^#v#-e7%+r z_Xnm^nEj^}02Ch@>JjgEi0h@lnzkPk{~GGLbp0rv1D0d{fXnym1Adz9|E9h~_IwlH zp5Jrv;R*xKE@OTsaN6?^Bz`)9<62)h-+u}58QQhJ;MVsL*Jrlx^H#Z@<-qpG%n5b0 z{IL8mIj|7&FcbV&=sz|7d+Yr+1?O|UU!ney;;B`XmFe;S121HUsJtZ$0MNm{y+)umq>Um@lM<03q4=4`BZ*|Q6Hkq44THfWei?8 zhT|&^nD&dyCpX6`S9|&koezEL6TXDXqxBb~@b~P?Du2G(T5tbjmSsMlX=DALGu`?> zS$~wz*ApIN`lE|!H9y~>@p<>2HQS8G6PVABfzI&xu0Md*FZ}v~pQiGLjRN5>^6=eU z7>-n*0PHRNlhhZSveQhv_5{tZV&7k}=M%pWK2pa!RQ{8W_8$z#-wfd$XnwXSeMZ-x z_D96yYI@6P_ru2Hi!GxU=Y(cCScv|O??p#@Ka(4lA66b{f0?aYSt>&KV)}J4P556W znv}nPv}PywZ+u-}mOTE)L`NoY?{xdC7Tcc{d%nU8Z~i!Viu?h+c(B9sjQ{@n65gBs z+~mL4X{`4qe=-LE!u*VMpM!hbv1gff*JE9`exUHcn-6jE=<{5Dq?`7OY1iu!T>Sqw z=Rc45NEGvv*AHUqJYe^W)8lN!S1D z^rk?*O~t66z><)_u5`S{71O`96GwANz*~(NAUwc;o1GS+04`C)QkA>_f2|8Vcu>vKY=4ADOm zKNJ5bK9u;s6EycIT-Q=3vc)H)fFBkuQ$oHrGZyWhkUrcXA;rp4Qb4Y*La;)Mo`6DJVLC~D2g1>+_ zf6wxQ^JQ9x+4oA^e*)*G5(4W1v7#|hDxWWz?uB<5?I*+g=Z?{OIvTs{@vNV}#nR#U zm6K)0^U!?B1>^k?p62Kah%bQUmResT{{z%#Ts=*Ge1JTA0{Hh=!=C;^?|<1^@Xt-^ z{RZ@UNUR6hgK!5^;yb;MqelJx_w&>4`}`}upKBk<`e?1+x#yqYeE)tKe%gP(sc0<+ zdPY(GvJm|p-ci54{s2Qhk-GRW@&^X6 z-ft9VWW$m0p6gBJ_hqCY>M+gX{&$-VW_z zMD$QR1dOLE<;h|s?b>;o(?DhB~^||Pd3!Lw+Cu9=)?a_XJLQf%t&+%q^eZSBLxjRNq|riFDt!!IUS^1>}qD0p9cbh1%+T_4|@WYS)81DbjaVo)A8X%tv~C zCB?&&_5jF+Tu(sj7mtNu4jWmpGDKj?ASJH*Bvr-Sqb zO@}DlpQevuJ){EzmY0voaLPw41u{YW26UbFXpvg@_lt-s7pJ}TcC_D7DJsP0Q+qJi-;jRN)ZqDNlwJyaPAfCG$WQzC3ob;j zLp+TMVx61(_)q%EM&zN2GI`%DO&qZNP;$WkEkBqO>Np?#m<0c$SnGFT zpqOTTze>3l3%Qv}U^$jZzx&D7F9aY%|(J)Q?R`_qx3hsH|-_PHF6`~7` z|Lf78V!B%QpM+0lJb1F_PDdAeexdT_JD>a?oq+ee@_u>#XVxxd4@jF7NNw z=YM6QHA8^T`BWCABI)!`X}${^6sIz&Om8+Rj<$xJ?) zW4ZwP&Cnp-e|L-`Ha`RT8^rFIq(1~cC+_z4$0B~NZ1UDOP`t=mV?P7nHR3^g<9j*( zV$4Snz9XEF)(2=kEYvaBUsNJ}xS^r0iD?&~`Oawa4*O^((O=7a?T_cu zdPL{iXSF`D_~|vfzBHUWeh-wI>k;LCE_(d#=dYjk+XJY7&$S0^p42~p8BEuM{~hTG z#Edv`|ZJEcc4 zKVjPUxqj()#2JAZ651bgl^Y*|A~@3c{SRKB_y={hfWH9Nk8W@1Vw&s;_^#z|-GMj5 z;Ged4MS!;h>z8Q@1o?LaoI_eZY5oSis-`L4^o~YPKa}!q#9yNGR|dTE{nuYF&3rK4 zp!~_w%o%mG{IL8mIWQmcAo2emM}6Fzaeu@2mNY#6E`A;T;Xq5v2tuUMe1CoS69*5s zzWOSk@5hIQrt|P0{iiwq|K5JAcM_c&xxN%XH`?aKrrhUOvtT6Rw}W_;vGo zfBExG$9&I&_<*q}0GgkN=5sf8GDY*%%eOgB;JWu~!uWC${{YYaOZFG(AK>0nu6HDR zfSbtQ4(dsJUk3UB))f2(_6P9x%gspr0ORkX;|;pSr{(?>(Wt_AV7kKhl}>svN%n!U z-Lb==Re0a{o+eBO4Sa8ENDYoEd~d7*zSn4cC;x*#MuoWkIqd~M7NSXeXuv; zn>u$h_UoGyYqlYtUK2n6C8-bT;Uw^Xa}4l9_$ZS*J}=T9 zP@(lF(g*zZfOY`9SH4;=;L*w+VA2&hAF+p%kiWF450J+xMe~hDJ%97N?v>;B7F?ee zy}hFn-&@uP(y+zjDaW3GJ)ZUpBz#Ygj%J_VBk_H28s>TY27kOzu)Wd4cPbCt4Qf0M z!Fmr;)7%=}`gR(0sx!8_&Z8&fB+GuJ;Hmq-)R08!gKP+13QNKey)9sNw$B@IqmUL^6(H+ z?ps)dRH5-dp+DASk@xfJ)hz=G|3~C{?1_m_<}9AAAJ2=W3*rBH*gHvo;SQ~>|H)el z|4H9TpXlVrhy6yzC)DBzu%dKdFNQ9%4<&9g}y*Lc#4J^lL*ys|qed{Z(!9{WWDgC}V#lviCRC*6R0H?D&4gf#useH+pZp?9%gljOBfz zVxDMb){W?o`QCK2_cys=`7s~zVB&uW?2ckV9dmur(D$esaeajN7}0*lg`|z~&td#9 zFc6JWtRL7cVUG>m8we~bnX11k7B6Odej)tt$h;9U5dQJ3 z>u)hEq&vRobN$gO3F~Q^d~+=1RM%8%eZz4R*T+Yv47xA%OSduUbpEmr-*wL9U+w|+ z(}#2O?)N&z`yY`1AL1XaU8Vi&X#OAT=XCP(*B_4n_WxKzo#!v8-k-PsuAg6in)o+t zydUx}(8dYWV!mjPFZ@j%=cE5M?_kR}xnc2sA>_ft|6J}bUTR$YE&Tr*rtH7S`!9tx z0Aa*mDJdz{{g=PLT4=fu{$DwX`EDfcU~e}2e{jU%S+kA!A$2lUUu5asKcVIm($iO$X7x4zJoOGP(?GNeoZrtMJ+3;u4 z^ongx0H3)^h48;G)0s(O!)A(KR9dpi*e_H1Us8-inF_U^X2jbX#`E&|qz}NqLqD%; z-`C~&`Fo>i=JP`IzkDw`+WVQ@u>4pEc`)%m1ooph%^m+QLYlDuo~&B`AC2bESJLV~ ziU2_Sy{*cdFZRYCh5E0#&M$=jZT)`x|KgheZ%(Xx86u*`>)0JDHRiwl@nFclzt_m8 z@#yOYKKb#+KmUBr7vF~L{}SKbI$?i;=cbEq!}0{_q!os}gs(7fXnqnmQN0?>C&(EE z?hOOZZO;GTe4EKx9~J&rO{qVV`b;&TctmTlAQiEOsKSW@nddfvU9SB_$0OAH1GxHD zh+mOQYyS)xU%H9afrgBPOz<$KZ5 z-p}NQ<;OzEgNgsS++W0$jQ)cNKyKpxLemueXGo0IBOWW_|LFPj=EUPKqyN(V5%*H1DL#NIwMb&qFN_`+bsLr6(dF!E|3?rJg@oBN#yq(V{{6{#!I;NlB^V5fst@9-wVS@qAFC2$pHK0dwjeQ0*PnXr2R~ri zm6x49TFZ}{pYfi9zp115#Fi!wSbiuu;Qu!xKTP}&;X$DO>V9Ui(xD8^0PudlQQe;P zdqC`8ngbyFKh`Vh{(<^ibA554{&}wR3yuG8^!z{YK8EF5dc03~Y`C}O`L{iZ^P>Y^ zd}SIxVLKP}3o11yF6~FidrfZ{ef(uJenG|P69-ND{Um6|>)-w7=hF}5lqdHGs;S<= z_kVBy=GXun1eiXL`S;`P-g*J@S373lccJ%9`xQ;UUf?USwfXjdPx$^*mQT@zU~{Ma zi>sQNB)@3Cs!RK+J$maASiYA#%Mo92Ba`!gY{h;dg~`rzub)dJ3k8@ZT(GdSbmT^`0<}cQ_Q6h$;{%R%eg+}`~M+q zrbO?I*68siNSRU@+Ww~(_Q6NWSCy7rcf6P>`)jwuC^o+k{@-Z-f5LAp*V6W9zrEf+ z-fsi`oB9>}|GEQkQ{(>B@6SKiw12*$4e^pNJn!QBlYIfXHH2<7y z54d=J_5gRjpXLu}xf`vu8^shB%?DIZG9R$hNtL8Z1Xlasuyl{}J$&4B4fUnOH1q%6 zupCbe^dTB?4`w(b(8o)c1@!#Azx|NEU<`?`r}qbaU60@W_)q+wZv5}Ze~Jfap6|au z>36mK5IA~Iq<*xt!5qty>H!-w67o`fj=3?@bf` zZ=vy@{PnS1yMp^$ioZ7<{?mN9IX)x2MSoh#*UvS+7h7IieUDLy5BRlFiz zVS2%jg#8Bo=hct)Lr96$ zPTaKt=Fh8qe}8`~@!uGqH7AbjDMjM*i^c2tKL1HyJVE7e;MoHr*w4na2T1?DV&ex? zOl=RK`+W%xZp@z<`v;6-uskOE!tpo5RXRRVR=Dy1tAYJ8dA-wZ&h1W_N6z=RLipbY z^oRf7`6T>r5RilX8)-of#qWW7rtLBQ_V<4B$euj>f9;Lod|Nesb5BS&fvx^=7&-aIO z>;Y~4@K=CAfctyDJz%!+1kd*$*+UBwx%>xS?#{6X5dP=+2Z%}R0TMmcdV+N4E6`;# zwEhnE^N?fOGr0HKiM{on-i>pUb!9{V3nhyQMT=1Q)&#Yg6ZI$C}#J$@_+{HM`>N{DqYhbaCp)+?(O%gu>% z9TOARrrdA*M&m!NPcrfUXzT76!WV0MWJl()7{*I_{Fom<#~)9pSh_g@f6q?tAIbmE z>>u;TTeM%E=bzP)d4A7vB))#`>sRdapr4(;sls{RK4s z6p|OV-}4Rq>jidWJzJ-=OsO+wY7aoDfNTm&1S8$RFT=lqdn57NkbjJ~nWp0kXQfHb z>-WEbFK&4jYY5!L&#&o}`i1uAf;(oEq6zd!eFhPZ10^~>XMOhzt)_lS<98GP>3v~2 zht@wMw0;8)eSAN%-`BL$I8G(HzO~)cAA-o=(eBv`>JyKYM?1aqn-lMb*K?(D%;l)1 zEk6w5SR(Ra;(rLwv?%@m-QEAVeyVkUtm6L~{(m(7K=*?9zlg4e5BC4P1L1#l|5B*` zp6~p;@xO2XKlE=o@lGk;%u4ReaP-H^nQQto_EWDV0dSKa|K<8CC?uSJ<>Ygl7P5Y` zeO}rxzRP$%8ef|0LHzaria#?O|A6zbXPfqb$9?+?Ol}XLnJbmFJYp>?A^eunHM_Vx zvZ+^$Qha{TzJ=y1(^Jj~N8Bbp%k;b->vHcv@wqRFLs}o<=i#%^I;DRD;sFFPePrPG zxsI-`uKj%ed;8`5{fA8Z<&Wn7*B9ac@Av-;s{I@*xcp|=3)fbzr4UXsS-fLTSbh)( zmZCiP@gL#;wY@Jy&%6j}^8cp~y%S2@eih|7?s8+q2c!7EiwXa4KLvYb8P_+6@yph& z)q4HH?mcU^0bcd^2L5=v5FJLZUy$}|EYIZY-_Fo_b|bzn=I;@1SLe6&e}(c5TAp8k z-Z`cJzdQbl@%>eOrmmmAzKf40{_N}G=TZIv-g#}4_N-i@A&NjC0H@|DbAkvBVuz-lxNC~b@b{X`NkOj zV@E-er1%`>`aOESw-0>&^UM;`*Q%?%{S*EA=#`ULe`3V0j+rcmFoT2P$2)Ua!BNq<+)hZwBWVdcIla zW4sA5=l5}*;ujeH0WTbUD`&sK+1dlJUSR)p@dG42<;M@;>Ip5c${vu4#FuZYYEtzl zdqCNx$?X90i~h*@iSw@WQ@$TRfTjnPf$nH)$bq}gYEr4_L*sA2wcZbj z_6yjK2`RqbkN;;Imv1w+2Za8#;sBO&XnP;|cbe-bDLypVtLDcvG~YuOdTyhmL5M${14&r&^WaGFIHON|A)%{ztfBV{|Nk-Xur}S^d+#Cfm>kbeO7 z>%o4*llcd@WpeLzyR*+pIYQgH`S(IcnqP|oKlwcJ4}|%t%}2Kb`TxRs$f+X#z^G{I za&Pb1>&QTt5~;@z!XE$&1Qhxc{$K8xxc0HJUXS*Fth>P1EBlP+52NA%4r_gw^e3=O z>!V?cR}FV0^q5gTU^Qr$a$NMy&=^yV8w0QCJ2!Csg`1&^*FJt4+?`gz@ zGxIOs9|(9cWbebe9mi9CD2@@=#64=5Br zfb@;L^#a+f_Gj1f>h9M=@pMU>%!&`h+t3Nf-@c~0R>yPX7M;I-u+%wm+Z@^l?%_MB zV@A%_{oKQUU_X7%Ayy={SH}M~`0IXx#PZgbSa$%+P4xR9ds!y)bL|h{*GDJg*Hf>@ zb$OI;zRw8s1yg?w#~*kZHD1QGw|K{#P)Ey;rN@t(5&tRrFMarJaDVX=!hiTH(DWjC z0Mhv1v;to!FCc&22G9Plq62#9A<-W; z07Bb=ftJ;b|1|#p3!Hk<#>dP15G=ydHbPm z8C`cE_k4wv>yu8`7a+VuKFqKAju^>_{Xz%KNs zNBI2w`uOWNJ35~qvwPmQ#L-sFuj}{oz{`m5hX8i`JhZ;wdz%#R<}BWyx1Mk+eCF%@ z`T6z$fBb;S>;aR+4{&e5<+DBz8(+RHCIyD($9l8BF=Kt8cLg*Gt#3ny;7|CC039by zKXu-fA2*Yqm(PW2PM_Wv5Fc>$>eZDd{!bY30cpOYLe^K6K=ysCf4souO*$Wtb3W$N zeEWa@$cPuu+cwJ{f`i1F$^G79^aPZI)zJDv;?H%C!yz41i7YuY{|HuB^t0|v!fHt)spw_Sa&+{Vf z4`9gC3-IrUzozyV^vfUZ_h{OqBJlS+*50b;18F^AzJEZ+39sJ#O&yIVls{P7^2g-B z%_t8yBmO&Gur4Bn@Q40sfclS*#Je01U?`fF@ossV%I>!Z4re1ExLUdHoJZ0ir)i{*RJ%T<~^eV4DixurX3 z{oy`uewOxI5tyLm`pfl#!!iB*=V?9SsOO*6)<3uPng8-~-_HwV&oS%)mro*o)9Mx} zkHiD=&%^$}Y6mZsvf#e^AY%QOp4^aFdPF@e9ez7!j#`1$WuoUFM#Q%_d zCg1vh1OT9Cr4+&+mIo|4x=vJyheY`&RKLmMk0N@CjHntsrR)I$Yo$iS8T5Csw_}4i z?!Wx~O|dlf$GP~wnebotM{WI&#VRYk{YnvkxBHmU|M=&h7duVs_sR@=YNY$i)2nT?pcr%3Nr0p$!djQ1?GUbo>g~!qUsr>x-O{S&L zzw@)u(LRsK4a*Ob2NVBuxpNayA0hVWA*?uZ6ZdCR(Vdy}2O=)|>Xm;$i#k6eN--ag z@7f=T`vWeo5M3Dm<$h&)ebQpbyJG7{^ZTYfmHf4H?E$&|0d4RX%v~?=B-RUf_K;%l zKi}s|ePS$?`(@kL_o!8~^?CmTwQB_)s<4{!Q|iZx6VB`-A`fewv=| zHvzcN1%~LEBiKK;4vkJ=JfA>>A{mbt0g9L({`R;D>jN?ThrceO0cX=#zxYTwmhbC$ zfNDP`Z#=K)tlpo>Zx5j7$9Bp3ermsJFMbBu1BMNKoAd$9*SPIp$9J0W>dD{K(c-7& zhslAZAP-9d|IL?z?>`rH0@24VhVY%|2dEF?)0DMS2zUp}{wIleq!_;RMY<1%0;OwL ztNzN}pM(OdxXIuD`RU2*|A?QX$7eMDHRGMlH(o7t`TqC;^#$Swz&|i&Jhs^52Nc5p zvyIRB#{ZX3&L#d!yfg62jgO=8j_|Dl0LSu5<6F}nK-c4PEsuWrohv$(O=sX^kPHLQ z8|tdMxIVi5xj$(7b=4wCU#NsaFgQ3iMyEV}uqt>A{rNv!5XO-~9jVy$^6)$9X6C2vXF5G!yvlxZ&BZ%A=OhjUX$M;=`uoJDZ>ks~}!B zk+w7htxzNci4ru)mT=r-nZ-RDBPxmvad#yj7kiauU5ONnD`Fsuu}NN~ydwj)ps;8U zfL$*TUnKy+*rG^5Bxf%dNEC&ccfVi1_x0;}_%j${Kmvo;DDutsx?jKUuls$!?ytZ8 z+SCUG{VfOe0kp^MW@cW9rf`B_#p-)?xwOP^@AwiVq{)GhA8tR8{}&@a$`SvqI=4k^ zT-^P|?>lulYtX&Re(MHJyZ%TVTHAB|mbOSdvD7<1Xx8hgQ{jJ}{vZ3}%NhTJ7Rl$uDy1n{gBGT>A@0?~k8G zA293we8c5cyAK`s--w*bY~=1k?l#C==Ke!$KOB?tPitT3CD7kzfF33I!-hbeA5gt^ zh|w_bf&Jh`jBR}T2abQX?P*GQk1P9541eAhIyfF^!TMD=1b+XYIfg$H-az1bB-3A^adLKa!qrFm=aUqYhXwJ! z%;*0>JXYuLfuSyUi3ch8|C4Ci*8{)uI!%`%a7~w7GIvDdF`S0*IU?u;)RCZGdxadvOSGA z9-#jI4>xjwjot{L@27vFZLK}>y!n0d-fZdq+$fh2Mw#F8HMK*0mOC2wzUR9q{wrw) zj)xkzZEbQX?uSwPSM+{h84vjHm0#}FFHuO710g@$ejxuZMt+$1Z=)iV)>5Bxr9Z}Q zf%kD{sawCs9U>2;-pYFbh5)n=!1mz|H@>ia0OaegeEUCT|F89}<*xq^;(w6dKfW_= z`V;i_3+VYO*K6Yd5NQwU3vm9trm5eKCC37^zai3%cWUH$kA|FbL+R=I<|D?2K=*t) zvwT>ePnzWm(i@uFl1^UvhVtmi>5*Gr`XG(nCbn5$a4#=Cwv%ew<*#49AnoxhVdfW0 zCbfNx8}GLd{6RObzUQ>UUp^B}T|AjQc5JHgzyRa9-yqXXtcE#GZr~%@=bGaIjZWegyGu~zis>|MfsHXfFD{m^P6(Nz^L+1GD`aZ z_$TSeLU!ymZ}f9qb>X1{ zvE&gwUu#d_aX+_fNeb>qG{+0=>8CcC@pGlSvO9N~`M-Sd$ivwFr|m;7sPb;qC2miD zqonUIT>h2&35vpxcKFYoiKc%ivp&Sf{Pag2&gb7tyBZUI{*hBJZUTDi`V&8|fAybHJmJFzWYuwYL>O-AD&6PTwcO2U;`J<{TOrq6p zM%oX!`n->nwt@L!#Q_QeH$D6fq*v}Y#{)c15dII;-eP844)WdQko$jFACntl`?5cn z_@B?6GNx>7Wvmh_0bia;jUkOP905>!J2bRb`6m_p|MXK|-i7!-Gu{XBKS=M-PN@$t z{0HRQYr{UE8OO!z{S#b|$9zrC=Ysi{nl7~d{|wFtFzx@_(+~GnAP7E{x;!^KKh{5g zeDDCqr?r%!)d(ArOYzEeh&{u9h?~Qk^ zIPhjgdtY51<9k+bI139PEJwxCxgUR)L5_UhS}ytlo)?Dm8Iiw)5HE!j?lt5``SD{( z;{Q*q|AfEk{Rg`CfbdUdM>;w>*1EHQ`X|HrWQKpz$?|GS|39Jr-;?h_yi)jGW9pCd z{Rcc9e;VuC{`jnA(tZJ+FW|2?2lFpA9pZmJ{x@JfeP;Zhr}MYG`F%_8rIRPnw^F%& zb>ac{5485U{bd3=gw8a_1KX$dSM;Q}UeI?X^K%D#5E}42?FU54hj=HPaIYah%8wsQ z68}H5@b?H+oho?nHob34Sr8IN{7eVqX7Jte;eb9eEA%BAOCv5H) zI6H{_?enM)2=RY$;Jgw$2&WG!X`$LHT?6+=^-t3}(Kjs5>+zh#aY4dVaV!RLCBR_g~k2iwyyPr5G8cTS2ArZ0{TzOU4D=U_`-eTbJ(zuvHY9{I5w z=QnD8!2Yih8wP}y{n|ovJ;2llbPh&S$BrG+`_GEipLC`hSpFKxU+rIr#kl0G!daZx zWcvT7{r^S;FB^ZG58-%t$eYrC!yuJ z+TZT@{@6G_tseK+8}?_h-x%j9iTq!1^mu;xT3~-|>CuYg1k2l=&W~?TuXr5Z`*i)< zVgF!RU7GG3ys*!*YKEl#@VAH)WUQ>vo#|*QnY7*!8vL8;yjEQz<E#GG)+H`qICye%5x&K$Td43bmJJ{GQxzpbfo;T8W1=_nk z4U6@ftdT!0*t<2|na=mO)1H10{IbU74U_nV@ecT9JkRlqpWYpR82*#gcx@8BL-Id6 zMSOR+;qND4|95n6ee>w(=x@vO-u}OmoqsS_e4p*}A_vMrzDr$r4eMiaBjgABgNgq( z*aP8_cfMaa(yzhy&rje3NYxh(07PC%?;!Tm2XHj?{R!45??8VUG( z^>x2|L4I-ku}as@fj{f|_$s5m&%ytqt{e&xq#rs^SB3V~N$AhmqtDmazE_< zjr_TPeyF2X@6Y6X`ZJ?}3VlBdC0^t}h?l|%_Zsq}{PCJszm4+G#Gh#D&i$9bR+0akue|%H>3=0Y4u2|!{GCic z6^JiH&z#@c!T0u=cvpxHmWSuP#o!=D>cjJt&HUgWc2^7)mU#MKje+Yvy)%yG4ugij zyO?uG;-5=D_yB%u$hi}E2Ds7d2@f6UebkJn{(TC1mE=b}#PfPc!Si!sv2h(w`;FMp z-9~v{+7-iTF!DUh-v$SdLI?3aNHhP_wY9a99{QpEJB;>k=*{OJ{qdUooXjtjcgLl? z@_=8OrvKkqY)3-g_t1eStI(Zve2^x-Bdv}HzUT2fm_A4c)02N|Dwk{iE)+Z$e$2K! zBKbnR6Hd6-kRRp8k0pWsb(Z_*HJ``>X-(ztC*zD_c4>92?EwB$1?`^y_y1o1RL}or zD?cRvF#V=~FTCKD`jHcihky1mDN zgKMz-LAoWtzi8^xNt_p8)TgvG-*2$jDOA6O8n5Moo*}q*Li`iXg!~`}%Ar4)_-~_5 zP#>0`{@+Fa`=ov%LKRK@|9~^fdoROZ=vvsDxu^e4zGtnp)Z&V{?B)P!u<2cr@{}2K^4kDzDr$r4eMiaBjgABgNgt7 z+$mq`8npkP;7@8O`1yBs@ch3Q)|uz0i+qsuAw9MHELZ+SQ&=H~fv41u>+RX>C;I%N zApTQdP+QxfSLA6QiavK-p67fSzqNlz&iA2iF!b>YjlOg;zkJ2gv#O6?-?>%amoFFO zmwOHIGvtTKfpX{%CjQ%~9EFwCv0Uj-oN+8Nzb5v7+TL60P47SO0hIIn|7d%rXevti ztmXBsl23vk;rnmy_=EVos-{Nk&m*Uv+LW8Prq7oR;y?F)v`J&(`rf_`&G+cu<~SE& zFSlykw?|}t=KhMx3-xhxe@HO?X44l>=9jM!eS3lW(4Nq&FYO(yRsMbmj-M>+gfV{l z0Q(;*P76!j@zZrZp7O>|a~?m49PlNfdncrYGa*07fpX{%CjRHQZuwHL0sY6J1CSbu zJP|sR!(TQt!SjEstE<;YJnGa{JpvOyU_R@O&xjoe1dYo4fIzCyOC=`(_Y^k zF9yd4K{|Ne!9t^hLm~&USnta-baKyVQl(us$X?LVmD6ED`*-VF7rbwEoAi?Pm~L7P&MIBy=IeSV{!pRRoI z{co`wO8P$boX`4<`QGs8bC7N?11r8~@6JZngf-x>l7_^=aF!^@*sS z3hMjEnSXD>`%G-8W9?V5#$`0qX_%`#*0#b*#e2 zCp90ne7q0R)NjW$nz{D=;|4ud`nJ6Ii+TGaqN$e;Zby%o{uxcZxCz@g4f?&kjfYGc z`yq|}oi$fL8~zds(bV6Y&ljdKKDzF|zo8d&qi+x4?$_LLUdsOx&KrU^e|_GsH(t=| zbHVWf?KQtXX7azjxnj*}Ltmi$K`mE8LGeX?xz}=#_hya4`k35czgv2=iU0YvFCXeP z=NHbW_>&rm{LnNf`@@-!8hS0O7W#hK!$kS(?gb3-j2u|%c)rx?&-E^IK26&6Pca{K z{(ei?TNv|sevi%F?zhPQ=`UgXd2_sg@dgwwlET$TbiO5Ya6G{HxRF1{CzaJ5dj7K% z@jzrEuVMX7Zj>iKO#HW1o9FNU!?&ZqheZ|th}A0P{S>}_7*IVG6oLP~@c`!gvDnZ+ zwm;X8Q$QMepRB4Z1OFvbzomv(VSN|YddSUg4~`Fh-YvbK;{(_e?CAlHx#6J$o9GWo zuXju}9vDLcUrxv`ksBdxa=@3UA%Dn$#mEm6|IM~t)W2IT_s^?@eE(7>`1={fp8tW1 zC+i|ZL$1F+&iU1Re`3Nl4gh_#1v+gh6vQYLr3 zpzCdsGa+6IC){hukMiTkLc;$I>*0R~LAd*3Y8~>0V zpLY(c|JU68{xHCn@11EFoXc4MA8?$r!%tRKd;VG`oHYFZt=tcFp|(H1+43rUUx=5| zS9uNlLuva1?I$6yWABK1@J;A+}BR>`!{+r_i8_hDld-rZ>CDO15 z{*KV=BcvVYhmQT3^+U^MJjWBf=U~n+>0H`x-2v?V$B1CG0sH?e*Hm}7@t5I`{?bW2 zr}uY<^0>6}ILJ?B-=0jqE$tJG59#^kf3f^Ud*S?He*;2^=Pd)L2=(P! zLb@#RC1gmG1LeSv#g6}g|2+Kv4uab|-TD6x1dpz=@q_fZbJ(%2J#>L|?1>$d^#Pv1 z`N#LW{(z|*;9um_lT{T(oCjR2{9J13U3|a(J0joP)6rBc_KrS3?(87;zZv_@I&r@J zOmuttVwYp=R}1MNKgd6KOiZ4anm@tznk(I&X8R}97@p;I`^#I}p1;)J3-gCMAhiF3 zTx2K*d~<8!{vX!ITWlf&J+%1nCo{{$3RRCu?ftyZ0r4$OVZBX>uUs&*JY7w-Enf-RB3p^Q5y6cRFB@ zXW6^|9U*!X^!JZF286z>%=HwW4*{>QcmhD47I{!4oq5XL|5vM?&y1vb{vXbRUk$o1 zJv;(^e_bSYy2k2*fdE6zl@*V78u(Od`LodT^YGrp^OMer)q1|p`Pxw4{5zV;R!~m3 zp)=jkYwqt3@qB6Fd9m$H{2#-BQ2Gz;_dZ4tI-0tj<4@iHqN$7MUe+Ezp63PlCk)U( zV?O;}fOgaSazuW)*AVYQewZ96hyGyVzm3Y#Tu$m(8oI3wo_F81uGi%x->>{1BMQQW zc4z1Qd*%C;_~~e#4uavpkc!Xrr7z%X2Y%CE?^OVJj{EszvHuAC0d>`JzMQM8qW<`t zqNq=N|IrRqas+VBl%>R(k z3!NV~yL|2G_TB`7@F$wO6aM@YO+rVoUZ2>5^Siz9(1H5+Aw!?X^BIrnSjVCNKe$`e z{WVA*-TNZWBMSBZzTA~x?$wvjAx#dH13!ZJk538ub2r$y+#vmkb-|k8^KETyyDxZK zY(c6Z-)n%*aQ7WP-=ix2T;K4;F4CtVe*x}St~wuO?MN)!Mf|=({Xhfu^PYx|VA#{= z6Tg=o^S^J-7haK<;YvI={g(ytEu?3*C!_xU-g{S5KcWKl^Fdgm7CHduE z%R%0oH45uva-%%(+^o@T+P8%G|A>v3C>dOD`>wWH}Y zob2a-&o8Vy4t=q!ZFl|g{NPugxF0M2C!P;$D%=k>-{TdIm&V5Y`9AIQ;2u%S&$;67 zd_V8v$4vN+^I!~ofA-+J53}D&;C}F~ee=EefP{{mLV0mMhtTkkpGUX!-tmC1 z?WR8K=F;(ToCjo-596n}S>8f4>XVl~SU=A1xg03<$9aLxV+cY=Q}6AoTvn<5cd-B7 zjS0OUA325P08LY#_>?PONQ(^hf4O%;S~wH(gB&P_{t(1}eq7SZHh#>CK4kra{n=lr z_4yd=>*afsd^|cM`ufb}(TTp?W#GMKt*Kn@%SU{#NkgAJ-}n~hUvR#EvU}sbzbWmh z=KF?zWxnydQ2rjikNf3&FED?f1->5}`?~*p5Z|AUpI)uTv?>Yb(}(qJoA&c9GwMG$ zpT%@v;}xHeYxLpsAME>X!p~ogAI5yTbCCY*$Mp9B{A@;Un#O!MkEVXYjK9@%uzYi+ z-TLgO&-KzZNGLtQyPBKjmG#KqzcX`cGCm%|0D;0yQhyH=UktG`{^gNwlbX07b~wy zonFa5O!!59a=vel&kEsjspE;CfX@yoPiML~e0TN3GvRxE9==mQ{-MzyOI@Er`Eh&& z_|YQ-j&FvH@dN2(fF8@EVNW2;!j<*8xpaHFyM*Pb9BEHOzUc82#z)Ot5u}Rqf&VoK zT5f4c=*h8=7S_0OJ>`NEBs_n5I8Il8pOQ{}pBZQ1 z*@HIL?}ye7F1j+RGzuU!(M*BmFVe_`g6S(=G=Nb$@TEgmJ=G0vPvIknc;=nCm-zqZ72Q8S1F6pb$yy% z>Gk^_{{C3XgZ;lJF@D#0>c)>9^5bdmb3&^`z2~*Y*P|u5+Ao0oy5)xJ|JTv9!u#4a z#(ch|H^d*|R$+fV?dc*G(yhwky$bI%T5I@x~6*N=zu_u}w$ zv5h}&KK{RXB+*k>r{!9x-xgM=>tet&v%q0_O>Rs*9y9R&J{!rg{V#T3?ibD{SfeLB z<$69vJl6C()3o33sHJ|NFdt1FwwD?6-D1bzh0;&P--}&vKcn%U`?byeeWZ5)zy*6G*`7Jhiy3oqoo__yZQ{eyGx;@e_?K17T7Fzkk^33n} zoBmxp zL;PRT{*P}y{?|7*HMNH4|9OJH9Pv&tjn}Y#mPP!p%2nm+uxDR*BlxQ60S9oOx!lqV z|Gc%;YqFmGekc6F+)Vp@;(s-Ql&{oy6y|qx#}C{;ADsUK|HJve*TI*1f1GdpSL=O- zec`2(_06qYw{6pMPfJAiPKX!6nUEjkKsodW;(w3xpJ2^@UH5juS846h>_GOMGlKd4 zrYh)TwLM?4^Y^)?5Apxz;`4mtPkZ{!BXtPU-@Ntz5dTB`R~#r7|2qdi*w=|5{i%?= zX-_|N0Oq@KN&oCY_!rvJsP{XSgM1emUM_eQ*2m|-9Qx;dR>Df~dE) zWFA!K<8-X;bFRRmZvy^yH#9FZ{J$0YzDgY*;(xi}|B;7-^MBa?X?u-O|6gA1UF>+W z)cEh&_tpsB)1P8bQ>*qT(9jEeQz$rnIViu}>m1~*${>6`E)(@<4Yh3VO zz6U9rLwo*yXCQJ4{(7+BKH=H((_iL9E~o9~OO5Y^@+&p|d;VokOZ{nIo=mRVE_6HA zpTQH2N1LzQx!*AVbAq(%zuiy2&}g@Q%B7>KV(Dq_uQ2n^rzi8PKHk&Qr1`D(`{6(# z;eUw#A^t->ukpH&|DQth|7hwVobZ{@`lgE~>*L!n-oTSB3?%8*Z6=4&Sdh z5c1#a2&L{1!2TKWzaQ>;@YkNMi_{wH?HoU2d$pF&h48x6@pHw0;4$#rKR@g_>>oGJ z4}*Ww_;zl9^a9U!NotDchrz#j%o_|LjYp49mp=G>+0!`h#^hI_`V#N|@`T@?-aK;T zVeqnB_{s4XmYcMFX|eOiF#X~lKNLIv-+ZO_QFH(Qr1?I+@4Wdw=pjt_rN8m~;KPRw z9TTY=;*W5`y@vcK6MhuJ|I3-nnU9>|Xv&V& zmpZ=G_}`x18D9$phsXo22S6RDXZ%5VwAAU~c&ZcQA#*(SGUo3a5rm)gw>yC#^it-rRC3D@t^DYJuom4`Sj3%-bXP!_2id(-mjCx(c@ka zc_VUf$>M{@fUy436WnV#@`L#QpPknn>r?CRZB!HI_iFu^)Ly=iZ(u*b5Z1>r6j0*< zp5I$hDdT}O&Ko-e-`hEH7wpLQB+t*4o)7$AgCOM#<@e0;JH-E)`4je^((-2t{EyFc z{$FtYKXS^BG$F|M{m=nB(t#i}{gcC-S+6jOeDdX<{Bp15DF4kGhV?VKu{88Q#D7bB zypn$YiPP%f%pWhv_Y$P*BJOygpQC{RjHgqZs#aHbDE&Eabq=nCz5KCR@5hzzPu>@# zOOO8*cdbT{_l5F%X89fB|IGXe`%h{4Gk5&23*bNemvwXu$@ku#e&*n@W5*5)E%L^f zbMni*hWHrr!{k6Y^aq9iW~KOhit#`qXMJCi$@elH-8}*8K`04mKe$Y<7r=jjS}&M9 z-j@92`P-G{x^vxn6MHdd)^$ zZ1?Wng4dE%=wC%${lKu(pBsP=!3Ovbu2}A$=T->sgYhB$-&*_$@&DHHf3f3vvE`pD z{s-m9mveQIy<`4 z|J}U(|Apj9G*xj|Q^MB|0ROF6;~v~`LpjQOsT;3h{Y-8wO@0)E|M}eVDIh=o5;N={ z0Q%>yIxRRaFvNcu9WB27>>>V#`0w}L`R~8Q;(sCke}%>aT%TOs?W3aq%awH@?aO@r z3i+}4`B4h||Iau-h=0Njkr6^)b*|#{pb_BzPi**eyW#VLNB_}PjA>l7yJG&{ic5}yyJD&{20khj82SZqp7+` z0uDvo6_%d+t=i+H(D+L(?tk<+>_-rU{tx%BSf4=1WC8^t|RNX-%sc_zghtwD1Lvg zzU#@zUIdBXu)ewKID*jCcl~_a_INIudTAHjU+DQG@&9m_f44`-hxz6f-(R_)OJ@1&%XV1*)Ut5{_Ly0@uV_4XvuMsA zF};k*`#k*DG|OYo??{L9|8V|~ZlHpV|IPm4-u3?v=l|h+)<>TZe~QJQ$f<8Ua2`Q; zxHDcK?=w9ZS{OKUCz_Me^Z}N{2w#+!*c#vS-I?n?ehwiCydYU->$!8 zryKfySV!_a1v|25>sIZbMC5|=y7OJ-oWYFy7RchU@>~`hU=V zAzc3#X&&NVh$s1Y668lA{C^4O+jk>KkBX+=f3yNY=wN;!Ju|;&%^y$S&-MPApS`mA zGPM14LjKSJ>iZifoxd=!tb5rXSYLPb{jr#yPY3aHvC|>`=eHpF5!(OxHFK9-*+O;?Zo%k(9k$8D%kj+oBv$O z9S@W<{qu1DUpW8A06_YCIR7tB{)c$EwE0y${;zmEod5d+fRcSbuD*YuJ-u>&O>*;Q z+V|)1_ugJR^4MdO_5IxyC#>#e+tqv@?w0fH`!V0o!~b%oDerMyo7Qjq+5P*fUU}t} zcEJPgKM42#3pd>Hpt;{Z-2Wf$|M#U?>GhcPW?=)L0s_+yy7zwZy6KX7(9Un5=to;AL4KRswY-(Tvq!t8~!t|Iq(mi0?iJZZtrb|DBy=DU1LCVyam zW+H?6Kh7Jg^ZhXkPB~w2D*2D|)6)oY|J`*!u%x5$E~JC}*c7R=YJ^=D`G@mdwg2G| z|3mzzKV9h{q5t0nG9U5)X35C^TU6gd_|N_SH3)+D!2ew#{tGwezFwy6{l~_};M*t5 zKl=A+GW;=!Tyk!AR`QSY``QlQ{{7eRFK#76TKF^@ezZRB^DD&v5dTB`FP%IK@p^HM zp9R+W$-6;B~J3qdk2QYbo8`1KED%;V+unRMq;(4z>l>f*zG@o zzn0!jRoif&kMLI{0I~m7oae*yPGYgF96#>S+War16@O;Wk0XKfQ`0+|q#c6S5dZVX zKjHbm;rYKJyLg?Gd<>tTcm9R=e~ZR{-0ueuf6>%o+roi9Jj;(^L$k71=YBsG1aI!P zR;fR(Z!ce#)$>!*-0>&rLV9L?aDKV(yN#M(J28K6H1<0RALVM}$8IB@w3(jIhx32m z|4xYiA^wZ(;x)woTZAuOBNXC)i2paSeKO8KOYg;#j&huL)M0mYn4%m2dCVh0V8Pi^1$QU0`AF%xi-@cIVGxgiS{F|ZAtwxah z)bI8o2wmuEBSGl@-yeUF|Ka&Rp70OxHynR_GBdsvkN+D&|9}4HRj_|~{`}*Z?GKM; z`<;f=;dPkqKO$K?9e3xGLW{h2ZXaFVW_?Y_@al2E#?_o}lWs%6WmdsPs#4iMaU=hNSOYH<$GE1FLJ8B+1zjTbi6)(?AWoS^d}GhHNEOW zeRH_~U$`@Qeak(+$Jv;aJvt-w37pK126R+WTU}=p9qN$zn zR>R*c@jjXK{rkBz&ZG50G<9_E^5vD4LNE3HqR;E)Y=4;ce0A8-lxT8i`;K#A-_-Ve z&Uc+vncKRT+>$==2k;-_Klm^of&1xj{Iebp1m9uf#&^Es$A|d881a8x>kpT@{0-|r zxA6+_e3$8O{-s?j9yjOr#DDsy5xkG4UfNZOAoLRFf2MOVnu^7SI^5a*gwxPl7r}IY z(*8ZguWsL-@Aom+uYfG3JdVX01Nwa5pT8Tw=;&$n`K(Wf|6sxb3IE~#$@Ys|jq!u) z|KA@k*eG`_wtKe}pZ0b*K50m3?mv0#vB$K3<#7LhzCR`M&pc0w^b-iUOc`w4jSY?K z^F7H=k-fYwarqn8zkq#Tq5cs~y|=HauBS)(6!E^ZEBUrh*AxG>{-64S$~9}&NPMCE z%Pn5d_XnK5%w^YKFZb`sd3{G7o@T!Ph3;i-)|WiIe?ouH>iag%?^&d@#(S3E)Gvd~ z3pS__|MOU~pb55@XtyHsp%aZRm_&qNc zn)N~7$iw>`*bpz}XS^xT<-S}QAL74oW8q)fUWM>~uI-8C2;G0)h5lfZu|C1~oBkF+ z=7midKdfE5wnJ_%iv54%**tw8eSb*#XDc5>KF_PX!%M>a=cZp@==_VOo{lFFq(4#r z|2BfqPsh1K&DS|aQd8i6GO6_g3%$O@manDv687sm-Ofm6qCY$0d@lE7)mVJ*cHz&1 z4@|dzZvY;9@0QPc$y{yJG{pb%X>PXXeB%FHImPms`g5*7H1GDu6T$q0>FK|rl;{7f zSdTX(S{voPJLwO?7$46T-{tw~(u@2lR-T3F%Nx&&ZQr@#f3fddH0d$dclt&zcV+Lm zKbahhUsk*Kuz&9){JZ0OmhVr#Q_!zF_c*uX>&N+$<;pAPc-1Mnm9U5O_@6Nxd+ zU+Vwgddr{BPn!Rq%AfxS%d@EIQKzq^_nCvqWXX81&J-z-NsY+&^wvIZa1X z^>OREKR>$IRUbcO%$M%mU*CKl{Fd?&Z;~gHLqhYsSu8JV{5q=Wm@Y4#kK=JYzVPVt z^1PQmAvE(pG1jH`U-SK|jrXJc@rrl+@~HAxWOezt-_5dC>GCzC-aG>Sj7$D5Kd%SJ z6S}-Xezz zjO)t>>*EOn4=?On@%SMlp7@aHN@{yA4{tTzy?KOqJf!g>n)=2Aj+4}{AfCpu6$ZUC z9y{T$C&T`H?+}&eWr`X(tdp8)H?}(e#-IAcP*2C`QTVy`ugTvJ{@no zX6A?THD1#BU&MF?`>_tm`&PcV;&J@GCN#$X+jsd>;m9`h8w`?v?jnI?3{muM(Q$vDi?Ju1_@e%{+d`$6ws!80+=X z)P;SS!217NZ_Tj&zrg1I-gwt`>z}#W0{cAtR{b$^wGXH3ar|aI$oRhW$kk}-4(xcc zb~po>;dC~q{PS3eJ&hdGGrY9RwjMLu6KPd&2Anph=EO1^6!$-ge?Ao%{--%$<5!6P znjMS&2ir5m|M}PFOGlaQ_`sD`4&)c)J+=o6z3RdS(i(DV0yOo#u~?T*PkS!zE|%w2 zJj|AarvK9MJiK`G$Z-@_;-jhCPXT`Q`zVhO<4#a~RYv(H*XQMf-_5J< zOS>8mne_+%Fu?Hn!STc~O$YfOq}BMyXb;fMv2HWJqq~N%QQXh}*@Hp;SLBsHQWU>A z{z~-pG)ev(@4fYQSEoK@CILC$Nik$Z^$^UC6znmOAu#Q%kh|Apl5LW_6t z;QA`cTL#zOz+W#2u9r_kA99~|9QQm`U*F;8e?rGEwEExb@=(8#tf|>7{3HIuU7fbS z{EboTK8fR1t?vwV)XF{DBP=)c5ryj0Ie1|o%;)3s{D;H&>meTw!@gc3ab^A$%a>IS zF3hN&?hAg=~a33#go?%B)-`4F0}OC{CSns$D_5qMX}}O`U2e5>G?G0 z_iw}DpXBe(_kDeT1J;XbtJi3MzkL5OEa*u3Lhp~j{-fu7Q{MUlUZCyBme9anN?%eKdw?SnM{XFS!2kdtN z|JpvE@e2w6Ssv;qa8bd=|FNN8{?er;|Ic_+J_l1UKAiviTp>Re)A-IW`K|dyewqD? zbnttbi~k>FH>Y6Z=~DJ@=C_#a|AP2fEY10|iI*O}&?Z_1;5T+a`FQK$`6?rx_&)7? zoB2VXtK~b#C#wg$m{o}*oo$=!cnBS{Fd%lgY zJ8cs83bFVZ3Y-+Fz3$kWcjhLj<`okDbb`u4ZbgnIr(`8quO|D2QjI6oh% zsL=CEo^N8>i!=Y3>HPG-cy@M>`xhNex2Ml^8O3u7(^y}}1_wWX z;=fQ1o=1IFFW2kUbFWV{)n@3UX+PK0po$5)t6>-O}`BUbb5Eb?~l(o zzQA-}^Nab-#eS3f5rXFn!(33m-}Ns%rfH5(g8qe3y{-)P0i#Z)A$8>8rUdz&!*0C^ zw67hBHEx-7-j0j@3vYj(jgJre2fl;Ll)=W`AigbP{I6quVzC`h*q7hMCYr26dK?Ol z5!iAvfK;In-CyB+8GA6)^WcvfpDnlkXEh!G{7=hI$zQHEeuVfh+$ek{ze4=?`{``$ z^M$kXmEQe&xLykVIskbldMqy<^YJ{qh@86nt6%-9Jl~#f>3su1=tA@DLh;0Zz`w@- z;QX-Ew5z|Usgd$iAAsSE#>+zGEfn90@kAU!@>lqa39V1Rw5t`3FLdM-_FE);n)n*~ zZbHW^I@Y*V(g)YyZwDTB)K=F@JnbQ_=W=vSqe75>QTT6wf1f&ukDPjO)3piLHlFvU z${)wq>HO)BX)g19)gNno{!hmLr=cJ5`4KEnL+?wwsu868ZhL~i8TXI%??xc@^N-#T zwjoG*=FPBB@ZUyRpw7?J=g%-do^pO$O8no1{SW5)!oDg+YaI6CljI>oA=-St>ap)D zd`A7gZMELN?=y5e8+kzgpvULTlfi4R%m!$?P@WE#9vNxDeh$!{Jj*%H!aEpftq*gb zwyc5w)=_g78#m}b{_~%AM-USKd28f$?BCG!;{D~;zxgLNt|9)D8?y^Gl7;y1_oMm3 zb7_s)<}dOtDF2J4J$WkGIW-qBe|P-(bdWwfc=4n$d~kv^=hukW-#h2ut*v`CU2OS^ zO;5b|s!>3WKPvR-i249nl;_b{-$?rV!C2mWdUE=v@A~N#{u}QrzPvB(a_6&d6S(7n zEqXjaeZgE^+BZ)dz>`I-PeCXMmO&N!C${paaFDWG3KamOUb$@Bf<_74W@OZ*4? zYYvwJ|CPSL#eeMgBmST8@gKYU7drk!U;1tNz9~;{CI0h#l_B7zl!yMw9jCKeX!<*& zy^w_2((gMTV}AdsL;t9ajaw$!XGnjOe4)!3z`xO*7{9H>0kRXLS#;B^)0vK(iXQy) zKc8@hoe}(9?5c}AHpTc(@_PaGL3J(&t@HP8XnNGWA#~L0Ugmt!S$GN}Dc}OR+9*ee z|K*GSQ_1f!1J5YWO?^M{?ng7m=cfjN&Hte^3GL7D##10RSGv`*Q!ZL1#dh}is+^+o)>D&$SO+IUk?fB$U+DFEYd zCH_k}7jNl>N35=740}JbPTI+Eb+5I_ z)feDK`p*4W?}=@(a5lqmKYBn*dQ;WW%H_$NlfHcQ9oJto+1j zr5?_g+&`hi>(m^uaXZBSrGx(=KF^HL^UWWQugv)~@qEj+RxQ6cpXPa0BF{J;Fz5SR z&+meVVu`1HJ*NA5zR&0L*Y}H?@7G*;|53n!pI_>!P1bomJfT0T`1aV4wr_ODFFCzl z5gd<9_AfjO{NLE!eNJr;=y$%HtBY($kot-gJ7Mwfb?X`68~h`#k^9jHN&6GrQqz=| zLx#OR>4l8{C|+LRe19zl1adP1exWx_O;=gA#9znU|1-?r$?q*3e|qaRJiUYCAz80E zJNVMB*gf~?{;~PWdwXNXe4;%K+OV&|{?q0m^mor36#6@q2ZfXN-hAc4KJ)pO-umVp z^cTUwA%=+Y@gooaF@mI*dWHBeoS6A)BRa(Yg^T~2U3o0s+X-ofPi4ao?uSnRvZO+w zU#!WaXP)oVKXLy0{?Wa~?B7@Z0+NCC{H??P)-O+eeCQtEzcbHQsyvpgk@#m19(i~I zLFk>kHau>KdnZV9d=j+(GxrN{{=c!?aW@BMN3#vRPgZT)I@v$az;Y+TzZL5(YmG6# z<$M>*JsQvEN;Cf+BR|T^#Wep%ar1%=Y9{@}8?L=T7KRGy&$AEcakcmUx#oiZ+zn&m z|NilMcYlZ1A%gZco#_wu0si%P_e|G@yz%bY!S*!RE!_$B&d>FN(Bs|bdZ9ma@n5Nk zHeU(xKd*s{B-kH9{9m~E&-G#dYjB*9URwO%{NA+x=YBd&&*LH>p+9Ig_wN%w{n@(X z6w+q|^$~9#*%|-02$H|bFPGCAJ&ZdKBs%* zZw_SB&fj9b*#i7;-MUS$FW^xXGAl<{@Q?G^;}}rL{hfFHdR+_#AU8@gzhqDAR(U>n zwQ-}I@t^j7%a3FHWLu9|Kd}CSbOHk^(cja4DaP}@y!k)v`@oM5J^vqmX&0vddj3y) zV{{kYKZ5ulg?_19IuEXA2Y1Ffev@0TjQ`Zu;E$W!zuL-pcY$a)#Q$IqEskb?Uds5- z`lDMl;-Z3$|3T~d!>yvF|Eu-XWK!>M59(7xI)8n+-1y<{-%INK^|bfLa{Rs0Ke#`! z5{K0YorkBmS%@Z{CtrEx6?y)9>2EynV+5gt_+Kc$qT(}7itE8Rk9U_X_oMySRQ~)&S9C9X-TH#X^S#%sxlMnspL@#A`+f`28`k3sPc-T0)%vzE--kHJ z3pS{mhyV6h_&$-(RiD3p6{HToO#AltyqN~ABd4N&%gNZdkNLl<@8_3Y{h!SAFbn|f zTh=IoHDq0{y56Mh`*FOO#$!qE(7q3U@9ncAYuB!=o$%K8+tc;&-}uCcwE6j|^(hgu_|H6tHuQp<(e=#BHa^C;X zI+~#x_ApLGm;U}K4;*L^CC#m(r9U_HLcite=&${3 zz<+y?uDnojm;PAsey-=)KeIGJjt*`Ifr9cp*3Id2i3qK3dPrB>zLvH#^`ocbrUt+6CkHXQhyPy6zM8r9q znCRNayXSq5Tp5Oay^3#3D3LLe9Z7c%a{ql>!p-k8+C$~H-KAapNB)!6TU30;892I& z_Vz<-`*VHp&Om+5ucFHg{nN7t-+k1y2MOXo_NU~n_fx-g%os0lyldJADE$C7h)Vf_ z_#aKZur8ecOD`(^YU7cmjQ_=R?B+Zn{XO{oEOeUV``QkFzQXh8v7)H`%g+_>z41hi z@TZ0A#g22g(A@tI{dkj4-}WMwAGJLDUV0_wpT50aOYh6jKOfTb7y1W){L}jOav#5V z^Z!?bUo9n`|Eu+U=eK{mALiPZ@kjr@TenWO=f~{+izk+SU4L8}`1PIH{h+;Htm9~> zr2ghzN7nr@{5c72<3~`xSp@!9@p%vbe^B+=|E=cBu>WuTFCGICt%C4#MmjS(OmES^ zQ+^-k`i6($|KQ20*!XJfe@kCx9zV|>UUwS$@!_lP2% z59evgnpXN`K~f8EC4%w@WA0esN95$Mf}P!T2B@IhFrB_hXy+ z2kBt?GqAtG^g#P(_v{n&{9cXEAz!5Y+}~CS`z)V^KSLZSFLZD`;NiKN-!KjL_hNz8 z-)|0iWF@v6`UcB71O=(&_u|8d27n9A`O`#z-e}O!rdX>D`epbdTQ%fAA4%CrFr@Q~ zV*U#K#%aml9dG3RPUv8L7CKG&jphIO!T(IAuXFHB7u@;%FT{SX5kCX|!rhA=kIBdN zb?fWaA6WN@KRWn4aD!)mPLo0vg7k{@Hs<$hYrSaen|G~P|EBI9a=r|GcP5kW&vL$PM~3cMZl$kWQCSd= zUog&FVtc%0d_Rk!|EyY7qrZ3P1LIq^oYV4YvOMAZ|Mzq}$1le8ALEbuJb%)ZCt!!x zPrL_v=+W1Idu=}c*VRpGk1slHyeI9$Ys7lqB*Wj}fQ^44{x7_)ApP0Zr~Cf;76RRr z@XN#R^T^xB^!M-Cr;qvNhd&zw|K0gu_s{)!;`@31eRFz4^NUnl-Q`d4n1Y$U{SK)OBUIjL_U z`VQ(F#J_D{-{sHcFn^Do?iw9V=P+HyeEwHaY@gJ4M}AK^Klff3;O``RjfEc1`c)X? z7t(MrpydN;90!_5WBX~1@SE~&&mQ03Q#AGB!zYaM#JE1tjYa|fbN_!o=l^weJsy9v z&YSLdOWTi1`#lfr=O6bo#9~MFevv2fJ!3vIYx@t$uUxJ+DiY%V!fQ?W9u~U3KUh9@ zygp`p-*#kG#XhZ1=ltjVR^NZ!boSj+e`y(^zXACVd8_f2^L3DhzJT-zEpM;nNc;9h z4ZtI~AJ_5!IuL)Ri}SU{L-M{m_cMJ=k57W-DMbG~Ye$X``S?QncFU?fE&03Sq1>lJ z-)#9#d2GsGuHQ_9|D)WLPkDpXs^G=Z%>?FIHkS5)X(78sPnZ^ZN|59 zmKJ@K->^3yl6?N`{wE`V6FnYy#;04Y!`3hU?EXy=*o()mc?FQ?rYMiP#nFr3zxpvd zCq2aTlFs#woXc^17aO|Ux(fX~@jaTVxW5+o?v8dGjCUfZy}{|MCg_=~1~VkZp$E!2lhwLcHV%{X7`UMBU=oLl#K z`OWKXCNaZr8*%1&dZf+sZdH6XtH%S1#>=f=Tkk)T`wKPSk3qnB?9=j9l@H??>ThCj zK$kh!2kpFTKlcvsd|0oSU+j9(=wHG9ROFOTMs<+60#6GSYuJ$M@x+56!4}&L3hi`qR9c9tK{k=kLXy%k*VcChQM>fb$!i zZQzXJKhA%)?>VpXqeZ5xzZ8403CGn>HBOpuK-+PSWsv@ESv6G|yuqiJSx@|~yWa!& zj}luJbq+SJVjr{2`Xh_L`t(`@4_EHr(7Z~c1N%>X zyy6{yejQQ!?^d67pJx2+u(vz*hS2(Z@op5NDgW_$JwI&dJ#5oKi{y7F^rPEm!24%h z{b{YFZvcK&SF-=R;kn+6C%unR-6&L^#TJkK1qV0RnCqQ(q;XqokJMlK({%Jj%umhn zKv(vT`_Ueql76oIVEe-S?`M))^KSq% z=b3|zXvp6oN#)Uc{grfZK4Rd19pkk;`0LBQJo|JO_Ia>T;QA9@U)!G>R`!UL$Hn+d zo-4nLeLnd8aeV=8Wvq8`#BJ@7_M?9Z&|^YhJbBm#t?ex%r)a-=NJ|ioPw6pP(tjCP zhTf`a;uFx!pqbvJgYndGnej8zA7OpWeBVnr&vN4GXL>y>ntD3EeEIU@Qa+wPivII2 zh4%QP?T>@}W&9XEm~$iU6CAJKji2ce_YTi1*a8J$U-pVh@FDyc9*4qE@(<>Bt7%nV zR0yMk2@DYiS|E?NHYGfHngw3)`)ZtI{~+~Y>oF9hSHY$S!A9C~Fr3d+T3=S<0i3s? z#{-PVe$qC^&quJ4ss7&Q;{^*ePiddv`g$Rn;|244+y;yfR#*G;$<0@wAAkYA&no_D#`6Z0*E;0ycVYXR`(5CD!@36fEYB0& zr&*6tNsyZglKxiHa(}*Ps3XaK~6b zRQ$ar&zFsSf$o5TL~r%HbT?+<-WMvZ^>y5oiP z@YVkB;k+f^9xCg+w^xlHCg~G!n)2Pw^Ui>cyvN6fyz%>T^}V*W?bw0a^Ac?2x|H$1 zp_l%!#`Jj2_5YeX&$ec8?d^O#4~`EQkKv*o&vJi`i68Xe0Tyd{=*|av^!`5D*UdD) zclA%x<30OlInVEd<0X&Q?NykrizMK0-fd0CdH>Pkh7!NI;qpX2#z9j8y%IwP6O{Wt7TR!^RVZ9%L|JXvoMgooh z_gVjiH1WS`=oc7a`1(jGAEH&5j{YX_5AZj{_)OnBm&uP<4E}KX`_p~sc%)%IVoi7% zu>KkhaIaWA@c6mU%MRz&J#+y4*7mLR$82E-s>D-2XIa+`nuw-9N0jfWO^Md+l3dN- zwi))R#7AE~J5I6mC9Ed_E%gf*8tvl0Z;!h({?w+PI+@Qp(9cs}Gky8p`L6#w^<_gw zddjnkd%AV~-S${DE)0*R=z+m9Xr)hKS5%=T{qjLWeBygJ!{az~dwT6J$(>af-aGqkh}7%$}a@H!r* z^9N`YhH2lrb!$_P7BCHvlh@ou*ZLjQO-m4}Xy^H?Lmh{%5E| z$A!Lhasz3XgpU<+Yuhmq2&5tJ)Oejqt^yBCI&(Fjo|OLT#jZ_}H78`eclB!I6yD&M zhx@DJKJ8?PKY+=5os^6B#D`TsZQUkgHm>hXIiGyhdEIGqZnyEB0)7MfK>s^-#{VPcsUfPB8v~}yc?P(eQ*4e)Kbba%&y!656XQt`j zD45?&@8|h%zV|Z6;eOq_4gC-OCv$_c)JOH-E|aD_J7L6gyo&Jz;GYQJIkgbzh4sO_9^beSg0Eo*IqsCn)cN=kXM(PpRYSpXj<#zGBP6`ry31F{%HD!_dcMJGH(Y z`;#|${`}z`HG}iW5bq@8BUdl0`RtoV?8xeHZ!< zu*db6b7h$R0zlEiQOifRf4k9t zO5H!h{BAD(-)epb<&Wn-t(%`0!+e*I?~5D#nd6DtHuY-tALlP{cNQDC;`)b-LiN^fX)MxU%Fq1wzcynp@{oA)m`Gemd`H%fY8ZWRO?%N{|IK!Mj zqpf?~)9W1PPhju6cl-47S?L$@J~iH={(98u8=dIGc)Kpr0fmYvaA+TSjd<6u^lw*N zK>y*!?%&K|Y`{Iwuph7*w{6wyHNpHfJ?g%Zqy4q`pk%(x@xiqEp67kMZ?jzJw~^r! zSfH1D)%Z6StMusm-bVs_4n6l}6V4zk20&swIW0dj+#ibSuXWPo-~`4yu6?K|Jh{Kq zfct`YKY4uv^Cj#29^p6qX~vt3`8(%x#mvw7yrWL2b0O#HA1)a?%ZYee|#@NI`8|K^gXHd!5O}{ImV-WdGF_V3GOha{a$!JFVr<_ zrG95QUN+V^;yKl$>|l~-eWzQ*|;?EN(D`e)VdF4TGPXbau{Jv=!f?cI#WC#=j`8^2>X_k#B<>+@>9q1O}Ln`QC8&tK>hQ6rxQ ze&^{YAy2GpT0cqsytT(~AI>KS!612_^6m(N(82a*f2u~1c<#UH>8WcHn*9g<+4TIk zD_b8wjUe&LfBv3?F0Ut#1M5j2)q+7ihCL7Q3P-+JC6#*599WelMC`M}=9@ z&pX_Dq=MkR&~jD&ccH%*dc*onk>wQ?)m9U{?R?+*{)YAMuB(H;eR-dagus8@Kjk^- zA8_Jte~#<3wQDMu%lFUzqB{#RDKx*Iy#5IZ(z8e7@k0lmtTOHUg8e;6yYjK-K`H;U z2kU?jdv*EA@AJm^f&PM~Tp#f=pnWIQXL^0E0sCvQ{Y8Hth3a>!m zp5}^Pg>LV&s6XIL_s6-`kMaxK74(F#bFigX6DSnpTaZA?*Pi}hA0fe~cg7p9nKb;r zH(t{5m%3hj7-`Q-dirz4?@xrD{JqrY*_XY1@ZE>iWH96OWhSt{mitj&dA_aB)8FxX zH}z{;9(XU9md>~dY$O;0L$5{+8aFKHBipQjWsJvsVhEQ-9faR!Fh8@t>*G1+6aPEv zFY!{z>1fKQwH^L={H0y*f9o)Uqz|@d5dRwj=W(g|l5rjf&-=U=LGlasZ{qc~LuP-& z{+;V49XS5I%!9mAD=D%2XYE8W3eaXeTQwg{|e37V=?VHb9?{m?;(56zZ;<~_^s#R zWk=DwcYpip)z5#P&#s3)jqeW9->q22XqBGwS`oAO@7E}QEnW!hKg_>ByMI0W?VUX; z^|O%&vWuZSYJCx_r&dSpY3LuaN~7r7n{s}9^=dzcI1RAZv#c&fbI8N}&aVB2dmc@I zhCf0?Cz7Y-ebi6=gAlj|`?o94x^;i0Jp~Y5kN-AMTVUWjV`sv5rbqQVipW8Wz{W#lO z6Ve{Hz36>U-i?=b;rt^5?amw*WXhSOE>UN&m#2Pr7sP1t5m`z8BVAKjhOK|KKDA{k^&0Q|`YCzvO!(_GAA+ z2KuooxMx-}Ckve=@hgT6Pm&&$apjeF1EdNb+5gNzoAI?SoprqLO@FUCeZ+Z{X>8oU zbXUz!*5OQ%#TvZ&7dL;yL$n|F`NjQO^fz%@%Ojqj@#&}k@Ui4C?Im=n@jv*z1?hI+ zG22Mq&+)<*Lw}(339;?EzbO3I(wp`w(GKrt(Nj}{9*d{SN+%c-qe2eBO@NChymX&7Z%pz7_X$XnyUC z{}d^F|D}R2{kaUy2{9h{iCu>TtUUZNUG>HT?)c%Ia}!+8j15(<9v$ve=V#C#D)nV> z@088pKaQ_We+TqO0{-gnS@?5e*=WUR#egXyB`WV~gTnJ#U*OSNuFVszAs&4aU>Tpz0>-QgjykPJ@`27WG z>i^C2KskSc`a#P(#?Pb=Xiq=K8Dv80Px*@NZu)!VdgYY*%p&oB;D2!akNJ&Rf!Vj` zFQd)JH5&;i5Bzj9|6+QKXLbLaIrZfEJD;Bk{}~UvzP$d9*}6-=X8nZmEbnWMYcc{- z1>xsSrbnUOhkWR$?a%gMHj#CX?t1s(!*3kZ`5hLTTI~-r8OS5?xcfRA>)89*vfqzn8mUjy#NJ4w# zfwzP%c03T`|IGG9osiGp?C|Hm?P;v98~f$jVc&cj3kJe}`X7v0$u|PDZoke!tcTJA zqZj5%?;rnQUz=gS%=tHkkL3T%!6&P_jq?{fah~T$#T&YO!S|mXZ0J3%OGo`{OYgq1 zjKW&x$^LT8IMA8$)}OCCIRAU<@qmi4+;k`e@!Pbp%6MKPZZuI zldB}YJM2}CudF1^0v5e3Q9sk|>yfP-`RrtNvx4-h{|C%3^ch%KLW0Ic!>=K83 ze=OL~(#!>2iHCo?xOpCt#(OV;riuUOoXpDozlx4Qz&ZoxMyT-S{IKKhii*n^vGT7$ zjX(YKO5Ik)4%=k|>W}T4#ehNXlQ#FSkjC|KR(kq~Eo!-t}7> z@h2!!7~voFyPI&ak@J;J$O5MMR-OVWyu3anf9M3%QgzrDNPv%eVGLtf_l8&cze)}DlG>52*El zN#lXcN}QL3KO4<6KJLq3(s19T37!|PR$`cBqgV}6@Frq{dO`LW;s$p10t z6RmHee^ax4ZZ`g_@k=s!hf$w2juY_O$F*0jsj=b`--7aA+ji~~q1k_aY|L+>DbBck zeSYK=EJBR^+i!Lqd01B-ne2?e`zWTH`g`Ph6D+)TNd9X7ma(58*#ETsKdt}!ohxzp z*X!!~=#MWeZ@A(wY4ZHoMgPLdAHc&DW5mL;*Y1)cqf5ru@UweAx z{zQ*&@1)LGaJuDn*e_5YudVg>dvQK*jt>fzCy4))*T)d#1yl8>6aMQlK7jwaZNC1V z<9pb1>G3Jo^Wu5(e`kD6b!~^_?|#o1&v-LjV?02MgFfmbaoma?Z+QEy8^Ho)k!(Z2 z#fEqy({if46 z4d{0Ui2r~5k=s9Wz)V;F?T?owe;5D#^Ka#Tu~!=ppnGaWS9sr1T`l>1^R8d7I}H34 zy85mS>uFC`h_1SBslRIAKaTTl68_0^p!t3Db3IS3x5L{2PXJK+*N{lk2fy!PX|_Mc zgEf*L+t=_%jPYB2ywlL{?^OHmX|do2_7BYWR|{R}{p^ox4SPY3ufaauB@4;B#U9W4 zKLUlR@JsQ(EBUt2LH>pKKlA)Q*dHkW#*F^dj`IRr4Ss9<@fhBjexb_TPw2|?8`lRA zzfFA>{dwnqPw;0p79W%L2L3nW^U?aUV0{YFEU!7gEQJ5T{uNE#d7v)g%MkXrV_3olAM_5H1TwR&6ODY~DQ&n+0gpE+}8-teF6wdVdm zj#myz;c#{3yMKOQG(`(6t4Wds@%`e-7dM?Z#ygyUW4ZV1k{_PU-A1^b&Z|5uMRz`r}k3lmr#=)-`3=Y?XqZ>!`d z9cOd}&S+cZd_m|^U5Wqn&mj5zn}6YcJ4Mq4@IP}|?cl+As4uL$&9JXvdz$u_`g`*j zP%Mq_9~MUbdKK-3wi)BaV0&==2ICQ}ucUv9na=NX=LhC|zafR=fAsfJNWPU@yo*o% z{FL8oE;ph3f3W>R{4WmwgZ<@0cno>oP++V5g@%0q^Z|MM2|pZu`N*+jZ|MDm!Tf@> zw|=0<&+Tc9FcRl=dqz$v|K1{=uwD;;L56)yd-_t>GAKwTK`{S9^xW}(s`UZ?`~i1; zuS<{5gZ>lguh7&7xOn61AAEa36*KWB>1EsPW&UUHyMo*FaYJ;~k-WnmNAL?|&8hQD1dNg?6ti zT>TPCEB9^um~0O?eLVH`)wM%fA8-cty%_IdmhOgGj|U3jKlktAkNe#?-VpxI760Au z(;N@(jQ2FP?veb}_ioJhJ^y5SzQXSv`pPwup7`XiW=^&@puW4?@K3?@D5xj3JSp`3 zlv{kzK7jnWcJ2Im;V0S$`)Pgu10nv;4gYB$U?qI{)d~DD<;7vw{$AU+VE_HPe0>1- zFZtuu_VhED!TRf;v^RjiE4`nI{#gEh_TC3Ns_VQLJqV0PqO2-?k5xD6TNzyN5=yD< zw%lHO#YVW`C3Bm`&hh}|VkAVcv3ye#Qs1yh9m!B%TaeVbm-1HMa#FyQf}~)YVBPjP zGQtLzi#?LwYMJD&7m1;-8GeXp4IYvsXtAoziXoW-<3Dn@5r_Xu;0db_5k+Zu*56qo2b8pgiN_# z(wk~50L=lQ*&~cc9xY!WbDbaKhxJQmTK3kqFX7o;MwtA+-Wp$1@ep6!_mAuS95%VX zV)SWr{{IV;|KaLa)n{G%|GJGZ4;%VGc@pfpOs=o&uiG~m{H6WIwzs2RB=q$#zl8Q( zsPBfK)8A|7PtkvNaNoZ9GJZ=E^*2l4_vlaS@cVeo=J#B`s_M|*Tq^%J^?w=s2Y*0S zXW6YskLu?|8xyO4A)eE$hdfXA$K$8eZBY#4r8>SX=Mi4}_P~I^=fM9Dc7*c4x_NtV zXlpyLNA`~?4_r0=fBg&9)fGm*BR@xYpII*#A6c);reA!&%dP&sh4h26^F-h-1D$^fX(+R$+@ ze4Z!i-b+?E#^Ds`N7}o{aI{D9^Y+Zc)b*w;j;h4C@iD zsoa1~_6wc#ulLLSU7_Bke`l!K)!Afzv^PWkdr4r(Z?JIN?+-c7*l;WQS0a6?NzP~d z-!HHU?9yAs&*yd+e2cxX1pUv#`1$KWug@S}QO*zW&){!WC*(D&-YMy|&EH9neb~?C zeDZtvt1bBy6$>qXPwVh_`n}8VTj6iZ=l3ngNpR$P#8ml0nXoKOEV`+1g41^*vp#$avd6E~oJTC*PC z_uY65p`*Q1U=4r=SKurCE%PIP{fYHH5g)>8j6Uk0AfCf;<3gC{+x;aOPu12Qp7A7L zT+57r{jBFKmzVxRhQI524k@FbQ=d;EVMOx_oiDIt-t5@Sxx>RU-jaDd0{wX3_byhB z+>&EFL4AFgpCreLygd2#|0g$|vEmK6zU@{&3T^KX@rBO^=Kg$pfADPhEcjs+ z@8cVK?e2HsTEx5A$BfP*l(BhgS0fsPAU3$NDfRS8eFcmBv@bAK3Jr_I4Y8%=>u+ z^s?U{RQ=K*|BDTR`NX#T|1*%M6z&JcRaE!U^cCiOBO=jWh;S>TzX$$7$`oqj^Qmqe zFbs_P=Tz2b3?kqd4{-BBbinhI+0&>YP|NtOO<}x&&_Bd(sgJ-{`a8HC#9RO2Z9#uo z^;0e6rOONFUr+J(YVVB92XI4~<}8051Z#5oWT48{MjYv2lo8c0y7?SJpKNU za*988$noU=wtjyS`K@hj7gvV+Prw&$9zXJ1SP$W5GrxfUoA>=;(2Gmt|BQ$4MgJez zpIc6{cP``M*`Id9s!{6!^RAnK&fxEf)O7E9c=5t|zJgEOZ}V&F|J1i+|3vx!u^Z5@ z8Jilf#!Ib%{ebm>j-j4k7K_H~KVZ=hxvud4hY_DVnf`yizx9^=P4WM>Fy2|wS4-aF z`#aOJ7rFT5!ph%|^$YRg>Eq8?<6mj|c&%S=lz4!{Bak;`{YvHkte25*UyHqP5u1!h z{=k408$M$_@0R5Ly=B;BKi}W_`rYPzCG1=M1V@9*%PYn`e&)<@Klx_|3c$$ql>gka zFS-0*)u-9DYnL3~lAP0E&$so|!+HI9iov8u_IjK=wI_~pc1LA=dQWD-p(rr)ol3jj z@YTjI&i|6)|NEeQ_xb2Qe(ataOaF%UM}KKye!kMy{hnIXTY))$fxiD7^m*1-IBM2M z%VT-@g4ACv{9=5d?GGToKzty_hme8zwc9WsGhR>+aXGkux&MH_OX#6|$MFZr%;YK-P3C1Ez)y5o}Dt^^{^j8em)|w>hEIN^MUQ-)>{XEr#>7! zZ`KFM=l8@nm=`=5f9X(FXPp4}CcW}4{|4<%hphdC4RYXj$}gA1|Fyk8-ICn5@gz3t z`~2*Ob&32`E+Kf~|3sr-CZU%JNo=Pgz^Pkc(@2hV%@X^ugD ze{)wpd?Bac_1sVU|50c#IDau=x!x$_{WbSL$MFs&5?{)a+w1d3vrnjdMEq*B@{^3cMNP0!-*>OS9{w1c z|0w;|%16H1^zvH2zK#d{@cf_gX7>7%9{kOBzx&$3ZEXnpG#kRZJW?fTK`A$m*QB}FYG4dbI;nDO5{L`Mj$}E(|2|Y_oBbJYZ?pZ0XSbA1ol+j~f5dOkY0&uwr07}QKhKIUh+_f? zC}bKm#(r3YN1vcv${BXHp$)Awxlb<4g;*7wwhrxelICcOV{B>c{_qMiw zH20%nbGXDC$ncjR*7anxa*V6G_@nth-bcm#{dDbd$^X~*dlLOSfxjkxU7oY%{?oj< z(Esg98PKjdKrS7_Kj{Z8Lj9>05xiFv5cwBGoqExl#Nj*d6i~Q{E#?A5o zls~UMe7+OKH`K~By1mzy4b z)W@GF|KE@Jb9?>CUw_;d+W%>ffw{*#-(u^<`Ji5>p*K4JEj*v`#H@%R&%4-o?*40y z|GV>J{eaBEF1bCw;_RAA+aB;RYP0Y<-Y$D1h3{)o^QhGjx6Djq%Tr&5dfZ|^`@ z?~U=`UfKKws3xX9e15bK(frQO(jmqF3+SheFZ47`?*abNUk`h}dEVL|VAB)C$65X1 z6g{!fC$J!6|x;cn;%1U{6tNrs3bZ?efAm-fE9e{eSg}P#<^s|C5NX zggUcO_ZOAr>)Nyi~p-W`?D(h zc-p6J|5&N(*MfSc=>KWx!^u7sKW^}Y^Tq2`ArIUgpYkl|m(e!@SPobI2$=s3{o?y! z$FCLA1N5gE$N%qMf1)t;`2mZ6wVrx8ZrcO4E{ZcgzTv6ue{9o#PCVD*W!^jVB zl=(i0dUC5^;1<}$mlMcmPVL;eK=FV0$7#R%zq^jyDg3|n67>H|;{S^KYyJ=R|AglL zn*WbxU(noN^MCNinVS3eX4zlF_OAmS)u!Gbc+?ngxd09|M!?br_fFq_#Cx}ydSi^& zyf6~_cP6^t?)g=n4?Szg|Gc&3%|EgIN$&cS|1Vh3u~VK8`O&EU#oz$qS2Z569N&7X zwiEJ&@fS{%9)H}@r@!a(_tsNiZnXLPO{9;Oen19Iy5*XfVIll?9C@6LZc z>g{&PPJGk;;gywJ`qA5m@pwM8JfP)?P#-|Pzf(Ut|M}m&#L-8NxpY>!0dvd3d&lE=h-i8&TP^@Qv59|F9 zJP`Xo@frOI_nlSV|2O?N;QxpIzgm{W=>Pfre~RF@%8wYuzaad-mG(cw|I=gh|3Kco z@mBZ`XYEW-e(8h%fb~Mlys{}WAL>(fJ>$uKK8oJL{wLR?JdW3Og}^SpzlHjcmiZI- z4tdnlZ`}EDe3%amJ>dP6!{8_5yY%#v4(t4_F#d___xXnl zq+<_2wHC$`8-3;^>YJBMZ5fi|SufD$?|1KjKi8sP%nv_k(eog`u2IgXe22fg1U}Ke zmGBvXgX4|AZT;~){*QRBs?J|WeJJ`msd2x3xF&W#6mB`6`N){Rk#7hq`l_^lzo+7C zP32B(qW=>=JF&_6F%=ImHa$`C0587yq8yL-wjEQaPBrvT(GSr7v^L0QpH9M_iUtaD zywLY6#s8U)kH=xw)1{BdSG{kcOb*|!JWz}G89y6)h)XYBnDzKjpT+P;;74A4mh;)& zaqDuBm-6dL*B(F7zNhVgp}+39N@jyDni_XGd$ReV3}tLFWr z{~zLfqVM$SevaA7{-AK6Ft?D~y2iM7KN2Jrfd6EC$gAr3lYMI{XAUP4J=uPB!hg!u z#5UIz9v__F!{{KqUL7o7*yq0s{(skP@Mjo$Li)LR^MHAuxqfh`P1^HhJ&0p`@yRLEVqE-+MIo{RZ1O8&xPuF)1`8(^c=hqin*J#%l zsvdgq*+y&q_ibL>@XPnY`f}_KWBY^n{NlUMoC(~KkOw@^mdAv?$$Sm0yqA6tv%6vc zU!eIv^Sw^w)vI7U-zFG9<$TIBV4oH}0eu-*YVMcx9pQu~o{-}K{i~^8^&lRa(kF&9 z@`;(x71IAz{fgzQH(B>Ht~}6k>aJV6I_U1o+92 zI-ak|T0hl)&Ge6Q>F?Est2(D|x9iQ_jeG^WpX_M;B+yQl`l7N}aeazZUe<+w?LGso^z{Cxq&>*;+xnS*^G zmgp!i>v{e4TrQJ&sr8iS&A>&`Ff;km(4eoPh0&lP=XVe0l75e>&rmUUmYz?}e`L6- z6Y7My-^qTS${)}i(kIGic^hgXgHd`sp3ZvG#~FDsjB=tHsf9gY8k9vl8e{^7!4KZZW>{8IV9eSGQs|8DA! zmwbQ4?!S<~@5}SQx1t`>c>4R3;CG1lEN0Da2D z{{^to(>^TB`HlEVT>tDA_#=#c!j%UCdyDaJy7mE;k0UpWZ`VG+`t`QHui{^zf66J0 zw`g_Ua#9c))*I zedH9GKkI|Qe2~a=9zpn^5B|QWa{kov1$ZZVdiwfuj1PpvV$(~5gX$E*cKvYHyHNJE zv>x#$#0Tuec!T~+x!!j(Kc#;W{v~5S*X!FpX1~}E^Sr99=fUTN^pa+|KmB~#za_AX z-zvWs3n2S7eor;?b>~C-#=(7IJVC$@jlZlIeg3HLZ$Z5_`+Zmber;+}OX#jwsr;Yu zNw&U6dOD?i=6rcR#nzAZf|V5&=KZAq-j3HT4zE9caCfNxy4M>`z5xHPkolF)|M%}j zJ9a~#-Rrq9^9{g`Uz6)mzeaqO@pp{E-}C(M)Yol$C1Jci12W!C;Jv#TOr+Hsmlk_l#{y%rV#bEkt?EZ4+;196lbBz5zm>}!%!{5F;&FE!NETvyt z{Mw~&1`gu?N2^B){r(^2{@H&H@qkAKR{H9D@4Y9mtM8HC%x65Hs^^*+4EUj`PxvPE zDZ4(Q%%=&oetVUFD2^W>Z>99_Q@qKF{|7Bs@d%8cE1#>MSD*h9`WMYnDr%xeWTK;{HD3@uzQReF!0uXAys|;+cc}eExXfQqxc! zf}a4+lmAkw{CZJMO^-LpI=kP&`2jvjy}(4k{Wqw3eYjqo+@G9}`Kpcam^*QR=m4;O zj9XvPoF5Em;3GOdmhb0+R3edsx1cA>_k%}-{56mVChht2`90bdOa@=H2P|K;B2S)& zd&$`I+~>*T=kCOU2b=O|L4XmM<1gGL(8u2%0Dj8+$7;D_^5gn@Lw%qA7@MEC?`x_2 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 zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? zSb4DWpmV^=gU$`xKUjIN@}P6T%7e}g+do)&u=1dDz{-Qp4ck9hd9d=JbHK`j&JEi? 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η{yf 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 diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h index 90e0cfd9..f6d98fc3 100644 --- a/src/animation/AnimBlendAssociation.h +++ b/src/animation/AnimBlendAssociation.h @@ -84,7 +84,8 @@ public: void SetRun(void) { flags |= ASSOC_RUNNING; } - inline float GetTimeLeft() { return hierarchy->totalLength - currentTime; } + float GetTimeLeft() { return hierarchy->totalLength - currentTime; } + float GetProgress() { return currentTime / hierarchy->totalLength; } static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) { return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link)); diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index 55bd7d53..f2db86ec 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -134,13 +134,13 @@ AnimAssocDesc aStdAnimDescs[] = { { ANIM_DRIVE_LOW_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, { ANIM_DRIVEBY_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, { ANIM_DRIVEBY_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, - { ANIM_DRIVEBY_L_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, - { ANIM_DRIVEBY_L_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_DRIVEBY_LOW_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_DRIVEBY_LOW_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, { ANIM_CAR_LB, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, { ANIM_DRIVE_BOAT, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING }, { ANIM_DRIVE_BOAT_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, { ANIM_DRIVE_BOAT_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, - { ANIM_DRIVE_BOAT_BACK, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, + { ANIM_BOAT_LB, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING }, { ANIM_BIKE_PICKUP_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_BIKE_PICKUP_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_BIKE_PULLUP_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h index 9fe0cb0e..a84aa3e8 100644 --- a/src/animation/AnimationId.h +++ b/src/animation/AnimationId.h @@ -118,13 +118,13 @@ enum AnimationId ANIM_DRIVE_LOW_R, ANIM_DRIVEBY_L, ANIM_DRIVEBY_R, - ANIM_DRIVEBY_L_L, // TODO: is this LOW? - ANIM_DRIVEBY_L_R, + ANIM_DRIVEBY_LOW_L, + ANIM_DRIVEBY_LOW_R, ANIM_CAR_LB, ANIM_DRIVE_BOAT, ANIM_DRIVE_BOAT_L, ANIM_DRIVE_BOAT_R, - ANIM_DRIVE_BOAT_BACK, + ANIM_BOAT_LB, ANIM_BIKE_PICKUP_R, ANIM_BIKE_PICKUP_L, diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 8138266f..df4d9366 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -9,6 +9,7 @@ #define TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING 2500 class CZoneInfo; +class CAutomobile; enum{ MAX_CARS_TO_KEEP = 2, diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 330b5788..eb772e13 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -44,15 +44,44 @@ uint32 CPickups::StaticCamStartTime; tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES]; -// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4) +// TODO(Miami) uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 }; -uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 }; +uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS] = { + 0, + 1, + 4, + 4, + 4, + 4, + 34, + 16, + 100, + 60, + 60, + 60, + 60, + 60, + 20, + 4, + 14, + 1, + 400, +}; uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 }; -uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 }; -uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 }; -uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 }; -float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f }; +// TODO(Miami): Those are all placeholders!! +uint8 aWeaponReds[] = { 0, 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, +255, 255, 255, 255, 255, 255, 255, 255, +255, 128, 0, 255, 0 }; +uint8 aWeaponGreens[] = { 0, 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, +0, 255, 0, 255, 0 }; +uint8 aWeaponBlues[] = { 0, 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, +255, 255, 255, 255, 255, 255, 255, 255, +0, 128, 255, 0, 0 }; +float aWeaponScale[] = { 1.0f, 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, +1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, +1.0f, 1.0f, 1.0f, 1.0f }; void CPickup::RemoveKeepType() @@ -380,6 +409,30 @@ CPickups::Init(void) CollectedPickUpIndex = 0; } +// --MIAMI: Done +bool +CPickups::TestForPickupsInBubble(CVector pos, float range) +{ + for (int i = 0; i < NUMPICKUPS; i++) { + if ((aPickUps[i].m_vecPos - pos).Magnitude() < range) + return true; + } + return false; +} + +// --MIAMI: Done +bool +CPickups::TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused) { + for (int i = 0; i < NUMPICKUPS; i++) { + if (aPickUps[i].m_eType == type && aPickUps[i].m_eModelIndex == ModelForWeapon(weapon)) + if ((aPickUps[i].m_vecPos - pos).Magnitude() < 7.5f) { + aPickUps[i].m_nQuantity += quantity; + return true; + } + } + return false; +} + bool CPickups::IsPickUpPickedUp(int32 pickupId) { @@ -561,53 +614,22 @@ CPickups::GetNewUniquePickupIndex(int32 slot) return slot | (aPickUps[slot].m_nIndex << 16); } +// --MIAMI: Done int32 CPickups::ModelForWeapon(eWeaponType weaponType) { - switch (weaponType) - { - case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT; - case WEAPONTYPE_COLT45: return MI_COLT; - case WEAPONTYPE_UZI: return MI_UZI; - case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN; - case WEAPONTYPE_AK47: return MI_AK47; - case WEAPONTYPE_M16: return MI_M16; - case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER; - case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER; - case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER; - case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV; - case WEAPONTYPE_GRENADE: return MI_GRENADE; - default: break; - } - return 0; + return CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId; } +// --MIAMI: Done eWeaponType CPickups::WeaponForModel(int32 model) { if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR; - switch (model) - { - case MI_GRENADE: return WEAPONTYPE_GRENADE; - case MI_AK47: return WEAPONTYPE_AK47; - case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT; - case MI_COLT: return WEAPONTYPE_COLT45; - case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV; - case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER; - case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN; - case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE; - case MI_UZI: return WEAPONTYPE_UZI; - case MI_MISSILE: return WEAPONTYPE_UNARMED; - case MI_M16: return WEAPONTYPE_M16; - case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER; - } - return WEAPONTYPE_UNARMED; -} - -int32 -CPickups::FindColourIndexForWeaponMI(int32 model) -{ - return WeaponForModel(model) - 1; + if (model == MI_PICKUP_HEALTH) return WEAPONTYPE_HEALTH; + if (model == MI_PICKUP_ADRENALINE) return WEAPONTYPE_ARMOUR; + if (model == -1) return WEAPONTYPE_UNARMED; + return (eWeaponType)((CWeaponModelInfo*)CModelInfo::GetModelInfo(model))->GetWeaponInfo(); } void @@ -685,15 +707,15 @@ CPickups::DoPickUpEffects(CEntity *entity) int16 colorId; if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) - colorId = 11; + colorId = WEAPONTYPE_LAST_WEAPONTYPE; else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE) - colorId = 12; + colorId = WEAPONTYPE_LAST_WEAPONTYPE + 1; else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) - colorId = 13; + colorId = WEAPONTYPE_LAST_WEAPONTYPE + 2; else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) - colorId = 14; + colorId = WEAPONTYPE_LAST_WEAPONTYPE + 3; else - colorId = FindColourIndexForWeaponMI(entity->GetModelIndex()); + colorId = WeaponForModel(entity->GetModelIndex()); assert(colorId >= 0); diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 2842edfa..79f52a67 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -85,11 +85,12 @@ public: static bool IsPickUpPickedUp(int32 pickupId); static int32 ModelForWeapon(eWeaponType weaponType); static enum eWeaponType WeaponForModel(int32 model); - static int32 FindColourIndexForWeaponMI(int32 model); static int32 GetActualPickupIndex(int32 index); static int32 GetNewUniquePickupIndex(int32 slot); static void PassTime(uint32 time); static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex); + static bool TestForPickupsInBubble(CVector pos, float range); + static bool TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused); static void Load(uint8 *buf, uint32 size); static void Save(uint8 *buf, uint32 *size); @@ -103,7 +104,7 @@ public: }; extern uint16 AmmoForWeapon[20]; -extern uint16 AmmoForWeapon_OnStreet[20]; +extern uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS]; extern uint16 CostOfWeapon[20]; enum ePacmanPickupType diff --git a/src/control/Script.cpp b/src/control/Script.cpp index cd0ea5b3..88cfda84 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -2901,13 +2901,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; pVehicle->bEngineOn = true; pPed->bUsesCollision = false; -#ifdef FIX_BUGS - AnimationId anim = pVehicle->GetDriverAnim(); -#else - AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT; -#endif - pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); - pPed->StopNonPartialAnims(); + pPed->AddInCarAnims(pVehicle, true); pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); CWorld::Add(pPed); ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); @@ -4080,13 +4074,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetPedState(PED_DRIVING); pVehicle->SetStatus(STATUS_PHYSICS); pPed->bUsesCollision = false; -#ifdef FIX_BUGS - AnimationId anim = pVehicle->GetDriverAnim(); -#else - AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT; -#endif - pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); - pPed->StopNonPartialAnims(); + pPed->AddInCarAnims(pVehicle, false); pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); CWorld::Add(pPed); ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); @@ -9753,6 +9741,12 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) return 0; } case COMMAND_IS_ANY_PICKUP_AT_COORDS: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + CRunningScript::UpdateCompareFlag(CPickups::TestForPickupsInBubble(pos, 0.5f)); + return 0; + } case COMMAND_GET_FIRST_PICKUP_COORDS: case COMMAND_GET_NEXT_PICKUP_COORDS: case COMMAND_REMOVE_ALL_CHAR_WEAPONS: @@ -9778,6 +9772,15 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) case COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT: case COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT: case COMMAND_GET_DEAD_CHAR_PICKUP_COORDS: + { + CollectParameters(&m_nIp, 1); + CPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CVector pos; + pTarget->CreateDeadPedPickupCoors(&pos.x, &pos.y, &pos.z); + *(CVector*)&ScriptParams[0] = pos; + StoreParameters(&m_nIp, 3); + return 0; + } case COMMAND_CREATE_PROTECTION_PICKUP: case COMMAND_IS_CHAR_IN_ANY_BOAT: case COMMAND_IS_PLAYER_IN_ANY_BOAT: diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index d27a98ec..56c83337 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5536,9 +5536,10 @@ CMenuManager::PrintMap(void) if (mapPoint.y > fMapCenterY - fMapSize && mapPoint.y < fMapCenterY + fMapSize && mapPoint.x > fMapCenterX - fMapSize && mapPoint.x < fMapCenterX + fMapSize) { + // Don't ask me the meanings, I don't know. Found them by trying float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize; - float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * 4000.0f - 2000.0f; - float y = 2000.0f - ((mapPoint.y - diffY) / (fMapSize * 2)) * 4000.0f; + float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT); + float y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapPoint.y - diffY) / (fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE); CRadar::ToggleTargetMarker(x, y); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); } @@ -5584,7 +5585,8 @@ CMenuManager::PrintMap(void) if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; - fMapCenterY = Min(fMapCenterY, fMapSize); // To not show beyond north border + if (fMapCenterY - fMapSize > SCREEN_HEIGHT / 2) + fMapCenterY = SCREEN_HEIGHT / 2 + fMapSize; bMenuMapActive = false; @@ -5654,9 +5656,7 @@ CMenuManager::ConstructStatLine(int rowIdx) STAT_LINE("PL_STAT", nil, false, nil); - int percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : - CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1)); - percentCompleted = Min(percentCompleted, 100); + int percentCompleted = CStats::GetPercentageProgress(); STAT_LINE("PER_COM", &percentCompleted, false, nil); STAT_LINE("NMISON", &CStats::MissionsGiven, false, nil); diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index d7b3f0e5..adf98701 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -142,6 +142,7 @@ CPlayerInfo::Clear(void) m_bFastReload = false; m_bGetOutOfJailFree = false; m_bGetOutOfHospitalFree = false; + m_bDriveByAllowed = true; m_nPreviousTimeRewardedForExplosion = 0; m_nExplosionsSinceLastReward = 0; } diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index c649d49d..d72d6cfe 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -54,6 +54,7 @@ public: bool m_bFastReload; bool m_bGetOutOfJailFree; bool m_bGetOutOfHospitalFree; + bool m_bDriveByAllowed; char m_aSkinName[32]; RwTexture *m_pSkinTexture; diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 5b0d38e8..94536b28 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -87,12 +87,11 @@ static_assert(RADAR_TILE_SIZE == (RADAR_SIZE_Y / RADAR_NUM_TILES), "CRadar: not CRGBA CRadar::ArrowBlipColour1; CRGBA CRadar::ArrowBlipColour2; uint16 CRadar::MapLegendCounter; -uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; +int16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; int CRadar::TargetMarkerId = -1; CVector CRadar::TargetMarkerPos; #endif -// taken from VC float CRadar::cachedCos; float CRadar::cachedSin; @@ -273,12 +272,9 @@ void CRadar::ClearBlip(int32 i) if (index != -1) { SetRadarMarkerState(index, false); ms_RadarTrace[index].m_bInUse = false; -#ifndef MENU_MAP - // Ssshhh ms_RadarTrace[index].m_eBlipType = BLIP_NONE; ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER; ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE; -#endif } } @@ -481,11 +477,6 @@ void CRadar::DrawBlips() CEntity *blipEntity = nil; for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) { -#ifdef MENU_MAP - // A little hack to reuse cleared blips in menu map. hehe - if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR || - ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT) -#endif if (!ms_RadarTrace[blipId].m_bInUse) continue; @@ -1338,9 +1329,8 @@ void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &i { #ifdef MENU_MAP if (CMenuManager::bMenuMapActive) { - // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0. - out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f; - out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f; + out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * CMenuManager::fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH; + out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * CMenuManager::fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH; } else #endif { @@ -1428,7 +1418,7 @@ CRadar::InitFrontEndMap() CalculateCachedSinCos(); vec2DRadarOrigin.x = 0.0f; vec2DRadarOrigin.y = 0.0f; - m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace + m_radarRange = MENU_MAP_LENGTH_UNIT; // just affects the multiplier in TransformRadarPointToScreenSpace for (int i = 0; i < NUM_MAP_LEGENDS; i++) { MapLegendList[i] = RADAR_SPRITE_NONE; } diff --git a/src/core/Radar.h b/src/core/Radar.h index 43c9766a..aa24296a 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -1,6 +1,13 @@ #pragma once #include "Sprite2d.h" +#define MENU_MAP_LENGTH_UNIT 1190.0f // in game unit +#define MENU_MAP_WIDTH_SCALE 1.112f // in game unit (originally 1.112494151260504f) +#define MENU_MAP_HEIGHT_SCALE 1.119f // in game unit (originally 1.118714268907563f) +#define MENU_MAP_TOP_OFFSET 0.28f // in length unit defined above - ~333 game unit +#define MENU_MAP_LEFT_OFFSET 0.185f // in length unit defined above - ~220 game unit +#define MENU_MAP_LENGTH (4000.f / MENU_MAP_LENGTH_UNIT) + enum eBlipType { BLIP_NONE, @@ -111,7 +118,7 @@ public: #define NUM_MAP_LEGENDS 75 static CRGBA ArrowBlipColour1; static CRGBA ArrowBlipColour2; - static uint16 MapLegendList[NUM_MAP_LEGENDS]; + static int16 MapLegendList[NUM_MAP_LEGENDS]; static uint16 MapLegendCounter; static int TargetMarkerId; static CVector TargetMarkerPos; diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index d50be0d5..ed3943c9 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -249,6 +249,14 @@ int32 CStats::FindCriminalRatingNumber() return rating; } +float CStats::GetPercentageProgress() +{ + float percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : + CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1.0f)); + + return Min(percentCompleted, 100.0f); +} + void CStats::SaveStats(uint8 *buf, uint32 *size) { CheckPointReachedSuccessfully(); diff --git a/src/core/Stats.h b/src/core/Stats.h index bf40a5a6..bf5450aa 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -90,4 +90,5 @@ public: static int32 FindCriminalRatingNumber(); static void SaveStats(uint8 *buf, uint32 *size); static void LoadStats(uint8 *buf, uint32 size); + static float GetPercentageProgress(); }; diff --git a/src/core/World.cpp b/src/core/World.cpp index ef124c07..f6817f8b 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -340,21 +340,6 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP if(e->IsPed()) { if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) { colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump()); -/* this should all be gone, right? - if(((CPed *)e)->UseGroundColModel()) - colmodel = &CTempColModels::ms_colModelPedGroundHit; - else -#ifdef ANIMATE_PED_COL_MODEL - colmodel = CPedModelInfo::AnimatePedColModel( - ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) - ->GetHitColModel(), - RpClumpGetFrame(e->GetClump())); -#else - colmodel = - ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) - ->GetHitColModel(); -#endif -*/ } else colmodel = nil; diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 6f8ebcb4..b35ddb25 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -400,22 +400,6 @@ CEntity::PreRender(void) GetMatrix().UpdateRW(); UpdateRwFrame(); } - }else if(IsPickupModel(GetModelIndex())){ - if(((CObject*)this)->bIsPickup){ - CPickups::DoPickUpEffects(this); - GetMatrix().UpdateRW(); - UpdateRwFrame(); - }else if(GetModelIndex() == MI_GRENADE){ - CMotionBlurStreaks::RegisterStreak((uintptr)this, - 100, 100, 100, - GetPosition() - 0.07f*TheCamera.GetRight(), - GetPosition() + 0.07f*TheCamera.GetRight()); - }else if(GetModelIndex() == MI_MOLOTOV){ - CMotionBlurStreaks::RegisterStreak((uintptr)this, - 0, 100, 0, - GetPosition() - 0.07f*TheCamera.GetRight(), - GetPosition() + 0.07f*TheCamera.GetRight()); - } }else if(GetModelIndex() == MI_MISSILE){ CVector pos = GetPosition(); float flicker = (CGeneral::GetRandomNumber() & 0xF)/(float)0x10; @@ -437,7 +421,22 @@ CEntity::PreRender(void) CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); }else if(IsGlass(GetModelIndex())){ - PreRenderForGlassWindow(); + if(!((CSimpleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_isArtistGlass) + PreRenderForGlassWindow(); + }else if (((CObject*)this)->bIsPickup) { + CPickups::DoPickUpEffects(this); + GetMatrix().UpdateRW(); + UpdateRwFrame(); + } else if (GetModelIndex() == MI_GRENADE) { + CMotionBlurStreaks::RegisterStreak((uintptr)this, + 100, 100, 100, + GetPosition() - 0.07f * TheCamera.GetRight(), + GetPosition() + 0.07f * TheCamera.GetRight()); + } else if (GetModelIndex() == MI_MOLOTOV) { + CMotionBlurStreaks::RegisterStreak((uintptr)this, + 0, 100, 0, + GetPosition() - 0.07f * TheCamera.GetRight(), + GetPosition() + 0.07f * TheCamera.GetRight()); } // fall through case ENTITY_TYPE_DUMMY: diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index a21da7d3..56956787 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -395,7 +395,9 @@ enum MI_AK47 = 276, MI_SHOTGUN = 279, MI_M16 = 280, + MI_TEC9 = 281, MI_UZI = 282, + MI_SILENCEDINGRAM = 283, MI_MP5 = 284, MI_SNIPER = 285, MI_ROCKETLAUNCHER = 287, @@ -511,29 +513,6 @@ IsBannerModel(int16 id) id == MI_ITALYBANNER1 || id == MI_CHINALANTERN; } -inline bool -IsPickupModel(int16 id) -{ - return id == MI_GRENADE || - id == MI_AK47 || - id == MI_BASEBALL_BAT || - id == MI_COLT || - id == MI_MOLOTOV || - id == MI_ROCKETLAUNCHER || - id == MI_SHOTGUN || - id == MI_SNIPER || - id == MI_UZI || - id == MI_M16 || - id == MI_FLAMETHROWER || - id == MI_PICKUP_ADRENALINE || - id == MI_PICKUP_BODYARMOUR || - id == MI_PICKUP_INFO || - id == MI_PICKUP_HEALTH || - id == MI_PICKUP_BONUS || - id == MI_PICKUP_BRIBE || - id == MI_PICKUP_KILLFRENZY || - id == MI_PICKUP_CAMERA; -} inline bool IsPolicePedModel(int16 id) diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 48785025..b68b96c0 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -200,7 +200,7 @@ CCivilianPed::ProcessControl(void) if (DyingOrDead()) return; - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); switch (m_nPedState) { case PED_WANDER_RANGE: case PED_WANDER_PATH: diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 1affb64d..578f2454 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -589,7 +589,7 @@ CCopPed::ProcessControl(void) ArrestPlayer(); return; } - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); if (m_moved.Magnitude() > 0.0f) Avoid(); diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 04e5dd6a..a62ac76d 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -49,7 +49,7 @@ CEmergencyPed::ProcessControl(void) return; if(!DyingOrDead()) { - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); if (IsPedInControl() && m_moved.Magnitude() > 0.0f) Avoid(); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 8da8249e..6514dda5 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -67,6 +67,9 @@ uint16 gnNumTempPedList; CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; +// TODO(Miami) +#define AUDIO_NOT_READY + // Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL) PedAudioData CommentWaitTime[39] = { {500, 800, 500, 2}, @@ -645,6 +648,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED; m_currentWeapon = WEAPONTYPE_UNARMED; m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; + m_delayedWeapon = WEAPONTYPE_UNIDENTIFIED; for(int i = 0; i < TOTAL_WEAPON_SLOTS; i++) { CWeapon &weapon = GetWeapon(i); @@ -656,7 +660,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) } m_lastFightMove = FIGHTMOVE_NULL; - GiveWeapon(WEAPONTYPE_UNARMED, 0); + GiveWeapon(WEAPONTYPE_UNARMED, 0, true); m_wepAccuracy = 60; m_lastWepDam = -1; m_collPoly.valid = false; @@ -1179,7 +1183,7 @@ CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg) crouchFireAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_WEAPON_CROUCHFIRE); } if (!!weapon->m_bReload && reloadAssoc) { - if (reloadAssoc->animId == ANIM_WEAPON_CROUCHRELOAD && !crouchFireAssoc) { + if (reloadAssoc->animId == GetCrouchReloadAnim(weapon) && !crouchFireAssoc) { CAnimBlendAssociation *crouchAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 8.0f); crouchAssoc->SetCurrentTime(crouchAssoc->hierarchy->totalLength); crouchAssoc->flags &= ~ASSOC_RUNNING; @@ -1212,7 +1216,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) if (ped->m_nPedState != PED_ATTACK) { if (ped->bIsDucking && ped->IsPedInControl()) { if (currentWeapon->m_bReload) { - reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_WEAPON_CROUCHRELOAD); + reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon)); } if (currentWeapon->m_bCrouchFire && attackAssoc) { if (attackAssoc->animId == ANIM_WEAPON_CROUCHFIRE && !reloadAnimAssoc) { @@ -1238,7 +1242,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) if (ped->bIsDucking && ped->bCrouchWhenShooting) { if (currentWeapon->m_bReload) { - reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_WEAPON_CROUCHRELOAD); + reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon)); } if (currentWeapon->m_bCrouchFire && attackAssoc) { if (attackAssoc->animId == ANIM_WEAPON_CROUCHFIRE && !reloadAnimAssoc) { @@ -1302,7 +1306,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) } } -// --MIAMI: Done +// --MIAMI: Done except melee weapons void CPed::Attack(void) { @@ -1354,11 +1358,11 @@ CPed::Attack(void) } if (ourWeapon->m_bReload) { - reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_RELOAD); + reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(ourWeapon)); } if (!!ourWeapon->m_bReload && !reloadAnimAssoc) { - reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHRELOAD); + reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(ourWeapon)); } if ( reloadAnimAssoc && reloadAnimAssoc->IsRunning() ) { @@ -1518,14 +1522,22 @@ CPed::Attack(void) case ASSOCGRP_UNARMED: if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH || // TODO(Miami): Remove after fighting done weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) { +#ifdef AUDIO_NOT_READY + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); +#else DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, (damagerType | (ourWeaponType << 8))); +#endif } break; case ASSOCGRP_KNIFE: case ASSOCGRP_BASEBALLBAT: case ASSOCGRP_GOLFCLUB: case ASSOCGRP_CHAINSAW: +#ifdef AUDIO_NOT_READY + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f); +#else DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (ourWeaponType << 8))); +#endif break; default: break; @@ -1587,12 +1599,12 @@ CPed::Attack(void) if (bIsDucking) { newReloadAssoc = CAnimManager::BlendAnimation( GetClump(), ourWeapon->m_AnimToPlay, - ANIM_WEAPON_CROUCHRELOAD, + GetCrouchReloadAnim(ourWeapon), 8.0f); } else { newReloadAssoc = CAnimManager::BlendAnimation( GetClump(), ourWeapon->m_AnimToPlay, - ANIM_WEAPON_RELOAD, + GetReloadAnim(ourWeapon), 8.0f); } newReloadAssoc->SetFinishCallback(FinishedReloadCB, this); @@ -1602,7 +1614,26 @@ CPed::Attack(void) bIsAttacking = false; bIsPointingGunAt = false; m_shootTimer = CTimer::GetTimeInMilliseconds(); +#ifdef AUDIO_NOT_READY + switch (ourWeaponType) { + case WEAPONTYPE_UZI: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_AK47: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_M16: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); + break; + default: + break; + } +#else DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType); +#endif return; } } @@ -1647,10 +1678,28 @@ CPed::Attack(void) ClearAimFlag(); // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading) - if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < ourWeapon->m_fAnimLoopEnd) { + if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < animLoopEnd) { - // What?! Weapon id as volume?? +#ifdef AUDIO_NOT_READY + switch (ourWeaponType) { + case WEAPONTYPE_UZI: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_AK47: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); + break; + case WEAPONTYPE_M16: + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); + break; + default: + break; + } +#else DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType); +#endif } // Fun fact: removing this part leds to reloading flamethrower @@ -2133,7 +2182,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) case ANIM_VAN_GETIN: #ifdef VC_PED_PORTS multExtractedFromAnim = true; - zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f); + zBlend = Max(m_pVehicleAnim->GetProgress() - 0.3f, 0.0f) / (1.0f - 0.3f); // fall through #endif case ANIM_CAR_QJACKED: @@ -2144,7 +2193,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) #ifdef VC_PED_PORTS if (!multExtractedFromAnim) { multExtractedFromAnim = true; - zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f); + zBlend = Max(m_pVehicleAnim->GetProgress() - 0.5f, 0.0f) / (1.0f - 0.5f); } // fall through #endif @@ -2152,14 +2201,14 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) case ANIM_CAR_CRAWLOUT_RHS2: case ANIM_VAN_GETOUT_L: case ANIM_VAN_GETOUT: - seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength; + seatPosMult = m_pVehicleAnim->GetProgress(); break; case ANIM_CAR_GETIN_RHS: case ANIM_CAR_GETIN_LHS: #ifdef VC_PED_PORTS if (veh && veh->IsCar() && veh->bIsBus) { multExtractedFromAnimBus = true; - zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f; + zBlend = Min(m_pVehicleAnim->GetProgress(), 0.5f) / 0.5f; } // fall through #endif @@ -4520,6 +4569,9 @@ CPed::SetGetUp(void) } if (m_nPedState != PED_GETUP) { SetStoredState(); + if (m_nPedState == PED_FOLLOW_PATH) + ClearFollowPath(); + m_nPedState = PED_GETUP; } @@ -5119,7 +5171,7 @@ CPed::SetAttack(CEntity *victim) return; if (curWeapon->m_bReload && - (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_RELOAD) || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHRELOAD))) { + (RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(curWeapon)) || RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(curWeapon)))) { if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected) bIsAttacking = false; else @@ -5511,13 +5563,13 @@ CPed::FightStrike(CVector &touchedNodePos) for (int j = 0; j < hisCol->numSpheres; j++) { attackDistance = hisCol->spheres[j].center; attackDistance -= touchedNodePos; - CColSphere *ourPieces = hisCol->spheres; - float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius; + CColSphere *hisPieces = hisCol->spheres; + float maxDistanceToBeat = hisPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius; // We can beat him too if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) { pedFound = true; - closestPedPiece = (ePedPieceTypes) ourPieces[j].piece; + closestPedPiece = (ePedPieceTypes) hisPieces[j].piece; break; } } @@ -6324,10 +6376,59 @@ CPed::CreateDeadPedMoney(void) } void -CPed::CreateDeadPedWeaponPickups(void) +CPed::CreateDeadPedPickupCoors(float *x, float *y, float *z) { bool found = false; - float angleToPed; + CVector pickupPos; + +#define NUMBER_OF_ATTEMPTS 32 + for (int i = 0; i < NUMBER_OF_ATTEMPTS; i++) { + + pickupPos = GetPosition(); + pickupPos.x = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x; + pickupPos.y = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y; + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; + + if (!found) + continue; + + CVector pedPos = GetPosition(); + pedPos.z += 0.3f; + + CVector pedToPickup = pickupPos - pedPos; + float distance = pedToPickup.Magnitude(); + + // outer edge of pickup + distance = (distance + 0.4f) / distance; + CVector pickupPos2 = pedPos; + pickupPos2 += distance * pedToPickup; + + if ((pickupPos - FindPlayerCoors()).Magnitude2D() > 2.0f || i > NUMBER_OF_ATTEMPTS / 2) { + + if (i > NUMBER_OF_ATTEMPTS / 2 || !CPickups::TestForPickupsInBubble(pickupPos, 1.3f)) { + + if (CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, + true, i < NUMBER_OF_ATTEMPTS / 2, false, i < NUMBER_OF_ATTEMPTS / 2, false, false, false)) { + + if (i > NUMBER_OF_ATTEMPTS / 2 || !CWorld::TestSphereAgainstWorld(pickupPos, 1.2f, nil, false, true, false, false, false, false)) { + *x = pickupPos.x; + *y = pickupPos.y; + *z = pickupPos.z; + return; + } + } + } + } + } + *x = GetPosition().x; + *y = GetPosition().y; + *z = GetPosition().z + 0.4f; +#undef NUMBER_OF_ATTEMPTS +} + +void +CPed::CreateDeadPedWeaponPickups(void) +{ CVector pickupPos; if (bInVehicle) @@ -6340,34 +6441,11 @@ CPed::CreateDeadPedWeaponPickups(void) if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || (weaponAmmo == 0 && !GetWeapon(i).IsTypeMelee())) continue; - angleToPed = i * 1.75f; - pickupPos = GetPosition(); - pickupPos.x += 1.5f * Sin(angleToPed); - pickupPos.y += 1.5f * Cos(angleToPed); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; - - CVector pedPos = GetPosition(); - pedPos.z += 0.3f; - - CVector pedToPickup = pickupPos - pedPos; - float distance = pedToPickup.Magnitude(); - - // outer edge of pickup - distance = (distance + 0.3f) / distance; - CVector pickupPos2 = pedPos; - pickupPos2 += distance * pedToPickup; - - // pickup must be on ground and line to its edge must be clear - if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) { - // otherwise try another position (but disregard second check apparently) - angleToPed += 3.14f; - pickupPos = GetPosition(); - pickupPos.x += 1.5f * Sin(angleToPed); - pickupPos.y += 1.5f * Cos(angleToPed); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; + int quantity = Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon] / 2); + CreateDeadPedPickupCoors(&pickupPos.x, &pickupPos.y, &pickupPos.z); + if (!CPickups::TryToMerge_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, quantity, false)) { + CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, quantity)); } - if (found) - CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); } ClearWeapons(); } @@ -8945,7 +9023,11 @@ CPed::InvestigateEvent(void) bool CPed::IsPedDoingDriveByShooting(void) { +#ifdef FIX_BUGS if (FindPlayerPed() == this && CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nWeaponSlot == 5) { +#else + if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) { +#endif if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight) return true; } @@ -9982,11 +10064,8 @@ CPed::ProcessControl(void) if (m_nPedState == PED_FOLLOW_PATH) { if (DotProduct(m_vecDamageNormal, GetForward()) < -0.866f && CanPedJumpThis(collidingEnt, &m_vecDamageNormal)) { SetJump(); - - // Moved break into here, for compatibility with III - break; } - // break; + break; } #endif if (m_pedInObjective && @@ -10957,15 +11036,13 @@ CPed::ProcessControl(void) return; } - if (m_pMyVehicle->pDriver != this || m_pMyVehicle->IsBoat()) { + if (m_pMyVehicle->pDriver != this) { LookForSexyPeds(); LookForSexyCars(); break; } - if (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE || !m_pMyVehicle->pDriver->IsPlayer()) { - break; - } + // TODO(Miami): Start KILL_CHAR_ON_BOAT objective CPad* pad = CPad::GetPad(0); @@ -10995,12 +11072,24 @@ CPed::ProcessControl(void) } } #endif + + // TODO(Miami): This part moved to DriveVehicle in VC float steerAngle = m_pMyVehicle->m_fSteerAngle; CAnimBlendAssociation *lDriveAssoc; CAnimBlendAssociation *rDriveAssoc; CAnimBlendAssociation *lbAssoc; CAnimBlendAssociation *sitAssoc; - if (m_pMyVehicle->bLowVehicle) { + if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) { + sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT); + + if (!sitAssoc || sitAssoc->blendAmount < 1.0f) { + break; + } + + lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT_L); + rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT_R); + lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BOAT_LB); + } else if (m_pMyVehicle->bLowVehicle) { sitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT); if (!sitAssoc || sitAssoc->blendAmount < 1.0f) { @@ -11020,18 +11109,21 @@ CPed::ProcessControl(void) lDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L); rDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R); lbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB); + } - if (lbAssoc && - TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON - && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) { - lbAssoc->blendDelta = -1000.0f; - } + if (lbAssoc && + TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON + && TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) { + lbAssoc->blendDelta = -1000.0f; } CAnimBlendAssociation *driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L); - if (!driveByAssoc) driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R); + if (!driveByAssoc) + driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_LOW_L); + if (!driveByAssoc) + driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_LOW_R); if (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc) { if (steerAngle == 0.0f || driveByAssoc) { @@ -11046,6 +11138,8 @@ CPed::ProcessControl(void) if (rDriveAssoc) rDriveAssoc->blendAmount = clamp(steerAngle * -100.0f / 61.0f, 0.0f, 1.0f); + else if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT_R); else if (m_pMyVehicle->bLowVehicle) CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_R); else @@ -11057,6 +11151,8 @@ CPed::ProcessControl(void) if (lDriveAssoc) lDriveAssoc->blendAmount = clamp(steerAngle * 100.0f / 61.0f, 0.0f, 1.0f); + else if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT_L); else if (m_pMyVehicle->bLowVehicle) CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_LOW_L); else @@ -11069,10 +11165,18 @@ CPed::ProcessControl(void) if ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON || TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT) - && (!lbAssoc || lbAssoc->blendAmount < 1.0f)) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f); + && (!lbAssoc || lbAssoc->blendAmount < 1.0f && lbAssoc->blendDelta <= 0.0f)) { + + if(m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_BOAT_LB, 4.0f); + else + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LB, 4.0f); } } + + // TODO(Miami): This part belongs to DriveVehicle + if (!m_pMyVehicle) + return; break; } case PED_DIE: @@ -11124,7 +11228,8 @@ CPed::ProcessControl(void) } m_pCurrentPhysSurface = nil; } - } + } else + ServiceTalking(); } void @@ -11145,11 +11250,27 @@ CPed::SetInTheAir(void) } +// --MIAMI: Done void CPed::RestoreHeadPosition(void) { + bool canUseMyBody = false; + if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) { + if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN) + canUseMyBody = true; + } + if (!canUseMyBody) + m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY; + if (m_pedIK.RestoreLookAt()) { bIsRestoringLook = false; + canUseMyBody = false; + if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) { + if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN) + canUseMyBody = true; + } + if(canUseMyBody) + m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY; } } @@ -12234,19 +12355,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) ped->SetObjective(OBJECTIVE_NONE); } - if (veh->pDriver == ped) { - if (veh->bLowVehicle) { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); - } else { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); - } - } else if (veh->bLowVehicle) { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f); - } else { - ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f); - } - - ped->StopNonPartialAnims(); + ped->AddInCarAnims(veh, veh->pDriver == ped); if (veh->bIsBus) ped->bRenderPedInCar = false; @@ -12651,11 +12760,11 @@ CPed::ReplaceWeaponWhenExitingVehicle(void) } } -// --MIAMI: Add driveby check, enumarate weapon slots +// --MIAMI: Done inline void CPed::RemoveWeaponWhenEnteringVehicle(void) { - if (IsPlayer() && GetWeapon(5).m_eWeaponType && GetWeapon(5).m_nAmmoTotal > 0) { + if (IsPlayer() && HasWeaponSlot(5) && GetWeapon(5).m_nAmmoTotal > 0 && ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed()->m_bDriveByAllowed) { if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED) m_storedWeapon = GetWeapon()->m_eWeaponType; SetCurrentWeapon(GetWeapon(5).m_eWeaponType); @@ -14190,7 +14299,7 @@ CPed::ProcessObjective(void) if (reloadAssoc || !m_pedInObjective->IsPedShootable()) { if (reloadAssoc && - (!reloadAssoc->IsRunning() || reloadAssoc->currentTime / reloadAssoc->hierarchy->totalLength > 0.8f)) { + (!reloadAssoc->IsRunning() || reloadAssoc->GetProgress() > 0.8f)) { CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); punchAssoc->flags |= ASSOC_DELETEFADEDOUT; punchAssoc->flags |= ASSOC_FADEOUTWHENDONE; @@ -17529,33 +17638,11 @@ CPed::WarpPedIntoCar(CVehicle *car) DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f); } -#ifdef VC_PED_PORTS RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); - // VC uses AddInCarAnims but we don't have that - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); + AddInCarAnims(car, car->pDriver == this); RemoveWeaponWhenEnteringVehicle(); -#else - if (car->IsBoat()) { -#ifndef FIX_BUGS - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); -#else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); -#endif - CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - RemoveWeaponModel(ourWeapon->m_nModelId); - } else { - // Because we can use Uzi for drive by - RemoveWeaponWhenEnteringVehicle(); - if (car->bLowVehicle) - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); - else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); - } -#endif - - StopNonPartialAnims(); if (car->bIsBus) bRenderPedInCar = false; @@ -17837,25 +17924,13 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) m_vecOffsetSeek = doorOpenPos - GetPosition(); m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; if (car->IsBoat()) { -#ifdef VC_PED_PORTS - // VC checks for handling flag, but we can't do that - if(car->GetModelIndex() == MI_SPEEDER) + if(car->pHandling->Flags & HANDLING_SIT_IN_BOAT) m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); else m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); PedSetInCarCB(nil, this); bVehExitWillBeInstant = true; -#else - -#ifndef FIX_BUGS - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); -#else - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); -#endif - - m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this); -#endif if (IsPlayer()) CWaterLevel::AllocateBoatWakeArray(); } else { @@ -18418,14 +18493,15 @@ CPed::Load(uint8*& buf) #undef CopyToBuf #endif +// --MIAMI: Done void CPed::GiveDelayedWeapon(eWeaponType weapon, uint32 ammo) { - m_storedWeapon = weapon; - m_storedWeaponAmmo = ammo; - if (m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) { - int modelId1 = CWeaponInfo::GetWeaponInfo(m_storedWeapon)->m_nModelId; - int modelId2 = CWeaponInfo::GetWeaponInfo(m_storedWeapon)->m_nModel2Id; + m_delayedWeapon = weapon; + m_delayedWeaponAmmo = ammo; + if (m_delayedWeapon != WEAPONTYPE_UNIDENTIFIED) { + int modelId1 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModelId; + int modelId2 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModel2Id; if (modelId1 != -1) CStreaming::RequestModel(modelId1, STREAMFLAGS_DEPENDENCY); if (modelId2 != -1) @@ -18433,18 +18509,19 @@ CPed::GiveDelayedWeapon(eWeaponType weapon, uint32 ammo) if ((modelId1 == -1 || CStreaming::HasModelLoaded(modelId1)) && (modelId2 == -1 || CStreaming::HasModelLoaded(modelId2))) { - GiveWeapon(m_storedWeapon, m_storedWeaponAmmo, 1); - m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; + GiveWeapon(m_delayedWeapon, m_delayedWeaponAmmo, true); + m_delayedWeapon = WEAPONTYPE_UNIDENTIFIED; } } } +// --MIAMI: Done void CPed::RequestDelayedWeapon() { - if (m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) { - int modelId1 = CWeaponInfo::GetWeaponInfo(m_storedWeapon)->m_nModelId; - int modelId2 = CWeaponInfo::GetWeaponInfo(m_storedWeapon)->m_nModel2Id; + if (m_delayedWeapon != WEAPONTYPE_UNIDENTIFIED) { + int modelId1 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModelId; + int modelId2 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModel2Id; if (modelId1 != -1) CStreaming::RequestModel(modelId1, STREAMFLAGS_DEPENDENCY); if (modelId2 != -1) @@ -18452,12 +18529,13 @@ CPed::RequestDelayedWeapon() if ((modelId1 == -1 || CStreaming::HasModelLoaded(modelId1)) && (modelId2 == -1 || CStreaming::HasModelLoaded(modelId2))) { - GiveWeapon(m_storedWeapon, m_storedWeaponAmmo, 1); - m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; + GiveWeapon(m_delayedWeapon, m_delayedWeaponAmmo, 1); + m_delayedWeapon = WEAPONTYPE_UNIDENTIFIED; } } } +// --MIAMI: Done void CPed::ClearFollowPath() { @@ -18466,4 +18544,44 @@ CPed::ClearFollowPath() } m_nPathNodes = 0; m_nCurPathNode = 0; +} + +// --MIAMI: Done +void +CPed::AddInCarAnims(CVehicle* car, bool isDriver) +{ + AnimationId anim; + AssocGroupId group; + if (car->IsBoat()) { + if (car->pHandling->Flags & HANDLING_SIT_IN_BOAT) { + anim = ANIM_CAR_SIT; + } else { + anim = ANIM_DRIVE_BOAT; + } + group = ASSOCGRP_STD; + } else if (car->IsBike()) { + if (isDriver) { + // TODO(Miami): Bikes + } else { + // TODO(Miami): Bikes + } + } else { + if (isDriver) { + if (car->bLowVehicle) { + anim = ANIM_CAR_LSIT; + } else { + anim = ANIM_CAR_SIT; + } + } else { + if (car->bLowVehicle) { + anim = ANIM_CAR_SITPLO; + } else { + anim = ANIM_CAR_SITP; + } + } + group = ASSOCGRP_STD; + } + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), group, anim, 100.0f); + + StopNonPartialAnims(); } \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 32557cb6..42fec06c 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -523,7 +523,8 @@ public: CVector2D *m_wanderRangeBounds; // array with 2 CVector2D (actually unused CRange2D class) - unused CWeapon m_weapons[TOTAL_WEAPON_SLOTS]; eWeaponType m_storedWeapon; - uint32 m_storedWeaponAmmo; + eWeaponType m_delayedWeapon; + uint32 m_delayedWeaponAmmo; uint8 m_currentWeapon; // eWeaponType uint8 m_maxWeaponTypeAllowed; // eWeaponType uint8 m_wepSkills; @@ -704,7 +705,7 @@ public: void RemoveWeaponAnims(int, float); void CreateDeadPedMoney(void); void CreateDeadPedWeaponPickups(void); -// void CreateDeadPedPickupCoors(float *x, float *y, float *z); + void CreateDeadPedPickupCoors(float *x, float *y, float *z); void SetAttackTimer(uint32); void SetBeingDraggedFromCar(CVehicle*, uint32, bool); void SetRadioStation(void); @@ -775,6 +776,7 @@ public: void ClearFollowPath(); void GiveDelayedWeapon(eWeaponType weapon, uint32 ammo); void RequestDelayedWeapon(); + void AddInCarAnims(CVehicle* car, bool isDriver); // Static methods static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset); @@ -875,7 +877,7 @@ public: bool Dead(void) { return m_nPedState == PED_DEAD; } bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } - bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD || m_nWaitState == WAITSTATE_SUN_BATHE_IDLE; } bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. @@ -891,7 +893,7 @@ public: void RemoveWeaponWhenEnteringVehicle(void); bool IsNotInWreckedVehicle(); - // My addons. Maybe inlined in VC? + // My names. Inlined in VC AnimationId GetFireAnimNotDucking(CWeaponInfo* weapon) { // TODO(Miami): Revert that when weapons got ported if (weapon->m_AnimToPlay == ASSOCGRP_STD) @@ -928,6 +930,20 @@ public: else return ANIM_WEAPON_FIRE; } + + static AnimationId GetCrouchReloadAnim(CWeaponInfo* weapon) { + if (!!weapon->m_bReload) + return ANIM_WEAPON_CROUCHRELOAD; + else + return (AnimationId)0; + } + + static AnimationId GetReloadAnim(CWeaponInfo* weapon) { + if (!!weapon->m_bReload) + return ANIM_WEAPON_RELOAD; + else + return (AnimationId)0; + } // -- // My additions, because there were many, many instances of that. diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 826cc9e9..69a6d211 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -451,7 +451,7 @@ CPlayerPed::SetRealMoveAnim(void) } else if (curSprintAssoc->blendDelta >= 0.0f || curSprintAssoc->blendAmount >= 0.8f) { if (m_fMoveSpeed < 0.4f) { AnimationId runStopAnim; - if (curSprintAssoc->currentTime / curSprintAssoc->hierarchy->totalLength < 0.5) // double + if (curSprintAssoc->GetProgress() < 0.5) // double runStopAnim = ANIM_RUN_STOP; else runStopAnim = ANIM_RUN_STOP_R; @@ -638,7 +638,7 @@ CPlayerPed::PlayerControlSniper(CPad *padUsed) firePos = GetMatrix() * firePos; GetWeapon()->Fire(this, &firePos); } - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); } // --MIAMI: Made compatible with slots, but still TODO @@ -742,7 +742,7 @@ CPlayerPed::PlayerControlM16(CPad *padUsed) firePos = GetMatrix() * firePos; GetWeapon()->Fire(this, &firePos); } - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, nil); } void @@ -1561,7 +1561,7 @@ CPlayerPed::ProcessControl(void) } if (padUsed && IsPedShootable()) { ProcessWeaponSwitch(padUsed); - GetWeapon()->Update(m_audioEntityId); + GetWeapon()->Update(m_audioEntityId, this); } ProcessAnimGroups(); if (padUsed) { diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 567f9c0f..edaa2aa3 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -734,7 +734,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree } CPed* -CPopulation::AddPedInCar(CVehicle* car, bool isPassenger) +CPopulation::AddPedInCar(CVehicle* car, bool isDriver) { int defaultModel = MI_MALE01; int miamiViceIndex = 0; @@ -777,7 +777,7 @@ CPopulation::AddPedInCar(CVehicle* car, bool isPassenger) case MI_VICECHEE: // TODO(MIAMI): figure out new structure of the function preferredModel = COP_MIAMIVICE; pedType = PEDTYPE_COP; - miamiViceIndex = (isPassenger ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1); + miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1); break; case MI_TAXI: case MI_CABBIE: @@ -828,29 +828,11 @@ CPopulation::AddPedInCar(CVehicle* car, bool isPassenger) CPed *newPed = CPopulation::AddPed((ePedType)pedType, preferredModel, car->GetPosition(), miamiViceIndex); newPed->bUsesCollision = false; - // what?? - if (pedType != PEDTYPE_COP) { - newPed->SetCurrentWeapon(WEAPONTYPE_COLT45); + if (newPed->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { newPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(newPed->GetWeapon()->m_eWeaponType)->m_nModelId); } - /* - // Miami leftover - if (car->m_vehType == VEHICLE_TYPE_BIKE) { - newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, *((CBike*)car + 308h), 100.0f); - } else */ - // FIX: Make peds comfortable while driving car/boat -#ifdef FIX_BUGS - { - newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); - } -#else - { - newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); - } -#endif - - newPed->StopNonPartialAnims(); + newPed->AddInCarAnims(car, isDriver); return newPed; } diff --git a/src/peds/Population.h b/src/peds/Population.h index 20d6e567..ae4aa44c 100644 --- a/src/peds/Population.h +++ b/src/peds/Population.h @@ -70,7 +70,7 @@ public: static void LoadPedGroups(); static void UpdatePedCount(ePedType, bool); static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool); - static CPed *AddPedInCar(CVehicle *car, bool isPassenger); + static CPed *AddPedInCar(CVehicle *car, bool isDriver); static bool IsPointInSafeZone(CVector *coors); static void RemovePed(CPed *ent); static int32 ChooseCivilianOccupation(int32); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index d1f2faaa..5f78e2a9 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -3017,11 +3017,15 @@ void CAutomobile::DoDriveByShootings(void) { CAnimBlendAssociation *anim; + CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); + if (playerInfo && !playerInfo->m_bDriveByAllowed) + return; + CWeapon *weapon = pDriver->GetWeapon(); if(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != 5) return; - weapon->Update(pDriver->m_audioEntityId); + weapon->Update(pDriver->m_audioEntityId, nil); bool lookingLeft = false; bool lookingRight = false; @@ -3037,37 +3041,42 @@ CAutomobile::DoDriveByShootings(void) lookingRight = true; } + AnimationId rightAnim = ANIM_DRIVEBY_R; + AnimationId leftAnim = ANIM_DRIVEBY_L; + if (pDriver->m_pMyVehicle->bLowVehicle) { + rightAnim = ANIM_DRIVEBY_LOW_R; + leftAnim = ANIM_DRIVEBY_LOW_L; + } + if(lookingLeft || lookingRight){ if(lookingLeft){ - anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim); if(anim) anim->blendDelta = -1000.0f; - anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim); if(anim == nil || anim->blendDelta < 0.0f) - CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_L); - else - anim->SetRun(); + anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, leftAnim); }else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){ - anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim); if(anim) anim->blendDelta = -1000.0f; - anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim); if(anim == nil || anim->blendDelta < 0.0f) - CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_R); - else - anim->SetRun(); + anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, rightAnim); } - if(CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer){ - weapon->FireFromCar(this, lookingLeft); - weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70; + if (!anim || !anim->IsRunning()) { + if (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) { + weapon->FireFromCar(this, lookingLeft); + weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70; + } } }else{ weapon->Reload(); - anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim); if(anim) anim->blendDelta = -1000.0f; - anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim); if(anim) anim->blendDelta = -1000.0f; } diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 784d859f..1e7f8ecf 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -19,6 +19,9 @@ #include "Pools.h" #include "Pad.h" #include "Boat.h" +#include "AnimBlendAssociation.h" +#include "RpAnimBlend.h" +#include "Record.h" #define INVALID_ORIENTATION (-9999.99f) @@ -149,6 +152,9 @@ CBoat::ProcessControl(void) ProcessControlInputs(0); if(GetModelIndex() == MI_PREDATOR) DoFixedMachineGuns(); + + if (!CRecordDataForChase::IsRecording()) + DoDriveByShootings(); break; case STATUS_SIMPLE: m_bIsAnchored = false; @@ -912,6 +918,68 @@ CBoat::AddWakePoint(CVector point) } } +void +CBoat::DoDriveByShootings(void) +{ + CAnimBlendAssociation *anim; + CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); + if (playerInfo && !playerInfo->m_bDriveByAllowed) + return; + + CWeapon *weapon = pDriver->GetWeapon(); + if(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != 5) + return; + + weapon->Update(pDriver->m_audioEntityId, nil); + + bool lookingLeft = false; + bool lookingRight = false; + if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN){ + if(CPad::GetPad(0)->GetLookLeft()) + lookingLeft = true; + if(CPad::GetPad(0)->GetLookRight()) + lookingRight = true; + }else{ + if(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft) + lookingLeft = true; + if(TheCamera.Cams[TheCamera.ActiveCam].LookingRight) + lookingRight = true; + } + + if(lookingLeft || lookingRight){ + if(lookingLeft){ + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R); + if(anim) + anim->blendDelta = -1000.0f; + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L); + if(anim == nil || anim->blendDelta < 0.0f) + anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_L); + }else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){ + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L); + if(anim) + anim->blendDelta = -1000.0f; + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R); + if(anim == nil || anim->blendDelta < 0.0f) + anim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_R); + } + + if (!anim || !anim->IsRunning()) { + if (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) { + weapon->FireFromCar(this, lookingLeft); + weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70; + } + } + }else{ + weapon->Reload(); + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L); + if(anim) + anim->blendDelta = -1000.0f; + anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R); + if(anim) + anim->blendDelta = -1000.0f; + } +} + #ifdef COMPATIBLE_SAVES void CBoat::Save(uint8*& buf) diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index 7a0a9be4..c8168db0 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -61,6 +61,7 @@ public: void SetupModelNodes(); void PruneWakeTrail(void); void AddWakePoint(CVector point); + void DoDriveByShootings(void); static CBoat *apFrameWakeGeneratingBoats[4]; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index e457f964..a4c6f3f3 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1045,7 +1045,7 @@ CVehicle::SetUpDriver(void) if(VehicleCreatedBy != RANDOM_VEHICLE) return nil; - pDriver = CPopulation::AddPedInCar(this, false); + pDriver = CPopulation::AddPedInCar(this, true); pDriver->m_pMyVehicle = this; pDriver->m_pMyVehicle->RegisterReference((CEntity**)&pDriver->m_pMyVehicle); pDriver->bInVehicle = true; @@ -1061,7 +1061,7 @@ CVehicle::SetupPassenger(int n) if(pPassengers[n]) return pPassengers[n]; - pPassengers[n] = CPopulation::AddPedInCar(this, true); + pPassengers[n] = CPopulation::AddPedInCar(this, false); pPassengers[n]->m_pMyVehicle = this; pPassengers[n]->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle); pPassengers[n]->bInVehicle = true; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index c9e6bf93..666a26a2 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -300,7 +300,6 @@ public: CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA || GetModelIndex() == MI_KAUFMAN; } bool IsRealHeli(void) { return !!(pHandling->Flags & HANDLING_IS_HELI); } - AnimationId GetDriverAnim(void) { return IsCar() && bLowVehicle ? ANIM_CAR_LSIT : (IsBoat() && GetModelIndex() != MI_SPEEDER ? ANIM_DRIVE_BOAT : ANIM_CAR_SIT); } static bool bWheelsOnlyCheat; static bool bAllDodosCheat; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 1ae26106..1f901f88 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -30,25 +30,28 @@ #include "WeaponInfo.h" #include "World.h" +// TODO(Miami) +#define AUDIO_NOT_READY + uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = { 0, // UNARMED 0, // BASEBALLBAT + 0, // GRENADE + 0, // DETONATEGRENADE + 0, // MOLOTOV + 0, // ROCKET 250, // COLT45 + 650, // SHOTGUN 400, // TEC9 400, // UZIhec 400, // SILENCED_INGRAM 400, // MP5 - 650, // SHOTGUN - 300, // AK47 300, // M16 + 300, // AK47 423, // SNIPERRIFLE 400, // ROCKETLAUNCHER 0, // FLAMETHROWER - 0, // MOLOTOV - 0, // ROCKET - 0, // GRENADE - 0, // DETONATEGRENADE 0, // DETONATOR 0 // HELICANNON }; @@ -96,10 +99,7 @@ CWeapon::Initialise(eWeaponType type, int32 ammo) { m_eWeaponType = type; m_eWeaponState = WEAPONSTATE_READY; - if (ammo > 99999) - m_nAmmoTotal = 99999; - else - m_nAmmoTotal = ammo; + m_nAmmoTotal = Min(ammo, 99999); m_nAmmoInClip = 0; Reload(); m_nTimer = 0; @@ -283,8 +283,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); } - if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; - if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--; + if ( m_nAmmoInClip > 0 ) + m_nAmmoInClip--; + + if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) && (!isPlayer || CStats::GetPercentageProgress() < 100.0f || m_eWeaponType == WEAPONTYPE_DETONATOR)) + m_nAmmoTotal--; if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); @@ -331,7 +334,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } bool -CWeapon::FireFromCar(CAutomobile *shooter, bool left) +CWeapon::FireFromCar(CVehicle *shooter, bool left) { ASSERT(shooter!=nil); @@ -393,10 +396,10 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { bool collided = false; - CColModel *victimPedCol = &CTempColModels::ms_colModelPed1; - if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) ) - victimPedCol = &CTempColModels::ms_colModelPedGroundHit; - + // TODO(Miami) + if (victimPed->m_nPedState == PED_DRIVING && (m_eWeaponType == WEAPONTYPE_UNARMED /*|| m_eWeaponType == WEAPONTYPE_BRASSKNUCKLES*/ + || info->m_bFightMode)) + continue; float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius; if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) @@ -405,12 +408,29 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() ) { CVector collisionDist; + CColModel* victimPedCol = &CTempColModels::ms_colModelPed1; + bool useLocalPos = false; + if (victimPed->m_nPedState == PED_FALL + || victimPed->m_nPedState == PED_DIE && victimPed->bIsPedDieAnimPlaying + || victimPed->m_nWaitState == WAITSTATE_SIT_IDLE + || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) + { + useLocalPos = true; + victimPedCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(victimPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(victimPed->GetClump()); + } else if (victimPed->DyingOrDead()) { + victimPedCol = &CTempColModels::ms_colModelPedGroundHit; + } int32 s = 0; while ( s < victimPedCol->numSpheres ) { CColSphere *sphere = &victimPedCol->spheres[s]; - collisionDist = victimPedPos+sphere->center-(*fireSource); + + if (useLocalPos) { + collisionDist = sphere->center - (*fireSource); + } else { + collisionDist = victimPedPos + sphere->center - (*fireSource); + } if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) { @@ -659,45 +679,15 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) switch ( m_eWeaponType ) { - case WEAPONTYPE_AK47: - { - static uint8 counter = 0; - - if ( !(++counter & 1) ) - { - CPointLights::AddLight(CPointLights::LIGHT_POINT, - *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, - 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - - CVector gunflashPos = *fireSource; - gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.10f); - gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); - gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); - gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - - CVector gunsmokePos = *fireSource; - float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - - CVector gunshellPos = *fireSource; - gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f); - CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); - dir.Normalise2D(); - AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f); - } - - break; - } - case WEAPONTYPE_M16: + case WEAPONTYPE_AK47: + // case WEAPONTYPE_M60: + // case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_HELICANNON: { static uint8 counter = 0; - if ( !(++counter & 1) ) + if ( info->m_nFiringRate >= 50 && !(++counter & 1) ) { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, @@ -1669,7 +1659,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) } bool -CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) +CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left) { CWeaponInfo *info = GetInfo(); @@ -2040,8 +2030,10 @@ CWeapon::Reload(void) } void -CWeapon::Update(int32 audioEntity) +CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) { + CWeaponInfo *info = GetInfo(); + switch ( m_eWeaponState ) { case WEAPONSTATE_MELEE_MADECONTACT: @@ -2074,9 +2066,57 @@ CWeapon::Update(int32 audioEntity) { if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) { - uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; - if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) - DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); + CAnimBlendAssociation *reloadAssoc = nil; + if (pedToAdjustSound) { + if (CPed::GetReloadAnim(info) && (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload || !pedToAdjustSound->IsPlayer())) { + reloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetReloadAnim(info)); + if (!reloadAssoc) { + reloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetCrouchReloadAnim(info)); + } + } + } + if (reloadAssoc && reloadAssoc->IsRunning() && reloadAssoc->blendAmount > 0.2f) { + float soundStart = 0.75f; + switch (info->m_AnimToPlay) { + case ASSOCGRP_PYTHON: + soundStart = 0.5f; + break; + case ASSOCGRP_COLT: + case ASSOCGRP_TEC: + soundStart = 0.7f; + break; + case ASSOCGRP_UZI: + soundStart = 0.75f; + break; + case ASSOCGRP_RIFLE: + soundStart = 0.75f; + break; + case ASSOCGRP_M60: + soundStart = 0.7f; + break; + default: + break; + } + if (reloadAssoc->GetProgress() >= soundStart && (reloadAssoc->currentTime - reloadAssoc->timeStep) / reloadAssoc->hierarchy->totalLength < soundStart) { +#ifdef AUDIO_NOT_READY + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); +#else + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType); +#endif + } + if (CTimer::GetTimeInMilliseconds() > m_nTimer && reloadAssoc->GetProgress() < 0.9f) { + m_nTimer = CTimer::GetTimeInMilliseconds(); + } + } else { + uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; + if (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed) { +#ifdef AUDIO_NOT_READY + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); +#else + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType); +#endif + } + } } if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 5c62a74b..f6228b32 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -7,7 +7,8 @@ class CEntity; class CPhysical; -class CAutomobile; +class CVehicle; +class CPed; struct CColPoint; class CWeaponInfo; @@ -35,7 +36,7 @@ public: void Shutdown(); bool Fire (CEntity *shooter, CVector *fireSource); - bool FireFromCar (CAutomobile *shooter, bool left); + bool FireFromCar (CVehicle *shooter, bool left); bool FireMelee (CEntity *shooter, CVector &fireSource); bool FireInstantHit(CEntity *shooter, CVector *fireSource); @@ -50,14 +51,14 @@ public: bool FireAreaEffect (CEntity *shooter, CVector *fireSource); bool FireSniper (CEntity *shooter); bool FireM16_1stPerson (CEntity *shooter); - bool FireInstantHitFromCar(CAutomobile *shooter, bool left); + bool FireInstantHitFromCar(CVehicle *shooter, bool left); static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target); static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target); static void DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target); void Reload(void); - void Update(int32 audioEntity); + void Update(int32 audioEntity, CPed *pedToAdjustSound); bool IsTypeMelee (void); bool IsType2Handed(void); diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index 7128a04f..420171f2 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -20,21 +20,21 @@ CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; static char ms_aWeaponNames[][32] = { "Unarmed", "BaseballBat", + "Grenade", + "DetonateGrenade", + "Molotov", + "Rocket", "Colt45", + "Shotgun", "Tec9", "Uzi", "SilencedIngram", "Mp5", - "Shotgun", - "AK47", "M16", + "AK47", "SniperRifle", "RocketLauncher", "FlameThrower", - "Molotov", - "Rocket", - "Grenade", - "DetonateGrenade", "Detonator", "HeliCannon", }; diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h index 61d03ad3..8c1f598d 100644 --- a/src/weapons/WeaponType.h +++ b/src/weapons/WeaponType.h @@ -5,24 +5,25 @@ enum eWeaponType { WEAPONTYPE_UNARMED, WEAPONTYPE_BASEBALLBAT, + WEAPONTYPE_GRENADE, + WEAPONTYPE_DETONATOR_GRENADE, + WEAPONTYPE_MOLOTOV, + WEAPONTYPE_ROCKET, WEAPONTYPE_COLT45, + WEAPONTYPE_SHOTGUN, WEAPONTYPE_TEC9, WEAPONTYPE_UZI, WEAPONTYPE_SILENCED_INGRAM, WEAPONTYPE_MP5, - WEAPONTYPE_SHOTGUN, - WEAPONTYPE_AK47, WEAPONTYPE_M16, + WEAPONTYPE_AK47, WEAPONTYPE_SNIPERRIFLE, WEAPONTYPE_ROCKETLAUNCHER, WEAPONTYPE_FLAMETHROWER, - WEAPONTYPE_MOLOTOV, - WEAPONTYPE_ROCKET, - WEAPONTYPE_GRENADE, - WEAPONTYPE_DETONATOR_GRENADE, WEAPONTYPE_DETONATOR, WEAPONTYPE_HELICANNON, WEAPONTYPE_LAST_WEAPONTYPE, + WEAPONTYPE_HEALTH, WEAPONTYPE_ARMOUR, WEAPONTYPE_RAMMEDBYCAR, WEAPONTYPE_RUNOVERBYCAR, From 91fbfc1d2352f985dfd926c22ffa0938133103c8 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Sun, 17 May 2020 21:13:25 +0300 Subject: [PATCH 033/148] nullsampman --- src/audio/sampman_null.cpp | 368 +++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 src/audio/sampman_null.cpp diff --git a/src/audio/sampman_null.cpp b/src/audio/sampman_null.cpp new file mode 100644 index 00000000..6ec8a521 --- /dev/null +++ b/src/audio/sampman_null.cpp @@ -0,0 +1,368 @@ +#include "common.h" +#if !defined(AUDIO_OAL) && !defined(AUDIO_MSS) +#include "sampman.h" +#include "AudioManager.h" + +cSampleManager SampleManager; +bool _bSampmanInitialised = false; + +uint32 BankStartOffset[MAX_SAMPLEBANKS]; +uint32 nNumMP3s; + +cSampleManager::cSampleManager(void) +{ + ; +} + +cSampleManager::~cSampleManager(void) +{ + +} + +void cSampleManager::SetSpeakerConfig(int32 nConfig) +{ + +} + +uint32 cSampleManager::GetMaximumSupportedChannels(void) +{ + return MAXCHANNELS; +} + +uint32 cSampleManager::GetNum3DProvidersAvailable() +{ + return 1; +} + +void cSampleManager::SetNum3DProvidersAvailable(uint32 num) +{ + +} + +char *cSampleManager::Get3DProviderName(uint8 id) +{ + static char name[64] = "NULL"; + return name; +} + +void cSampleManager::Set3DProviderName(uint8 id, char *name) +{ + +} + +int8 cSampleManager::GetCurrent3DProviderIndex(void) +{ + return 0; +} + +int8 cSampleManager::SetCurrent3DProvider(uint8 nProvider) +{ + return 0; +} + +bool +cSampleManager::IsMP3RadioChannelAvailable(void) +{ + return nNumMP3s != 0; +} + + +void cSampleManager::ReleaseDigitalHandle(void) +{ +} + +void cSampleManager::ReacquireDigitalHandle(void) +{ +} + +bool +cSampleManager::Initialise(void) +{ + return true; +} + +void +cSampleManager::Terminate(void) +{ + +} + +bool cSampleManager::CheckForAnAudioFileOnCD(void) +{ + return true; +} + +char cSampleManager::GetCDAudioDriveLetter(void) +{ + return '\0'; +} + +void +cSampleManager::UpdateEffectsVolume(void) +{ + +} + +void +cSampleManager::SetEffectsMasterVolume(uint8 nVolume) +{ +} + +void +cSampleManager::SetMusicMasterVolume(uint8 nVolume) +{ +} + +void +cSampleManager::SetEffectsFadeVolume(uint8 nVolume) +{ +} + +void +cSampleManager::SetMusicFadeVolume(uint8 nVolume) +{ +} + +void +cSampleManager::SetMonoMode(uint8 nMode) +{ +} + +bool +cSampleManager::LoadSampleBank(uint8 nBank) +{ + ASSERT( nBank < MAX_SAMPLEBANKS ); + return false; +} + +void +cSampleManager::UnloadSampleBank(uint8 nBank) +{ + ASSERT( nBank < MAX_SAMPLEBANKS ); +} + +bool +cSampleManager::IsSampleBankLoaded(uint8 nBank) +{ + ASSERT( nBank < MAX_SAMPLEBANKS ); + + return false; +} + +bool +cSampleManager::IsPedCommentLoaded(uint32 nComment) +{ + ASSERT( nComment < TOTAL_AUDIO_SAMPLES ); + + return false; +} + + +int32 +cSampleManager::_GetPedCommentSlot(uint32 nComment) +{ + return -1; +} + +bool +cSampleManager::LoadPedComment(uint32 nComment) +{ + ASSERT( nComment < TOTAL_AUDIO_SAMPLES ); + return false; +} + +int32 +cSampleManager::GetBankContainingSound(uint32 offset) +{ + return SAMPLEBANK_INVALID; +} + +int32 +cSampleManager::GetSampleBaseFrequency(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return 0; +} + +int32 +cSampleManager::GetSampleLoopStartOffset(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return 0; +} + +int32 +cSampleManager::GetSampleLoopEndOffset(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return 0; +} + +uint32 +cSampleManager::GetSampleLength(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return 0; +} + +bool cSampleManager::UpdateReverb(void) +{ + return false; +} + +void +cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +bool +cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + return false; +} + +void +cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume) +{ + ASSERT( nChannel != CHANNEL2D ); + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ) +{ + ASSERT( nChannel != CHANNEL2D ); + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin) +{ + ASSERT( nChannel != CHANNEL2D ); + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume) +{ + ASSERT( nChannel == CHANNEL2D ); + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan) +{ + ASSERT(nChannel == CHANNEL2D); + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +bool +cSampleManager::GetChannelUsedFlag(uint32 nChannel) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + return false; +} + +void +cSampleManager::StartChannel(uint32 nChannel) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::StopChannel(uint32 nChannel) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); +} + +void +cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); +} + +void +cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); +} + +void +cSampleManager::StartPreloadedStreamedFile(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); +} + +bool +cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + return false; +} + +void +cSampleManager::StopStreamedFile(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); +} + +int32 +cSampleManager::GetStreamedFilePosition(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + return 0; +} + +void +cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); +} + +int32 +cSampleManager::GetStreamedFileLength(uint8 nStream) +{ + ASSERT( nStream < TOTAL_STREAMED_SOUNDS ); + + return 1; +} + +bool +cSampleManager::IsStreamPlaying(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + return false; +} + +bool +cSampleManager::InitialiseSampleBanks(void) +{ + + return true; +} + +#endif From a5b84eb9fe32689f0aee10077854a3652c986c08 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 17 May 2020 21:43:11 +0300 Subject: [PATCH 034/148] full script basic support --- src/animation/AnimBlendAssocGroup.cpp | 4 +- src/control/CarAI.cpp | 16 +- src/control/CarCtrl.cpp | 4 +- src/control/Garages.cpp | 2 +- src/control/Pickups.cpp | 10 + src/control/Pickups.h | 2 + src/control/Script.cpp | 626 +++++++++++++++++++++++--- src/control/Script.h | 6 +- src/core/Camera.cpp | 2 + src/core/Camera.h | 4 +- src/modelinfo/ModelIndices.h | 3 +- src/peds/Ped.cpp | 68 +-- src/peds/Ped.h | 5 +- src/peds/Population.cpp | 4 +- src/vehicles/Automobile.cpp | 17 +- src/vehicles/Automobile.h | 3 + src/vehicles/Vehicle.cpp | 13 +- src/vehicles/Vehicle.h | 13 +- 18 files changed, 675 insertions(+), 127 deletions(-) diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index c5711fda..ef0161db 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -104,7 +104,7 @@ strcmpIgnoringDigits(const char *s1, const char *s2) c2 = toupper(c2); #endif - if(c1 != c2) + if(c1 && c2 && c1 != c2) return false; } } @@ -126,6 +126,8 @@ GetModelFromName(const char *name) for(i = 0; i < MODELINFOSIZE; i++){ mi = CModelInfo::GetModelInfo(i); + if (mi && strcmp("drink", mi->GetName()) == 0 && strcmp(name, "drink01") == 0) + debug("TEST"); if(mi && mi->GetRwObject() && RwObjectGetType(mi->GetRwObject()) == rpCLUMP && strcmpIgnoringDigits(mi->GetName(), name)) return mi; diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index 0f80954b..a4406da9 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -358,7 +358,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle); pVehicle->SetStatus(STATUS_PHYSICS); pVehicle->AutoPilot.m_nCarMission = - pVehicle->GetVehicleAppearance() == VEHICLE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel(); + pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel(); pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; }else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){ @@ -432,7 +432,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (pVehicle->bIsLawEnforcer) { if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) { - if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE) + if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY; } } @@ -489,16 +489,16 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0) { if (!FindPlayerVehicle() || - FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_CAR || - FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE) { - if (pVehicle->GetVehicleAppearance() == VEHICLE_BOAT) { + FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR || + FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) { + if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) { pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; } } - else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BOAT) { - if (pVehicle->GetVehicleAppearance() == VEHICLE_CAR || - pVehicle->GetVehicleAppearance() == VEHICLE_BIKE) { + else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) { + if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR || + pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) { pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; } diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 956bad28..920fba81 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -655,10 +655,10 @@ CCarCtrl::GenerateOneRandomCar() } int nMadDrivers; switch (pVehicle->GetVehicleAppearance()) { - case VEHICLE_BIKE: + case VEHICLE_APPEARANCE_BIKE: nMadDrivers = 30; break; - case VEHICLE_BOAT: + case VEHICLE_APPEARANCE_BOAT: nMadDrivers = 40; break; default: diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 82003561..a177343b 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -960,7 +960,7 @@ void CGarage::Update() if (m_pDoor1) { if (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) && CTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) { - if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_PLANE) { + if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE) { CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage. CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds(); } diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index b2cd1e05..b764eac8 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1436,3 +1436,13 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer() FindPlayerVehicle()->m_fForceMultiplier = 1.0f; } } + +bool +CPickups::TestForPickupsInBubble(CVector pos, float radius) +{ + for (int i = 0; i < NUMPICKUPS; i++) { + if ((pos - aPickUps[i].m_vecPos).Magnitude() < radius) + return true; + } + return false; +} diff --git a/src/control/Pickups.h b/src/control/Pickups.h index fde3e134..d2d1657b 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -93,6 +93,8 @@ public: static void Load(uint8 *buf, uint32 size); static void Save(uint8 *buf, uint32 *size); + static bool TestForPickupsInBubble(CVector pos, float radius); + static CPickup aPickUps[NUMPICKUPS]; // unused diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 805d6469..cfa5be46 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -58,11 +58,14 @@ #include "Rubbish.h" #include "Shadows.h" #include "SpecialFX.h" +#include "Sprite.h" #include "Stats.h" #include "Streaming.h" #include "Text.h" +#include "Timecycle.h" #include "TxdStore.h" #include "User.h" +#include "VisibilityPlugins.h" #include "WaterLevel.h" #include "Weather.h" #include "World.h" @@ -70,7 +73,7 @@ #include "main.h" #define PICKUP_PLACEMENT_OFFSET 0.5f -#define PED_FIND_Z_OFFSET 5.0f +#define PED_FIND_Z_OFFSET 10.0f #define SPHERE_MARKER_R 0 #define SPHERE_MARKER_G 128 @@ -285,6 +288,9 @@ void CMissionCleanup::Process() CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false; CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false; CWorld::Players[0].MakePlayerSafe(false); + + CVehicle::bDisableRemoteDetonation = false; + CTheScripts::StoreVehicleIndex = -1; CTheScripts::StoreVehicleWasRandom = true; CTheScripts::UpsideDownCars.Init(); @@ -2084,8 +2090,10 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) } else { CVehicle* car; - if (!CModelInfo::IsBikeModel(ScriptParams[0])) - car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE); + + // TODO(MIAMI) + //if (!CModelInfo::IsBikeModel(ScriptParams[0])) + car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE); CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); @@ -8331,13 +8339,21 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) DMAudio.PreloadMissionAudio(str); return 0; case COMMAND_HAS_MISSION_AUDIO_LOADED: - UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1); + CollectParameters(&m_nIp, 1); + debug("HAS_MISSION_AUDIO_LOADED doesn't support parameter yet, default to TRUE\n"); + UpdateCompareFlag(true); + //UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1); return 0; case COMMAND_PLAY_MISSION_AUDIO: - DMAudio.PlayLoadedMissionAudio(); + CollectParameters(&m_nIp, 1); + debug("PLAY_MISSION_AUDIO doesn't support parameter yet, skipping\n"); + //DMAudio.PlayLoadedMissionAudio(); return 0; case COMMAND_HAS_MISSION_AUDIO_FINISHED: - UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished()); + CollectParameters(&m_nIp, 1); + debug("HAS_MISSION_AUDIO_FINISHED doesn't support parameter yet, default to TRUE\n"); + UpdateCompareFlag(true); + //UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished()); return 0; case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING: { @@ -8650,8 +8666,15 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CStats::RegisterLongestFlightInDodo(ScriptParams[0]); return 0; case COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS: - assert(0 && "GET_OFFSET_FROM_CAR_IN_WORLD_COORDS not yet implemented"); + { + CollectParameters(&m_nIp, 4); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + CVector result = pVehicle->GetMatrix() * *(CVector*)&ScriptParams[1] + pVehicle->GetPosition(); + *(CVector*)&ScriptParams[0] = result; + StoreParameters(&m_nIp, 3); return 0; + } case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES: CollectParameters(&m_nIp, 1); CStats::SetTotalNumberKillFrenzies(ScriptParams[0]); @@ -9178,7 +9201,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) { char tmp[48]; switch (command) { - case COMMAND_LOAD_COLLISION_WITH_SCREEN: + case COMMAND_LOAD_COLLISION_WITH_SCREEN: // NB: not actually implemented CollectParameters(&m_nIp, 1); CTimer::Stop(); CGame::currLevel = (eLevelName)ScriptParams[0]; @@ -9205,7 +9228,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) m_nIp += 8; LoadSplash(tmp); return 0; - case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: + case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: // NB: not actually implemented { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9216,7 +9239,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); return 0; } - case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: + case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: // NB: not actually implemented { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9240,7 +9263,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED); printf("End preload end of game audio\n"); return 0; - case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: + case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: // NB: not actually implemented CPad::GetPad(0)->DisablePlayerControls &= PLAYERCONTROL_DISABLED_1; return 0; case COMMAND_SET_OBJECT_ROTATION: @@ -9262,11 +9285,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source; StoreParameters(&m_nIp, 3); return 0; - case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: + case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: // NB: not actually implemented *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front; StoreParameters(&m_nIp, 3); return 0; - case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: + case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: // NB: not actually implemented { CollectParameters(&m_nIp, 1); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; @@ -9283,10 +9306,38 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); assert(pTestedPed); CEntity* pTarget = pPed->m_pPointGunAt; - UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed); + bool bTargetting = pTarget && pTarget->IsPed() && pTarget == pTestedPed; + // PC shit + static int nCounter = 0; + nCounter = Max(0, nCounter - 1); + if (!pPed->GetWeapon()->IsTypeMelee() && !bTargetting) { + if ((pTarget->GetPosition() - TheCamera.GetPosition()).Magnitude() < 10.0f) { + CVector vTestedPos(pTarget->GetPosition().x, pTarget->GetPosition().y, pTarget->GetPosition().z + 0.4); + CVector vScreenPos; + float w, h; + if (CSprite::CalcScreenCoors(vTestedPos, vScreenPos, &w, &h, false)) { + CVector2D vCrosshairPosition(CCamera::m_f3rdPersonCHairMultX * RsGlobal.maximumWidth, CCamera::m_f3rdPersonCHairMultY * RsGlobal.maximumHeight); + float fScreenDistance = ((CVector2D)vScreenPos - vCrosshairPosition).Magnitude(); + if (SCREEN_STRETCH_X(0.45f) > fScreenDistance / w) { + CColPoint point; + CEntity* entity; + if (!CWorld::ProcessLineOfSight(TheCamera.GetPosition() + 2.0f * TheCamera.GetForward(), + vTestedPos, point, entity, true, true, true, true, true, false) || + entity == pTarget) { + nCounter += 2; + if (nCounter > 20) { + bTargetting = true; + nCounter = 20; + } + } + } + } + } + } + UpdateCompareFlag(bTargetting); return 0; } - case COMMAND_IS_PLAYER_TARGETTING_OBJECT: + case COMMAND_IS_PLAYER_TARGETTING_OBJECT: // NB: not actually implemented { CollectParameters(&m_nIp, 2); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; @@ -9339,7 +9390,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) case COMMAND_FAIL_CURRENT_MISSION: CTheScripts::FailCurrentMission = 2; return 0; - case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: + case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: // NB: actually does nothing { CollectParameters(&m_nIp, 5); CVector pos = *(CVector*)&ScriptParams[0]; @@ -9385,7 +9436,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 1); return 0; } - case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: + case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: // NB: not actually implemented { CollectParameters(&m_nIp, 5); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); @@ -9401,24 +9452,14 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - if (pVehicle->pDriver) { - pVehicle->pDriver->bScriptObjectiveCompleted = false; - pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); - } - for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++) - { - if (pVehicle->pPassengers[i]) { - pVehicle->pPassengers[i]->bScriptObjectiveCompleted = false; - pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); - } - } + CCarAI::TellOccupantsToLeaveCar(pVehicle); return 0; } case COMMAND_SET_INTERPOLATION_PARAMETERS: CollectParameters(&m_nIp, 2); - TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]); + TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 100.0f - *(float*)&ScriptParams[0], ScriptParams[1]); return 0; - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: // NB: not actually implemented { CollectParameters(&m_nIp, 5); CVector pos = *(CVector*)&ScriptParams[0]; @@ -9433,7 +9474,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 4); return 0; } - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: // NB: not actually implemented { CollectParameters(&m_nIp, 5); CVector pos = *(CVector*)&ScriptParams[0]; @@ -9453,10 +9494,12 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 3); return 0; case COMMAND_ATTACH_CHAR_TO_CAR: - // empty implementation + // TODO(MIAMI) + assert(0); return 0; case COMMAND_DETACH_CHAR_FROM_CAR: - // empty implementation + // TODO(MIAMI) + assert(0); return 0; case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA { @@ -9470,15 +9513,20 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) { CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - assert(pPed); - pPed->m_lastWepDam = -1; + if (pPed) + pPed->m_lastWepDam = -1; + else + debug("CLEAR_CHAR_LAST_WEAPON_DAMAGE - Character doesn't exist\n"); return 0; } case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE: { CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - pVehicle->m_nLastWeaponDamage = -1; + if (pVehicle) + pVehicle->m_nLastWeaponDamage = -1; + else + debug("CLEAR_CAR_LAST_WEAPON_DAMAGE - Vehicle doesn't exist\n"); return 0; } case COMMAND_GET_RANDOM_COP_IN_AREA: @@ -9499,9 +9547,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) continue; if (pPed->m_nPedType != PEDTYPE_COP) continue; + if (!ThisIsAValidRandomCop(pPed->GetModelIndex(), ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8])) + continue; if (pPed->CharCreatedBy != RANDOM_CHAR) continue; - if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING) + if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING /* && pPed->GetPedState() != PED_ONROPE */) // TODO(MIAMI)! continue; if (pPed->bRemoveFromWorld) continue; @@ -9527,7 +9577,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 1); return 0; } - case COMMAND_GET_RANDOM_COP_IN_ZONE: + case COMMAND_GET_RANDOM_COP_IN_ZONE: // NB: not actually implemented { char zone[KEY_LENGTH_IN_SCRIPT]; strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); @@ -9631,7 +9681,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType; + ScriptParams[0] = pPed->GetWeapon()->m_eWeaponType; StoreParameters(&m_nIp, 1); return 0; } @@ -9640,7 +9690,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType; + ScriptParams[0] = pPed->GetWeapon()->m_eWeaponType; StoreParameters(&m_nIp, 1); return 0; } @@ -9661,7 +9711,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[2]; return 0; } - case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: + case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: // NB: not actually implemented { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9670,7 +9720,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; return 0; } - case COMMAND_SET_CAR_HANDBRAKE_STOP: + case COMMAND_SET_CAR_HANDBRAKE_STOP: // NB: not actually implemented { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9684,11 +9734,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE); + UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE); return 0; } - case COMMAND_LOCATE_SNIPER_BULLET_2D: - case COMMAND_LOCATE_SNIPER_BULLET_3D: + case COMMAND_LOCATE_SNIPER_BULLET_2D: // NB: not actually implemented + case COMMAND_LOCATE_SNIPER_BULLET_3D: // NB: not actually implemented LocateSniperBulletCommand(command, &m_nIp); return 0; case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL: @@ -9701,10 +9751,10 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE); return 0; } - case COMMAND_IS_CHAR_LYING_DOWN: + case COMMAND_IS_CHAR_LYING_DOWN: // NB: not actually implemented { CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); @@ -9736,14 +9786,39 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0]; return 0; case COMMAND_SET_CHAR_CEASE_ATTACK_TIMER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->m_ceaseAttackTimer = ScriptParams[1]; + return 0; + } case COMMAND_GET_REMOTE_CONTROLLED_CAR: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CWorld::Players[ScriptParams[0]].m_pRemoteVehicle; + if (pVehicle) + ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle); + else + ScriptParams[0] = -1; + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_IS_PC_VERSION: - case COMMAND_REPLAY: - case COMMAND_IS_REPLAY_PLAYING: + UpdateCompareFlag(true); + return 0; + //case COMMAND_REPLAY: + //case COMMAND_IS_REPLAY_PLAYING: case COMMAND_IS_MODEL_AVAILABLE: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CModelInfo::GetModelInfo(ScriptParams[0]) != nil); + return 0; case COMMAND_SHUT_CHAR_UP: + assert("SHUT_CHAR_UP not implemented"); // TODO(MIAMI) case COMMAND_SET_ENABLE_RC_DETONATE: - assert(0); + CollectParameters(&m_nIp, 1); + CVehicle::bDisableRemoteDetonation = ScriptParams[0]; + return 0; case COMMAND_SET_CAR_RANDOM_ROUTE_SEED: { CollectParameters(&m_nIp, 2); @@ -9753,40 +9828,232 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) return 0; } case COMMAND_IS_ANY_PICKUP_AT_COORDS: - case COMMAND_GET_FIRST_PICKUP_COORDS: - case COMMAND_GET_NEXT_PICKUP_COORDS: + { + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + bool bFound = false; + for (int i = 0; i < NUMPICKUPS; i++) { + if ((CPickups::aPickUps[i].m_vecPos - pos).Magnitude() < 0.5f) + bFound = true; + } + UpdateCompareFlag(bFound); + return 0; + } + //case COMMAND_GET_FIRST_PICKUP_COORDS: + //case COMMAND_GET_NEXT_PICKUP_COORDS: case COMMAND_REMOVE_ALL_CHAR_WEAPONS: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->ClearWeapons(); + return 0; + } case COMMAND_HAS_PLAYER_GOT_WEAPON: - case COMMAND_HAS_CHAR_GOT_WEAPON: - case COMMAND_IS_PLAYER_FACING_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + bool bFound = false; + for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) { + if (pPed->GetWeapon(i).m_eWeaponType == ScriptParams[1]) { + bFound = true; + break; + } + } + UpdateCompareFlag(bFound); + return 0; + } + //case COMMAND_HAS_CHAR_GOT_WEAPON: + //case COMMAND_IS_PLAYER_FACING_CHAR: case COMMAND_SET_TANK_DETONATE_CARS: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle && pVehicle->m_vehType == VEHICLE_TYPE_CAR); + ((CAutomobile*)pVehicle)->bTankDetonateCars = ScriptParams[1]; + return 0; + } case COMMAND_GET_POSITION_OF_ANALOGUE_STICKS: + { + CollectParameters(&m_nIp, 1); + CPad* pPad = CPad::GetPad(ScriptParams[0]); + ScriptParams[0] = pPad->NewState.LeftStickX; + ScriptParams[1] = pPad->NewState.LeftStickY; + ScriptParams[2] = pPad->NewState.RightStickX; + ScriptParams[3] = pPad->NewState.RightStickY; + StoreParameters(&m_nIp, 4); + return 0; + } case COMMAND_IS_CAR_ON_FIRE: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + bool bOnFire = false; + if (pVehicle->m_pCarFire) + bOnFire = true; + if (pVehicle->m_vehType == VEHICLE_TYPE_CAR && ((CAutomobile*)pVehicle)->Damage.GetEngineStatus() >= ENGINE_STATUS_ON_FIRE) + bOnFire = true; + if (pVehicle->m_fHealth < 250.0f) + bOnFire = true; + UpdateCompareFlag(bOnFire); + return 0; + } case COMMAND_IS_CAR_TYRE_BURST: - case COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD: - case COMMAND_SET_CAR_WAIT: - case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE: - case COMMAND_IS_PLAYER_FOOT_DOWN: - case COMMAND_IS_CHAR_FOOT_DOWN: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + bool bIsBurst = false; + if (pVehicle->m_vehType == VEHICLE_APPEARANCE_BIKE) { + assert("IS_CAR_TYPE_BURST not yet implemented for bikes"); + } + else { + CAutomobile* pCar = (CAutomobile*)pVehicle; + if (ScriptParams[1] == 4) { + for (int i = 0; i < 4; i++) { + if (pCar->Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST) + bIsBurst = true; + } + } + else + bIsBurst = pCar->Damage.GetWheelStatus(ScriptParams[1] == WHEEL_STATUS_BURST); + } + UpdateCompareFlag(bIsBurst); + } + //case COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD: + //case COMMAND_SET_CAR_WAIT: + //case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE: + //case COMMAND_IS_PLAYER_FOOT_DOWN: + //case COMMAND_IS_CHAR_FOOT_DOWN: case COMMAND_INITIALISE_OBJECT_PATH: + // TODO(MIAMI): script path + CollectParameters(&m_nIp, 2); + debug("INITALISE_OBJECT_PATH not yet implemented, skipping\n"); + ScriptParams[0] = 0; + StoreParameters(&m_nIp, 1); + return 0; case COMMAND_START_OBJECT_ON_PATH: + { + CollectParameters(&m_nIp, 2); + debug("START_OBJECT_ON_PATH not yet implemented, skipping\n"); + return 0; + } case COMMAND_SET_OBJECT_PATH_SPEED: + { + CollectParameters(&m_nIp, 2); + debug("SET_OBJECT_PATH_SPEED not yet implemented, skipping\n"); + return 0; + } case COMMAND_SET_OBJECT_PATH_POSITION: - case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH: + { + CollectParameters(&m_nIp, 2); + debug("SET_OBJECT_PATH_POSITION not yet implemented, skipping\n"); + return 0; + } + //case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH: case COMMAND_CLEAR_OBJECT_PATH: + { + CollectParameters(&m_nIp, 1); + debug("CLEAR_OBJECT_PATH not yet implemented, skipping\n"); + return 0; + } case COMMAND_HELI_GOTO_COORDS: + { + CollectParameters(&m_nIp, 5); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle && pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI); + ((CAutomobile*)pVehicle)->TellHeliToGoToCoors(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], ScriptParams[4]); + return 0; + } case COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT: + { + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(*ptr = ScriptParams[0]); + return 0; + } case COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT: + { + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(*ptr = ScriptParams[0]); + return 0; + } case COMMAND_GET_DEAD_CHAR_PICKUP_COORDS: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + pPed->CreateDeadPedPickupCoors((float*)&ScriptParams[0], (float*)&ScriptParams[1], (float*)&ScriptParams[2]); + StoreParameters(&m_nIp, 3); + return 0; + } case COMMAND_CREATE_PROTECTION_PICKUP: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_REVENUE, PICKUP_ASSET_REVENUE, ScriptParams[3], ScriptParams[4]); + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_IS_CHAR_IN_ANY_BOAT: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT); + return 0; + } case COMMAND_IS_PLAYER_IN_ANY_BOAT: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE); + return 0; + } case COMMAND_IS_CHAR_IN_ANY_HELI: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI); + return 0; + } case COMMAND_IS_PLAYER_IN_ANY_HELI: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI); + return 0; + } case COMMAND_IS_CHAR_IN_ANY_PLANE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE); + return 0; + } case COMMAND_IS_PLAYER_IN_ANY_PLANE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI); + return 0; + } case COMMAND_IS_CHAR_IN_WATER: - assert(0); + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(pPed && pPed->bIsInWater); + return 0; + } case COMMAND_SET_VAR_INT_TO_CONSTANT: { int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); @@ -9812,17 +10079,74 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) { switch (command) { case COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT: + { + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(*ptr > ScriptParams[0]); + return 0; + } case COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT: + { + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(*ptr > ScriptParams[0]); + return 0; + } case COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR: + { + CollectParameters(&m_nIp, 1); + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); + UpdateCompareFlag(ScriptParams[0] > *ptr); + return 0; + } case COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR: + { + CollectParameters(&m_nIp, 1); + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL); + UpdateCompareFlag(ScriptParams[0] > *ptr); + return 0; + } case COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT: + { + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(*ptr >= ScriptParams[0]); + return 0; + } case COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT: + { + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(*ptr >= ScriptParams[0]); + return 0; + } case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR: + { + CollectParameters(&m_nIp, 1); + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL); + UpdateCompareFlag(ScriptParams[0] >= *ptr); + return 0; + } case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR: + { + CollectParameters(&m_nIp, 1); + int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL); + UpdateCompareFlag(ScriptParams[0] >= *ptr); + return 0; + } case COMMAND_GET_CHAR_WEAPON_IN_SLOT: case COMMAND_GET_CLOSEST_STRAIGHT_ROAD: - case COMMAND_SET_CAR_FORWARD_SPEED: assert(0); + case COMMAND_SET_CAR_FORWARD_SPEED: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + float speed = *(float*)&ScriptParams[1] / GAME_SPEED_TO_CARAI_SPEED; + pVehicle->SetMoveSpeed(pVehicle->GetForward() * speed); + // TODO(MIAMI): heli hack! + return 0; + } case COMMAND_SET_AREA_VISIBLE: CollectParameters(&m_nIp, 1); CGame::currArea = ScriptParams[0]; @@ -9850,7 +10174,15 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR: case COMMAND_SWITCH_SECURITY_CAMERA: case COMMAND_IS_CHAR_IN_FLYING_VEHICLE: + assert(0); case COMMAND_IS_PLAYER_IN_FLYING_VEHICLE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + UpdateCompareFlag(pPed->bInVehicle && (pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)); + return 0; + } case COMMAND_HAS_SONY_CD_BEEN_READ: case COMMAND_GET_NUMBER_OF_SONY_CDS_READ: case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD: @@ -9948,11 +10280,36 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_SET_CHAR_AS_PLAYER_FRIEND: case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER: case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING: + assert(0); case COMMAND_ADD_SET_PIECE: + { + CollectParameters(&m_nIp, 13); + debug("ADD_SET_PIECE not implemented, skipping\n"); + return 0; + } case COMMAND_SET_EXTRA_COLOURS: + { + CollectParameters(&m_nIp, 2); + debug("SET_EXTRA_COLOURS not implemented, skipping\n"); + return 0; + } case COMMAND_CLEAR_EXTRA_COLOURS: + { + CollectParameters(&m_nIp, 1); + debug("CLEAR_EXTRA_COLOURS not implemented, skipping\n"); + return 0; + } case COMMAND_CLOSE_CAR_BOOT: + assert(0); case COMMAND_GET_WHEELIE_STATS: + { + CollectParameters(&m_nIp, 1); + debug("GET_WHEELIE_STATS not implemented, skipping\n"); + for (int i = 0; i < 6; i++) + ScriptParams[i] = 0; + StoreParameters(&m_nIp, 6); + return 0; + } case COMMAND_DISARM_CHAR: case COMMAND_BURST_CAR_TYRE: case COMMAND_IS_CHAR_OBJ_NO_OBJ: @@ -10023,7 +10380,12 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS: case COMMAND_IS_CAR_DROWNING_IN_WATER: case COMMAND_IS_CHAR_DROWNING_IN_WATER: + assert(0); case COMMAND_DISABLE_CUTSCENE_SHADOWS: + { + debug("DISABLE_CUTSCENE_SHADOWS not implemented, skipping\n"); + return 0; + } case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY: case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE: case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT: @@ -10065,7 +10427,15 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_CLEAR_CHAR_FOLLOW_PATH: case COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE: case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE: + assert(0); case COMMAND_LOAD_MISSION_TEXT: + { + char key[8]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + debug("skipping LOAD_MISSION_TEXT\n"); + return 0; + } case COMMAND_SET_TONIGHTS_EVENT: case COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY: case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY: @@ -10080,6 +10450,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT: case COMMAND_GET_CLOSEST_WATER_NODE: case COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH: + assert(0); case COMMAND_CREATE_CLOTHES_PICKUP: { CollectParameters(&m_nIp, 4); @@ -10117,7 +10488,64 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + CPed* pPed = CPopulation::AddPedInCar(pVehicle, true); + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + pPed->bAllowMedicsToReviveMe = false; + // TODO(MIAMI): two more flags and more stuff + pPed->SetPosition(pVehicle->GetPosition()); + pPed->SetOrientation(0.0f, 0.0f, 0.0f); + pPed->SetPedState(PED_DRIVING); + pPed->m_pMyVehicle = pVehicle; + pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); + pVehicle->pDriver = pPed; + pVehicle->pDriver->RegisterReference((CEntity**)&pVehicle->pDriver); + pPed->bInVehicle = true; + pVehicle->SetStatus(STATUS_PHYSICS); + if (pVehicle->m_vehType == VEHICLE_TYPE_BOAT) + pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; + pVehicle->bEngineOn = true; + pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); + CPopulation::ms_nTotalMissionPeds++; + ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + CPed* pPed = CPopulation::AddPedInCar(pVehicle, false); + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + pPed->bAllowMedicsToReviveMe = false; + // TODO(MIAMI): two more flags and more stuff (ClearFollowPath) + pPed->SetPosition(pVehicle->GetPosition()); + pPed->SetOrientation(0.0f, 0.0f, 0.0f); + CPopulation::ms_nTotalMissionPeds++; + pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); + if (ScriptParams[1] >= 0) + pVehicle->AddPassenger(pPed, ScriptParams[1]); + else + pVehicle->AddPassenger(pPed); + + pPed->m_pMyVehicle = pVehicle; + pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); + pPed->bInVehicle = true; + // TODO + pPed->SetPedState(PED_DRIVING); + + ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS: case COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON: case COMMAND_MAKE_HELI_COME_CRASHING_DOWN: @@ -10134,12 +10562,31 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_WAS_VEHICLE_EVER_POLICE: case COMMAND_SET_CHAR_NEVER_TARGETTED: case COMMAND_LOAD_UNCOMPRESSED_ANIM: + assert(0); case COMMAND_WAS_CUTSCENE_SKIPPED: + { + debug("WAS_CUTSCENE_SKIPPED is not implemented, defaulted to TRUE\n"); + UpdateCompareFlag(true); + return 0; + } case COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + debug("SET_CHAR_CROUCH_WHEN_THREATENED not implemented, skipping\n"); + return 0; + } case COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE: + { + CollectParameters(&m_nIp, 1); + debug("IS_CHAR_IN_ANY_POLICE_VEHICLE is not implemented, defaulted to FALSE\n"); + UpdateCompareFlag(false); + return 0; + } case COMMAND_DOES_CHAR_EXIST: case COMMAND_DOES_VEHICLE_EXIST: case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT: + assert(0); case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT: { CollectParameters(&m_nIp, 4); @@ -10177,14 +10624,37 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) CGarages::SetMaxNumStoredCarsForGarage(ScriptParams[0], ScriptParams[1]); break; case COMMAND_WANTED_STARS_ARE_FLASHING: + { + debug("WANTED_STARS_ARE_FLASHING not implemented, default to FALSE\n"); + UpdateCompareFlag(false); + return 0; + } case COMMAND_SET_ALLOW_HURRICANES: + CollectParameters(&m_nIp, 1); + CStats::NoMoreHurricanes = ScriptParams[0]; + return 0; case COMMAND_PLAY_ANNOUNCEMENT: + { + CollectParameters(&m_nIp, 1); + debug("PLAY_ANNOUNCEMENT not implemented, skipping\n"); + return 0; + } case COMMAND_SET_PLAYER_IS_IN_STADIUM: case COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER: case COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM: case COMMAND_DISPLAY_RADAR: case COMMAND_REGISTER_BEST_POSITION: + assert(0); case COMMAND_IS_PLAYER_IN_INFO_ZONE: + { + CollectParameters(&m_nIp, 1); + char key[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + debug("IS_PLAYER_IN_INFO_ZONE not implemented, default to FALSE\n"); + UpdateCompareFlag(false); + return 0; + } case COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE: case COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED: case COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR: @@ -10199,6 +10669,11 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) StoreParameters(&m_nIp, 1); return 0; case COMMAND_SET_SHORTCUT_PICKUP_POINT: + { + CollectParameters(&m_nIp, 4); + debug("SET_SHORTCUT_PICKUP_POINT not implemented, skipping\n"); + return 0; + } case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION: case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA: case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE: @@ -10209,9 +10684,23 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) CGangs::SetWillAttackPlayerWithCops((ePedType)((int)PEDTYPE_GANG1 + ScriptParams[0]), !!ScriptParams[1]); return 0; case COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR: + assert(0); case COMMAND_SET_VEHICLE_TO_FADE_IN: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), ScriptParams[1]); + return 0; + } case COMMAND_REGISTER_ODDJOB_MISSION_PASSED: + assert(0); case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI: + { + CollectParameters(&m_nIp, 1); + debug("IS_PLAYER_IN_SHORTCUT_TAXI not implemented, default to FALSE\n"); + return 0; + } case COMMAND_IS_CHAR_DUCKING: case COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI: case COMMAND_REGISTER_FIRE_LEVEL: @@ -10223,6 +10712,19 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return -1; } +bool CRunningScript::ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami) +{ + switch (mi) + { + case MI_COP: if (cop) return true; + case MI_SWAT: if (swat) return true; + case MI_FBI: if (fbi) return true; + case MI_ARMY: if (army) return true; + default: + return miami && (mi >= MI_VICE1 && mi <= MI_VICE8); + } +} + int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index) { if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1) diff --git a/src/control/Script.h b/src/control/Script.h index 9931f13e..c7a6e1e6 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -221,8 +221,8 @@ enum { }; enum { - SIZE_MAIN_SCRIPT = 128 * 1024, - SIZE_MISSION_SCRIPT = 32 * 1024, + SIZE_MAIN_SCRIPT = 225512, + SIZE_MISSION_SCRIPT = 35000, SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT }; @@ -507,4 +507,6 @@ private: return false; } } + + static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami); }; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 623b2ea9..1efe6bae 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -61,6 +61,8 @@ enum CCamera TheCamera; bool CCamera::m_bUseMouse3rdPerson = true; bool bDidWeProcessAnyCinemaCam; +float CCamera::m_f3rdPersonCHairMultX; +float CCamera::m_f3rdPersonCHairMultY; #ifdef IMPROVED_CAMERA #define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k) diff --git a/src/core/Camera.h b/src/core/Camera.h index 80fc878e..8f2b6c51 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -472,8 +472,8 @@ public: // not static yet float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls - float m_f3rdPersonCHairMultX; - float m_f3rdPersonCHairMultY; + static float m_f3rdPersonCHairMultX; + static float m_f3rdPersonCHairMultY; CCam Cams[3]; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 3a53074d..5a3bee9f 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -161,7 +161,8 @@ X("files", MI_FILES, 0x5F5BC4) \ X("property_locked", MI_PICKUP_PROPERTY, 0x0) \ X("property_fsale", MI_PICKUP_PROPERTY_FORSALE, 0x0) \ - X("clothesp", MI_PICKUP_CLOTHES, 0x0) + X("clothesp", MI_PICKUP_CLOTHES, 0x0) \ + X("bigdollar", MI_PICKUP_REVENUE, 0x0) #define X(name, var, addr) extern int16 var; MODELINDICES diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 8da8249e..1d872b9c 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -534,6 +534,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_fAirResistance = 0.4f / m_fMass; m_fElasticity = 0.05f; + m_ceaseAttackTimer = 0; + bIsStanding = false; bWasStanding = false; bIsAttacking = false; @@ -6326,8 +6328,6 @@ CPed::CreateDeadPedMoney(void) void CPed::CreateDeadPedWeaponPickups(void) { - bool found = false; - float angleToPed; CVector pickupPos; if (bInVehicle) @@ -6340,34 +6340,10 @@ CPed::CreateDeadPedWeaponPickups(void) if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || (weaponAmmo == 0 && !GetWeapon(i).IsTypeMelee())) continue; - angleToPed = i * 1.75f; - pickupPos = GetPosition(); - pickupPos.x += 1.5f * Sin(angleToPed); - pickupPos.y += 1.5f * Cos(angleToPed); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; - - CVector pedPos = GetPosition(); - pedPos.z += 0.3f; - - CVector pedToPickup = pickupPos - pedPos; - float distance = pedToPickup.Magnitude(); - - // outer edge of pickup - distance = (distance + 0.3f) / distance; - CVector pickupPos2 = pedPos; - pickupPos2 += distance * pedToPickup; - - // pickup must be on ground and line to its edge must be clear - if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) { - // otherwise try another position (but disregard second check apparently) - angleToPed += 3.14f; - pickupPos = GetPosition(); - pickupPos.x += 1.5f * Sin(angleToPed); - pickupPos.y += 1.5f * Cos(angleToPed); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; - } - if (found) - CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); + CreateDeadPedPickupCoors(&pickupPos.x, &pickupPos.y, &pickupPos.z); + pickupPos.z += 0.4f; + // TODO(MIAMI): there is more stuff it seems + CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); } ClearWeapons(); } @@ -18466,4 +18442,36 @@ CPed::ClearFollowPath() } m_nPathNodes = 0; m_nCurPathNode = 0; +} + +void +CPed::CreateDeadPedPickupCoors(float* x, float* y, float* z) +{ + for (int i = 0; i < 32; i++) { + CVector pickupPos = GetPosition(); + pickupPos.x += 1.5f * Sin(CGeneral::GetRandomNumberInRange(0.0f, TWOPI)); + pickupPos.y += 1.5f * Cos(CGeneral::GetRandomNumberInRange(0.0f, TWOPI)); + bool found; + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; + if (!found) + continue; + CVector vPedPos = GetPosition(); + vPedPos.z += 0.3f; + CVector vTestPos = vPedPos + (pickupPos - vPedPos) * (((pickupPos - vPedPos).Magnitude() + 0.4f) / (pickupPos - vPedPos).Magnitude()); + if ((vTestPos - FindPlayerCoors()).Magnitude2D() > 2.0f || i > 16) { + if (i > 16 || CPickups::TestForPickupsInBubble(pickupPos, 1.3f)) { + if (CWorld::GetIsLineOfSightClear(vTestPos, vPedPos, true, i < 16, false, i < 16, false, false)) { + if (i > 16 || !CWorld::TestSphereAgainstWorld(pickupPos, 1.2f, nil, false, true, false, false, false, false)) { + *x = pickupPos.x; + *y = pickupPos.y; + *z = pickupPos.z; + return; + } + } + } + } + } + *x = GetPosition().x; + *y = GetPosition().y; + *z = GetPosition().z + 0.4f; } \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 32557cb6..63e60991 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -209,7 +209,7 @@ enum eObjective : uint32 { OBJECTIVE_LEAVE_CAR_AND_DIE, OBJECTIVE_USE_SEAT_ATTRACTOR, OBJECTIVE_USE_ATM_ATTRACTOR, - OBJECTIVE_FLEE_CAR, // is it 41? + OBJECTIVE_FLEE_CAR, OBJ_42, OBJECTIVE_USE_STOP_ATTRACTOR, OBJECTIVE_USE_PIZZA_ATTRACTOR, @@ -550,7 +550,7 @@ public: uint32 m_duckAndCoverTimer; uint32 m_bloodyFootprintCountOrDeathTime; // Death time when bDoBloodyFootprints is false. Weird decision uint32 m_shotTime; - uint32 m_shotTimeAdd; + uint32 m_ceaseAttackTimer; uint8 m_panicCounter; bool m_deadBleeding; int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't @@ -865,6 +865,7 @@ public: void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int); void ClearWaitState(void); + void CreateDeadPedPickupCoors(float* x, float* y, float* z); bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; } CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; } diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 1c613acc..9d8d65dd 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -722,7 +722,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree } CPed* -CPopulation::AddPedInCar(CVehicle* car, bool isPassenger) +CPopulation::AddPedInCar(CVehicle* car, bool isDriver) { int defaultModel = MI_MALE01; int miamiViceIndex = 0; @@ -765,7 +765,7 @@ CPopulation::AddPedInCar(CVehicle* car, bool isPassenger) case MI_VICECHEE: // TODO(MIAMI): figure out new structure of the function preferredModel = COP_MIAMIVICE; pedType = PEDTYPE_COP; - miamiViceIndex = (isPassenger ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1); + miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1); break; case MI_TAXI: case MI_CABBIE: diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index d1f2faaa..8486d9e1 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -72,6 +72,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) bFixedColour = false; bBigWheels = false; bWaterTight = false; + bTankDetonateCars = true; SetModelIndex(id); @@ -332,7 +333,7 @@ CAutomobile::ProcessControl(void) bool playerRemote = false; switch(GetStatus()){ case STATUS_PLAYER_REMOTE: - if(CPad::GetPad(0)->WeaponJustDown()){ + if(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){ BlowUpCar(FindPlayerPed()); CRemote::TakeRemoteControlledCarFromPlayer(); } @@ -4139,7 +4140,7 @@ CAutomobile::BlowUpCarsInPath(void) { int i; - if(m_vecMoveSpeed.Magnitude() > 0.1f) + if(m_vecMoveSpeed.Magnitude() > 0.1f && bTankDetonateCars) for(i = 0; i < m_nCollisionRecords; i++) if(m_aCollisionRecords[i] && m_aCollisionRecords[i]->IsVehicle() && @@ -4601,6 +4602,18 @@ CAutomobile::SetAllTaxiLights(bool set) m_sAllTaxiLights = set; } +void +CAutomobile::TellHeliToGoToCoors(float x, float y, float z, uint8 speed) +{ + AutoPilot.m_nCarMission = MISSION_HELI_FLYTOCOORS; + AutoPilot.m_vecDestinationCoors.x = x; + AutoPilot.m_vecDestinationCoors.y = y; + AutoPilot.m_vecDestinationCoors.z = z; + AutoPilot.m_nCruiseSpeed = speed; + SetStatus(STATUS_PHYSICS); + assert(0); // TODO(MIAMI) +} + #ifdef COMPATIBLE_SAVES void CAutomobile::Save(uint8*& buf) diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 8c5c8f8e..e096465e 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -91,6 +91,7 @@ public: uint8 bWaterTight : 1; // no damage for non-player peds uint8 bNotDamagedUpsideDown : 1; uint8 bMoreResistantToDamage : 1; + uint8 bTankDetonateCars : 1; int16 field_4E0; uint16 m_hydraulicState; uint32 m_nBusDoorTimerEnd; @@ -178,6 +179,8 @@ public: void SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents = false); void SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents = false); + void TellHeliToGoToCoors(float x, float y, float z, uint8 speed); + void Fix(void); void SetComponentVisibility(RwFrame *frame, uint32 flags); void SetupModelNodes(void); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index df8c71b0..2fdc298f 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -29,6 +29,7 @@ bool CVehicle::bCheat5; bool CVehicle::bAltDodoCheat; #endif bool CVehicle::m_bDisableMouseSteering = true; +bool CVehicle::bDisableRemoteDetonation; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } @@ -1353,14 +1354,14 @@ eVehicleAppearance CVehicle::GetVehicleAppearance(void) { if (IsCar()) - return VEHICLE_CAR; + return VEHICLE_APPEARANCE_CAR; if (IsBoat()) - return VEHICLE_BOAT; + return VEHICLE_APPEARANCE_BOAT; if (IsBike()) - return VEHICLE_BIKE; + return VEHICLE_APPEARANCE_BIKE; if (IsPlane()) - return VEHICLE_PLANE; + return VEHICLE_APPEARANCE_PLANE; if (IsHeli()) - return VEHICLE_HELI; - return VEHICLE_NONE; + return VEHICLE_APPEARANCE_HELI; + return VEHICLE_APPEARANCE_NONE; } diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index c9e6bf93..fc138f45 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -112,12 +112,12 @@ enum eFlightModel enum eVehicleAppearance { - VEHICLE_NONE, - VEHICLE_CAR, - VEHICLE_BIKE, - VEHICLE_HELI, - VEHICLE_BOAT, - VEHICLE_PLANE, + VEHICLE_APPEARANCE_NONE, + VEHICLE_APPEARANCE_CAR, + VEHICLE_APPEARANCE_BIKE, + VEHICLE_APPEARANCE_HELI, + VEHICLE_APPEARANCE_BOAT, + VEHICLE_APPEARANCE_PLANE, }; // Or Weapon.h? @@ -311,6 +311,7 @@ public: static bool bAltDodoCheat; #endif static bool m_bDisableMouseSteering; + static bool bDisableRemoteDetonation; }; void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle); From d5d2f6a822ecc655437c5121550db6d929508036 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 17 May 2020 21:48:21 +0300 Subject: [PATCH 035/148] sync with upstream --- src/control/Pickups.cpp | 10 ---------- src/control/Pickups.h | 2 -- src/peds/Ped.h | 1 - 3 files changed, 13 deletions(-) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 02f2335d..01a28193 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1458,13 +1458,3 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer() FindPlayerVehicle()->m_fForceMultiplier = 1.0f; } } - -bool -CPickups::TestForPickupsInBubble(CVector pos, float radius) -{ - for (int i = 0; i < NUMPICKUPS; i++) { - if ((pos - aPickUps[i].m_vecPos).Magnitude() < radius) - return true; - } - return false; -} diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 3971002c..810f3dff 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -94,8 +94,6 @@ public: static void Load(uint8 *buf, uint32 size); static void Save(uint8 *buf, uint32 *size); - static bool TestForPickupsInBubble(CVector pos, float radius); - static CPickup aPickUps[NUMPICKUPS]; // unused diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 32c54d5d..0e80c378 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -867,7 +867,6 @@ public: void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int); void ClearWaitState(void); - void CreateDeadPedPickupCoors(float* x, float* y, float* z); bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; } CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; } From 7bd6c70318662b9fff37bac48e4f916f0fd14053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 17 May 2020 22:17:43 +0300 Subject: [PATCH 036/148] just in case --- src/control/Script.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 13f242e2..ee580cbd 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -9771,6 +9771,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) case COMMAND_HELI_GOTO_COORDS: case COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT: case COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT: + assert(0); case COMMAND_GET_DEAD_CHAR_PICKUP_COORDS: { CollectParameters(&m_nIp, 1); From 13903d7c465c2ea0e288cfcd1eb7e172e1485b17 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 22:21:29 +0200 Subject: [PATCH 037/148] radar sprites --- src/core/Radar.cpp | 233 ++++++++++++++++++++++++++++++--------------- src/core/Radar.h | 117 +++++++++++++++-------- src/core/main.cpp | 1 - 3 files changed, 232 insertions(+), 119 deletions(-) diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 94536b28..1267896a 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -21,49 +21,87 @@ sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS]; CVector2D vec2DRadarOrigin; int32 gRadarTxdIds[64]; -CSprite2d CRadar::AsukaSprite; -CSprite2d CRadar::BombSprite; -CSprite2d CRadar::CatSprite; CSprite2d CRadar::CentreSprite; -CSprite2d CRadar::CopcarSprite; -CSprite2d CRadar::DonSprite; -CSprite2d CRadar::EightSprite; -CSprite2d CRadar::ElSprite; -CSprite2d CRadar::IceSprite; -CSprite2d CRadar::JoeySprite; -CSprite2d CRadar::KenjiSprite; -CSprite2d CRadar::LizSprite; -CSprite2d CRadar::LuigiSprite; +CSprite2d CRadar::MapHereSprite; CSprite2d CRadar::NorthSprite; -CSprite2d CRadar::RaySprite; -CSprite2d CRadar::SalSprite; -CSprite2d CRadar::SaveSprite; +CSprite2d CRadar::AverySprite; +CSprite2d CRadar::BikerSprite; +CSprite2d CRadar::CortezSprite; +CSprite2d CRadar::DiazSprite; +CSprite2d CRadar::KentSprite; +CSprite2d CRadar::LawyerSprite; +CSprite2d CRadar::PhilSprite; +CSprite2d CRadar::BikersSprite; +CSprite2d CRadar::BoatyardSprite; +CSprite2d CRadar::MalibuClubSprite; +CSprite2d CRadar::CubansSprite; +CSprite2d CRadar::FilmSprite; +CSprite2d CRadar::GunSprite; +CSprite2d CRadar::HaitiansSprite; +CSprite2d CRadar::HardwareSprite; +CSprite2d CRadar::SaveHouseSprite; +CSprite2d CRadar::StripSprite; +CSprite2d CRadar::IceSprite; +CSprite2d CRadar::KCabsSprite; +CSprite2d CRadar::LovefistSprite; +CSprite2d CRadar::PrintworksSprite; +CSprite2d CRadar::PropertySprite; +CSprite2d CRadar::SunYardSprite; CSprite2d CRadar::SpraySprite; -CSprite2d CRadar::TonySprite; -CSprite2d CRadar::WeaponSprite; +CSprite2d CRadar::TShirtSprite; +CSprite2d CRadar::TommySprite; +CSprite2d CRadar::PhoneSprite; +CSprite2d CRadar::RadioWildstyleSprite; +CSprite2d CRadar::RadioFlashSprite; +CSprite2d CRadar::RadioKChatSprite; +CSprite2d CRadar::RadioFeverSprite; +CSprite2d CRadar::RadioVRockSprite; +CSprite2d CRadar::RadioVCPRSprite; +CSprite2d CRadar::RadioEspantosoSprite; +CSprite2d CRadar::RadioEmotionSprite; +CSprite2d CRadar::RadioWaveSprite; CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { nil, - &AsukaSprite, - &BombSprite, - &CatSprite, &CentreSprite, - &CopcarSprite, - &DonSprite, - &EightSprite, - &ElSprite, - &IceSprite, - &JoeySprite, - &KenjiSprite, - &LizSprite, - &LuigiSprite, + &MapHereSprite, &NorthSprite, - &RaySprite, - &SalSprite, - &SaveSprite, + &AverySprite, + &BikerSprite, + &CortezSprite, + &DiazSprite, + &KentSprite, + &LawyerSprite, + &PhilSprite, + &BikersSprite, + &BoatyardSprite, + &MalibuClubSprite, + &CubansSprite, + &FilmSprite, + &GunSprite, + &HaitiansSprite, + &HardwareSprite, + &SaveHouseSprite, + &StripSprite, + &IceSprite, + &KCabsSprite, + &LovefistSprite, + &PrintworksSprite, + &PropertySprite, + &SunYardSprite, &SpraySprite, - &TonySprite, - &WeaponSprite + &TShirtSprite, + &TommySprite, + &PhoneSprite, + &RadioWildstyleSprite, + &RadioFlashSprite, + &RadioKChatSprite, + &RadioFeverSprite, + &RadioVRockSprite, + &RadioVCPRSprite, + &RadioEspantosoSprite, + &RadioEmotionSprite, + &RadioWaveSprite }; // Why this doesn't coincide with world coordinates i don't know @@ -374,9 +412,8 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) bool CRadar::DisplayThisBlip(int32 counter) { switch (ms_RadarTrace[counter].m_eRadarSprite) { - case RADAR_SPRITE_BOMB: case RADAR_SPRITE_SPRAY: - case RADAR_SPRITE_WEAPON: + case RADAR_SPRITE_GUN: return true; default: return false; @@ -484,8 +521,8 @@ void CRadar::DrawBlips() case BLIP_CAR: case BLIP_CHAR: case BLIP_OBJECT: - if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE - || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) { + if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE + || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_GUN) { switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_CAR: @@ -543,8 +580,8 @@ void CRadar::DrawBlips() break; case BLIP_COORD: case BLIP_CONTACT_POINT: - if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE - || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) + if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE + || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_GUN) && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) { uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); @@ -594,8 +631,8 @@ void CRadar::DrawBlips() case BLIP_CAR: case BLIP_CHAR: case BLIP_OBJECT: - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE - && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) { + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN) { switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_CAR: @@ -663,8 +700,8 @@ void CRadar::DrawBlips() switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_COORD: case BLIP_CONTACT_POINT: - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE - && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) { uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); @@ -1038,26 +1075,45 @@ CRadar::LoadTextures() { CTxdStore::PushCurrentTxd(); CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud")); - AsukaSprite.SetTexture("radar_asuka"); - BombSprite.SetTexture("radar_bomb"); - CatSprite.SetTexture("radar_cat"); CentreSprite.SetTexture("radar_centre"); - CopcarSprite.SetTexture("radar_copcar"); - DonSprite.SetTexture("radar_don"); - EightSprite.SetTexture("radar_eight"); - ElSprite.SetTexture("radar_el"); - IceSprite.SetTexture("radar_ice"); - JoeySprite.SetTexture("radar_joey"); - KenjiSprite.SetTexture("radar_kenji"); - LizSprite.SetTexture("radar_liz"); - LuigiSprite.SetTexture("radar_luigi"); + MapHereSprite.SetTexture("arrow"); NorthSprite.SetTexture("radar_north"); - RaySprite.SetTexture("radar_ray"); - SalSprite.SetTexture("radar_sal"); - SaveSprite.SetTexture("radar_save"); - SpraySprite.SetTexture("radar_spray"); - TonySprite.SetTexture("radar_tony"); - WeaponSprite.SetTexture("radar_weapon"); + AverySprite.SetTexture("radar_avery"); + BikerSprite.SetTexture("radar_biker"); + CortezSprite.SetTexture("radar_cortez"); + DiazSprite.SetTexture("radar_diaz"); + KentSprite.SetTexture("radar_kent"); + LawyerSprite.SetTexture("radar_lawyer"); + PhilSprite.SetTexture("radar_phil"); + BikersSprite.SetTexture("bikers"); + BoatyardSprite.SetTexture("boatyard"); + MalibuClubSprite.SetTexture("club"); + CubansSprite.SetTexture("cubans"); + FilmSprite.SetTexture("filmstudio"); + GunSprite.SetTexture("gun"); + HaitiansSprite.SetTexture("haitians"); + HardwareSprite.SetTexture("hardware"); + SaveHouseSprite.SetTexture("radar_save"); + StripSprite.SetTexture("radar_strip"); + IceSprite.SetTexture("icecream"); + KCabsSprite.SetTexture("kcabs"); + LovefistSprite.SetTexture("lovefist"); + PrintworksSprite.SetTexture("printworks"); + PropertySprite.SetTexture("property"); + SunYardSprite.SetTexture("SunYard"); + SpraySprite.SetTexture("spray"); + TShirtSprite.SetTexture("tshirt"); + TommySprite.SetTexture("tommy"); + PhoneSprite.SetTexture("phone"); + RadioWildstyleSprite.SetTexture("RWildstyle"); + RadioFlashSprite.SetTexture("RFlash"); + RadioKChatSprite.SetTexture("RKchat"); + RadioFeverSprite.SetTexture("RFever"); + RadioVRockSprite.SetTexture("RVRock"); + RadioVCPRSprite.SetTexture("RVCPR"); + RadioEspantosoSprite.SetTexture("REspantoso"); + RadioEmotionSprite.SetTexture("REmotion"); + RadioWaveSprite.SetTexture("RWave"); CTxdStore::PopCurrentTxd(); } @@ -1239,26 +1295,45 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, void CRadar::Shutdown() { - AsukaSprite.Delete(); - BombSprite.Delete(); - CatSprite.Delete(); CentreSprite.Delete(); - CopcarSprite.Delete(); - DonSprite.Delete(); - EightSprite.Delete(); - ElSprite.Delete(); - IceSprite.Delete(); - JoeySprite.Delete(); - KenjiSprite.Delete(); - LizSprite.Delete(); - LuigiSprite.Delete(); + MapHereSprite.Delete(); NorthSprite.Delete(); - RaySprite.Delete(); - SalSprite.Delete(); - SaveSprite.Delete(); + AverySprite.Delete(); + BikerSprite.Delete(); + CortezSprite.Delete(); + DiazSprite.Delete(); + KentSprite.Delete(); + LawyerSprite.Delete(); + PhilSprite.Delete(); + BikersSprite.Delete(); + BoatyardSprite.Delete(); + MalibuClubSprite.Delete(); + CubansSprite.Delete(); + FilmSprite.Delete(); + GunSprite.Delete(); + HaitiansSprite.Delete(); + HardwareSprite.Delete(); + SaveHouseSprite.Delete(); + StripSprite.Delete(); + IceSprite.Delete(); + KCabsSprite.Delete(); + LovefistSprite.Delete(); + PrintworksSprite.Delete(); + PropertySprite.Delete(); + SunYardSprite.Delete(); SpraySprite.Delete(); - TonySprite.Delete(); - WeaponSprite.Delete(); + TShirtSprite.Delete(); + TommySprite.Delete(); + PhoneSprite.Delete(); + RadioWildstyleSprite.Delete(); + RadioFlashSprite.Delete(); + RadioKChatSprite.Delete(); + RadioFeverSprite.Delete(); + RadioVRockSprite.Delete(); + RadioVCPRSprite.Delete(); + RadioEspantosoSprite.Delete(); + RadioEmotionSprite.Delete(); + RadioWaveSprite.Delete(); RemoveRadarSections(); } diff --git a/src/core/Radar.h b/src/core/Radar.h index aa24296a..f68d290c 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -33,27 +33,47 @@ enum eRadarSprite RADAR_SPRITE_COORD_BLIP = -1, #endif RADAR_SPRITE_NONE = 0, - RADAR_SPRITE_ASUKA = 1, - RADAR_SPRITE_BOMB = 2, - RADAR_SPRITE_CAT = 3, - RADAR_SPRITE_CENTRE = 4, - RADAR_SPRITE_COPCAR = 5, - RADAR_SPRITE_DON = 6, - RADAR_SPRITE_EIGHT = 7, - RADAR_SPRITE_EL = 8, - RADAR_SPRITE_ICE = 9, - RADAR_SPRITE_JOEY = 10, - RADAR_SPRITE_KENJI = 11, - RADAR_SPRITE_LIZ = 12, - RADAR_SPRITE_LUIGI = 13, - RADAR_SPRITE_NORTH = 14, - RADAR_SPRITE_RAY = 15, - RADAR_SPRITE_SAL = 16, - RADAR_SPRITE_SAVE = 17, - RADAR_SPRITE_SPRAY = 18, - RADAR_SPRITE_TONY = 19, - RADAR_SPRITE_WEAPON = 20, - RADAR_SPRITE_COUNT = 21, + RADAR_SPRITE_CENTRE, + RADAR_SPRITE_MAP_HERE, + RADAR_SPRITE_NORTH, + RADAR_SPRITE_AVERY, + RADAR_SPRITE_BIKER, + RADAR_SPRITE_CORTEZ, + RADAR_SPRITE_DIAZ, + RADAR_SPRITE_KENT, + RADAR_SPRITE_LAWYER, + RADAR_SPRITE_PHIL, + RADAR_SPRITE_BIKERS, + RADAR_SPRITE_BOATYARD, + RADAR_SPRITE_MALIBU_CLUB, + RADAR_SPRITE_CUBANS, + RADAR_SPRITE_FILM, + RADAR_SPRITE_GUN, + RADAR_SPRITE_HAITIANS, + RADAR_SPRITE_HARDWARE, + RADAR_SPRITE_SAVE, + RADAR_SPRITE_STRIP, + RADAR_SPRITE_ICE, + RADAR_SPRITE_KCABS, + RADAR_SPRITE_LOVEFIST, + RADAR_SPRITE_PRINTWORKS, + RADAR_SPRITE_PROPERTY, + RADAR_SPRITE_SUNYARD, + RADAR_SPRITE_SPRAY, + RADAR_SPRITE_TSHIRT, + RADAR_SPRITE_TOMMY, + RADAR_SPRITE_PHONE, + RADAR_SPRITE_RADIO_WILDSTYLE, + RADAR_SPRITE_RADIO_FLASH, + RADAR_SPRITE_RADIO_KCHAT, + RADAR_SPRITE_RADIO_FEVER, + RADAR_SPRITE_RADIO_VROCK, + RADAR_SPRITE_RADIO_VCPR, + RADAR_SPRITE_RADIO_ESPANTOSO, + RADAR_SPRITE_RADIO_EMOTION, + RADAR_SPRITE_RADIO_WAVE, + + RADAR_SPRITE_COUNT }; enum @@ -91,27 +111,46 @@ class CRadar public: static float m_radarRange; static sRadarTrace ms_RadarTrace[NUMRADARBLIPS]; - static CSprite2d AsukaSprite; - static CSprite2d BombSprite; - static CSprite2d CatSprite; static CSprite2d CentreSprite; - static CSprite2d CopcarSprite; - static CSprite2d DonSprite; - static CSprite2d EightSprite; - static CSprite2d ElSprite; - static CSprite2d IceSprite; - static CSprite2d JoeySprite; - static CSprite2d KenjiSprite; - static CSprite2d LizSprite; - static CSprite2d LuigiSprite; + static CSprite2d MapHereSprite; static CSprite2d NorthSprite; - static CSprite2d RaySprite; - static CSprite2d SalSprite; - static CSprite2d SaveSprite; + static CSprite2d AverySprite; + static CSprite2d BikerSprite; + static CSprite2d CortezSprite; + static CSprite2d DiazSprite; + static CSprite2d KentSprite; + static CSprite2d LawyerSprite; + static CSprite2d PhilSprite; + static CSprite2d BikersSprite; + static CSprite2d BoatyardSprite; + static CSprite2d MalibuClubSprite; + static CSprite2d CubansSprite; + static CSprite2d FilmSprite; + static CSprite2d GunSprite; + static CSprite2d HaitiansSprite; + static CSprite2d HardwareSprite; + static CSprite2d SaveHouseSprite; + static CSprite2d StripSprite; + static CSprite2d IceSprite; + static CSprite2d KCabsSprite; + static CSprite2d LovefistSprite; + static CSprite2d PrintworksSprite; + static CSprite2d PropertySprite; + static CSprite2d SunYardSprite; static CSprite2d SpraySprite; - static CSprite2d TonySprite; - static CSprite2d WeaponSprite; - static CSprite2d *RadarSprites[21]; + static CSprite2d TShirtSprite; + static CSprite2d TommySprite; + static CSprite2d PhoneSprite; + static CSprite2d RadioWildstyleSprite; + static CSprite2d RadioFlashSprite; + static CSprite2d RadioKChatSprite; + static CSprite2d RadioFeverSprite; + static CSprite2d RadioVRockSprite; + static CSprite2d RadioVCPRSprite; + static CSprite2d RadioEspantosoSprite; + static CSprite2d RadioEmotionSprite; + static CSprite2d RadioWaveSprite; + static CSprite2d *RadarSprites[RADAR_SPRITE_COUNT]; static float cachedCos; static float cachedSin; #ifdef MENU_MAP diff --git a/src/core/main.cpp b/src/core/main.cpp index fa1f87b9..9b40b81d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -445,7 +445,6 @@ ResetLoadingScreenBar() NumberOfChunksLoaded = 0.0f; } -// TODO: compare with PS2 //--MIAMI: done void LoadingScreen(const char *str1, const char *str2, const char *splashscreen) From d4a429d986908a36618fc58b52db87d5752fde20 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 17 May 2020 22:24:23 +0200 Subject: [PATCH 038/148] little cleanup on radar --- src/core/Radar.h | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/core/Radar.h b/src/core/Radar.h index 7d07671d..ec2bacd0 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -26,27 +26,27 @@ enum eRadarSprite RADAR_SPRITE_COORD_BLIP = -1, #endif RADAR_SPRITE_NONE = 0, - RADAR_SPRITE_ASUKA = 1, - RADAR_SPRITE_BOMB = 2, - RADAR_SPRITE_CAT = 3, - RADAR_SPRITE_CENTRE = 4, - RADAR_SPRITE_COPCAR = 5, - RADAR_SPRITE_DON = 6, - RADAR_SPRITE_EIGHT = 7, - RADAR_SPRITE_EL = 8, - RADAR_SPRITE_ICE = 9, - RADAR_SPRITE_JOEY = 10, - RADAR_SPRITE_KENJI = 11, - RADAR_SPRITE_LIZ = 12, - RADAR_SPRITE_LUIGI = 13, - RADAR_SPRITE_NORTH = 14, - RADAR_SPRITE_RAY = 15, - RADAR_SPRITE_SAL = 16, - RADAR_SPRITE_SAVE = 17, - RADAR_SPRITE_SPRAY = 18, - RADAR_SPRITE_TONY = 19, - RADAR_SPRITE_WEAPON = 20, - RADAR_SPRITE_COUNT = 21, + RADAR_SPRITE_ASUKA, + RADAR_SPRITE_BOMB, + RADAR_SPRITE_CAT, + RADAR_SPRITE_CENTRE, + RADAR_SPRITE_COPCAR, + RADAR_SPRITE_DON, + RADAR_SPRITE_EIGHT, + RADAR_SPRITE_EL, + RADAR_SPRITE_ICE, + RADAR_SPRITE_JOEY, + RADAR_SPRITE_KENJI, + RADAR_SPRITE_LIZ, + RADAR_SPRITE_LUIGI, + RADAR_SPRITE_NORTH, + RADAR_SPRITE_RAY, + RADAR_SPRITE_SAL, + RADAR_SPRITE_SAVE, + RADAR_SPRITE_SPRAY, + RADAR_SPRITE_TONY, + RADAR_SPRITE_WEAPON, + RADAR_SPRITE_COUNT }; enum @@ -104,7 +104,7 @@ public: static CSprite2d SpraySprite; static CSprite2d TonySprite; static CSprite2d WeaponSprite; - static CSprite2d *RadarSprites[21]; + static CSprite2d *RadarSprites[RADAR_SPRITE_COUNT]; static float cachedCos; static float cachedSin; #ifdef MENU_MAP From 39931a5284699cf900c5556a5e5e82f3cc6ad3ac Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 17 May 2020 23:31:16 +0300 Subject: [PATCH 039/148] some more script stubs --- src/control/Script.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 6a6c5160..6dbfdc43 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8739,6 +8739,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) #ifdef USE_DEBUG_SCRIPT_LOADER CFileMgr::ChangeDir("\\data\\"); int handle = CFileMgr::OpenFile(scriptfile, "rb"); + CFileMgr::ChangeDir("\\"); #else CFileMgr::ChangeDir("\\"); int handle = CFileMgr::OpenFile("data\\main.scm", "rb"); @@ -10422,6 +10423,11 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_SET_TONIGHTS_EVENT: + { + CollectParameters(&m_nIp, 1); + debug("skipping SET_TONIGHTS_EVENT\n"); + return 0; + } case COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY: case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY: case COMMAND_FREEZE_OBJECT_POSITION: From ad8a8913d92b37aa79f467c6f24468947dfee919 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 18 May 2020 00:20:26 +0300 Subject: [PATCH 040/148] a few more stubs --- src/control/Script.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 6dbfdc43..42468f48 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -10140,7 +10140,13 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) //CStreaming::RemoveBuildingsNotInArea(ScriptParams[0]); return 0; case COMMAND_SET_CUTSCENE_ANIM_TO_LOOP: - assert(0); + { + char key[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + debug("SET_CUTSCENE_ANIM_TO_LOOP not implemented yet, skipping\n"); + return 0; + } case COMMAND_MARK_CAR_AS_CONVOY_CAR: { CollectParameters(&m_nIp, 2); @@ -10406,7 +10412,12 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_SET_PROPERTY_AS_OWNED: case COMMAND_ADD_BLOOD_RING_KILLS: case COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING: + assert(0); case COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE: + { + debug("REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE not implemented, skipping\n"); + return 0; + } case COMMAND_IS_PLAYER_TOUCHING_VEHICLE: case COMMAND_IS_CHAR_TOUCHING_VEHICLE: case COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER: @@ -10666,6 +10677,11 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION: + { + CollectParameters(&m_nIp, 4); + debug("SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION not implemented, skipping"); + return 0; + } case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA: case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE: case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA: From 96151ec0f09d25d8bffe6a1f46c9c20610469e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 18 May 2020 00:26:44 +0300 Subject: [PATCH 041/148] TransformToNode crash fix? --- src/peds/Ped.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 6514dda5..0eb85f34 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2677,6 +2677,7 @@ CPed::SetPedStats(ePedStats pedStat) m_pedStats = CPedStats::ms_apPedStats[pedStat]; } +// --MIAMI: Done void CPed::SetModelIndex(uint32 mi) { @@ -2689,12 +2690,24 @@ CPed::SetModelIndex(uint32 mi) m_animGroup = (AssocGroupId) modelInfo->m_animGroup; CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE); + // TODO(Miami): This is something inlined for sure + bool canUseMyBody = false; + if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) { + if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN) + canUseMyBody = true; + } + if (!canUseMyBody) + m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY; + // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D. (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta; #ifdef PED_SKIN if(modelInfo->GetHitColModel() == nil) modelInfo->CreateHitColModelSkinned(GetClump()); + + if (IsClumpSkinned(GetClump())) // condition isn't there in VC + UpdateRpHAnim(); #endif } From 5ab2c85e977ffa98a204fb64070ab8acbba214af Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 18 May 2020 00:34:24 +0300 Subject: [PATCH 042/148] some debug changes --- src/animation/AnimBlendAssocGroup.cpp | 2 - src/control/Script.cpp | 53 +++++++++++++++++++++++---- src/vehicles/Automobile.cpp | 2 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index ef0161db..83c1742a 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -126,8 +126,6 @@ GetModelFromName(const char *name) for(i = 0; i < MODELINFOSIZE; i++){ mi = CModelInfo::GetModelInfo(i); - if (mi && strcmp("drink", mi->GetName()) == 0 && strcmp(name, "drink01") == 0) - debug("TEST"); if(mi && mi->GetRwObject() && RwObjectGetType(mi->GetRwObject()) == rpCLUMP && strcmpIgnoringDigits(mi->GetName(), name)) return mi; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 42468f48..a1287d09 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8327,22 +8327,34 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) DMAudio.PreloadMissionAudio(str); return 0; case COMMAND_HAS_MISSION_AUDIO_LOADED: + { CollectParameters(&m_nIp, 1); - debug("HAS_MISSION_AUDIO_LOADED doesn't support parameter yet, default to TRUE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("HAS_MISSION_AUDIO_LOADED not implemented, default to TRUE\n"); + bShowed = true; + } UpdateCompareFlag(true); //UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1); return 0; + } case COMMAND_PLAY_MISSION_AUDIO: CollectParameters(&m_nIp, 1); debug("PLAY_MISSION_AUDIO doesn't support parameter yet, skipping\n"); //DMAudio.PlayLoadedMissionAudio(); return 0; case COMMAND_HAS_MISSION_AUDIO_FINISHED: + { CollectParameters(&m_nIp, 1); - debug("HAS_MISSION_AUDIO_FINISHED doesn't support parameter yet, default to TRUE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("HAS_MISSION_AUDIO_FINISHED not implemented, default to TRUE\n"); + bShowed = true; + } UpdateCompareFlag(true); //UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished()); return 0; + } case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING: { CollectParameters(&m_nIp, 3); @@ -10296,7 +10308,11 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_GET_WHEELIE_STATS: { CollectParameters(&m_nIp, 1); - debug("GET_WHEELIE_STATS not implemented, skipping\n"); + static bool bShowed = false; + if (!bShowed) { + debug("GET_WHEELIE_STATS not implemented\n"); + bShowed = true; + } for (int i = 0; i < 6; i++) ScriptParams[i] = 0; StoreParameters(&m_nIp, 6); @@ -10567,7 +10583,11 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) assert(0); case COMMAND_WAS_CUTSCENE_SKIPPED: { - debug("WAS_CUTSCENE_SKIPPED is not implemented, defaulted to TRUE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("COMMAND_WAS_CUTSCENE_SKIPPED not implemented, default to TRUE\n"); + bShowed = true; + } UpdateCompareFlag(true); return 0; } @@ -10581,7 +10601,11 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE: { CollectParameters(&m_nIp, 1); - debug("IS_CHAR_IN_ANY_POLICE_VEHICLE is not implemented, defaulted to FALSE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("IS_CHAR_IN_ANY_POLICE_VEHICLE not implemented, default to FALSE\n"); + bShowed = true; + } UpdateCompareFlag(false); return 0; } @@ -10627,7 +10651,11 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) break; case COMMAND_WANTED_STARS_ARE_FLASHING: { - debug("WANTED_STARS_ARE_FLASHING not implemented, default to FALSE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("WANTED_STARS_ARE_FLASHING not implemented, default to FALSE\n"); + bShowed = true; + } UpdateCompareFlag(false); return 0; } @@ -10653,7 +10681,11 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) char key[KEY_LENGTH_IN_SCRIPT]; CTheScripts::ReadTextLabelFromScript(&m_nIp, key); m_nIp += KEY_LENGTH_IN_SCRIPT; - debug("IS_PLAYER_IN_INFO_ZONE not implemented, default to FALSE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("IS_PLAYER_IN_INFO_ZONE not implemented, default to FALSE\n"); + bShowed = true; + } UpdateCompareFlag(false); return 0; } @@ -10705,7 +10737,12 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI: { CollectParameters(&m_nIp, 1); - debug("IS_PLAYER_IN_SHORTCUT_TAXI not implemented, default to FALSE\n"); + static bool bShowed = false; + if (!bShowed) { + debug("IS_PLAYER_IN_SHORTCUT_TAXI not implemented, default to FALSE\n"); + bShowed = true; + } + UpdateCompareFlag(false); return 0; } case COMMAND_IS_CHAR_DUCKING: diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index aff09b8c..aad31bbf 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -4620,7 +4620,7 @@ CAutomobile::TellHeliToGoToCoors(float x, float y, float z, uint8 speed) AutoPilot.m_vecDestinationCoors.z = z; AutoPilot.m_nCruiseSpeed = speed; SetStatus(STATUS_PHYSICS); - assert(0); // TODO(MIAMI) + //TODO(MIAMI) } #ifdef COMPATIBLE_SAVES From af22bb1495dca506e635bf4805d1469f95f92c69 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 18 May 2020 01:28:40 +0300 Subject: [PATCH 043/148] CText --- src/core/config.h | 2 +- src/text/Text.cpp | 252 +++++++++++++++++++++++++++++++++++++--------- src/text/Text.h | 41 +++++++- 3 files changed, 245 insertions(+), 50 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index 30f6b898..83aca235 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -194,7 +194,7 @@ enum Config { #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more #define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things -#define MORE_LANGUAGES // Add more translations to the game +//#define MORE_LANGUAGES // Add more translations to the game #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 1e58fcd1..74f53f80 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -7,27 +7,36 @@ #include "Frontend.h" #include "Messages.h" #include "Text.h" +#include "Timer.h" static wchar WideErrorString[25]; CText TheText; +//--MIAMI: DONE CText::CText(void) { encoding = 'e'; + bHasMissionTextOffsets = false; + bIsMissionTextLoaded = false; + memset(szMissionTableName, 0, sizeof(szMissionTableName)); memset(WideErrorString, 0, sizeof(WideErrorString)); } +//--MIAMI: DONE void CText::Load(void) { - uint8 *filedata; - char filename[32], type[4]; - int length; - int offset, sectlen; + char filename[32]; + uint32 offset; + int file; + bool tkey_loaded = false, tdat_loaded = false; + ChunkHeader m_ChunkHeader; + + bIsMissionTextLoaded = false; + bHasMissionTextOffsets = false; Unload(); - filedata = new uint8[0x40000]; CFileMgr::SetDir("TEXT"); switch(CMenuManager::m_PrefsLanguage){ @@ -59,49 +68,64 @@ CText::Load(void) #endif } - length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb"); - CFileMgr::SetDir(""); + file = CFileMgr::OpenFile(filename, "rb"); offset = 0; - while(offset < length){ - type[0] = filedata[offset++]; - type[1] = filedata[offset++]; - type[2] = filedata[offset++]; - type[3] = filedata[offset++]; - sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 | - (int)filedata[offset+1]<<8 | (int)filedata[offset+0]; - offset += 4; - if(sectlen != 0){ - if(strncmp(type, "TKEY", 4) == 0) - keyArray.Load(sectlen, filedata, &offset); - else if(strncmp(type, "TDAT", 4) == 0) - data.Load(sectlen, filedata, &offset); - else - offset += sectlen; + while (!tkey_loaded || !tdat_loaded) { + ReadChunkHeader(&m_ChunkHeader, file, &offset); + if (m_ChunkHeader.size != 0) { + if (strncmp(m_ChunkHeader.magic, "TABL", 4) == 0) { + MissionTextOffsets.Load(m_ChunkHeader.size, file, &offset, 0x58000); + bHasMissionTextOffsets = true; + } else if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) { + this->keyArray.Load(m_ChunkHeader.size, file, &offset); + tkey_loaded = true; + } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) { + this->data.Load(m_ChunkHeader.size, file, &offset); + tdat_loaded = true; + } else { + CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR); + offset += m_ChunkHeader.size; + } } } keyArray.Update(data.chars); - - delete[] filedata; + CFileMgr::CloseFile(file); + CFileMgr::SetDir(""); } +//--MIAMI: DONE void CText::Unload(void) { CMessages::ClearAllMessagesDisplayedByGame(); - data.Unload(); keyArray.Unload(); + data.Unload(); + mission_keyArray.Unload(); + mission_data.Unload(); + bIsMissionTextLoaded = false; + memset(szMissionTableName, 0, sizeof(szMissionTableName)); } +//--MIAMI: DONE wchar* CText::Get(const char *key) { + uint8 result = false; #ifdef FIX_BUGS - return keyArray.Search(key, data.chars); + wchar *outstr = keyArray.Search(key, data.chars, &result); #else - return keyArray.Search(key); + wchar *outstr = keyArray.Search(key, &result); #endif + + if (!result && bHasMissionTextOffsets && bIsMissionTextLoaded) +#ifdef FIX_BUGS + outstr = mission_keyArray.Search(key, mission_data.chars, &result); +#else + outstr = mission_keyArray.Search(key, &result); +#endif + return outstr; } wchar UpperCaseTable[128] = { @@ -134,6 +158,7 @@ wchar FrenchUpperCaseTable[128] = { 253, 254, 255 }; +//--MIAMI: TODO (check tables) wchar CText::GetUpperCase(wchar c) { @@ -165,6 +190,7 @@ CText::GetUpperCase(wchar c) return c; } +//--MIAMI: DONE void CText::UpperCase(wchar *s) { @@ -174,21 +200,131 @@ CText::UpperCase(wchar *s) } } - +//--MIAMI: DONE void -CKeyArray::Load(uint32 length, uint8 *data, int *offset) +CText::GetNameOfLoadedMissionText(char *outName) { - uint32 i; - uint8 *rawbytes; + strcpy(outName, szMissionTableName); +} + +//--MIAMI: DONE +void +CText::ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *offset) +{ + // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded + CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader)); + *offset += sizeof(ChunkHeader); +} + +//--MIAMI: DONE +void +CText::LoadMissionText(char *MissionTableName) +{ + char filename[32]; + + mission_keyArray.Unload(); + mission_data.Unload(); + + bool search_result = false; + int missionTableId = 0; + + for (missionTableId = 0; missionTableId < MissionTextOffsets.size; missionTableId++) { + if (strncmp(MissionTextOffsets.data[missionTableId].szMissionName, MissionTableName, strlen(MissionTextOffsets.data[missionTableId].szMissionName)) == 0) { + search_result = true; + break; + } + } + + if (!search_result) { + printf("CText::LoadMissionText - couldn't find %s", MissionTableName); + return; + } + + CFileMgr::SetDir("TEXT"); + switch (CMenuManager::m_PrefsLanguage) { + case LANGUAGE_AMERICAN: + sprintf(filename, "AMERICAN.GXT"); + break; + case LANGUAGE_FRENCH: + sprintf(filename, "FRENCH.GXT"); + break; + case LANGUAGE_GERMAN: + sprintf(filename, "GERMAN.GXT"); + break; + case LANGUAGE_ITALIAN: + sprintf(filename, "ITALIAN.GXT"); + break; + case LANGUAGE_SPANISH: + sprintf(filename, "SPANISH.GXT"); + break; +#ifdef MORE_LANGUAGES + case LANGUAGE_POLISH: + sprintf(filename, "POLISH.GXT"); + break; + case LANGUAGE_RUSSIAN: + sprintf(filename, "RUSSIAN.GXT"); + break; + case LANGUAGE_JAPANESE: + sprintf(filename, "JAPANESE.GXT"); + break; +#endif + } + CTimer::Suspend(); + int file = CFileMgr::OpenFile(filename, "rb"); + CFileMgr::Seek(file, MissionTextOffsets.data[missionTableId].offset, SEEK_SET); + + char TableCheck[8]; + CFileMgr::Read(file, TableCheck, 8); + if (strncmp(TableCheck, MissionTableName, 8) != 0) + printf("CText::LoadMissionText - expected to find %s in the text file", MissionTableName); + + bool tkey_loaded = false, tdat_loaded = false; + ChunkHeader m_ChunkHeader; + while (!tkey_loaded || !tdat_loaded) { + uint32 bytes_read = 0; + ReadChunkHeader(&m_ChunkHeader, file, &bytes_read); + if (m_ChunkHeader.size != 0) { + if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) { + uint32 bytes_read = 0; + mission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read); + tkey_loaded = true; + } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) { + uint32 bytes_read = 0; + mission_data.Load(m_ChunkHeader.size, file, &bytes_read); + tdat_loaded = true; + } else + CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR); + } + } + + mission_keyArray.Update(mission_data.chars); + CFileMgr::CloseFile(file); + CTimer::Resume(); + CFileMgr::SetDir(""); + strcpy(szMissionTableName, MissionTableName); + bIsMissionTextLoaded = true; +} + + +//--MIAMI: DONE +void +CKeyArray::Load(uint32 length, int file, uint32 *offset) +{ + char *rawbytes; numEntries = length / sizeof(CKeyEntry); entries = new CKeyEntry[numEntries]; - rawbytes = (uint8*)entries; + rawbytes = (char*)entries; - for(i = 0; i < length; i++) - rawbytes[i] = data[(*offset)++]; +#if DUMB + for (uint32 i = 0; i < length; i++) + CFileMgr::Read(file, &rawbytes[i], 1); +#else + CFileMgr::Read(file, rawbytes, length); +#endif } +//--MIAMI: DONE void CKeyArray::Unload(void) { @@ -197,6 +333,7 @@ CKeyArray::Unload(void) numEntries = 0; } +//--MIAMI: DONE void CKeyArray::Update(wchar *chars) { @@ -207,6 +344,7 @@ CKeyArray::Update(wchar *chars) #endif } +//--MIAMI: DONE CKeyEntry* CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high) { @@ -227,11 +365,12 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi return nil; } +//--MIAMI: DONE wchar* #ifdef FIX_BUGS -CKeyArray::Search(const char *key, wchar *data) +CKeyArray::Search(const char *key, wchar *data, uint8 *result) #else -CKeyArray::Search(const char *key) +CKeyArray::Search(const char *key, uint8 *result) #endif { CKeyEntry *found; @@ -240,34 +379,47 @@ CKeyArray::Search(const char *key) #ifdef FIX_BUGS found = BinarySearch(key, entries, 0, numEntries-1); - if(found) + if (found) { + *result = true; return (wchar*)((uint8*)data + found->valueOffset); + } #else found = BinarySearch(key, entries, 0, numEntries-1); - if(found) + if (found) { + *result = true; return found->value; + } #endif + *result = false; +#ifdef MASTER + sprintf(errstr, "%"); +#else sprintf(errstr, "%s missing", key); +#endif // MASTER for(i = 0; i < 25; i++) WideErrorString[i] = errstr[i]; return WideErrorString; } - +//--MIAMI: DONE void -CData::Load(uint32 length, uint8 *data, int *offset) +CData::Load(uint32 length, int file, uint32 *offset) { - uint32 i; - uint8 *rawbytes; + char *rawbytes; numChars = length / sizeof(wchar); chars = new wchar[numChars]; - rawbytes = (uint8*)chars; + rawbytes = (char*)chars; - for(i = 0; i < length; i++) - rawbytes[i] = data[(*offset)++]; +#if DUMB + for(uint32 i = 0; i < length; i++) + CFileMgr::Read(file, &rawbytes[i], 1); +#else + CFileMgr::Read(file, rawbytes, length); +#endif } +//--MIAMI: DONE void CData::Unload(void) { @@ -276,6 +428,16 @@ CData::Unload(void) numChars = 0; } +//--MIAMI: DONE +void +CMissionTextOffsets::Load(uint32 table_size, int file, uint32 *offset, int) +{ + // not exact VC code but smaller and better :P + size = table_size / sizeof(CMissionTextOffsets::Entry); + CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size); + *offset += sizeof(CMissionTextOffsets::Entry) * size; +} + void AsciiToUnicode(const char *src, wchar *dst) { diff --git a/src/text/Text.h b/src/text/Text.h index 18a904bc..dcffccbf 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -28,14 +28,14 @@ public: CKeyArray(void) : entries(nil), numEntries(0) {} ~CKeyArray(void) { Unload(); } - void Load(uint32 length, uint8 *data, int *offset); + void Load(uint32 length, int file, uint32 *offset); void Unload(void); void Update(wchar *chars); CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high); #ifdef FIX_BUGS - wchar *Search(const char *key, wchar *data); + wchar *Search(const char *key, wchar *data, uint8 *result); #else - wchar *Search(const char *key); + wchar *Search(const char *key, uint8* result); #endif }; @@ -47,15 +47,45 @@ public: CData(void) : chars(nil), numChars(0) {} ~CData(void) { Unload(); } - void Load(uint32 length, uint8 *data, int *offset); + void Load(uint32 length, int file, uint32 *offset); void Unload(void); }; +class CMissionTextOffsets +{ +public: + struct Entry + { + char szMissionName[8]; + uint32 offset; + }; + + enum {MAX_MISSION_TEXTS = 90}; // beware that LCS has more + + Entry data[MAX_MISSION_TEXTS]; + uint16 size; + + CMissionTextOffsets(void) : size(0) {} + void Load(uint32 table_size, int file, uint32* bytes_read, int); +}; + +struct ChunkHeader +{ + char magic[4]; + int size; +}; + class CText { CKeyArray keyArray; CData data; + CKeyArray mission_keyArray; + CData mission_data; char encoding; + bool bHasMissionTextOffsets; + bool bIsMissionTextLoaded; + char szMissionTableName[8]; + CMissionTextOffsets MissionTextOffsets; public: CText(void); void Load(void); @@ -63,6 +93,9 @@ public: wchar *Get(const char *key); wchar GetUpperCase(wchar c); void UpperCase(wchar *s); + void GetNameOfLoadedMissionText(char *outName); + void ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *bytes_read); + void LoadMissionText(char *MissionTableName); }; extern CText TheText; From 9b09aa3384213dab45db023d95487096e64ad5c6 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 18 May 2020 16:40:30 +0200 Subject: [PATCH 044/148] fixes for braking and cloud rotation at high fps --- src/render/Clouds.cpp | 5 +++++ src/vehicles/Vehicle.cpp | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 9c0fde0f..60450213 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -69,8 +69,13 @@ void CClouds::Update(void) { float s = Sin(TheCamera.Orientation - 0.85f); +#ifdef FIX_BUGS + CloudRotation += CWeather::Wind*s*0.0025f*CTimer::GetTimeStepFix(); + IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f*CTimer::GetTimeStepFix()) * 60.0f; +#else CloudRotation += CWeather::Wind*s*0.0025f; IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f) * 60.0f; +#endif } void diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 5dc7bc72..f85f0d50 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -514,6 +514,9 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon brake = 0.2f * mod_HandlingManager.field_4 / m_fMass; else brake = mod_HandlingManager.field_4 / m_fMass; +#ifdef FIX_BUGS + brake *= CTimer::GetTimeStepFix(); +#endif } } From 68f1c03a85833a0efedf5df52160bca02786ccac Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 18 May 2020 16:43:40 +0200 Subject: [PATCH 045/148] fixes for braking and cloud rotation at high fps --- src/render/Clouds.cpp | 7 +++++++ src/vehicles/Vehicle.cpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 9cd3b5d2..05210c77 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -64,6 +64,13 @@ CClouds::Update(void) float s = Sin(TheCamera.Orientation - 0.85f); CloudRotation += CWeather::Wind*s*0.001f; IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f; +#ifdef FIX_BUGS + CloudRotation += CWeather::Wind*s*0.001f*CTimer::GetTimeStepFix(); + IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f*CTimer::GetTimeStepFix()) * 60.0f; +#else + CloudRotation += CWeather::Wind*s*0.001f; + IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f; +#endif } void diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 55f0dd1c..2b0132b2 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -521,6 +521,9 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon brake = 0.2f * mod_HandlingManager.field_4 / m_fMass; else brake = mod_HandlingManager.field_4 / m_fMass; +#ifdef FIX_BUGS + brake *= CTimer::GetTimeStepFix(); +#endif } } From 2588e69849c3a0e4d8c234a3a0e425fceb973d97 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 18 May 2020 16:55:38 +0200 Subject: [PATCH 046/148] some less certainly fps fixes --- src/vehicles/Automobile.cpp | 6 ++++++ src/vehicles/Vehicle.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 83fe44d5..2212ddff 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -871,8 +871,14 @@ CAutomobile::ProcessControl(void) CVector wheelFwd = GetForward(); CVector wheelRight = GetRight(); +#ifdef FIX_BUGS + // Not sure if this is needed, but brake usually has timestep as a factor + if(bIsHandbrakeOn) + brake = 20000.0f * CTimer::GetTimeStepFix(); +#else if(bIsHandbrakeOn) brake = 20000.0f; +#endif if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){ if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index f85f0d50..6646f7f3 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -487,6 +487,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(contactSpeedRight != 0.0f){ // exert opposing force right = -contactSpeedRight/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedRight is independent of framerate but right has timestep as a factor + // so we probably have to fix this + right *= CTimer::GetTimeStepFix(); +#endif if(wheelStatus == WHEEL_STATUS_BURST){ float fwdspeed = Min(contactSpeedFwd, 0.3f); @@ -507,6 +512,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } }else if(contactSpeedFwd != 0.0f){ fwd = -contactSpeedFwd/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedFwd is independent of framerate but fwd has timestep as a factor + // so we probably have to fix this + fwd *= CTimer::GetTimeStepFix(); +#endif if(!bBraking){ if(m_fGasPedal < 0.01f){ From e891cf858f7d2a7c5bbb4ff46400508ffbe3c8b9 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 18 May 2020 20:17:24 +0300 Subject: [PATCH 047/148] Remove MAX_VOLUME dups --- src/audio/AudioLogic.cpp | 133 ++++++++++++++++++------------------- src/audio/AudioManager.cpp | 5 +- src/audio/MusicManager.cpp | 6 +- src/audio/PoliceRadio.cpp | 3 +- 4 files changed, 71 insertions(+), 76 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 2a6581ee..6f1a3432 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -41,7 +41,6 @@ const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); const int policeChannel = channels + 1; const int allChannels = channels + 2; -const int maxVolume = 127; uint32 gPornNextTime; uint32 gSawMillNextTime; @@ -207,8 +206,8 @@ cAudioManager::ProcessSpecial() if (m_nUserPause) { if (!m_nPreviousUserPause) { MusicManager.ChangeMusicMode(MUSICMODE_FRONTEND); - SampleManager.SetEffectsFadeVolume(maxVolume); - SampleManager.SetMusicFadeVolume(maxVolume); + SampleManager.SetEffectsFadeVolume(MAX_VOLUME); + SampleManager.SetMusicFadeVolume(MAX_VOLUME); } } else { if (m_nPreviousUserPause) { @@ -2566,7 +2565,7 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params) float dist; float baseDist; int32 emittingVol; - static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, maxVolume}, {60.f, 30.f, maxVolume}}; + static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, MAX_VOLUME}, {60.f, 30.f, MAX_VOLUME}}; if (gHeliSfxRanges[0].m_fMaxDistance * gHeliSfxRanges[0].m_fMaxDistance <= params->m_fDistance) return false; @@ -2691,15 +2690,15 @@ cAudioManager::ProcessJumboAccel(CPlane *plane) modificator = (plane->m_fSpeed - 0.10334f) * 1.676f; if (modificator > 1.0f) modificator = 1.0f; - if (SetupJumboRumbleSound(maxVolume * modificator) && SetupJumboTaxiSound((1.0f - modificator) * 75.f)) { + if (SetupJumboRumbleSound(MAX_VOLUME * modificator) && SetupJumboTaxiSound((1.0f - modificator) * 75.f)) { if (modificator < 0.2f) { whineSoundFreq = modificator * 5.f * 14600.0f + 29500; - vol = modificator * 5.f * maxVolume; + vol = modificator * 5.f * MAX_VOLUME; engineFreq = modificator * 5.f * 6050.f + 16000; } else { whineSoundFreq = 44100; engineFreq = 22050; - vol = maxVolume; + vol = MAX_VOLUME; } SetupJumboEngineSound(vol, engineFreq); SetupJumboWhineSound(18, whineSoundFreq); @@ -2712,8 +2711,8 @@ cAudioManager::ProcessJumboTakeOff(CPlane *plane) { const float modificator = (PlanePathPosition[plane->m_nPlaneId] - TakeOffPoint) / 300.f; - if (SetupJumboFlySound((107.f * modificator) + 20) && SetupJumboRumbleSound(maxVolume * (1.f - modificator))) { - if (SetupJumboEngineSound(maxVolume, 22050)) + if (SetupJumboFlySound((107.f * modificator) + 20) && SetupJumboRumbleSound(MAX_VOLUME * (1.f - modificator))) { + if (SetupJumboEngineSound(MAX_VOLUME, 22050)) SetupJumboWhineSound(18.f * (1.f - modificator), 44100); } } @@ -2721,7 +2720,7 @@ cAudioManager::ProcessJumboTakeOff(CPlane *plane) void cAudioManager::ProcessJumboFlying() { - if (SetupJumboFlySound(maxVolume)) + if (SetupJumboFlySound(MAX_VOLUME)) SetupJumboEngineSound(63, 22050); } @@ -2731,7 +2730,7 @@ cAudioManager::ProcessJumboLanding(CPlane *plane) const float modificator = (LandingPoint - PlanePathPosition[plane->m_nPlaneId]) / 350.f; if (SetupJumboFlySound(107.f * modificator + 20)) { if (SetupJumboTaxiSound(75.f * (1.f - modificator))) { - SetupJumboEngineSound(maxVolume, 22050); + SetupJumboEngineSound(MAX_VOLUME, 22050); SetupJumboWhineSound(18.f * (1.f - modificator), 14600.f * modificator + 29500); } } @@ -2742,7 +2741,7 @@ cAudioManager::ProcessJumboDecel(CPlane *plane) { if (SetupJumboFlySound(20) && SetupJumboTaxiSound(75)) { const float modificator = Min(1.f, (plane->m_fSpeed - 0.10334f) * 1.676f); - SetupJumboEngineSound(maxVolume * modificator, 6050.f * modificator + 16000); + SetupJumboEngineSound(MAX_VOLUME * modificator, 6050.f * modificator + 16000); SetupJumboWhineSound(18, 29500); } } @@ -2906,7 +2905,7 @@ cAudioManager::SetupJumboRumbleSound(uint8 emittingVol) m_sQueueSample.m_nCounter = 6; m_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE; m_sQueueSample.m_nFrequency += 200; - m_sQueueSample.m_nOffset = maxVolume; + m_sQueueSample.m_nOffset = MAX_VOLUME; AddSampleToRequestedQueue(); } return true; @@ -3795,11 +3794,11 @@ cAudioManager::SetupPedComments(cPedParams *params, uint32 sound) case SOUND_AMMUNATION_WELCOME_1: case SOUND_AMMUNATION_WELCOME_2: case SOUND_AMMUNATION_WELCOME_3: - emittingVol = maxVolume; + emittingVol = MAX_VOLUME; break; default: if (CWorld::GetIsLineOfSightClear(TheCamera.GetPosition(), m_sQueueSample.m_vecPos, true, false, false, false, false, false)) - emittingVol = maxVolume; + emittingVol = MAX_VOLUME; else emittingVol = 31; break; @@ -6265,7 +6264,7 @@ cPedComments::Process() AudioManager.m_sQueueSample.m_nLoopCount = 1; AudioManager.m_sQueueSample.m_nLoopStart = 0; AudioManager.m_sQueueSample.m_nLoopEnd = -1; - AudioManager.m_sQueueSample.m_nEmittingVolume = maxVolume; + AudioManager.m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; AudioManager.m_sQueueSample.m_fSpeedMultiplier = 3.0f; switch (sampleIndex) { case SFX_POLICE_HELI_1: @@ -6376,7 +6375,7 @@ cAudioManager::ProcessExplosions(int32 explosion) distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { m_sQueueSample.m_nCounter = i; m_sQueueSample.m_fSpeedMultiplier = 2.0f; @@ -6384,7 +6383,7 @@ cAudioManager::ProcessExplosions(int32 explosion) m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; m_sQueueSample.m_nLoopStart = 0; m_sQueueSample.m_nLoopEnd = -1; m_sQueueSample.m_bReverbFlag = true; @@ -6580,7 +6579,7 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_TRAIN_STATION_ANNOUNCE; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_STATION_ANNOUNCE); m_sQueueSample.m_nReleasingVolumeModificator = 0; m_sQueueSample.m_fSpeedMultiplier = 2.0f; @@ -6777,7 +6776,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6787,7 +6786,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6797,7 +6796,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_2); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6807,7 +6806,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_2); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6817,7 +6816,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_3); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6827,7 +6826,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_3); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6837,7 +6836,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_4); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6847,7 +6846,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_4); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6857,7 +6856,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_5); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6867,7 +6866,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_5); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6877,7 +6876,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_6); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6887,7 +6886,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_6); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6897,7 +6896,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_7); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6907,7 +6906,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_7); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6917,7 +6916,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_8); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6927,7 +6926,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_8); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6937,7 +6936,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_9); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6947,7 +6946,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_9); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6957,7 +6956,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_10); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6967,7 +6966,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_10); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6977,7 +6976,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_11); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6987,7 +6986,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_11); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -6997,7 +6996,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_12); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7007,7 +7006,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_12); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7017,7 +7016,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_RAGGA); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7027,7 +7026,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_RAGGA); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7037,7 +7036,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_1); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7047,7 +7046,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_1); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7057,7 +7056,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_2); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7067,7 +7066,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_STRIP_CLUB_2); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7209,7 +7208,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_PIANO_BAR_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PIANO_BAR_1); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7219,7 +7218,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CLUB_1); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7259,7 +7258,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BALL_1); m_sQueueSample.m_nReleasingVolumeModificator = 2; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7269,7 +7268,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BALL_1); m_sQueueSample.m_nReleasingVolumeModificator = 2; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7279,7 +7278,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_INDUSTRIAL); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7289,7 +7288,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_INDUSTRIAL); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7304,7 +7303,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7315,7 +7314,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7325,7 +7324,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 30.0f; m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_SUBURBAN); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7335,7 +7334,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSoundIntensity = 80.0f; m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - emittingVolume = maxVolume; + emittingVolume = MAX_VOLUME; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAVE_SUBURBAN); m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_nReleasingVolumeDivider = 3; @@ -7429,7 +7428,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); if (sound != SCRIPT_SOUND_MISTY_SEX_S && sound != SCRIPT_SOUND_MISTY_SEX_L) { - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nCounter = 0; @@ -7438,7 +7437,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) m_sQueueSample.m_bReleasingSoundFlag = false; m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_bReverbFlag = true; @@ -8155,7 +8154,7 @@ cAudioManager::ProcessFrontEnd() if (stereo) { ++m_sQueueSample.m_nSampleIndex; m_sQueueSample.m_nCounter = counter++; - m_sQueueSample.m_nOffset = maxVolume - m_sQueueSample.m_nOffset; + m_sQueueSample.m_nOffset = MAX_VOLUME - m_sQueueSample.m_nOffset; AddSampleToRequestedQueue(); } } @@ -8224,7 +8223,7 @@ cAudioManager::ProcessProjectiles() if (CProjectileInfo::GetProjectileInfo(i)->m_bInUse) { switch (CProjectileInfo::GetProjectileInfo(i)->m_eWeaponType) { case WEAPONTYPE_ROCKETLAUNCHER: - emittingVol = maxVolume; + emittingVol = MAX_VOLUME; m_sQueueSample.m_fSoundIntensity = rocketLauncherIntensity; m_sQueueSample.m_nSampleIndex = SFX_ROCKET_FLY; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -8498,7 +8497,7 @@ void cAudioManager::ProcessBridgeMotor() { if (m_sQueueSample.m_fDistance < bridgeIntensity) { - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, bridgeIntensity, m_sQueueSample.m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, bridgeIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { m_sQueueSample.m_nCounter = 1; m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; // todo check sfx name @@ -8507,7 +8506,7 @@ cAudioManager::ProcessBridgeMotor() m_sQueueSample.m_nReleasingVolumeModificator = 1; m_sQueueSample.m_nFrequency = 5500; m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_fSpeedMultiplier = 2.0f; @@ -8540,7 +8539,7 @@ cAudioManager::ProcessBridgeOneShots() } } if (m_sQueueSample.m_fDistance < bridgeIntensity) { - m_sQueueSample.m_nVolume = ComputeVolume(maxVolume, bridgeIntensity, m_sQueueSample.m_fDistance); + m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, bridgeIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { m_sQueueSample.m_nCounter = 2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -8548,7 +8547,7 @@ cAudioManager::ProcessBridgeOneShots() m_sQueueSample.m_nReleasingVolumeModificator = 1; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_nEmittingVolume = maxVolume; + m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; m_sQueueSample.m_nLoopStart = 0; m_sQueueSample.m_nLoopEnd = -1; m_sQueueSample.m_fSpeedMultiplier = 2.0f; diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 458341b9..bd1ac84b 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -16,7 +16,6 @@ cAudioManager AudioManager; const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); const int policeChannel = channels + 1; const int allChannels = channels + 2; -const int maxVolume = 127; cAudioManager::cAudioManager() { @@ -548,7 +547,7 @@ cAudioManager::AddSampleToRequestedQueue() bool bReflections; if (m_sQueueSample.m_nSampleIndex < TOTAL_AUDIO_SAMPLES) { - calculatedVolume = m_sQueueSample.m_nReleasingVolumeModificator * (maxVolume - m_sQueueSample.m_nVolume); + calculatedVolume = m_sQueueSample.m_nReleasingVolumeModificator * (MAX_VOLUME - m_sQueueSample.m_nVolume); sampleIndex = m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; if (sampleIndex >= m_nActiveSamples) { sampleIndex = m_abSampleQueueIndexTable[m_nActiveSampleQueue][m_nActiveSamples - 1]; @@ -942,7 +941,7 @@ void cAudioManager::GenerateIntegerRandomNumberTable() { for (int32 i = 0; i < ARRAY_SIZE(m_anRandomTable); i++) { - m_anRandomTable[i] = rand(); + m_anRandomTable[i] = myrand(); } } diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index fd02691e..8e8e9c24 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -21,8 +21,6 @@ int32 gNumRetunePresses; int32 gRetuneCounter; bool bHasStarted; -const int maxVolume = 127; - cMusicManager::cMusicManager() { m_bIsInitialised = false; @@ -375,7 +373,7 @@ cMusicManager::Service() if (!m_bIsInitialised || m_bDisabled) return; if (m_nMusicMode == MUSICMODE_CUTSCENE) { - SampleManager.SetStreamedVolumeAndPan(maxVolume, 63, 1, 0); + SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 0); return; } @@ -676,7 +674,7 @@ cMusicManager::PreloadCutSceneMusic(uint8 track) while (SampleManager.IsStreamPlaying(0)) SampleManager.StopStreamedFile(0); SampleManager.PreloadStreamedFile(track, 0); - SampleManager.SetStreamedVolumeAndPan(maxVolume, 63, 1, 0); + SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 0); m_nCurrentStreamedSound = track; } } diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp index ec02368e..af346479 100644 --- a/src/audio/PoliceRadio.cpp +++ b/src/audio/PoliceRadio.cpp @@ -14,7 +14,6 @@ #include "Zones.h" #include "sampman.h" -const int maxVolume = 127; const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); const int policeChannel = channels + 1; @@ -225,7 +224,7 @@ cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel) } } else if (!SampleManager.GetChannelUsedFlag(policeChannel)) { SampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1); - SampleManager.SetStreamedVolumeAndPan(maxVolume, 63, 1, 1); + SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 1); SampleManager.StartPreloadedStreamedFile(1); g_nMissionAudioPlayingStatus = 1; bMissionAudioPhysicalPlayingStatus = 0; From b55ba13586ad297718a4cf84ceec7e2de88a76f5 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Tue, 12 May 2020 15:42:53 +0200 Subject: [PATCH 048/148] Add basic linux build on travis --- .travis.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..51ef58eb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: cpp +os: linux +dist: focal +matrix: + include: + - env: TARGET=release_linux-amd64-librw_gl3_glfw-oal + - env: TARGET=debug_linux-amd64-librw_gl3_glfw-oal +script: + - sudo apt-get update + - sudo apt-get -y install linux-libc-dev libopenal-dev libglew-dev libglfw3-dev libsndfile1-dev libmpg123-dev gcc-8-multilib g++-8-multilib + - mkdir -p "$TRAVIS_BUILD_DIR/build" + - cd "$TRAVIS_BUILD_DIR" + - ./premake5Linux --with-librw gmake2 + - cd build + - CC=gcc-8 CXX=g++-8 make config=$TARGET -j4 verbose=1 From 6bf79120dcd535dc6a63c4d0da858444facb0d8d Mon Sep 17 00:00:00 2001 From: shfil Date: Mon, 18 May 2020 21:08:01 +0200 Subject: [PATCH 049/148] Fix string assignment (aldlist.cpp) --- src/audio/oal/aldlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/oal/aldlist.cpp b/src/audio/oal/aldlist.cpp index 458b7c80..7401e036 100644 --- a/src/audio/oal/aldlist.cpp +++ b/src/audio/oal/aldlist.cpp @@ -73,7 +73,7 @@ ALDeviceList::ALDeviceList() if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) { memset(&ALDeviceInfo, 0, sizeof(ALDEVICEINFO)); ALDeviceInfo.bSelected = true; - ALDeviceInfo.strDeviceName.assign(actualDeviceName, strlen(actualDeviceName)); + ALDeviceInfo.strDeviceName = actualDeviceName; alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion); alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion); From 746f2aa47903d6aaeaa8046d8397458617460876 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 18 May 2020 22:43:06 +0300 Subject: [PATCH 050/148] script FPS fix --- src/control/Script.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 357436c6..844b1858 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -6862,7 +6862,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) float heading = LimitAngleOnCircle( RADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y))); float headingTarget = *(float*)&ScriptParams[1]; +#ifdef FIX_BUGS + float rotateBy = *(float*)&ScriptParams[2] * CTimer::GetTimeStepFix(); +#else float rotateBy = *(float*)&ScriptParams[2]; +#endif if (headingTarget == heading) { // using direct comparasion here is fine UpdateCompareFlag(true); return 0; @@ -6911,7 +6915,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) assert(pObject); CVector pos = pObject->GetPosition(); CVector posTarget = *(CVector*)&ScriptParams[1]; +#ifdef FIX_BUGS + CVector slideBy = *(CVector*)&ScriptParams[4] * CTimer::GetTimeStepFix(); +#else CVector slideBy = *(CVector*)&ScriptParams[4]; +#endif if (posTarget == pos) { // using direct comparasion here is fine UpdateCompareFlag(true); return 0; From a8f4f74a7619e847cf98605767934a21d2373c23 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 18 May 2020 22:25:06 +0200 Subject: [PATCH 051/148] only one sunbathe anim group --- src/animation/AnimManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index e37c0f8e..16207f54 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -926,7 +926,7 @@ const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_ { "grenade", "grenade", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs }, { "flame", "flame", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs }, { "medic", "medic", MI_COP, awc(aMedicAnimations), aMedicAnimDescs }, - { "sunbathe", "sunbathe", MI_COP, awc(aSunbatheAnimations), aSunbatheAnimDescs }, + { "sunbathe", "sunbathe", MI_COP, 1, aSunbatheAnimations, aSunbatheAnimDescs }, // NB: not using awc here! { "playidles", "playidles", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs }, { "riot", "riot", MI_COP, awc(aRiotAnimations), aRiotAnimDescs }, { "strip", "strip", MI_COP, awc(aStripAnimations), aStripAnimDescs }, From abd230dcddd7e878f8a6b69193eb0cb74959c7b9 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 18 May 2020 16:55:38 +0200 Subject: [PATCH 052/148] some less certainly fps fixes --- src/vehicles/Automobile.cpp | 6 ++++++ src/vehicles/Vehicle.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index aad31bbf..e0ee0296 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -865,8 +865,14 @@ CAutomobile::ProcessControl(void) CVector wheelFwd = GetForward(); CVector wheelRight = GetRight(); +#ifdef FIX_BUGS + // Not sure if this is needed, but brake usually has timestep as a factor + if(bIsHandbrakeOn) + brake = 20000.0f * CTimer::GetTimeStepFix(); +#else if(bIsHandbrakeOn) brake = 20000.0f; +#endif if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){ if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 2b0132b2..4b36b3d3 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -494,6 +494,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(contactSpeedRight != 0.0f){ // exert opposing force right = -contactSpeedRight/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedRight is independent of framerate but right has timestep as a factor + // so we probably have to fix this + right *= CTimer::GetTimeStepFix(); +#endif if(wheelStatus == WHEEL_STATUS_BURST){ float fwdspeed = Min(contactSpeedFwd, 0.3f); @@ -514,6 +519,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } }else if(contactSpeedFwd != 0.0f){ fwd = -contactSpeedFwd/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedFwd is independent of framerate but fwd has timestep as a factor + // so we probably have to fix this + fwd *= CTimer::GetTimeStepFix(); +#endif if(!bBraking){ if(m_fGasPedal < 0.01f){ From c47292b518724c003a5c4b3f79e24de9fdf56f99 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 19 May 2020 00:10:45 +0300 Subject: [PATCH 053/148] script fix --- src/control/Script.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 844b1858..864799f8 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -759,6 +759,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) case COMMAND_WAIT: CollectParameters(&m_nIp, 1); m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0]; + m_bSkipWakeTime = false; return 1; case COMMAND_GOTO: CollectParameters(&m_nIp, 1); From 6510b15704998b14b89fa453ba9d142f85c30dd5 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 19 May 2020 01:49:09 +0300 Subject: [PATCH 054/148] script revision --- src/control/Script.cpp | 215 +++++++++++++++++++------------------- src/control/Script.h | 17 ++- src/core/PlayerInfo.cpp | 4 +- src/entities/Building.cpp | 22 ++++ src/entities/Building.h | 2 + src/entities/Dummy.cpp | 15 +++ src/entities/Dummy.h | 2 + src/entities/Entity.cpp | 17 +++ src/entities/Entity.h | 2 + src/objects/Object.cpp | 15 +++ src/objects/Object.h | 2 + src/peds/Ped.cpp | 27 ++++- src/peds/Ped.h | 3 + src/vehicles/Vehicle.cpp | 15 +++ src/vehicles/Vehicle.h | 1 + 15 files changed, 236 insertions(+), 123 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index a1287d09..2ad1e9de 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -54,6 +54,7 @@ #include "Remote.h" #include "Replay.h" #include "Restart.h" +#include "RoadBlocks.h" #include "RpAnimBlend.h" #include "Rubbish.h" #include "Shadows.h" @@ -92,13 +93,10 @@ uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE]; CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS]; -int32 CTheScripts::BaseBriefIdForContact[MAX_NUM_CONTACTS]; -int32 CTheScripts::OnAMissionForContactFlag[MAX_NUM_CONTACTS]; intro_text_line CTheScripts::IntroTextLines[MAX_NUM_INTRO_TEXT_LINES]; intro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; CSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; script_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; -tCollectiveData CTheScripts::CollectiveArray[MAX_NUM_COLLECTIVES]; tUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS]; int32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; tBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; @@ -119,8 +117,6 @@ uint16 CTheScripts::NumberOfMissionScripts; uint32 CTheScripts::LargestMissionScriptSize; uint32 CTheScripts::MainScriptSize; uint8 CTheScripts::FailCurrentMission; -uint8 CTheScripts::CountdownToMakePlayerUnsafe; -uint8 CTheScripts::DelayMakingPlayerUnsafeThisTime; uint16 CTheScripts::NumScriptDebugLines; uint16 CTheScripts::NumberOfIntroRectanglesThisFrame; uint16 CTheScripts::NumberOfIntroTextLinesThisFrame; @@ -131,6 +127,11 @@ CStuckCarCheck CTheScripts::StuckCars; uint16 CTheScripts::CommandsExecuted; uint16 CTheScripts::ScriptsUpdated; int32 ScriptParams[32]; +uint8 CTheScripts::RiotIntensity; +uint32 CTheScripts::LastMissionPassedTime; +uint16 CTheScripts::NumberOfExclusiveMissionScripts; +bool CTheScripts::bPlayerHasMetDebbieHarry; +bool CTheScripts::bPlayerIsInTheStatium; const uint32 CRunningScript::nSaveStructSize = @@ -272,9 +273,19 @@ void CMissionCleanup::Process() CPopulation::m_AllRandomPedsThisType = -1; CPopulation::PedDensityMultiplier = 1.0f; CCarCtrl::CarDensityMultiplier = 1.0f; + CPed::nThreatReactionRangeMultiplier = 1; + CPed::nEnterCarRangeMultiplier = 1; FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f; - TheCamera.Restore(); + //CRoadBlocks::ClearScriptRoadblocks() // TODO(MIAMI) + CRouteNode::Initialise(); + if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) + TheCamera.Restore(); TheCamera.SetWideScreenOff(); + // TODO(MIAMI) + //CSpecialFX::bLiftCam = false; + //CSpecialFX::bVideoCam = false; + //CTimeCycle::StopExtraColour(0); + // TODO(MIAMI): change this to loop when it supports parameters DMAudio.ClearMissionAudio(); CWeather::ReleaseWeather(); for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++) @@ -283,14 +294,18 @@ void CMissionCleanup::Process() CStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i); CStreaming::ms_disableStreaming = false; CHud::m_ItemToFlash = -1; - CHud::SetHelpMessage(nil, false); + CHud::SetHelpMessage(nil, false); // TODO(MIAMI): third parameter is false CUserDisplay::OnscnTimer.m_bDisabled = false; + CTheScripts::RemoveScriptTextureDictionary(); CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false; CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false; CWorld::Players[0].MakePlayerSafe(false); - + //TODO(MIAMI): drunkenness, enable drive by + //DMAudio::ShutUpPlayerTalking(0); CVehicle::bDisableRemoteDetonation = false; - + //CVehicle::bDisableRemoteDetonationOnContact = false; // TODO(MIAMI) + //CGameLogic::ClearShortCut(); // TODO(MIAMI) + CTheScripts::RiotIntensity = 0; CTheScripts::StoreVehicleIndex = -1; CTheScripts::StoreVehicleWasRandom = true; CTheScripts::UpsideDownCars.Init(); @@ -513,7 +528,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total) int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip) { uint32* pIp = &ip; - float tmp; switch (CTheScripts::Read1ByteFromScript(pIp)) { case ARGUMENT_INT32: @@ -527,8 +541,7 @@ int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip) case ARGUMENT_INT16: return CTheScripts::Read2BytesFromScript(pIp); case ARGUMENT_FLOAT: - tmp = CTheScripts::ReadFloatFromScript(pIp); - return *(int32*)&tmp; + return CTheScripts::Read4BytesFromScript(pIp); default: assert(0); } @@ -637,14 +650,7 @@ void CTheScripts::Init() StoreVehicleIndex = -1; StoreVehicleWasRandom = true; OnAMissionFlag = 0; - for (int i = 0; i < MAX_NUM_CONTACTS; i++){ - BaseBriefIdForContact[i] = 0; - OnAMissionForContactFlag[i] = 0; - } - for (int i = 0; i < MAX_NUM_COLLECTIVES; i++){ - CollectiveArray[i].index = -1; - CollectiveArray[i].unk_data = 0; - } + LastMissionPassedTime = (uint32)-1; NextFreeCollectiveIndex = 0; LastRandomPedId = -1; for (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){ @@ -658,15 +664,17 @@ void CTheScripts::Init() bUsingAMultiScriptFile = true; for (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++) MultiScriptArray[i] = 0; + NumberOfExclusiveMissionScripts = 0; NumberOfMissionScripts = 0; LargestMissionScriptSize = 0; MainScriptSize = 0; ReadMultiScriptFileOffsetsFromScript(); FailCurrentMission = 0; - CountdownToMakePlayerUnsafe = 0; DbgFlag = false; - DelayMakingPlayerUnsafeThisTime = 1; NumScriptDebugLines = 0; + RiotIntensity = 0; + bPlayerHasMetDebbieHarry = false; + bPlayerIsInTheStatium = false; for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){ ScriptSphereArray[i].m_bInUse = false; ScriptSphereArray[i].m_Index = 1; @@ -687,6 +695,7 @@ void CTheScripts::Init() IntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255); } NumberOfIntroRectanglesThisFrame = 0; + RemoveScriptTextureDictionary(); for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){ BuildingSwapArray[i].m_pBuilding = nil; BuildingSwapArray[i].m_nNewModel = -1; @@ -696,6 +705,15 @@ void CTheScripts::Init() InvisibilitySettingArray[i] = nil; } +void CTheScripts::RemoveScriptTextureDictionary() +{ + for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++) + CTheScripts::ScriptSprites[i].Delete(); + int slot = CTxdStore::FindTxdSlot("script"); + if (slot != -1) + CTxdStore::RemoveTxd(slot); +} + void CRunningScript::RemoveScriptFromList(CRunningScript** ppScript) { if (prev) @@ -739,10 +757,6 @@ void CTheScripts::Process() DrawScriptSpheres(); if (FailCurrentMission) --FailCurrentMission; - if (CountdownToMakePlayerUnsafe){ - if (--CountdownToMakePlayerUnsafe == 0) - CWorld::Players[0].MakePlayerSafe(false); - } if (UseTextCommands){ for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) IntroTextLines[i].Reset(); @@ -849,6 +863,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) case COMMAND_WAIT: CollectParameters(&m_nIp, 1); m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0]; + m_bSkipWakeTime = false; return 1; case COMMAND_GOTO: CollectParameters(&m_nIp, 1); @@ -1262,13 +1277,11 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) UpdateCompareFlag(*ptr1 == *ptr2); return 0; } - /* Following commands are not implemented, and go to default case - case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER: - case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER: - case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR: - case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR: - case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR: - */ + //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER: + //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER: + //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR: + //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR: + //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR: case COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER: { int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); @@ -1304,19 +1317,18 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) UpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2); return 0; } - /* Following commands are not implemented, and go to default case - case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER: - case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER: - case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR: - case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR: - case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR: - */ + //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER: + //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER: + //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR: + //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR: + //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR: + /* case COMMAND_GOTO_IF_TRUE: CollectParameters(&m_nIp, 1); if (m_bCondResult) SetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]); - /* Check COMMAND_GOTO note. */ return 0; + */ case COMMAND_GOTO_IF_FALSE: CollectParameters(&m_nIp, 1); if (!m_bCondResult) @@ -1328,12 +1340,14 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) CTheScripts::bAlreadyRunningAMissionScript = false; RemoveScriptFromList(&CTheScripts::pActiveScripts); AddScriptToList(&CTheScripts::pIdleScripts); + m_bIsActive = false; return 1; case COMMAND_START_NEW_SCRIPT: { CollectParameters(&m_nIp, 1); assert(ScriptParams[0] >= 0); CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]); + m_bIsActive = true; int8 type = CTheScripts::Read1ByteFromScript(&m_nIp); float tmp; for (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) { @@ -1381,7 +1395,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) { CollectParameters(&m_nIp, 4); int32 index = ScriptParams[0]; - assert(index < 1); /* Constant? Also no more double player glitch */ + assert(index < NUMPLAYERS); printf("&&&&&&&&&&&&&Creating player: %d\n", index); if (!CStreaming::HasModelLoaded(MI_PLAYER)) { CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY); @@ -1421,20 +1435,49 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CPlayerPed* ped = CWorld::Players[index].m_pPed; - if (!ped->bInVehicle) { - pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel(); - ped->Teleport(pos); - CTheScripts::ClearSpaceForMissionEntity(pos, ped); + if (ped->bInVehicle) { + pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); + ped->m_pMyVehicle->Teleport(pos); // removed dumb stuff that was present here + CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle); return 0; } - pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); - if (ped->m_pMyVehicle->IsBoat()) - ped->m_pMyVehicle->Teleport(pos); - else - ped->m_pMyVehicle->Teleport(pos); - /* I'll keep this condition here but obviously it is absolutely pointless */ - /* It's clearly present in disassembly so it had to be in original code */ - CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle); + pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel(); + CVector vOldPos = ped->GetPosition(); + ped->Teleport(pos); + CTheScripts::ClearSpaceForMissionEntity(pos, ped); + if (ped) { // great time to check + for (int i = 0; i < ped->m_numNearPeds; i++) { + CPed* pTestedPed = ped->m_nearPeds[i]; + if (!pTestedPed || !IsPedPointerValid(pTestedPed)) + continue; + if (pTestedPed->m_pedInObjective == ped && pTestedPed->m_objective == OBJ_15) { + CVector vFollowerPos = pTestedPed->GetFormationPosition(); + CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped); + bool bFound = false; + vFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f; + if (bFound) { + if (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) { + pTestedPed->Teleport(vFollowerPos); + } + } + } + else if (pTestedPed->m_leader == ped) { + CVector vFollowerPos; + if (pTestedPed->m_pedFormation) + vFollowerPos = pTestedPed->GetFormationPosition(); + else + vFollowerPos = ped->GetPosition() + pTestedPed->GetPosition() - vOldPos; + CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped); + bool bFound = false; + vFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f; + if (bFound) { + if (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) { + pTestedPed->Teleport(vFollowerPos); + } + } + } + } + } return 0; } case COMMAND_IS_PLAYER_IN_AREA_2D: @@ -3508,14 +3551,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) case COMMAND_DECLARE_MISSION_FLAG: CTheScripts::OnAMissionFlag = CTheScripts::Read2BytesFromScript(&++m_nIp); return 0; - case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: - CollectParameters(&m_nIp, 1); - CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = CTheScripts::Read2BytesFromScript(&++m_nIp); - return 0; - case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT: - CollectParameters(&m_nIp, 2); - CTheScripts::BaseBriefIdForContact[ScriptParams[0]] = ScriptParams[1]; - return 0; + //case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: + //case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT: case COMMAND_IS_PLAYER_HEALTH_GREATER: { CollectParameters(&m_nIp, 2); @@ -3830,13 +3867,8 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CollectParameters(&m_nIp, 2); CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; if (ScriptParams[1]){ - if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){ - CTheScripts::CountdownToMakePlayerUnsafe = 50; - if (CTheScripts::DelayMakingPlayerUnsafeThisTime) - CTheScripts::DelayMakingPlayerUnsafeThisTime--; - }else{ - pPlayer->MakePlayerSafe(false); - } + pPlayer->MakePlayerSafe(false); + // TODO(MIAMI): Four Iron hack }else{ pPlayer->MakePlayerSafe(true); if (strcmp(m_abScriptName, "camera") == 0){ @@ -7720,9 +7752,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) } case COMMAND_REMOVE_TEXTURE_DICTIONARY: { - for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++) - CTheScripts::ScriptSprites[i].Delete(); - CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script")); + CTheScripts::RemoveScriptTextureDictionary(); return 0; } case COMMAND_SET_OBJECT_DYNAMIC: @@ -10446,7 +10476,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) char key[8]; CTheScripts::ReadTextLabelFromScript(&m_nIp, key); m_nIp += KEY_LENGTH_IN_SCRIPT; - debug("skipping LOAD_MISSION_TEXT\n"); + TheText.LoadMissionText(key); return 0; } case COMMAND_SET_TONIGHTS_EVENT: @@ -12133,29 +12163,6 @@ void CRunningScript::DoDeatharrestCheck() while (m_nStackPointer > 1) --m_nStackPointer; m_nIp = m_anStack[--m_nStackPointer]; - int16 messageId; - if (pPlayer->IsRestartingAfterDeath()) - messageId = 0; - else if (pPlayer->IsRestartingAfterArrest()) - messageId = 5; - else - messageId = 10; - messageId += CGeneral::GetRandomNumberInRange(0, 5); - bool found = false; - for (int16 contact = 0; !found && contact < MAX_NUM_CONTACTS; contact++) { - int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact]; - if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) { - messageId += CTheScripts::BaseBriefIdForContact[contact]; - found = true; - } - } - if (!found) - messageId = 8001; - char tmp[16]; - sprintf(tmp, "%d", messageId); - CMessages::ClearSmallMessagesOnly(); - wchar* text = TheText.Get(tmp); - // ...and do nothing about it *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0; m_bDeatharrestExecuted = true; m_nWakeTime = 0; @@ -12299,8 +12306,8 @@ void CTheScripts::RenderTheScriptDebugLines() RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0); } -#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\ - sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32) +#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) +\ + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32) void CTheScripts::SaveAllScripts(uint8* buf, uint32* size) { @@ -12320,12 +12327,6 @@ INITSAVEBUF uint32 script_data_size = SCRIPT_DATA_SIZE; WriteSaveBuf(buf, script_data_size); WriteSaveBuf(buf, OnAMissionFlag); - for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { - WriteSaveBuf(buf, OnAMissionForContactFlag[i]); - WriteSaveBuf(buf, BaseBriefIdForContact[i]); - } - for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) - WriteSaveBuf(buf, CollectiveArray[i]); WriteSaveBuf(buf, NextFreeCollectiveIndex); for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding; @@ -12398,12 +12399,6 @@ INITSAVEBUF ScriptSpace[i] = ReadSaveBuf(buf); assert(ReadSaveBuf(buf) == SCRIPT_DATA_SIZE); OnAMissionFlag = ReadSaveBuf(buf); - for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { - OnAMissionForContactFlag[i] = ReadSaveBuf(buf); - BaseBriefIdForContact[i] = ReadSaveBuf(buf); - } - for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) - CollectiveArray[i] = ReadSaveBuf(buf); NextFreeCollectiveIndex = ReadSaveBuf(buf); for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { uint32 type = ReadSaveBuf(buf); diff --git a/src/control/Script.h b/src/control/Script.h index c7a6e1e6..e84e76bf 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -228,12 +228,10 @@ enum { enum { MAX_NUM_SCRIPTS = 128, - MAX_NUM_CONTACTS = 16, MAX_NUM_INTRO_TEXT_LINES = 2, MAX_NUM_INTRO_RECTANGLES = 16, MAX_NUM_SCRIPT_SRPITES = 16, MAX_NUM_SCRIPT_SPHERES = 16, - MAX_NUM_COLLECTIVES = 32, MAX_NUM_USED_OBJECTS = 200, MAX_NUM_MISSION_SCRIPTS = 120, MAX_NUM_BUILDING_SWAPS = 25, @@ -245,13 +243,10 @@ class CTheScripts { static uint8 ScriptSpace[SIZE_SCRIPT_SPACE]; static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS]; - static int32 BaseBriefIdForContact[MAX_NUM_CONTACTS]; - static int32 OnAMissionForContactFlag[MAX_NUM_CONTACTS]; static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES]; static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; - static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES]; static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS]; static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; @@ -275,14 +270,17 @@ class CTheScripts static uint32 LargestMissionScriptSize; static uint32 MainScriptSize; static uint8 FailCurrentMission; - static uint8 CountdownToMakePlayerUnsafe; - static uint8 DelayMakingPlayerUnsafeThisTime; static uint16 NumScriptDebugLines; static uint16 NumberOfIntroRectanglesThisFrame; static uint16 NumberOfIntroTextLinesThisFrame; static uint8 UseTextCommands; static uint16 CommandsExecuted; static uint16 ScriptsUpdated; + static uint8 RiotIntensity; + static uint32 LastMissionPassedTime; + static uint16 NumberOfExclusiveMissionScripts; + static bool bPlayerIsInTheStatium; + static bool bPlayerHasMetDebbieHarry; public: static void Init(); @@ -306,9 +304,6 @@ public: static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; } - static void ResetCountdownToMakePlayerUnsafe() { CountdownToMakePlayerUnsafe = 0; } - static bool IsCountdownToMakePlayerUnsafeOn() { return CountdownToMakePlayerUnsafe != 0; } - static int32 Read4BytesFromScript(uint32* pIp) { int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp]; *pIp += 4; @@ -371,6 +366,7 @@ private: static int32 AddScriptSphere(int32 id, CVector pos, float radius); static int32 GetNewUniqueScriptSphereIndex(int32 index); static void RemoveScriptSphere(int32 index); + static void RemoveScriptTextureDictionary(); friend class CRunningScript; friend class CHud; @@ -414,6 +410,7 @@ class CRunningScript uint32 m_anStack[MAX_STACK_DEPTH]; uint16 m_nStackPointer; int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS]; + bool m_bIsActive; bool m_bCondResult; bool m_bIsMissionScript; bool m_bSkipWakeTime; diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index f4e762c0..37a62adf 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -173,7 +173,6 @@ void CPlayerInfo::MakePlayerSafe(bool toggle) { if (toggle) { - CTheScripts::ResetCountdownToMakePlayerUnsafe(); m_pPed->m_pWanted->m_bIgnoredByEveryone = true; CWorld::StopAllLawEnforcersInTheirTracks(); CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20; @@ -194,7 +193,8 @@ CPlayerInfo::MakePlayerSafe(bool toggle) CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); CReplay::DisableReplays(); - } else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { + } + else { m_pPed->m_pWanted->m_bIgnoredByEveryone = false; CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20; m_pPed->bBulletProof = false; diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp index 3c096636..3217e684 100644 --- a/src/entities/Building.cpp +++ b/src/entities/Building.cpp @@ -20,3 +20,25 @@ CBuilding::ReplaceWithNewModel(int32 id) if(m_level == LEVEL_NONE || m_level == CGame::currLevel) CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE); } + +bool +IsBuildingPointerValid(CBuilding* pBuilding) +{ + if (!pBuilding) + return false; + if (pBuilding->GetIsATreadable()) { + int index = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding); +#ifdef FIX_BUGS + return index >= 0 && index < CPools::GetTreadablePool()->GetSize(); +#else + return index >= 0 && index <= CPools::GetTreadablePool()->GetSize(); +#endif + } else { + int index = CPools::GetBuildingPool()->GetJustIndex(pBuilding); +#ifdef FIX_BUGS + return index >= 0 && index < CPools::GetBuildingPool()->GetSize(); +#else + return index >= 0 && index <= CPools::GetBuildingPool()->GetSize(); +#endif + } +} diff --git a/src/entities/Building.h b/src/entities/Building.h index 29608c10..2c2dfb1f 100644 --- a/src/entities/Building.h +++ b/src/entities/Building.h @@ -16,3 +16,5 @@ public: virtual bool GetIsATreadable(void) { return false; } }; + +bool IsBuildingPointerValid(CBuilding*); diff --git a/src/entities/Dummy.cpp b/src/entities/Dummy.cpp index 8a4bfd5f..92b69761 100644 --- a/src/entities/Dummy.cpp +++ b/src/entities/Dummy.cpp @@ -50,3 +50,18 @@ CDummy::Remove(void) m_entryInfoList.DeleteNode(node); } } + +bool +IsDummyPointerValid(CDummy* pDummy) +{ + if (!pDummy) + return false; + int index = CPools::GetDummyPool()->GetJustIndex(pDummy); +#ifdef FIX_BUGS + if (index < 0 || index >= CPools::GetDummyPool()->GetSize()) +#else + if (index < 0 || index > CPools::GetDummyPool()->GetSize()) +#endif + return false; + return pDummy->m_entryInfoList.first; +} diff --git a/src/entities/Dummy.h b/src/entities/Dummy.h index 7998a748..84b1ce1a 100644 --- a/src/entities/Dummy.h +++ b/src/entities/Dummy.h @@ -15,3 +15,5 @@ public: static void *operator new(size_t); static void operator delete(void*, size_t); }; + +bool IsDummyPointerValid(CDummy* pDummy); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index b35ddb25..e83df204 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -28,6 +28,8 @@ #include "Bones.h" #include "Debug.h" #include "Renderer.h" +#include "Ped.h" +#include "Dummy.h" int gBuildings; @@ -1028,3 +1030,18 @@ CEntity::LoadEntityFlags(uint8*& buf) } #endif + +bool IsEntityPointerValid(CEntity* pEntity) +{ + if (!pEntity) + return false; + switch (pEntity->GetType()) { + case ENTITY_TYPE_NOTHING: return false; + case ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity); + case ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity); + case ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity); + case ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity); + case ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity); + } + return false; +} diff --git a/src/entities/Entity.h b/src/entities/Entity.h index fa57519e..dc5378a5 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -180,3 +180,5 @@ public: static void AddSteamsFromGround(CPtrList& list); }; + +bool IsEntityPointerValid(CEntity*); diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 0107c75c..4a45050c 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -396,3 +396,18 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius) } } } + +bool +IsObjectPointerValid(CObject* pObject) +{ + if (!pObject) + return false; + int index = CPools::GetObjectPool()->GetJustIndex(pObject); +#ifdef FIX_BUGS + if (index < 0 || index >= CPools::GetObjectPool()->GetSize()) +#else + if (index < 0 || index > CPools::GetObjectPool()->GetSize()) +#endif + return false; + return pObject->bIsBIGBuilding || pObject->m_entryInfoList.first; +} diff --git a/src/objects/Object.h b/src/objects/Object.h index 20c99b1b..73f710f0 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -113,3 +113,5 @@ public: static void DeleteAllTempObjects(); static void DeleteAllTempObjectsInArea(CVector point, float fRadius); }; + +bool IsObjectPointerValid(CObject* pObject); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index e25e592e..91dafbc2 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -18599,4 +18599,29 @@ CPed::AddInCarAnims(CVehicle* car, bool isDriver) m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), group, anim, 100.0f); StopNonPartialAnims(); -} \ No newline at end of file +} + +bool +IsPedPointerValid_NotInWorld(CPed* pPed) +{ + if (!pPed) + return false; + int index = CPools::GetPedPool()->GetJustIndex(pPed); +#ifdef FIX_BUGS + if (index < 0 || index >= NUMPEDS) +#else + if (index < 0 || index > NUMPEDS) +#endif + return false; + return true; +} + +bool +IsPedPointerValid(CPed* pPed) +{ + if (!IsPedPointerValid_NotInWorld(pPed)) + return false; + if (pPed->bInVehicle && pPed->m_pMyVehicle) + return IsEntityPointerValid(pPed->m_pMyVehicle); + return pPed->m_entryInfoList.first || pPed == FindPlayerPed(); +} diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 0e80c378..1fa36b05 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -1018,3 +1018,6 @@ void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg); #ifndef PED_SKIN VALIDATE_SIZE(CPed, 0x53C); #endif + +bool IsPedPointerValid(CPed*); +bool IsPedPointerValid_NotInWorld(CPed*); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 2b0132b2..fe798514 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1368,3 +1368,18 @@ CVehicle::GetVehicleAppearance(void) return VEHICLE_APPEARANCE_HELI; return VEHICLE_APPEARANCE_NONE; } + +bool +IsVehiclePointerValid(CVehicle* pVehicle) +{ + if (!pVehicle) + return false; + int index = CPools::GetVehiclePool()->GetJustIndex(pVehicle); +#ifdef FIX_BUGS + if (index < 0 || index >= NUMVEHICLES) +#else + if (index < 0 || index > NUMVEHICLES) +#endif + return false; + return pVehicle->m_vehType == VEHICLE_TYPE_PLANE || pVehicle->m_entryInfoList.first; +} diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 5ec20c43..c2cfa5e4 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -314,3 +314,4 @@ public: }; void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle); +bool IsVehiclePointerValid(CVehicle* pVehicle); From d4253581817181291e8c3624e7c453700b234daf Mon Sep 17 00:00:00 2001 From: Xinerki Date: Tue, 19 May 2020 10:07:15 +0300 Subject: [PATCH 055/148] Load VC frontend textures and use some --- src/core/Frontend.cpp | 294 +++++++++++++++++------------------------- src/core/Frontend.h | 41 +++--- 2 files changed, 142 insertions(+), 193 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 56c83337..767fb5fc 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -149,53 +149,7 @@ bool CMenuManager::m_PrefsMarketing = false; bool CMenuManager::m_PrefsDisableTutorials = false; #endif // !MASTER -// 0x5F311C -const char* FrontendFilenames[][2] = { - {"fe2_mainpanel_ul", "" }, - {"fe2_mainpanel_ur", "" }, - {"fe2_mainpanel_dl", "" }, - {"fe2_mainpanel_dr", "" }, - {"fe2_mainpanel_dr2", "" }, - {"fe2_tabactive", "" }, - {"fe_iconbrief", "" }, - {"fe_iconstats", "" }, - {"fe_iconcontrols", "" }, - {"fe_iconsave", "" }, - {"fe_iconaudio", "" }, - {"fe_icondisplay", "" }, - {"fe_iconlanguage", "" }, - {"fe_controller", "" }, - {"fe_controllersh", "" }, - {"fe_arrows1", "" }, - {"fe_arrows2", "" }, - {"fe_arrows3", "" }, - {"fe_arrows4", "" }, - {"fe_radio1", "" }, - {"fe_radio2", "" }, - {"fe_radio3", "" }, - {"fe_radio4", "" }, - {"fe_radio5", "" }, - {"fe_radio6", "" }, - {"fe_radio7", "" }, - {"fe_radio8", "" }, - {"fe_radio9", "" }, -}; - -#ifdef MENU_MAP -const char* MapFilenames[][2] = { - {"mapMid01", "mapMid01A"}, - {"mapMid02", "mapMid02A"}, - {"mapMid03", "mapMid03A"}, - {"mapBot01", "mapBot01A"}, - {"mapBot02", "mapBot02A"}, - {"mapBot03", "mapBot03A"}, - {"mapTop01", "mapTop01A"}, - {"mapTop02", "mapTop02A"}, - {"mapTop03", "mapTop03A"}, -}; -CSprite2d CMenuManager::m_aMapSprites[NUM_MAP_SPRITES]; -#endif - +/* // 0x5F3344 const char* MenuFilenames[][2] = { {"connection24", ""}, @@ -219,6 +173,37 @@ const char* MenuFilenames[][2] = { {"gta3logo256", "gta3logo256m"}, { nil, nil } }; +*/ + +// 0x68C144 +const char* FrontendFilenames[][2] = { + {"background", ""}, + {"vc_logo", "vc_logom"}, + {"mouse", "mousea"}, + {"mapTop01", "mapTop01A"}, + {"mapTop02", "mapTop02A"}, + {"mapTop03", "mapTop03A"}, + {"mapMid01", "mapMid01A"}, + {"mapMid02", "mapMid02A"}, + {"mapMid03", "mapMid03A"}, + {"mapBot01", "mapBot01A"}, + {"mapBot02", "mapBot02A"}, + {"mapBot03", "mapBot03A"}, + {"wildstyle", "wildstyleA"}, + {"flash", "flashA"}, + {"kchat", "kchatA"}, + {"fever", "feverA"}, + {"vrock", "vrockA"}, + {"vcpr", "vcprA"}, + {"espantoso", "espantosoA"}, + {"emotion", "emotionA"}, + {"wave", "waveA"}, + {"mp3", "mp3A"}, + {"downOff", "buttonA"}, + {"downOn", "buttonA"}, + {"upOff", "buttonA"}, + {"upOn", "buttonA"} +}; #ifdef ASPECT_RATIO_SCALE // All of the defines below replace the StretchX function. Otherwise use SCREEN_SCALE_X. @@ -1332,7 +1317,7 @@ CMenuManager::Draw() ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO9], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); if (DMAudio.IsMP3RadioChannelAvailable()) - ProcessRadioIcon(m_aMenuSprites[MENUSPRITE_MP3LOGO], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_MP3], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); nextYToUse += 70.0f; } @@ -2079,13 +2064,13 @@ CMenuManager::DrawFrontEndSaveZone() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); if(field_518 == 4){ - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); } } } @@ -2273,13 +2258,13 @@ CMenuManager::DrawFrontEndNormal() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); if(field_518 == 4){ - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); } } } @@ -2293,65 +2278,24 @@ CMenuManager::DrawFrontEndNormal() LoadSplash(nil); - eMenuSprites previousSprite; + eMenuSprites previousSprite = MENUSPRITE_BACKGROUND; + if (m_nMenuFadeAlpha < 255) { - switch (m_nPrevScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - previousSprite = MENUSPRITE_MAINMENU; - break; - case MENUPAGE_NEW_GAME: - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_EXIT: - previousSprite = MENUSPRITE_SINGLEPLAYER; - break; - case MENUPAGE_MULTIPLAYER_MAIN: - previousSprite = MENUSPRITE_MULTIPLAYER; - break; - case MENUPAGE_MULTIPLAYER_MAP: - case MENUPAGE_MULTIPLAYER_FIND_GAME: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - previousSprite = MENUSPRITE_FINDGAME; - break; - case MENUPAGE_MULTIPLAYER_CONNECTION: - case MENUPAGE_MULTIPLAYER_MODE: - previousSprite = MENUSPRITE_CONNECTION; - break; - case MENUPAGE_MULTIPLAYER_CREATE: - previousSprite = MENUSPRITE_HOSTGAME; - break; - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - previousSprite = MENUSPRITE_PLAYERSET; - break; - default: - previousSprite = MENUSPRITE_MAINMENU; - break; - } - if (m_nPrevScreen == m_nCurrScreen) CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255 - m_nMenuFadeAlpha)); else - m_aMenuSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha)); + m_aFrontEndSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha)); } RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - eMenuSprites currentSprite = MENUSPRITE_MAINMENU; // actually uninitialized + eMenuSprites currentSprite = MENUSPRITE_BACKGROUND; // actually uninitialized + switch (m_nCurrScreen) { case MENUPAGE_STATS: case MENUPAGE_START_MENU: case MENUPAGE_PAUSE_MENU: - currentSprite = MENUSPRITE_MAINMENU; - break; case MENUPAGE_NEW_GAME: case MENUPAGE_CHOOSE_LOAD_SLOT: case MENUPAGE_CHOOSE_DELETE_SLOT: @@ -2359,28 +2303,18 @@ CMenuManager::DrawFrontEndNormal() case MENUPAGE_LOAD_SLOT_CONFIRM: case MENUPAGE_DELETE_SLOT_CONFIRM: case MENUPAGE_EXIT: - currentSprite = MENUSPRITE_SINGLEPLAYER; - break; case MENUPAGE_MULTIPLAYER_MAIN: - currentSprite = MENUSPRITE_MULTIPLAYER; - break; case MENUPAGE_MULTIPLAYER_MAP: case MENUPAGE_MULTIPLAYER_FIND_GAME: case MENUPAGE_SKIN_SELECT: case MENUPAGE_KEYBOARD_CONTROLS: case MENUPAGE_MOUSE_CONTROLS: - currentSprite = MENUSPRITE_FINDGAME; - break; case MENUPAGE_MULTIPLAYER_CONNECTION: case MENUPAGE_MULTIPLAYER_MODE: - currentSprite = MENUSPRITE_CONNECTION; - break; case MENUPAGE_MULTIPLAYER_CREATE: - currentSprite = MENUSPRITE_HOSTGAME; - break; case MENUPAGE_SKIN_SELECT_OLD: case MENUPAGE_OPTIONS: - currentSprite = MENUSPRITE_PLAYERSET; + currentSprite = MENUSPRITE_BACKGROUND; break; } @@ -2404,13 +2338,13 @@ CMenuManager::DrawFrontEndNormal() #endif if (m_nMenuFadeAlpha > 255){ - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); } else { RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); + m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); } } else { - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); // TODO: what is this? waiting mouse? if(field_518 == 4){ if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || @@ -2422,14 +2356,16 @@ CMenuManager::DrawFrontEndNormal() } } + m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); + // GTA LOGO RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) { if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - m_aMenuSprites[MENUSPRITE_GTA3LOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); else - m_aMenuSprites[MENUSPRITE_GTALOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); } RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); @@ -2457,19 +2393,19 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f)); - CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f)); + CRect mouse(0.0f, 0.0f, MENU_X(40.0f), MENU_Y(40.0f)); + CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(55.0f), MENU_Y(43.0f)); mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); if(field_518 == 4){ - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); } } } @@ -2711,21 +2647,21 @@ CMenuManager::DrawPlayerSetupScreen() // 2 - leaves gap between button and scrollbar if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), CRGBA(255, 255, 255, FadeIn(255))); #endif } else { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), CRGBA(255, 255, 255, FadeIn(255))); #endif @@ -2733,21 +2669,21 @@ CMenuManager::DrawPlayerSetupScreen() if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), + m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), + m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), CRGBA(255, 255, 255, FadeIn(255))); #endif } else { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), + m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f), + m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f), MENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), CRGBA(255, 255, 255, FadeIn(255))); #endif @@ -3021,51 +2957,59 @@ CMenuManager::LoadAllTextures() CStreaming::ImGonnaUseStreamingMemory(); CGame::TidyUpMemory(false, true); CTxdStore::PushCurrentTxd(); - int frontendTxdSlot = CTxdStore::FindTxdSlot("frontend"); + int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1"); - if(frontendTxdSlot == -1) - frontendTxdSlot = CTxdStore::AddTxdSlot("frontend"); + if(frontendTxdSlot1 == -1) + frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1"); - printf("LOAD frontend\n"); - CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD"); - CTxdStore::AddRef(frontendTxdSlot); - CTxdStore::SetCurrentTxd(frontendTxdSlot); -#ifndef GTA3_1_1_PATCH - CStreaming::IHaveUsedStreamingMemory(); - CTimer::Update(); -#endif + printf("LOAD frontend1\n"); + CTxdStore::LoadTxd(frontendTxdSlot1, "MODELS/FRONTEN1.TXD"); + CTxdStore::AddRef(frontendTxdSlot1); + CTxdStore::SetCurrentTxd(frontendTxdSlot1); - for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); i++) { + for (int i = 0; i < 3; i++) { m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } - int menuTxdSlot = CTxdStore::FindTxdSlot("menu"); + CTxdStore::PopCurrentTxd(); + CStreaming::IHaveUsedStreamingMemory(); - if (menuTxdSlot == -1) - menuTxdSlot = CTxdStore::AddTxdSlot("menu"); - printf("LOAD sprite\n"); - CTxdStore::LoadTxd(menuTxdSlot, "MODELS/MENU.TXD"); - CTxdStore::AddRef(menuTxdSlot); - CTxdStore::SetCurrentTxd(menuTxdSlot); + // if ( !*(_BYTE *)(v1 + 124) ) - for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) { - m_aMenuSprites[i].SetTexture(MenuFilenames[i][0], MenuFilenames[i][1]); - m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); + + int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2"); + + if (frontendTxdSlot2 == -1) + frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2"); + + printf("LOAD frontend2\n"); + CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD"); + CTxdStore::AddRef(frontendTxdSlot2); + CTxdStore::SetCurrentTxd(frontendTxdSlot2); + + for (int i = 3; i < NUM_MENU_SPRITES; i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } -#ifdef MENU_MAP + + CTxdStore::PopCurrentTxd(); + CStreaming::IHaveUsedStreamingMemory(); + + +#if 0 //MENU_MAP for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) { m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]); m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } #endif -#ifdef GTA3_1_1_PATCH - CStreaming::IHaveUsedStreamingMemory(); - CTimer::Update(); -#endif + m_bSpritesLoaded = true; - CTxdStore::PopCurrentTxd(); + CTimer::Update(); } void @@ -5147,18 +5091,16 @@ CMenuManager::UnloadTextures() for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i) m_aFrontEndSprites[i].Delete(); - int frontend = CTxdStore::FindTxdSlot("frontend"); + int frontend = CTxdStore::FindTxdSlot("frontend1"); CTxdStore::RemoveTxd(frontend); - printf("REMOVE menu textures\n"); - for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i) - m_aMenuSprites[i].Delete(); -#ifdef MENU_MAP + int frontend2 = CTxdStore::FindTxdSlot("frontend2"); + CTxdStore::RemoveTxd(frontend2); + +#ifdef false //MENU_MAP for (int i = 0; i < ARRAY_SIZE(MapFilenames); ++i) m_aMapSprites[i].Delete(); #endif - int menu = CTxdStore::FindTxdSlot("menu"); - CTxdStore::RemoveTxd(menu); m_bSpritesLoaded = false; } @@ -5468,47 +5410,47 @@ CMenuManager::PrintMap(void) RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aMapSprites[MAPTOP1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize, + m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize, fMapCenterX - halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aMapSprites[MAPTOP2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize, + m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize, fMapCenterX + halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aMapSprites[MAPTOP3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize, + m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize, fMapCenterX + fMapSize, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aMapSprites[MAPMID1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile, + m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile, fMapCenterX - halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aMapSprites[MAPMID2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile, + m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile, fMapCenterX + halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aMapSprites[MAPMID3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile, + m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile, fMapCenterX + fMapSize, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aMapSprites[MAPBOT1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile, + m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile, fMapCenterX - halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aMapSprites[MAPBOT2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile, + m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile, fMapCenterX + halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); } if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aMapSprites[MAPBOT3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile, + m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile, fMapCenterX + fMapSize, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); } diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 16da5cb1..2fe18b8c 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -131,26 +131,32 @@ enum eFrontendSprites enum eMenuSprites { - MENUSPRITE_CONNECTION, - MENUSPRITE_FINDGAME, - MENUSPRITE_HOSTGAME, - MENUSPRITE_MAINMENU, - MENUSPRITE_PLAYERSET, - MENUSPRITE_SINGLEPLAYER, - MENUSPRITE_MULTIPLAYER, - MENUSPRITE_DMALOGO, - MENUSPRITE_GTALOGO, - MENUSPRITE_RSTARLOGO, - MENUSPRITE_GAMESPY, + MENUSPRITE_BACKGROUND, + MENUSPRITE_VCLOGO, MENUSPRITE_MOUSE, - MENUSPRITE_MOUSET, - MENUSPRITE_MP3LOGO, + MENUSPRITE_MAPTOP01, + MENUSPRITE_MAPTOP02, + MENUSPRITE_MAPTOP03, + MENUSPRITE_MAPMID01, + MENUSPRITE_MAPMID02, + MENUSPRITE_MAPMID03, + MENUSPRITE_MAPBOT01, + MENUSPRITE_MAPBOT02, + MENUSPRITE_MAPBOT03, + MENUSPRITE_WILDSTYLE, + MENUSPRITE_FLASH, + MENUSPRITE_KCHAT, + MENUSPRITE_FEVER, + MENUSPRITE_VROCK, + MENUSPRITE_VCPR, + MENUSPRITE_ESPANTOSO, + MENUSPRITE_EMOTION, + MENUSPRITE_WAVE, + MENUSPRITE_MP3, MENUSPRITE_DOWNOFF, MENUSPRITE_DOWNON, MENUSPRITE_UPOFF, MENUSPRITE_UPON, - MENUSPRITE_GTA3LOGO, - MENUSPRITE_UNUSED, NUM_MENU_SPRITES }; @@ -509,8 +515,9 @@ public: char field_455; bool m_bStartWaitingForKeyBind; bool m_bSpritesLoaded; - CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES]; - CSprite2d m_aMenuSprites[NUM_MENU_SPRITES]; + //CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES]; + //CSprite2d m_aMenuSprites[NUM_MENU_SPRITES]; + CSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES]; int32 field_518; int32 m_nMenuFadeAlpha; bool m_bPressedPgUpOnList; From 62db8cd9b0030f042403e996b20c3ceca5cd4f7a Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 19 May 2020 10:23:08 +0200 Subject: [PATCH 056/148] finished CFileLoader; some COcclusion stubs --- src/core/FileLoader.cpp | 37 ++++++++++++++++++++++++++++++------- src/core/FileLoader.h | 1 + src/core/Game.cpp | 2 ++ src/core/config.h | 2 ++ src/render/Occlusion.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/render/Occlusion.h | 19 +++++++++++++++++++ 6 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 612851fb..1463b4a5 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include #include "main.h" #include "Quaternion.h" @@ -26,6 +27,9 @@ #include "FileLoader.h" #include "Streaming.h" #include "ColStore.h" +#include "Occlusion.h" + +//--MIAMI: file done char CFileLoader::ms_line[256]; @@ -159,7 +163,6 @@ struct ColHeader uint32 size; }; -//--MIAMI: done void CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot) { @@ -196,7 +199,6 @@ CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot) } -//--MIAMI: done bool CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot) { @@ -298,13 +300,15 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) model.numLines = *(int16*)buf; buf += 4; if(model.numLines > 0){ - model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); + //model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); for(i = 0; i < model.numLines; i++){ - model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); + //model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); buf += 24; } }else model.lines = nil; + model.numLines = 0; + model.lines = nil; model.numBoxes = *(int16*)buf; buf += 4; @@ -323,10 +327,12 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector)); for(i = 0; i < numVertices; i++){ model.vertices[i] = *(CVector*)buf; +#if 0 if(Abs(model.vertices[i].x) >= 256.0f || Abs(model.vertices[i].y) >= 256.0f || Abs(model.vertices[i].z) >= 256.0f) printf("%s:Collision volume too big\n", modelname); +#endif buf += 12; } }else @@ -349,7 +355,7 @@ GetNameAndLOD(char *nodename, char *name, int *n) { char *underscore = nil; for(char *s = nodename; *s != '\0'; s++){ - if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L')) + if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L') && isdigit(s[2])) underscore = s; } if(underscore){ @@ -1093,7 +1099,7 @@ CFileLoader::LoadScene(const char *filename) LoadCullZone(line); break; case OCCL: - // TODO(MIAMI): occlusion + LoadOcclusionVolume(line); break; case PICK: // unused @@ -1187,7 +1193,9 @@ CFileLoader::LoadObjectInstance(const char *line) CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect()); }else entity->bUsesCollision = false; - // TODO(MIAMI): set some flag here if col min is below 6 + + if(entity->GetPosition().z + col->boundingBox.min.z < 6.0f) + entity->bUnderwater = true; }else{ entity = new CDummyObject; entity->SetModelIndexNoCreate(id); @@ -1241,6 +1249,21 @@ CFileLoader::LoadPickup(const char *line) sscanf(line, "%d %f %f %f", &id, &x, &y, &z); } +void +CFileLoader::LoadOcclusionVolume(const char *line) +{ + float x, y, z; + float width, length, height; + float angle; + + sscanf(line, "%f %f %f %f %f %f %f", + &x, &y, &z, + &width, &length, &height, + &angle); + COcclusion::AddOne(x, y, z, width, length, z + height/2.0f, angle); +} + + //--MIAMI: unused void CFileLoader::ReloadPaths(const char *filename) diff --git a/src/core/FileLoader.h b/src/core/FileLoader.h index 584a2312..077e7bdd 100644 --- a/src/core/FileLoader.h +++ b/src/core/FileLoader.h @@ -39,6 +39,7 @@ public: static void LoadZone(const char *line); static void LoadCullZone(const char *line); static void LoadPickup(const char *line); + static void LoadOcclusionVolume(const char *line); static void ReloadPaths(const char *filename); static void ReloadObjectTypes(const char *filename); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index b96c8988..3f4a3217 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -84,6 +84,7 @@ #include "World.h" #include "ZoneCull.h" #include "Zones.h" +#include "Occlusion.h" #include "debugmenu.h" @@ -272,6 +273,7 @@ bool CGame::Initialise(const char* datFile) ThePaths.AllocatePathFindInfoMem(4500); CWeather::Init(); CCullZones::Init(); + COcclusion::Init(); CCollision::Init(); CTheZones::Init(); CUserDisplay::Init(); diff --git a/src/core/config.h b/src/core/config.h index 83aca235..5bed9c64 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -66,6 +66,8 @@ enum Config { // Cull zones NUMATTRIBZONES = 704, + NUMOCCLUSIONVOLUMES = 350, + NUMHANDLINGS = 106, PATHNODESIZE = 4500, diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp index b33b1d01..1c4e4266 100644 --- a/src/render/Occlusion.cpp +++ b/src/render/Occlusion.cpp @@ -2,6 +2,42 @@ #include "Occlusion.h" +int32 COcclusion::NumOccludersOnMap; +int16 COcclusion::FarAwayList; +int16 COcclusion::NearbyList; +int16 COcclusion::ListWalkThroughFA; +int16 COcclusion::PreviousListWalkThroughFA; +COccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES]; + +void +COcclusion::Init(void) +{ + NumOccludersOnMap = 0; + FarAwayList = -1; + NearbyList = -1; + ListWalkThroughFA = -1; + PreviousListWalkThroughFA = -1; +} + +void +COcclusion::AddOne(float x, float y, float z, float width, float length, float height, float angle) +{ + if(NumOccludersOnMap >= NUMOCCLUSIONVOLUMES) + return; + + aOccluders[NumOccludersOnMap].x = x; + aOccluders[NumOccludersOnMap].y = y; + aOccluders[NumOccludersOnMap].z = z; + aOccluders[NumOccludersOnMap].width = width; + aOccluders[NumOccludersOnMap].length = length; + aOccluders[NumOccludersOnMap].height = height; + while(angle < 0.0f) angle += 360.0f; + while(angle > 360.0f) angle -= 360.0f; + aOccluders[NumOccludersOnMap].angle = angle * UINT16_MAX/360.0f; + aOccluders[NumOccludersOnMap].listIndex = FarAwayList; + FarAwayList = NumOccludersOnMap++; +} + void COcclusion::ProcessBeforeRendering(void) { diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h index 977649b8..ac0ede5e 100644 --- a/src/render/Occlusion.h +++ b/src/render/Occlusion.h @@ -1,7 +1,26 @@ #pragma once +class COccluder +{ +public: + int16 width, length, height; + int16 x, y, z; + uint16 angle; + int16 listIndex; +}; + class COcclusion { public: + static int32 NumOccludersOnMap; + static int16 FarAwayList; + static int16 NearbyList; + static int16 ListWalkThroughFA; + static int16 PreviousListWalkThroughFA; + + static COccluder aOccluders[NUMOCCLUSIONVOLUMES]; + + static void Init(void); + static void AddOne(float x, float y, float z, float width, float length, float height, float angle); static void ProcessBeforeRendering(void); }; From 00ee82aba676c9889761cd3efcb47f78773b6ea8 Mon Sep 17 00:00:00 2001 From: Xinerki Date: Tue, 19 May 2020 11:36:08 +0300 Subject: [PATCH 057/148] Zone and Vehicle text slant --- src/render/Hud.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 6a8e6f9a..6a0b7eea 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -546,15 +546,20 @@ void CHud::Draw() else CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); + CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f)); + CFont::SetSlant(0.15f); + CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); CFont::SetFontStyle(FONT_BANK); CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint); CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint); + + CFont::SetSlant(0.f); } } } @@ -640,15 +645,20 @@ void CHud::Draw() else CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f)); + CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f)); + CFont::SetSlant(0.15f); + CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); CFont::SetFontStyle(FONT_BANK); CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(105.f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint); CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f), m_pVehicleNameToPrint); + + CFont::SetSlant(0.f); } } } From 9e14e8553fcd37dc58bb236588d1790224771b85 Mon Sep 17 00:00:00 2001 From: Xinerki Date: Tue, 19 May 2020 13:47:55 +0300 Subject: [PATCH 058/148] match frontend to vc more; isolate crgba --- src/core/Frontend.cpp | 54 ++++++++++++++++++++++++++++++------------- src/core/Frontend.h | 6 ++--- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 767fb5fc..40da314d 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -37,6 +37,18 @@ #include "Messages.h" #include "FileLoader.h" +// Similar story to Hud.cpp: +// Game has colors inlined in code. +// For easier modification we collect them here: +CRGBA LABEL_COLOR(255, 150, 225, 255); +CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255); +CRGBA MENUOPTION_COLOR(255, 150, 225, 255); +CRGBA SELECTEDMENUOPTION_COLOR(255, 150, 225, 255); +CRGBA HEADER_COLOR(255, 150, 255, 255); +CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); +CRGBA SLIDERON_COLOR(97, 194, 247, 255); +CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); + #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 #define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result @@ -269,7 +281,7 @@ ScaleAndCenterX(float x) #endif #define PREPARE_MENU_HEADER \ - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \ + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \ CFont::SetRightJustifyOn(); \ CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -636,15 +648,15 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR int lastActiveBarX = 0; float curBarX = 0.0f; - float spacing = SCREEN_SCALE_X(10.0f); + float spacing = SCREEN_SCALE_X(4.0f); // TODO: find actual numbers used in the game for (int i = 0; i < 16; i++) { - curBarX = i * rectSize/16.0f + x; + curBarX = i * rectSize/32.0f + x; if (i / 16.0f + 1 / 32.0f < progress) { - color = CRGBA(255, 217, 106, FadeIn(255)); + color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); lastActiveBarX = curBarX; } else - color = CRGBA(185, 120, 0, FadeIn(255)); + color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255)); maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); @@ -685,8 +697,10 @@ CMenuManager::Draw() CFont::SetCentreOff(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); -#ifdef GTA3_1_1_PATCH - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + + // no V1.1 text in vc obv +#if 0 //def GTA3_1_1_PATCH + CFont::SetColor(CRGBA(255, 150, 225, FadeIn(255))); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); @@ -696,6 +710,7 @@ CMenuManager::Draw() AsciiToUnicode(gString, gUString); CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); #endif + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); @@ -721,9 +736,13 @@ CMenuManager::Draw() if(!m_bRenderGameInMenu) #endif if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - + PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(17.f), SCREEN_SCALE_Y(17.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(10.f), SCREEN_SCALE_Y(10.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); // Weird place to put that. nextYToUse += 24.0f + 10.0f; @@ -732,7 +751,7 @@ CMenuManager::Draw() CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y)); CFont::SetRightJustifyOff(); - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); // Label wchar *str; @@ -830,7 +849,7 @@ CMenuManager::Draw() break; case MENUPAGE_START_MENU: columnWidth = 320; - headerHeight = 140; + headerHeight = 110; lineHeight = 24; CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); @@ -883,7 +902,7 @@ CMenuManager::Draw() } float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider - float smallestSliderBar = lineHeight * 0.1f; + float smallestSliderBar = lineHeight * 0.25f; // TODO: find actual number bool foundTheHoveringItem = false; wchar unicodeTemp[64]; char asciiTemp[32]; @@ -1211,7 +1230,7 @@ CMenuManager::Draw() // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(100, 200, 50, FadeIn(50))); + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); } CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); @@ -1230,14 +1249,14 @@ CMenuManager::Draw() if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") && !m_bGameNotLoaded && textLayer == 1) { - CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); } if (i == m_nCurrOption && itemsAreSelectable){ - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } else { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } } @@ -2361,12 +2380,15 @@ CMenuManager::DrawFrontEndNormal() // GTA LOGO RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + /* if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) { if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); else m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); } + */ + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_SCALE_X(27.0f), MENU_Y(8.0f), SCREEN_SCALE_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 2fe18b8c..ae74b16d 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -7,8 +7,8 @@ #define MENUHEADER_POS_Y 75.0f #define MENUHEADER_HEIGHT 1.3f #else -#define MENUHEADER_POS_X 35.0f -#define MENUHEADER_POS_Y 93.0f +#define MENUHEADER_POS_X 0.0f +#define MENUHEADER_POS_Y 412.0f #define MENUHEADER_HEIGHT 1.6f #endif #define MENUHEADER_WIDTH 0.84f @@ -20,7 +20,7 @@ #define MENURADIO_ICON_SCALE 60.0f -#define MENUSLIDER_X 256.0f +#define MENUSLIDER_X 128.0f #define MENUSLIDER_UNK 256.0f #define BIGTEXT_X_SCALE 0.75f From 53cdf6ab415eed19090785d24a818b3dc0d08939 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 19 May 2020 13:07:12 +0200 Subject: [PATCH 059/148] HandlingMgr --- src/core/config.h | 2 - src/vehicles/HandlingMgr.cpp | 244 +++++++++++++++++++++++++++-------- src/vehicles/HandlingMgr.h | 78 ++++++++++- src/vehicles/Vehicle.cpp | 4 +- 4 files changed, 264 insertions(+), 64 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index 5bed9c64..548092f7 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -68,8 +68,6 @@ enum Config { NUMOCCLUSIONVOLUMES = 350, - NUMHANDLINGS = 106, - PATHNODESIZE = 4500, NUMWEATHERS = 7, diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index cc6428e1..51e2604c 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -127,7 +127,7 @@ cHandlingDataMgr::Initialise(void) { LoadHandlingData(); field_0 = 0.1f; - field_4 = 0.9f; + fWheelFriction = 0.9f; field_8 = 1.0f; field_C = 0.8f; field_10 = 0.98f; @@ -143,6 +143,9 @@ cHandlingDataMgr::LoadHandlingData(void) int field, handlingId; int keepGoing; tHandlingData *handling; + tFlyingHandlingData *flyingHandling; + tBoatHandlingData *boatHandling; + tBikeHandlingData *bikeHandling; CFileMgr::SetDir("DATA"); CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r"); @@ -151,6 +154,9 @@ cHandlingDataMgr::LoadHandlingData(void) start = (char*)work_buff; end = start+1; handling = nil; + flyingHandling = nil; + boatHandling = nil; + bikeHandling = nil; keepGoing = 1; while(keepGoing){ @@ -166,61 +172,158 @@ cHandlingDataMgr::LoadHandlingData(void) // yeah, this is kinda crappy if(strncmp(line, ";the end", 9) == 0) keepGoing = 0; -// else if(line[0] != ';'){ -// TODO(MIAMI): read boat, bike, flying values - else if(line[0] != ';' && line[0] != '%' && line[0] != '!' && line[0] != '$'){ - field = 0; - strcpy(delim, " \t"); - // FIX: game seems to use a do-while loop here - for(word = strtok(line, delim); word; word = strtok(nil, delim)){ - switch(field){ - case 0: - handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); - assert(handlingId >= 0 && handlingId < NUMHANDLINGS); - handling = &HandlingData[handlingId]; - handling->nIdentifier = (eHandlingId)handlingId; - break; - case 1: handling->fMass = strtod(word, nil); break; - case 2: handling->Dimension.x = strtod(word, nil); break; - case 3: handling->Dimension.y = strtod(word, nil); break; - case 4: handling->Dimension.z = strtod(word, nil); break; - case 5: handling->CentreOfMass.x = strtod(word, nil); break; - case 6: handling->CentreOfMass.y = strtod(word, nil); break; - case 7: handling->CentreOfMass.z = strtod(word, nil); break; - case 8: handling->nPercentSubmerged = atoi(word); break; - case 9: handling->fTractionMultiplier = strtod(word, nil); break; - case 10: handling->fTractionLoss = strtod(word, nil); break; - case 11: handling->fTractionBias = strtod(word, nil); break; - case 12: handling->Transmission.nNumberOfGears = atoi(word); break; - case 13: handling->Transmission.fMaxVelocity = strtod(word, nil); break; - case 14: handling->Transmission.fEngineAcceleration = strtod(word, nil) * 0.4f; break; - case 15: handling->Transmission.nDriveType = word[0]; break; - case 16: handling->Transmission.nEngineType = word[0]; break; - case 17: handling->fBrakeDeceleration = strtod(word, nil); break; - case 18: handling->fBrakeBias = strtod(word, nil); break; - case 19: handling->bABS = !!atoi(word); break; - case 20: handling->fSteeringLock = strtod(word, nil); break; - case 21: handling->fSuspensionForceLevel = strtod(word, nil); break; - case 22: handling->fSuspensionDampingLevel = strtod(word, nil); break; - case 23: handling->fSeatOffsetDistance = strtod(word, nil); break; - case 24: handling->fCollisionDamageMultiplier = strtod(word, nil); break; - case 25: handling->nMonetaryValue = atoi(word); break; - case 26: handling->fSuspensionUpperLimit = strtod(word, nil); break; - case 27: handling->fSuspensionLowerLimit = strtod(word, nil); break; - case 28: handling->fSuspensionBias = strtod(word, nil); break; - case 29: - // TODO(MIAMI): suspension anti-dive multiplier - break; - case 30: - sscanf(word, "%x", &handling->Flags); - handling->Transmission.Flags = handling->Flags; - break; - case 31: handling->FrontLights = atoi(word); break; - case 32: handling->RearLights = atoi(word); break; + else if(line[0] != ';'){ + if(line[0] == '!'){ + // Bike data + field = 0; + strcpy(delim, " \t"); + // FIX: game seems to use a do-while loop here + for(word = strtok(line, delim); word; word = strtok(nil, delim)){ + switch(field){ + case 0: break; + case 1: + handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); + assert(handlingId >= 0 && handlingId < NUMHANDLINGS); + bikeHandling = GetBikePointer(handlingId); + bikeHandling->nIdentifier = (eHandlingId)handlingId; + break; + case 2: bikeHandling->fLeanFwdCOM = atof(word); break; + case 3: bikeHandling->fLeanFwdForce = atof(word); break; + case 4: bikeHandling->fLeanBakCOM = atof(word); break; + case 5: bikeHandling->fLeanBackForce = atof(word); break; + case 6: bikeHandling->fMaxLean = atof(word); break; + case 7: bikeHandling->fFullAnimLean = atof(word); break; + case 8: bikeHandling->fDesLean = atof(word); break; + case 9: bikeHandling->fSpeedSteer = atof(word); break; + case 10: bikeHandling->fSlipSteer = atof(word); break; + case 11: bikeHandling->fNoPlayerCOMz = atof(word); break; + case 12: bikeHandling->fWheelieAng = atof(word); break; + case 13: bikeHandling->fStoppieAng = atof(word); break; + case 14: bikeHandling->fWheelieSteer = atof(word); break; + case 15: bikeHandling->fWheelieStabMult = atof(word); break; + case 16: bikeHandling->fStoppieStabMult = atof(word); break; + } + field++; } - field++; + ConvertBikeDataToGameUnits(bikeHandling); + }else if(line[0] == '$'){ + // Flying data + field = 0; + strcpy(delim, " \t"); + // FIX: game seems to use a do-while loop here + for(word = strtok(line, delim); word; word = strtok(nil, delim)){ + switch(field){ + case 0: break; + case 1: + handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); + assert(handlingId >= 0 && handlingId < NUMHANDLINGS); + flyingHandling = GetFlyingPointer(handlingId); + flyingHandling->nIdentifier = (eHandlingId)handlingId; + break; + case 2: flyingHandling->fThrust = atof(word); break; + case 3: flyingHandling->fThrustFallOff = atof(word); break; + case 4: flyingHandling->fYaw = atof(word); break; + case 5: flyingHandling->fYawStab = atof(word); break; + case 6: flyingHandling->fSideSlip = atof(word); break; + case 7: flyingHandling->fRoll = atof(word); break; + case 8: flyingHandling->fRollStab = atof(word); break; + case 9: flyingHandling->fPitch = atof(word); break; + case 10: flyingHandling->fPitchStab = atof(word); break; + case 11: flyingHandling->fFormLift = atof(word); break; + case 12: flyingHandling->fAttackLift = atof(word); break; + case 13: flyingHandling->fMoveRes = atof(word); break; + case 14: flyingHandling->vecTurnRes.x = atof(word); break; + case 15: flyingHandling->vecTurnRes.y = atof(word); break; + case 16: flyingHandling->vecTurnRes.z = atof(word); break; + case 17: flyingHandling->vecSpeedRes.x = atof(word); break; + case 18: flyingHandling->vecSpeedRes.y = atof(word); break; + case 19: flyingHandling->vecSpeedRes.z = atof(word); break; + } + field++; + } + }else if(line[0] == '%'){ + // Boat data + field = 0; + strcpy(delim, " \t"); + // FIX: game seems to use a do-while loop here + for(word = strtok(line, delim); word; word = strtok(nil, delim)){ + switch(field){ + case 0: break; + case 1: + handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); + assert(handlingId >= 0 && handlingId < NUMHANDLINGS); + boatHandling = GetBoatPointer(handlingId); + boatHandling->nIdentifier = (eHandlingId)handlingId; + break; + case 2: boatHandling->fThrustY = atof(word); break; + case 3: boatHandling->fThrustZ = atof(word); break; + case 4: boatHandling->fThrustAppZ = atof(word); break; + case 5: boatHandling->fAqPlaneForce = atof(word); break; + case 6: boatHandling->fAqPlaneLimit = atof(word); break; + case 7: boatHandling->fAqPlaneOffset = atof(word); break; + case 8: boatHandling->fWaveAudioMult = atof(word); break; + case 9: boatHandling->vecMoveRes.x = atof(word); break; + case 10: boatHandling->vecMoveRes.y = atof(word); break; + case 11: boatHandling->vecMoveRes.z = atof(word); break; + case 12: boatHandling->vecTurnRes.x = atof(word); break; + case 13: boatHandling->vecTurnRes.y = atof(word); break; + case 14: boatHandling->vecTurnRes.z = atof(word); break; + case 15: boatHandling->fLook_L_R_BehindCamHeight = atof(word); break; + } + field++; + } + }else{ + field = 0; + strcpy(delim, " \t"); + // FIX: game seems to use a do-while loop here + for(word = strtok(line, delim); word; word = strtok(nil, delim)){ + switch(field){ + case 0: + handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); + assert(handlingId >= 0 && handlingId < NUMHANDLINGS); + handling = &HandlingData[handlingId]; + handling->nIdentifier = (eHandlingId)handlingId; + break; + case 1: handling->fMass = atof(word); break; + case 2: handling->Dimension.x = atof(word); break; + case 3: handling->Dimension.y = atof(word); break; + case 4: handling->Dimension.z = atof(word); break; + case 5: handling->CentreOfMass.x = atof(word); break; + case 6: handling->CentreOfMass.y = atof(word); break; + case 7: handling->CentreOfMass.z = atof(word); break; + case 8: handling->nPercentSubmerged = atoi(word); break; + case 9: handling->fTractionMultiplier = atof(word); break; + case 10: handling->fTractionLoss = atof(word); break; + case 11: handling->fTractionBias = atof(word); break; + case 12: handling->Transmission.nNumberOfGears = atoi(word); break; + case 13: handling->Transmission.fMaxVelocity = atof(word); break; + case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4f; break; + case 15: handling->Transmission.nDriveType = word[0]; break; + case 16: handling->Transmission.nEngineType = word[0]; break; + case 17: handling->fBrakeDeceleration = atof(word); break; + case 18: handling->fBrakeBias = atof(word); break; + case 19: handling->bABS = !!atoi(word); break; + case 20: handling->fSteeringLock = atof(word); break; + case 21: handling->fSuspensionForceLevel = atof(word); break; + case 22: handling->fSuspensionDampingLevel = atof(word); break; + case 23: handling->fSeatOffsetDistance = atof(word); break; + case 24: handling->fCollisionDamageMultiplier = atof(word); break; + case 25: handling->nMonetaryValue = atoi(word); break; + case 26: handling->fSuspensionUpperLimit = atof(word); break; + case 27: handling->fSuspensionLowerLimit = atof(word); break; + case 28: handling->fSuspensionBias = atof(word); break; + case 29: handling->fSuspensionAntidiveMultiplier = atof(word); break; + case 30: + sscanf(word, "%x", &handling->Flags); + handling->Transmission.Flags = handling->Flags; + break; + case 31: handling->FrontLights = atoi(word); break; + case 32: handling->RearLights = atoi(word); break; + } + field++; + } + ConvertDataToGameUnits(handling); } - ConvertDataToGameUnits(handling); } } } @@ -253,6 +356,7 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling) if(handling->fTurnMass < 10.0f) handling->fTurnMass *= 5.0f; handling->fInvMass = 1.0f/handling->fMass; + handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass; handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * 0.008f*handling->fMass; // What the hell is going on here? @@ -268,11 +372,16 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling) if(handling->nIdentifier == HANDLING_RCBANDIT){ handling->Transmission.fUnkMaxVelocity = handling->Transmission.fMaxVelocity; + handling->Transmission.fMaxReverseVelocity = -handling->Transmission.fMaxVelocity; + }else if(handling->nIdentifier >= HANDLING_BIKE && handling->nIdentifier <= HANDLING_FREEWAY){ + handling->Transmission.fUnkMaxVelocity = velocity; + handling->Transmission.fMaxVelocity = velocity * 1.2f; + handling->Transmission.fMaxReverseVelocity = -0.05f; }else{ handling->Transmission.fUnkMaxVelocity = velocity; handling->Transmission.fMaxVelocity = velocity * 1.2f; + handling->Transmission.fMaxReverseVelocity = -0.2f; } - handling->Transmission.fMaxReverseVelocity = -0.2f; if(handling->Transmission.nDriveType == '4') handling->Transmission.fEngineAcceleration /= 4.0f; @@ -282,6 +391,15 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling) handling->Transmission.InitGearRatios(); } +void +cHandlingDataMgr::ConvertBikeDataToGameUnits(tBikeHandlingData *handling) +{ + handling->fMaxLean = Sin(DEGTORAD(handling->fMaxLean)); + handling->fFullAnimLean = DEGTORAD(handling->fFullAnimLean); + handling->fWheelieAng = Sin(DEGTORAD(handling->fWheelieAng)); + handling->fStoppieAng = Sin(DEGTORAD(handling->fStoppieAng)); +} + int32 cHandlingDataMgr::GetHandlingId(const char *name) { @@ -291,3 +409,19 @@ cHandlingDataMgr::GetHandlingId(const char *name) break; return i; } + +tFlyingHandlingData* +cHandlingDataMgr::GetFlyingPointer(uint8 id) +{ + if(id >= HANDLING_SEAPLANE && id <= HANDLING_RCCOPTER) + return &FlyingHandlingData[id-HANDLING_SEAPLANE]; + return &FlyingHandlingData[0]; +} + +tBoatHandlingData* +cHandlingDataMgr::GetBoatPointer(uint8 id) +{ + if(id >= HANDLING_PREDATOR && id <= HANDLING_SEAPLANE) + return &BoatHandlingData[id-HANDLING_PREDATOR]; + return &BoatHandlingData[0]; +} diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index e629d885..663a548a 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -85,11 +85,13 @@ enum eHandlingId HANDLING_LOVEFIST, HANDLING_BLOODRA, HANDLING_BLOODRB, + HANDLING_BIKE, HANDLING_MOPED, HANDLING_DIRTBIKE, HANDLING_ANGEL, HANDLING_FREEWAY, + HANDLING_PREDATOR, HANDLING_SPEEDER, HANDLING_REEFER, @@ -100,7 +102,7 @@ enum eHandlingId HANDLING_DINGHY, HANDLING_MARQUIS, HANDLING_CUPBOAT, - HANDLING_SEAPLANE, + HANDLING_SEAPLANE, // both boat and plane! HANDLING_SPARROW, HANDLING_SEASPAR, HANDLING_MAVERICK, @@ -109,7 +111,13 @@ enum eHandlingId HANDLING_HUNTER, HANDLING_RCBARON, HANDLING_RCGOBLIN, - HANDLING_RCCOPTER + HANDLING_RCCOPTER, + + NUMHANDLINGS, + + NUMBIKEHANDLINGS = HANDLING_FREEWAY+1 - HANDLING_BIKE, + NUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_SEAPLANE, + NUMBOATHANDLINGS = HANDLING_SEAPLANE+1 - HANDLING_PREDATOR, }; enum @@ -168,6 +176,7 @@ struct tHandlingData float fSuspensionUpperLimit; float fSuspensionLowerLimit; float fSuspensionBias; + float fSuspensionAntidiveMultiplier; float fCollisionDamageMultiplier; uint32 Flags; float fSeatOffsetDistance; @@ -175,19 +184,74 @@ struct tHandlingData int8 FrontLights; int8 RearLights; }; -VALIDATE_SIZE(tHandlingData, 0xD8); + +struct tBikeHandlingData +{ + eHandlingId nIdentifier; + float fLeanFwdCOM; + float fLeanFwdForce; + float fLeanBakCOM; + float fLeanBackForce; + float fMaxLean; + float fFullAnimLean; + float fDesLean; + float fSpeedSteer; + float fSlipSteer; + float fNoPlayerCOMz; + float fWheelieAng; + float fStoppieAng; + float fWheelieSteer; + float fWheelieStabMult; + float fStoppieStabMult; +}; + +struct tBoatHandlingData +{ + eHandlingId nIdentifier; + float fThrustY; + float fThrustZ; + float fThrustAppZ; + float fAqPlaneForce; + float fAqPlaneLimit; + float fAqPlaneOffset; + float fWaveAudioMult; + float fLook_L_R_BehindCamHeight; + CVector vecMoveRes; + CVector vecTurnRes; +}; + +struct tFlyingHandlingData +{ + eHandlingId nIdentifier; + float fThrust; + float fThrustFallOff; + float fYaw; + float fYawStab; + float fSideSlip; + float fRoll; + float fRollStab; + float fPitch; + float fPitchStab; + float fFormLift; + float fAttackLift; + float fMoveRes; + CVector vecTurnRes; + CVector vecSpeedRes; +}; class cHandlingDataMgr { float field_0; // unused it seems public: - float field_4; // wheel related + float fWheelFriction; private: float field_8; // float field_C; // unused it seems float field_10; // tHandlingData HandlingData[NUMHANDLINGS]; - uint32 field_302C; // unused it seems + tBikeHandlingData BikeHandlingData[NUMBIKEHANDLINGS]; + tFlyingHandlingData FlyingHandlingData[NUMFLYINGHANDLINGS]; + tBoatHandlingData BoatHandlingData[NUMBOATHANDLINGS]; public: cHandlingDataMgr(void); @@ -195,8 +259,12 @@ public: void LoadHandlingData(void); int FindExactWord(const char *word, const char *words, int wordLen, int numWords); void ConvertDataToGameUnits(tHandlingData *handling); + void ConvertBikeDataToGameUnits(tBikeHandlingData *handling); int32 GetHandlingId(const char *name); tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; } + tBikeHandlingData *GetBikePointer(uint8 id) { return &BikeHandlingData[id-HANDLING_BIKE]; } + tFlyingHandlingData *GetFlyingPointer(uint8 id); + tBoatHandlingData *GetBoatPointer(uint8 id); bool HasRearWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'R'; } bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; } }; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 4b36b3d3..a7465a0d 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -528,9 +528,9 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(!bBraking){ if(m_fGasPedal < 0.01f){ if(GetModelIndex() == MI_RCBANDIT) - brake = 0.2f * mod_HandlingManager.field_4 / m_fMass; + brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass; else - brake = mod_HandlingManager.field_4 / m_fMass; + brake = mod_HandlingManager.fWheelFriction / m_fMass; #ifdef FIX_BUGS brake *= CTimer::GetTimeStepFix(); #endif From 12b48edada074ae79084dcb39fdd3f6faa0d11ea Mon Sep 17 00:00:00 2001 From: Xinerki Date: Tue, 19 May 2020 14:07:24 +0300 Subject: [PATCH 060/148] fix audio menu crash --- src/core/Frontend.cpp | 29 +++++++++++++++++------------ src/core/Frontend.h | 6 ++++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 40da314d..cf827fd1 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -209,7 +209,7 @@ const char* FrontendFilenames[][2] = { {"vcpr", "vcprA"}, {"espantoso", "espantosoA"}, {"emotion", "emotionA"}, - {"wave", "waveA"}, + {"wave103", "wave103A"}, {"mp3", "mp3A"}, {"downOff", "buttonA"}, {"downOn", "buttonA"}, @@ -303,9 +303,10 @@ ScaleAndCenterX(float x) m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ } while(0) +// TODO: this is COMPLETELY different in VC #define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \ do { \ - sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \ + sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(255, 255, 255, 100)); \ if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ m_nHoverOption = hoverOpt; \ } while (0) @@ -742,7 +743,7 @@ CMenuManager::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(17.f), SCREEN_SCALE_Y(17.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(10.f), SCREEN_SCALE_Y(10.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); // Weird place to put that. nextYToUse += 24.0f + 10.0f; @@ -1325,15 +1326,15 @@ CMenuManager::Draw() // Radio icons if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO1], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO2], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO5], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO7], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO8], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO3], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO4], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO6], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO9], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WILDSTYLE], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FLASH], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_KCHAT], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FEVER], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VROCK], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VCPR], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_ESPANTOSO], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_EMOTION], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WAVE], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); if (DMAudio.IsMP3RadioChannelAvailable()) ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_MP3], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); @@ -5161,6 +5162,9 @@ CMenuManager::PrintController(void) // FIX: Originally this function doesn't have StretchX/Y, everything had constant pixel size (due to screen was abandoned early?) // Also texts and their alignment were very bad, so I tried to make them readable (commented out the original code, and marked the ones I added with X) + // sorry! + + /* m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(240.0f), MENU_Y(180.0f), CRGBA(0, 0, 0, 255)); m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); if (m_DisplayControllerOnFoot) { @@ -5174,6 +5178,7 @@ CMenuManager::PrintController(void) else m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); } + */ CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // X diff --git a/src/core/Frontend.h b/src/core/Frontend.h index ae74b16d..114ea6ba 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -7,8 +7,8 @@ #define MENUHEADER_POS_Y 75.0f #define MENUHEADER_HEIGHT 1.3f #else -#define MENUHEADER_POS_X 0.0f -#define MENUHEADER_POS_Y 412.0f +#define MENUHEADER_POS_X 10.0f +#define MENUHEADER_POS_Y 10.0f #define MENUHEADER_HEIGHT 1.6f #endif #define MENUHEADER_WIDTH 0.84f @@ -95,6 +95,7 @@ enum eLanguages #endif }; +/* enum eFrontendSprites { FE2_MAINPANEL_UL, @@ -128,6 +129,7 @@ enum eFrontendSprites NUM_FE_SPRITES }; +*/ enum eMenuSprites { From 0d0f4da27ad982c5281f5949c22cb62593e2aab9 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 19 May 2020 13:09:20 +0200 Subject: [PATCH 061/148] little cleanup of handlingmgr --- src/core/config.h | 2 -- src/vehicles/HandlingMgr.cpp | 2 +- src/vehicles/HandlingMgr.h | 6 ++++-- src/vehicles/Vehicle.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index d9f892a6..40882128 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -65,8 +65,6 @@ enum Config { NUMATTRIBZONES = 288, NUMZONEINDICES = 55000, - NUMHANDLINGS = 57, - PATHNODESIZE = 4500, NUMWEATHERS = 4, diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 3ac0da38..5beed29e 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -78,7 +78,7 @@ cHandlingDataMgr::Initialise(void) { LoadHandlingData(); field_0 = 0.1f; - field_4 = 0.9f; + fWheelFriction = 0.9f; field_8 = 1.0f; field_C = 0.8f; field_10 = 0.98f; diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 398a415f..10e25573 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -60,7 +60,9 @@ enum eHandlingId HANDLING_PANLANT, HANDLING_FLATBED, HANDLING_YANKEE, - HANDLING_BORGNINE + HANDLING_BORGNINE, + + NUMHANDLINGS }; enum @@ -120,7 +122,7 @@ class cHandlingDataMgr { float field_0; // unused it seems public: - float field_4; // wheel related + float fWheelFriction; // wheel related private: float field_8; // float field_C; // unused it seems diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 6646f7f3..0dd95faf 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -521,9 +521,9 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(!bBraking){ if(m_fGasPedal < 0.01f){ if(GetModelIndex() == MI_RCBANDIT) - brake = 0.2f * mod_HandlingManager.field_4 / m_fMass; + brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass; else - brake = mod_HandlingManager.field_4 / m_fMass; + brake = mod_HandlingManager.fWheelFriction / m_fMass; #ifdef FIX_BUGS brake *= CTimer::GetTimeStepFix(); #endif From ffd175c705c2f515a4610074c8d36e771404d6bf Mon Sep 17 00:00:00 2001 From: Xinerki Date: Tue, 19 May 2020 14:23:59 +0300 Subject: [PATCH 062/148] fix frontend control config menu a little thank erorcun --- src/core/Frontend.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index cf827fd1..dd840bdc 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -740,7 +740,7 @@ CMenuManager::Draw() PREPARE_MENU_HEADER CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(17.f), SCREEN_SCALE_Y(17.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); PREPARE_MENU_HEADER CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); @@ -1818,11 +1818,21 @@ CMenuManager::DrawControllerSetupScreen() switch (m_ControlMethod) { case CONTROL_STANDARD: - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), + TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); break; case CONTROL_CLASSIC: - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), + TheText.Get("FET_CTI")); + + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_CTI")); break; default: From a6972714b7ce5b7834e55a3b23acf28cf51a78ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Tue, 19 May 2020 17:39:19 +0300 Subject: [PATCH 063/148] Melee weapons(half-working), Ped and Hud bits --- src/control/Pickups.cpp | 22 ++- src/control/Script.cpp | 12 ++ src/core/EventList.h | 6 +- src/core/Streaming.cpp | 3 +- src/entities/Physical.h | 2 +- src/modelinfo/ModelIndices.h | 1 + src/peds/CopPed.cpp | 2 +- src/peds/Gangs.cpp | 2 +- src/peds/Ped.cpp | 279 ++++++++++++++-------------- src/peds/Ped.h | 52 +++--- src/peds/PedAttactor.cpp | 6 +- src/peds/PlayerPed.cpp | 29 ++- src/peds/Population.cpp | 14 +- src/render/Hud.cpp | 294 +++++++++++++++++++++++------ src/render/Hud.h | 39 ++++ src/vehicles/Vehicle.h | 1 + src/weapons/Weapon.cpp | 346 ++++++++++++++++++++++++++++------- src/weapons/WeaponInfo.cpp | 15 +- src/weapons/WeaponType.h | 10 + 19 files changed, 820 insertions(+), 315 deletions(-) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index eb772e13..78b8d198 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -49,6 +49,16 @@ uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 5 uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS] = { 0, 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, 4, 4, 4, @@ -70,16 +80,20 @@ uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS] = { uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 }; // TODO(Miami): Those are all placeholders!! -uint8 aWeaponReds[] = { 0, 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, +uint8 aWeaponReds[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 255, 0 }; -uint8 aWeaponGreens[] = { 0, 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, +uint8 aWeaponGreens[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 255, 0 }; -uint8 aWeaponBlues[] = { 0, 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, +uint8 aWeaponBlues[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 128, 255, 0, 0 }; -float aWeaponScale[] = { 1.0f, 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, +float aWeaponScale[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, +2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index ee580cbd..0ff3c53d 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -9986,8 +9986,20 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) { switch (command) { case COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG: + { + CollectParameters(&m_nIp, 3); + CPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]); + uint8 flag = 1 << (uint8)ScriptParams[1]; + if (ScriptParams[2]) + pTarget->m_gangFlags |= flag; + else + pTarget->m_gangFlags &= ~flag; + + return 0; + } case COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE: case COMMAND_IS_MISSION_AUDIO_PLAYING: + assert(0); case COMMAND_CREATE_LOCKED_PROPERTY_PICKUP: { CollectParameters(&m_nIp, 3); diff --git a/src/core/EventList.h b/src/core/EventList.h index 8840afc4..f2c3d7a8 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -22,10 +22,12 @@ enum eEventType EVENT_PED_SET_ON_FIRE, EVENT_COP_SET_ON_FIRE, EVENT_CAR_SET_ON_FIRE, - EVENT_ASSAULT_NASTYWEAPON, // not sure + EVENT_ASSAULT_NASTYWEAPON, + EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ICECREAM, EVENT_ATM, - EVENT_SHOPSTALL, // used on graffitis + EVENT_SHOPSTALL, + EVENT_SHOPWINDOW, EVENT_LAST_EVENT }; diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 09d5cc72..0ce8b50e 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1337,8 +1337,7 @@ CStreaming::LoadInitialPeds(void) void CStreaming::LoadInitialWeapons(void) { - // TODO(Miami): Enable when weapons have been ported - //CStreaming::RequestModel(MI_NIGHTSTICK, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_NIGHTSTICK, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(MI_MISSILE, STREAMFLAGS_DONT_REMOVE); } diff --git a/src/entities/Physical.h b/src/entities/Physical.h index ce02e463..b6e28275 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -46,7 +46,7 @@ public: float m_fDistanceTravelled; // damaged piece - float m_fDamageImpulse; + float m_fDamageImpulse; // fCollisionPower CEntity *m_pDamageEntity; CVector m_vecDamageNormal; int16 m_nDamagePieceType; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 9846796d..07d832f3 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -404,6 +404,7 @@ enum MI_TRAIN = -1, MI_DODO = -2, + MI_NIGHTSTICK = 262, MI_BASEBALL_BAT = 264, MI_GRENADE = 270, MI_MOLOTOV = 272, diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 578f2454..b84dcf14 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -23,7 +23,7 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) switch (copType) { case COP_STREET: SetModelIndex(MI_COP); - // GiveWeapon(WEAPONTYPE_NIGHTSTICK, 1000, true); // TODO(Miami) + GiveWeapon(WEAPONTYPE_NIGHTSTICK, 1000, true); GiveDelayedWeapon(WEAPONTYPE_COLT45, 1000); m_currentWeapon = WEAPONTYPE_UNARMED; m_fArmour = 0.0f; diff --git a/src/peds/Gangs.cpp b/src/peds/Gangs.cpp index 301eb3be..2d6d1137 100644 --- a/src/peds/Gangs.cpp +++ b/src/peds/Gangs.cpp @@ -36,7 +36,7 @@ void CGangs::Initialise(void) SetGangVehicleModel(GANG_BIKER, MI_ANGEL); SetGangVehicleModel(GANG_PLAYER, -1); SetGangVehicleModel(GANG_GOLFER, MI_CADDY); - //SetGangWeapons(GANG_GOLFER, WEAPONTYPE_GOLFCLUB, WEAPONTYPE_GOLFCLUB); // TODO(MIAMI) + SetGangWeapons(GANG_GOLFER, WEAPONTYPE_GOLFCLUB, WEAPONTYPE_GOLFCLUB); #ifdef FIX_BUGS for (int i = 0; i < NUM_GANGS; i++) SetGangPedModelOverride(i, -1); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 0eb85f34..2e5898f6 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -116,32 +116,8 @@ uint16 nPlayerInComboMove; RpClump *flyingClumpTemp; -// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat. FightMove tFightMoves[NUM_FIGHTMOVES] = { - {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0}, - {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0}, - {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0}, - {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0}, - {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0}, - {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0}, - {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0}, - {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0}, - {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0}, - {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0}, - {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, - {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, + // TODO(Miami) }; uint16 CPed::nThreatReactionRangeMultiplier = 1; @@ -621,6 +597,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bSomeVCflag1 = false; #endif + m_gangFlags = 0xFF; + bReachedAttractorHeadingTarget = false; bTurnedAroundOnAttractor = false; bCarPassenger = false; @@ -663,9 +641,16 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) GiveWeapon(WEAPONTYPE_UNARMED, 0, true); m_wepAccuracy = 60; m_lastWepDam = -1; + m_lastDamEntity = nil; + m_attachedTo = nil; + m_attachWepAmmo = 0; m_collPoly.valid = false; m_fCollisionSpeed = 0.0f; m_wepModelID = -1; + uint16 random = CGeneral::GetRandomNumber(); + m_nPedMoney = random % 25; + if (m_nPedMoney == 23) + m_nPedMoney = 400; #ifdef PED_SKIN m_pWeaponModel = nil; #endif @@ -1180,7 +1165,7 @@ CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg) if (ped->bIsDucking && ped->bCrouchWhenShooting) { CAnimBlendAssociation *crouchFireAssoc = nil; if (!!weapon->m_bCrouchFire) { - crouchFireAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_WEAPON_CROUCHFIRE); + crouchFireAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchFireAnim(weapon)); } if (!!weapon->m_bReload && reloadAssoc) { if (reloadAssoc->animId == GetCrouchReloadAnim(weapon) && !crouchFireAssoc) { @@ -1219,7 +1204,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon)); } if (currentWeapon->m_bCrouchFire && attackAssoc) { - if (attackAssoc->animId == ANIM_WEAPON_CROUCHFIRE && !reloadAnimAssoc) { + if (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) { newAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 8.0f); newAnim->SetCurrentTime(newAnim->hierarchy->totalLength); newAnim->flags &= ~ASSOC_RUNNING; @@ -1245,7 +1230,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) reloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon)); } if (currentWeapon->m_bCrouchFire && attackAssoc) { - if (attackAssoc->animId == ANIM_WEAPON_CROUCHFIRE && !reloadAnimAssoc) { + if (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) { newAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 8.0f); newAnim->SetCurrentTime(newAnim->hierarchy->totalLength); newAnim->flags &= ~ASSOC_RUNNING; @@ -1273,15 +1258,6 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) newAnim->SetFinishCallback(FinishedAttackCB, ped); } } else { - // TODO(Miami): Remove this block when fighting has been ported - if (attackAssoc && attackAssoc->animId == ANIM_FIGHT_PPUNCH && currentWeapon->m_AnimToPlay == ASSOCGRP_STD) - { - attackAssoc->blendDelta = -8.0f; - attackAssoc->flags |= ASSOC_DELETEFADEDOUT; - ped->ClearAttack(); - return; - } - if (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK && currentWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) { attackAssoc->blendDelta = -8.0f; @@ -1340,7 +1316,7 @@ CPed::Attack(void) if (bIsDucking) { if (!!ourWeapon->m_bCrouchFire && bCrouchWhenShooting) { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(ourWeapon)); if (weaponAnimAssoc) { animLoopStart = ourWeapon->m_fAnim2LoopStart; animLoopEnd = ourWeapon->m_fAnim2LoopEnd; @@ -1393,7 +1369,6 @@ CPed::Attack(void) meleeAttackStarted = true; switch ( ourWeapon->m_AnimToPlay ) { - case ASSOCGRP_STD: // TODO(Miami): Remove that when weapons ported case ASSOCGRP_UNARMED: case ASSOCGRP_SCREWDRIVER: case ASSOCGRP_KNIFE: @@ -1434,7 +1409,7 @@ CPed::Attack(void) if (attackShouldContinue) { if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) { if (bCrouchWhenShooting && bIsDucking && !!ourWeapon->m_bCrouchFire) { - weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_CROUCHFIRE, 8.0f); + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f); } else if(!!ourWeapon->m_bUse2nd && CGeneral::GetRandomNumber() & 1){ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE_2ND, 8.0f); @@ -1496,9 +1471,7 @@ CPed::Attack(void) if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) { firePos = GetMatrix() * firePos; } else { - // TODO(Miami): Remove ANIM_KICK_FLOOR when fighting is done - TransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_KICK_FLOOR || - weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR); + TransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR); } GetWeapon()->Fire(this, &firePos); @@ -1518,10 +1491,8 @@ CPed::Attack(void) damagerType = m_pDamageEntity->GetType(); } switch (ourWeapon->m_AnimToPlay) { - case ASSOCGRP_STD: // TODO(Miami): Remove after fighting done case ASSOCGRP_UNARMED: - if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH || // TODO(Miami): Remove after fighting done - weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) { + if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) { #ifdef AUDIO_NOT_READY DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); #else @@ -1780,15 +1751,19 @@ CPed::SetCurrentWeapon(int slot) } } -// --MIAMI: TODO when weapons got converted +// --MIAMI: Done // Only used while deciding which gun ped should switch to, if no ammo left. bool CPed::SelectGunIfArmed(void) { - for (int i = 0; i < m_maxWeaponTypeAllowed; i++) { + for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) { if (GetWeapon(i).m_nAmmoTotal > 0) { eWeaponType weaponType = GetWeapon(i).m_eWeaponType; - if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) { + + // First condition checks for Pistol, Python and Shotguns + if ((weaponType >= WEAPONTYPE_COLT45 && weaponType < WEAPONTYPE_TEC9) || + weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M16 || weaponType == WEAPONTYPE_MP5 || + weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_SNIPERRIFLE) { SetCurrentWeapon(i); return true; } @@ -1798,39 +1773,54 @@ CPed::SelectGunIfArmed(void) return false; } +// --MIAMI: Done void CPed::Duck(void) { if (CTimer::GetTimeInMilliseconds() > m_duckTimer) ClearDuck(); + else if (bIsDucking && bCrouchWhenShooting) { + CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + CAnimBlendAssociation *attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH); + if (!attackAssoc) { + if(!!weapon->m_bCrouchFire) + attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon)); + } + if (!attackAssoc) { + if(!!weapon->m_bReload) + attackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(weapon)); + } + if (!attackAssoc) { + bIsDucking = false; + } + } } +// --MIAMI: Done void -CPed::ClearDuck(void) +CPed::ClearDuck(bool clearTimer) { CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); if (!animAssoc) { animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); - - if (!animAssoc) { - bIsDucking = false; - return; - } } - if (!bCrouchWhenShooting) - return; + if (!animAssoc) { + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH); + } - if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN) - return; + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -4.0f; + } + bIsDucking = false; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); - if (!animAssoc || animAssoc->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); + if (clearTimer) { + m_duckTimer = 0; } } -// --MIAMI: Done except commented thing +// --MIAMI: Done void CPed::ClearPointGunAt(void) { @@ -1851,7 +1841,7 @@ CPed::ClearPointGunAt(void) animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE); if (!animAssoc || animAssoc->blendDelta < 0.0f) { if (!!weaponInfo->m_bCrouchFire) { - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo)); } } if (animAssoc) { @@ -2690,7 +2680,7 @@ CPed::SetModelIndex(uint32 mi) m_animGroup = (AssocGroupId) modelInfo->m_animGroup; CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE); - // TODO(Miami): This is something inlined for sure + // TODO(Miami): This is inlined CanUseTorsoWhenLooking bool canUseMyBody = false; if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) { if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN) @@ -2714,7 +2704,13 @@ CPed::SetModelIndex(uint32 mi) void CPed::RemoveLighting(bool reset) { - CRenderer::RemoveVehiclePedLights(this, reset); + if (!bRenderScorched) { + CRenderer::RemoveVehiclePedLights(this, reset); + if (reset) + ReSetAmbientAndDirectionalColours(); + } + SetAmbientColours(); + DeActivateDirectional(); } bool @@ -2779,14 +2775,15 @@ CPed::WorkOutHeadingForMovingFirstPerson(float offset) angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown); } else { if (leftRight < 0.0f) - angle = 0.5f * PI; + angle = HALFPI; else if (leftRight > 0.0f) - angle = -0.5f * PI; + angle = -HALFPI; } return CGeneral::LimitRadianAngle(offset + angle); } +// --MIAMI: Done void CPed::CalculateNewVelocity(void) { @@ -2801,9 +2798,6 @@ CPed::CalculateNewVelocity(void) limitedRotDest -= 2 * PI; } - if (IsPlayer() && m_nPedState == PED_ATTACK) - headAmount /= 4.0f; - float neededTurn = limitedRotDest - m_fRotationCur; if (neededTurn <= headAmount) { if (neededTurn > (-headAmount)) @@ -2827,8 +2821,12 @@ CPed::CalculateNewVelocity(void) } if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam()) - || FindPlayerPed() != this || !CanStrafeOrMouseControl()) + || FindPlayerPed() != this || !CanStrafeOrMouseControl()) { + + if (FindPlayerPed() == this) + FindPlayerPed()->m_fWalkAngle = 0.0f; return; + } float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur); float pedSpeed = m_moved.Magnitude(); @@ -2848,16 +2846,13 @@ CPed::CalculateNewVelocity(void) CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); -#ifdef VC_PED_PORTS if(!fightAssoc) fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); - // There is one more anim in VC. + if(!fightAssoc) + fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHRELOAD); if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) { -#else - if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) { -#endif LimbOrientation newUpperLegs; newUpperLegs.yaw = localWalkAngle; @@ -3941,7 +3936,7 @@ CPed::ClearAttackByRemovingAnim(void) if (!weaponAssoc) { if (!!weapon->m_bCrouchFire) - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon)); } if (!weaponAssoc) { if(!!weapon->m_bFinish3rd) @@ -4913,7 +4908,7 @@ CPed::SetPointGunAt(CEntity *to) if (bCrouchWhenShooting && bIsDucking) { if (!!curWeapon->m_bCrouchFire) { - aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon)); } } else { aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE); @@ -4922,7 +4917,7 @@ CPed::SetPointGunAt(CEntity *to) if (!aimAssoc || aimAssoc->blendDelta < 0.0f) { if (bCrouchWhenShooting && bIsDucking) { if (!!curWeapon->m_bCrouchFire) { - aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_CROUCHFIRE, 4.0f); + aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f); } } else { aimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE); @@ -5194,7 +5189,7 @@ CPed::SetAttack(CEntity *victim) } // TODO(Miami): Brass knuckles - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || curWeapon->m_bFightMode /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLES */) { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || curWeapon->m_bFightMode || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) { if (IsPlayer() || (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS) && curWeapon->m_bPartialAttack)) { @@ -5206,10 +5201,7 @@ CPed::SetAttack(CEntity *victim) m_nPedState = PED_ATTACK; bIsAttacking = false; - // TODO(Miami): Revert when fighting got ported - animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, - GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED ? ANIM_FIGHT_PPUNCH : ANIM_MELEE_ATTACK_START, 8.0f); - // CAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f); + CAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f); animAssoc->SetRun(); if (animAssoc->currentTime == animAssoc->hierarchy->totalLength) animAssoc->SetCurrentTime(0.0f); @@ -5313,13 +5305,13 @@ CPed::SetAttack(CEntity *victim) m_nPedState = PED_ATTACK; SetMoveState(PEDMOVE_NONE); if (bCrouchWhenShooting && bIsDucking && !!curWeapon->m_bCrouchFire) { - CAnimBlendAssociation* curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + CAnimBlendAssociation* curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon)); if (curMoveAssoc) { - if (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, ANIM_WEAPON_CROUCHFIRE)->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) { + if (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon))->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) { delete curMoveAssoc; } } - animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_CROUCHFIRE, 8.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 8.0f); } else { float animDelta = 8.0f; if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) @@ -5439,10 +5431,11 @@ CPed::StartFightAttack(uint8 buttonPressure) nPlayerInComboMove = 0; } +// --MIAMI: Done void CPed::LoadFightData(void) { - float startFireTime, endFireTime, comboFollowOnTime, strikeRadius; + float startFireTime, endFireTime, comboFollowOnTime, strikeRadius, extendReachMultiplier; int damage, flags; char line[256], moveName[32], animName[32], hitLevel; int moveId = 0; @@ -5471,12 +5464,13 @@ CPed::LoadFightData(void) sscanf( &line[lp], - "%s %f %f %f %f %c %s %d %d", + "%s %f %f %f %f %f %c %s %d %d", moveName, &startFireTime, &endFireTime, &comboFollowOnTime, &strikeRadius, + &extendReachMultiplier, &hitLevel, animName, &damage, @@ -5489,6 +5483,7 @@ CPed::LoadFightData(void) tFightMoves[moveId].endFireTime = endFireTime / 30.0f; tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f; tFightMoves[moveId].strikeRadius = strikeRadius; + tFightMoves[moveId].extendReachMultiplier = extendReachMultiplier; tFightMoves[moveId].damage = damage; tFightMoves[moveId].flags = flags; @@ -5512,11 +5507,14 @@ CPed::LoadFightData(void) break; } - if (strncmp(animName, "null", 4) != 0) { - animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName); - tFightMoves[moveId].animId = (AnimationId)animAssoc->animId; - } else { - tFightMoves[moveId].animId = ANIM_WALK; + if (strncmp(animName, "default", 8) != 0) { + if (strncmp(animName, "null", 5) != 0) { + animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName); + tFightMoves[moveId].animId = (AnimationId)animAssoc->animId; + } + else { + tFightMoves[moveId].animId = ANIM_WALK; + } } moveId++; } @@ -5609,6 +5607,7 @@ CPed::FightStrike(CVector &touchedNodePos) damageMult *= m_pedStats->m_attackStrength; } + /* // Change direction if we used kick. if (m_lastFightMove == FIGHTMOVE_KICK) { if (CGeneral::GetRandomNumber() & 1) { @@ -5616,7 +5615,7 @@ CPed::FightStrike(CVector &touchedNodePos) if (direction > 3) direction -= 4; } - } + } */ nearPed->ReactToAttack(this); // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it. @@ -6356,6 +6355,7 @@ CPed::CollideWithPed(CPed *collideWith) } } +// --MIAMI: Done except commented thing void CPed::CreateDeadPedMoney(void) { @@ -6363,29 +6363,31 @@ CPed::CreateDeadPedMoney(void) return; int skin = GetModelIndex(); + + // TODO(Miami): New flag if ((skin >= MI_COP && skin <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle) return; - int money = CGeneral::GetRandomNumber() % 60; + int money = m_nPedMoney; if (money < 10) return; - if (money == 43) - money = 700; + CVector pickupPos = GetPosition(); + bool found; - int pickupCount = money / 40 + 1; + int pickupCount = Min(money / 20 + 1, 7); int moneyPerPickup = money / pickupCount; for(int i = 0; i < pickupCount; i++) { // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. - float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x; - float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y; - bool found = false; - float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; + pickupPos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128); + pickupPos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128); + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; if (found) { - CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7)); + CPickups::GenerateNewOne(CVector(pickupPos.x, pickupPos.y, pickupPos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3)); } } + m_nPedMoney = 0; } void @@ -6556,13 +6558,6 @@ CPed::RemoveWeaponAnims(int unused, float animDelta) CAnimBlendAssociation *weaponAssoc; //CWeaponInfo::GetWeaponInfo(unused); - // TODO(Miami): Remove when fighting got ported - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_PPUNCH); - if (weaponAssoc) { - weaponAssoc->blendDelta = animDelta; - weaponAssoc->flags |= ASSOC_DELETEFADEDOUT; - } - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE); if (weaponAssoc) { weaponAssoc->blendDelta = animDelta; @@ -6723,6 +6718,7 @@ CPed::DoesLOSBulletHitPed(CColPoint &colPoint) return retVal; } +// TODO(Miami): Ducking doesn't work, fix this bool CPed::DuckAndCover(void) { @@ -6740,9 +6736,11 @@ CPed::DuckAndCover(void) SetAimFlag(m_pedInObjective); } else { - bCrouchWhenShooting = false; bKindaStayInSamePlace = false; - bIsDucking = false; + if (bIsDucking) + ClearDuck(true); + + bCrouchWhenShooting = false; bDuckAndCover = false; m_headingRate = 10.0f; m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000); @@ -6755,8 +6753,11 @@ CPed::DuckAndCover(void) bool justDucked = false; CVehicle *foundVeh = nil; float maxDist = 225.0f; - bIsDucking = false; + if (bIsDucking) + ClearDuck(true); + bCrouchWhenShooting = false; + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { CVector pos = GetPosition(); int16 lastVehicle; @@ -7145,13 +7146,9 @@ CPed::Fight(void) case FIGHTMOVE_KNEE: TransformToNode(touchingNodePos, PED_LOWERLEGR); break; - case FIGHTMOVE_HEADBUTT: - TransformToNode(touchingNodePos, PED_HEAD); - break; case FIGHTMOVE_PUNCHJAB: TransformToNode(touchingNodePos, PED_HANDL); break; - case FIGHTMOVE_KICK: case FIGHTMOVE_LONGKICK: case FIGHTMOVE_ROUNDHOUSE: case FIGHTMOVE_GROUNDKICK: @@ -7212,12 +7209,12 @@ CPed::Fight(void) canRoundhouse = false; punchOnly = false; canKick = true; - nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE); + nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_BODYBLOW : FIGHTMOVE_KNEE); hasShoppingBags = false; canKneeHead = true; nPlayerInComboMove = 0; } else { - nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE); + nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_BODYBLOW : FIGHTMOVE_KNEE); uint16 pedFeatures = m_pedStats->m_flags; punchOnly = pedFeatures & STAT_PUNCH_ONLY; canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE; @@ -7256,7 +7253,7 @@ CPed::Fight(void) && neededTurn < DEGTORAD(35.0f) && (canKick || hasShoppingBags)) { - nextFightMove = FIGHTMOVE_KICK; + nextFightMove = FIGHTMOVE_LONGKICK; if (hasShoppingBags) { nextFightMove = FIGHTMOVE_ROUNDHOUSE; } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) { @@ -7349,7 +7346,7 @@ CPed::Fight(void) if (fightingPedDist >= 1.3f) { if (fightingPedDist < 1.7f && canKick) { - nextFightMove = FIGHTMOVE_KICK; + nextFightMove = FIGHTMOVE_LONGKICK; if (canRoundhouse && CGeneral::GetRandomNumber() & 1) nextFightMove = FIGHTMOVE_ROUNDHOUSE; @@ -9326,7 +9323,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) void CPed::Look(void) { - // UNUSED: This is a perfectly empty function. + TurnBody(); } bool @@ -11267,6 +11264,7 @@ CPed::SetInTheAir(void) void CPed::RestoreHeadPosition(void) { + // TODO(Miami): This is inlined CanUseTorsoWhenLooking bool canUseMyBody = false; if (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) { if (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN) @@ -11296,7 +11294,7 @@ CPed::PointGunAt(void) CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE); if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f) { if (!!weaponInfo->m_bCrouchFire) { - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo)); animLoopStart = weaponInfo->m_fAnim2LoopStart; } } @@ -15624,19 +15622,22 @@ CPed::SetEnterTrain(CVehicle *train, uint32 unused) } #endif +// --MIAMI: Done, but what is this parameter for? void -CPed::SetDuck(uint32 time) +CPed::SetDuck(uint32 time, bool sth) { - if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer) - return; - - if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) { - CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); - if (!duckAssoc || duckAssoc->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f); - bIsDucking = true; + if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer && !sth) { + if (sth && CTimer::GetTimeInMilliseconds() + time > m_duckTimer) m_duckTimer = CTimer::GetTimeInMilliseconds() + time; - } + return; + } + + CAnimBlendAssociation *duckAssoc; + if (bCrouchWhenShooting) { + duckAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WEAPON_CROUCH, 4.0f); + duckAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + bIsDucking = true; + m_duckTimer = CTimer::GetTimeInMilliseconds() + time; } else { CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); if (!duckAssoc || duckAssoc->blendDelta < 0.0f) { @@ -18559,7 +18560,7 @@ CPed::ClearFollowPath() m_nCurPathNode = 0; } -// --MIAMI: Done +// --MIAMI: Done except bikes void CPed::AddInCarAnims(CVehicle* car, bool isDriver) { @@ -18597,4 +18598,10 @@ CPed::AddInCarAnims(CVehicle* car, bool isDriver) m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), group, anim, 100.0f); StopNonPartialAnims(); +} + +bool +CPed::CanBeDamagedByThisGangMember(CPed* who) +{ + return m_gangFlags & (1 << (uint8)(who->m_nPedType - PEDTYPE_GANG1)); } \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 42fec06c..f1138722 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -79,11 +79,11 @@ struct FightMove float endFireTime; float comboFollowOnTime; float strikeRadius; + float extendReachMultiplier; uint8 hitLevel; // FightMoveHitLevel uint8 damage; uint8 flags; }; -VALIDATE_SIZE(FightMove, 0x18); // TODO: This is eFightState on mobile. enum PedFightMoves @@ -94,13 +94,21 @@ enum PedFightMoves FIGHTMOVE_IDLE, FIGHTMOVE_SHUFFLE_F, FIGHTMOVE_KNEE, - FIGHTMOVE_HEADBUTT, - FIGHTMOVE_PUNCHJAB, FIGHTMOVE_PUNCHHOOK, - FIGHTMOVE_KICK, + FIGHTMOVE_PUNCHJAB, + FIGHTMOVE_PUNCH, + FIGHTMOVE_BODYBLOW = FIGHTMOVE_PUNCH, FIGHTMOVE_LONGKICK, FIGHTMOVE_ROUNDHOUSE, - FIGHTMOVE_BODYBLOW, + // Directionals + FIGHTMOVE_FWDLEFT, + FIGHTMOVE_FWDRIGHT, + FIGHTMOVE_BACKKICK, + FIGHTMOVE_BACKFLIP, + FIGHTMOVE_BACKLEFT, + FIGHTMOVE_BACKRIGHT, + FIGHTMOVE_RIGHTSWEEP, + // Special FIGHTMOVE_GROUNDKICK, // Opponent FIGHTMOVE_HITFRONT, @@ -113,6 +121,9 @@ enum PedFightMoves FIGHTMOVE_HITBIGSTEP, FIGHTMOVE_HITONFLOOR, FIGHTMOVE_HITBEHIND, + FIGHTMOVE_MELEE1, + FIGHTMOVE_MELEE2, + FIGHTMOVE_MELEE3, FIGHTMOVE_IDLE2NORM, NUM_FIGHTMOVES }; @@ -435,6 +446,7 @@ public: uint32 bMiamiViceCop : 1; // 0x155 0x20 uint32 bDeadPedInFrontOfCar : 1; // 0x156 0x40 + uint8 m_gangFlags; uint8 CharCreatedBy; eObjective m_objective; eObjective m_prevObjective; @@ -557,7 +569,7 @@ public: int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't CPed *m_nearPeds[10]; uint16 m_numNearPeds; - uint16 m_pedMoney; + uint16 m_nPedMoney; int8 m_lastWepDam; CEntity *m_lastDamEntity; CEntity *m_attachedTo; @@ -620,7 +632,7 @@ public: void SetCurrentWeapon(eWeaponType weaponType); void SetCurrentWeapon(int weapon); void Duck(void); - void ClearDuck(void); + void ClearDuck(bool = false); void ClearPointGunAt(void); void BeingDraggedFromCar(void); void RestartNonPartialAnims(void); @@ -648,7 +660,7 @@ public: void ClearChat(void); void InformMyGangOfAttack(CEntity*); void ReactToAttack(CEntity*); - void SetDuck(uint32); + void SetDuck(uint32, bool = false); void RegisterThreatWithGangPeds(CEntity*); bool TurnBody(void); void Chat(void); @@ -777,6 +789,7 @@ public: void GiveDelayedWeapon(eWeaponType weapon, uint32 ammo); void RequestDelayedWeapon(); void AddInCarAnims(CVehicle* car, bool isDriver); + bool CanBeDamagedByThisGangMember(CPed*); // Static methods static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset); @@ -877,7 +890,7 @@ public: bool Dead(void) { return m_nPedState == PED_DEAD; } bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } - bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD || m_nWaitState == WAITSTATE_SUN_BATHE_IDLE; } + bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. @@ -895,10 +908,6 @@ public: // My names. Inlined in VC AnimationId GetFireAnimNotDucking(CWeaponInfo* weapon) { - // TODO(Miami): Revert that when weapons got ported - if (weapon->m_AnimToPlay == ASSOCGRP_STD) - return ANIM_FIGHT_PPUNCH; - if (m_nPedType == PEDTYPE_COP && !!weapon->m_bCop3rd) return ANIM_WEAPON_FIRE_3RD; else @@ -906,14 +915,10 @@ public: } static AnimationId GetFireAnimGround(CWeaponInfo* weapon, bool kickFloorIfNone = true) { - // TODO(Miami): Revert that when weapons got ported - if (weapon->m_AnimToPlay == ASSOCGRP_STD) - return ANIM_KICK_FLOOR; - if (!!weapon->m_bGround2nd) return ANIM_WEAPON_CROUCHFIRE; else if (!!weapon->m_bGround3rd) - return ANIM_WEAPON_SPECIAL; + return ANIM_WEAPON_FIRE_3RD; else if (kickFloorIfNone) return ANIM_KICK_FLOOR; else @@ -921,10 +926,6 @@ public: } static AnimationId GetPrimaryFireAnim(CWeaponInfo* weapon) { - // TODO(Miami): Revert that when weapons got ported - if (weapon->m_AnimToPlay == ASSOCGRP_STD) - return ANIM_FIGHT_PPUNCH; - if (weapon->m_bAnimDetonate) return ANIM_BOMBER; else @@ -938,6 +939,13 @@ public: return (AnimationId)0; } + static AnimationId GetCrouchFireAnim(CWeaponInfo* weapon) { + if (!!weapon->m_bCrouchFire) + return ANIM_WEAPON_CROUCHFIRE; + else + return (AnimationId)0; + } + static AnimationId GetReloadAnim(CWeaponInfo* weapon) { if (!!weapon->m_bReload) return ANIM_WEAPON_RELOAD; diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp index 0df59b1c..782d2770 100644 --- a/src/peds/PedAttactor.cpp +++ b/src/peds/PedAttactor.cpp @@ -12,7 +12,7 @@ const int gcMaxSizeOfPizzaQueue = 5; const int gcMaxSizeOfShelterQueue = 5; const int gcMaxSizeOfIceCreamQueue = 1; -//--MIAMI: file done, except TODO(MIAMI) +//--MIAMI: file done std::vector CPedShelterAttractor::ms_displacements; @@ -167,19 +167,15 @@ CPedAttractor::CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 ma void CPedPizzaAttractor::UpdatePedStateOnDeparture(CPed* pPed) const { - /* TODO(MIAMI): uncomment if (pPed->m_nPedMoney > 10) pPed->m_nPedMoney -= 10; else pPed->m_nPedMoney = 0; - */ } void CPedAtmAttractor::UpdatePedStateOnDeparture(CPed* pPed) const { - /* TODO(MIAMI): uncomment pPed->m_nPedMoney += 20 * CGeneral::GetRandomNumberInRange(1, 51); - */ }; float CPedAttractor::ComputeDeltaHeading() const diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 69a6d211..9f972882 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1088,6 +1088,7 @@ CPlayerPed::ProcessAnimGroups(void) } } +// TODO(Miami): Hella TODO void CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) { @@ -1099,8 +1100,9 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) } if (!m_pFire) { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || - GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { - if (padUsed->TargetJustDown()) { + GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 || + GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47) { + if (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) { SetStoredState(); m_nPedState = PED_SNIPER_MODE; #ifdef FREE_CAM @@ -1134,7 +1136,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) else #endif SetAttack(m_pPointGunAt); - } else if (m_currentWeapon != WEAPONTYPE_UNARMED) { + } else { if (m_nPedState == PED_ATTACK) { if (padUsed->WeaponJustDown()) { m_bHaveTargetSelected = true; @@ -1145,12 +1147,19 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; } - SetAttack(nil); - } else if (padUsed->WeaponJustDown()) { - if (m_fMoveSpeed < 1.0f) - StartFightAttack(padUsed->GetWeapon()); - else - SetAttack(nil); + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && + !weaponInfo->m_bFightMode) { + + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR && GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE || + padUsed->WeaponJustDown()) + + SetAttack(nil); + } else if (padUsed->WeaponJustDown()) { + if (m_fMoveSpeed < 1.0f || m_nPedState == PED_FIGHT) + StartFightAttack(padUsed->GetWeapon()); + else + SetAttack(nil); + } } } } else { @@ -1185,7 +1194,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) #endif } else { m_fRotationDest = limitedCam; - m_headingRate = 50.0f; + m_headingRate = 12.5f; // Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly) if (weaponInfo->m_bCanAim && padUsed->WeaponJustDown()) { diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 44bedab9..338c47f0 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -461,17 +461,16 @@ CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors, if (ms_bGivePedsWeapons) { eWeaponType weapon; - // TODO(Miami): Look here when weapons have been ported switch (CGeneral::GetRandomNumber() & 3) { case 0: weapon = WEAPONTYPE_COLT45; break; case 1: - //weapon = WEAPONTYPE_NIGHTSTICK; - //break; + weapon = WEAPONTYPE_NIGHTSTICK; + break; case 2: - //weapon = WEAPONTYPE_GOLFCLUB; - //break; + weapon = WEAPONTYPE_GOLFCLUB; + break; case 3: weapon = WEAPONTYPE_TEC9; break; @@ -1093,8 +1092,7 @@ CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit) return nil; CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - //TODO(MIAMI): uncomment - //pPed->m_nPedMoney = 0; + pPed->m_nPedMoney = 0; pPed->bDeadPedInFrontOfCar = true; pPed->m_vehicleInAccident = pCulprit; pCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident); @@ -1108,7 +1106,7 @@ CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit) } } } - CColPoint colpts[32]; + CColPoint colpts[MAX_COLLISION_POINTS]; if (CCollision::ProcessColModels(pCulprit->GetMatrix(), *pCulprit->GetColModel(), pPed->GetMatrix(), *pPed->GetColModel(), colpts, nil, nil)) { CWorld::Remove(pPed); delete pPed; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 6a8e6f9a..3844953a 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -88,6 +88,21 @@ float CHud::PagerXOffset; int16 CHud::PagerTimer; int16 CHud::PagerOn; +uint32 CHud::m_WantedFadeTimer; +uint32 CHud::m_WantedState; +uint32 CHud::m_WantedTimer; +uint32 CHud::m_EnergyLostFadeTimer; +uint32 CHud::m_EnergyLostState; +uint32 CHud::m_EnergyLostTimer; +uint32 CHud::m_DisplayScoreFadeTimer; +uint32 CHud::m_DisplayScoreState; +uint32 CHud::m_DisplayScoreTimer; +uint32 CHud::m_WeaponFadeTimer; +uint32 CHud::m_WeaponState; +uint32 CHud::m_WeaponTimer; + +uint32 CHud::m_LastDisplayScore; + CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; struct @@ -125,6 +140,10 @@ RwTexture *gpRocketSightTex; void CHud::Draw() { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + // disable hud via second controller if (CPad::GetPad(1)->GetStartJustDown()) m_Wants_To_Draw_Hud = !m_Wants_To_Draw_Hud; @@ -136,22 +155,29 @@ void CHud::Draw() bool DrawCrossHair = 0; bool DrawCrossHairPC = 0; - int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType; + CPlayerPed *playerPed = FindPlayerPed(); + eWeaponType WeaponType = playerPed->GetWeapon()->m_eWeaponType; int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON) - DrawCrossHair = 1; - if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT) - DrawCrossHairPC = 1; + // TODO(Miami): New cam mode + if ((Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON/* || Mode == 46*/) + && playerPed && !playerPed->GetWeapon()->IsTypeMelee()) + DrawCrossHair = true; - /* - Draw Crosshairs - */ - if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && - (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) { - if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) { - if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER) - DrawCrossHairPC = 1; + if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT) + DrawCrossHairPC = true; + if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) + || Mode == CCam::MODE_1STPERSON_RUNABOUT) { + if (playerPed) { + if (playerPed->m_nPedState != PED_ENTER_CAR && playerPed->m_nPedState != PED_CARJACK) { + + // TODO(Miami): Uncomment + if (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_AK47 + /*|| WeaponType == WEAPONTYPE_M60 || || WeaponType == WEAPONTYPE_MINIGUN */ + || WeaponType == WEAPONTYPE_FLAMETHROWER) { + DrawCrossHairPC = 1; + } + } } } @@ -171,7 +197,8 @@ void CHud::Draw() #ifdef ASPECT_RATIO_SCALE f3rdY -= SCREEN_SCALE_Y(2.0f); #endif - if (FindPlayerPed() && WeaponType == WEAPONTYPE_M16) { + // TODO(Miami): M60 + if (playerPed && (WeaponType == WEAPONTYPE_M16 || WeaponType == WEAPONTYPE_AK47/* || WeaponType == WEAPONTYPE_M60*/)) { rect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.6f); rect.top = f3rdY - SCREEN_SCALE_Y(32.0f * 0.6f); rect.right = f3rdX + SCREEN_SCALE_X(32.0f * 0.6f); @@ -187,8 +214,7 @@ void CHud::Draw() Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255)); } - } - else { + } else { if (Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_HELICANNON_1STPERSON) { @@ -215,8 +241,11 @@ void CHud::Draw() RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex)); CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); } else { + + // TODO(Miami) // Sniper rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(210.0f); rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(210.0f); @@ -243,9 +272,9 @@ void CHud::Draw() Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255)); } } - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); } else { SpriteBrightness = 0; @@ -254,34 +283,48 @@ void CHud::Draw() /* DrawMoneyCounter */ + wchar sPrint[16]; wchar sPrintIcon[16]; char sTemp[16]; + float alpha; - sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); - AsciiToUnicode(sTemp, sPrint); + if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) { + alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 0); + } else { + alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 1); + m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + } + if (m_DisplayScoreState != FADED_OUT) { + sprintf(sTemp, "$%08d", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney); + AsciiToUnicode(sTemp, sPrint); - CFont::SetPropOff(); - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetPropOff(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::SetPropOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetPropOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, alpha)); + MONEY_COLOR.a = alpha; + CFont::SetColor(MONEY_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f), SCREEN_SCALE_Y(43.0f + 2.0f), sPrint); - - CFont::SetColor(MONEY_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); + // TODO(Miami): m_nHudMode + //if (CMenuManager.m_nHudMode) + { + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); + } + } /* DrawAmmo */ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType); - CWeapon *weapon = FindPlayerPed()->GetWeapon(); + CWeapon *weapon = playerPed->GetWeapon(); uint32 AmmoAmount = weaponInfo->m_nAmountofAmmunition; uint32 AmmoInClip = weapon->m_nAmmoInClip; uint32 TotalAmmo = weapon->m_nAmmoTotal; @@ -347,14 +390,15 @@ void CHud::Draw() } CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.4f), SCREEN_SCALE_Y(0.6f)); + CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f)); CFont::SetJustifyOff(); CFont::SetCentreOn(); CFont::SetCentreSize(SCREEN_SCALE_X(640.0f)); CFont::SetPropOn(); + CFont::SetDropShadowPosition(0); CFont::SetFontStyle(FONT_BANK); - if (!CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { + if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { CFont::SetDropShadowPosition(2); CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(AMMO_COLOR); @@ -366,7 +410,7 @@ void CHud::Draw() DrawHealth */ CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetJustifyOff(); CFont::SetCentreOff(); CFont::SetRightJustifyWrap(0.0f); @@ -376,16 +420,16 @@ void CHud::Draw() if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_HEALTH - || FindPlayerPed()->m_fHealth < 10 + || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { - if (FindPlayerPed()->m_fHealth >= 10 - || FindPlayerPed()->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { + if (playerPed->m_fHealth >= 10 + || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { AsciiToUnicode("{", sPrintIcon); #ifdef FIX_BUGS - sprintf(sTemp, "%03d", int32(FindPlayerPed()->m_fHealth + 0.5f)); + sprintf(sTemp, "%03d", int32(playerPed->m_fHealth + 0.5f)); #else - sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fHealth); + sprintf(sTemp, "%03d", (int32)playerPed->m_fHealth); #endif AsciiToUnicode(sTemp, sPrint); @@ -409,13 +453,13 @@ void CHud::Draw() DrawArmour */ if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) { - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - if (FindPlayerPed()->m_fArmour > 1.0f) { + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + if (playerPed->m_fArmour > 1.0f) { AsciiToUnicode("[", sPrintIcon); #ifdef FIX_BUGS - sprintf(sTemp, "%03d", int32(FindPlayerPed()->m_fArmour + 0.5f)); + sprintf(sTemp, "%03d", int32(playerPed->m_fArmour + 0.5f)); #else - sprintf(sTemp, "%03d", (int32)FindPlayerPed()->m_fArmour); + sprintf(sTemp, "%03d", (int32)playerPed->m_fArmour); #endif AsciiToUnicode(sTemp, sPrint); @@ -440,30 +484,33 @@ void CHud::Draw() DrawWantedLevel */ CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(1.25f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetJustifyOff(); CFont::SetCentreOff(); CFont::SetRightJustifyOn(); CFont::SetPropOn(); CFont::SetFontStyle(FONT_HEADING); + CFont::SetDropShadowPosition(2); // TODO(Miami): Remove that, VC keeps that open above AsciiToUnicode("]", sPrintIcon); for (int i = 0; i < 6; i++) { - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(2.0f + SCREEN_SCALE_FROM_RIGHT(110.0f - 2.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f + 2.0f), sPrintIcon); - if (FindPlayerPed()->m_pWanted->m_nWantedLevel > i - && (CTimer::GetTimeInMilliseconds() > FindPlayerPed()->m_pWanted->m_nLastWantedLevelChange + if (playerPed->m_pWanted->m_nWantedLevel > i + && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange + 2000 || CTimer::GetFrameCounter() & 4)) { CFont::SetColor(WANTED_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); - }else{ + + // TODO(Miami): There is one more condition in here + }else if (playerPed->m_pWanted->m_nWantedLevel <= i) { CFont::SetColor(NOTWANTED_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); } } + CFont::SetDropShadowPosition(0); // TODO(Miami): Remove that, VC keeps that open + /* DrawZoneName */ @@ -665,7 +712,7 @@ void CHud::Draw() CFont::SetJustifyOff(); CFont::SetCentreOff(); CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetBackGroundOnlyTextOff(); CFont::SetPropOff(); CFont::SetFontStyle(FONT_HEADING); @@ -714,7 +761,7 @@ void CHud::Draw() AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer); CFont::SetPropOn(); CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -722,7 +769,7 @@ void CHud::Draw() CFont::SetBackGroundOnlyTextOn(); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetColor(TIMER_COLOR); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer); @@ -754,7 +801,7 @@ void CHud::Draw() CFont::SetPropOn(); CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetCentreOff(); CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); @@ -780,7 +827,7 @@ void CHud::Draw() if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) { CFont::SetPropOn(); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); @@ -1446,6 +1493,21 @@ void CHud::Initialise() PagerSoundPlayed = 0; PagerXOffset = 150.0f; + m_WantedFadeTimer = 0; + m_WantedState = FADE_DISABLED; + m_WantedTimer = 0; + m_EnergyLostFadeTimer = 0; + m_EnergyLostState = FADE_DISABLED; + m_EnergyLostTimer = 0; + m_DisplayScoreFadeTimer = 0; + m_DisplayScoreState = FADE_DISABLED; + m_DisplayScoreTimer = 0; + m_WeaponFadeTimer = 0; + m_WeaponState = FADE_DISABLED; + m_WeaponTimer = 0; + + m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + CTxdStore::PopCurrentTxd(); } @@ -1469,6 +1531,21 @@ void CHud::ReInitialise() { PagerTimer = 0; PagerSoundPlayed = 0; PagerXOffset = 150.0f; + + m_WantedFadeTimer = 0; + m_WantedState = FADE_DISABLED; + m_WantedTimer = 0; + m_EnergyLostFadeTimer = 0; + m_EnergyLostState = FADE_DISABLED; + m_EnergyLostTimer = 0; + m_DisplayScoreFadeTimer = 0; + m_DisplayScoreState = FADE_DISABLED; + m_DisplayScoreTimer = 0; + m_WeaponFadeTimer = 0; + m_WeaponState = FADE_DISABLED; + m_WeaponTimer = 0; + + m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; } wchar LastBigMessage[6][128]; @@ -1565,3 +1642,106 @@ void CHud::Shutdown() int HudTXD = CTxdStore::FindTxdSlot("hud"); CTxdStore::RemoveTxdSlot(HudTXD); } + +float CHud::DrawFadeState(DRAW_FADE_STATE fadingElement, int forceFadingIn) +{ + float alpha = 255.0f; + uint32 operation, timer; + int32 fadeTimer; + + switch (fadingElement) { + case HUD_WANTED_FADING: + fadeTimer = m_WantedFadeTimer; + operation = m_WantedState; + timer = m_WantedTimer; + break; + case HUD_ENERGY_FADING: + fadeTimer = m_EnergyLostFadeTimer; + operation = m_EnergyLostState; + timer = m_EnergyLostTimer; + break; + case HUD_SCORE_FADING: + fadeTimer = m_DisplayScoreFadeTimer; + operation = m_DisplayScoreState; + timer = m_DisplayScoreTimer; + break; + case HUD_WEAPON_FADING: + fadeTimer = m_WeaponFadeTimer; + operation = m_WeaponState; + timer = m_WeaponTimer; + break; + default: + break; + } + if (forceFadingIn) { + switch (operation) { + case FADED_OUT: + fadeTimer = 0; + case START_FADE_OUT: + case FADING_OUT: + timer = 5; + operation = FADING_IN; + break; + default: + break; + } + } + if (operation != FADED_OUT && operation != FADE_DISABLED) { + switch (operation) { + case START_FADE_OUT: + fadeTimer = 1000; + alpha = 255.0f; + if (timer > 10000) { + fadeTimer = 3000; + operation = FADING_OUT; + } + break; + case FADING_IN: + fadeTimer += CTimer::GetTimeStepInMilliseconds(); + if (fadeTimer > 1000.0f) { + operation = START_FADE_OUT; + fadeTimer = 1000; + } + alpha = fadeTimer / 1000.0f * 255.0f; + break; + case FADING_OUT: + fadeTimer -= CTimer::GetTimeStepInMilliseconds(); + if (fadeTimer < 0.0f) { + fadeTimer = 0; + operation = FADED_OUT; + } + alpha = fadeTimer / 1000.0f * 255.0f; + break; + default: + break; + } + timer += CTimer::GetTimeStepInMilliseconds(); + } + + switch (fadingElement) { + case HUD_WANTED_FADING: + m_WantedFadeTimer = fadeTimer; + m_WantedState = operation; + m_WantedTimer = timer; + break; + case HUD_ENERGY_FADING: + m_EnergyLostFadeTimer = fadeTimer; + m_EnergyLostState = operation; + m_EnergyLostTimer = timer; + break; + case HUD_SCORE_FADING: + m_DisplayScoreFadeTimer = fadeTimer; + m_DisplayScoreState = operation; + m_DisplayScoreTimer = timer; + break; + case HUD_WEAPON_FADING: + m_WeaponFadeTimer = fadeTimer; + m_WeaponState = operation; + m_WeaponTimer = timer; + break; + default: + break; + } + + return clamp(alpha, 0.0f, 255.0f); +} diff --git a/src/render/Hud.h b/src/render/Hud.h index 701e47e2..bae19ee4 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -9,6 +9,25 @@ enum eItems ITEM_RADAR = 8 }; +// Thanks for vague name, R* +enum DRAW_FADE_STATE +{ + HUD_WANTED_FADING = 0, + HUD_ENERGY_FADING, + HUD_SCORE_FADING, + HUD_WEAPON_FADING, +}; + +// My name +enum eFadeOperation +{ + FADED_OUT = 0, + START_FADE_OUT, + FADING_IN, + FADING_OUT, + FADE_DISABLED = 5, +}; + enum eSprites { HUD_FIST, @@ -32,6 +51,10 @@ enum eSprites NUM_HUD_SPRITES, }; +// TODO(Miami): Make those 0.7f - 1.25f once fonts have been ported +#define HUD_TEXT_SCALE_X 0.8f +#define HUD_TEXT_SCALE_Y 1.35f + class CHud { public: @@ -82,6 +105,21 @@ public: static int16 PagerTimer; static int16 PagerOn; + static uint32 m_WantedFadeTimer; + static uint32 m_WantedState; + static uint32 m_WantedTimer; + static uint32 m_EnergyLostFadeTimer; + static uint32 m_EnergyLostState; + static uint32 m_EnergyLostTimer; + static uint32 m_DisplayScoreFadeTimer; + static uint32 m_DisplayScoreState; + static uint32 m_DisplayScoreTimer; + static uint32 m_WeaponFadeTimer; + static uint32 m_WeaponState; + static uint32 m_WeaponTimer; + + static uint32 m_LastDisplayScore; + public: static void Draw(); static void DrawAfterFade(); @@ -95,4 +133,5 @@ public: static void SetVehicleName(wchar *name); static void SetZoneName(wchar *name); static void Shutdown(); + static float DrawFadeState(DRAW_FADE_STATE, int); }; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 666a26a2..65a31117 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -207,6 +207,7 @@ public: float m_fMapObjectHeightBehind; // rear Z? eCarLock m_nDoorLock; int8 m_nLastWeaponDamage; // see eWeaponType, -1 if no damage + CEntity *m_pLastDamageEntity; int8 m_nRadioStation; uint8 m_bRainAudioCounter; uint8 m_bRainSamplesCounter; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 1f901f88..4c1f1c52 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -36,7 +36,17 @@ uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = { 0, // UNARMED - 0, // BASEBALLBAT + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, // GRENADE 0, // DETONATEGRENADE 0, // MOLOTOV @@ -156,6 +166,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) return false; bool fired; + bool addFireRateAsDelay = true; if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE ) { @@ -166,6 +177,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) { case WEAPONTYPE_SHOTGUN: { + addFireRateAsDelay = true; fired = FireShotgun(shooter, source); break; @@ -181,13 +193,13 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) case WEAPONTYPE_HELICANNON: { if ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON) - && shooter == FindPlayerPed()) - { + && shooter == FindPlayerPed()) { + addFireRateAsDelay = false; fired = FireM16_1stPerson(shooter); - } - else + } else { + addFireRateAsDelay = true; fired = FireInstantHit(shooter, source); - + } break; } @@ -267,54 +279,58 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } } - if ( fired ) + if (fired) { bool isPlayer = false; - if ( shooter->IsPed() ) + if (shooter->IsPed()) { - CPed *shooterPed = (CPed*)shooter; + CPed* shooterPed = (CPed*)shooter; shooterPed->bIsShooting = true; - if ( shooterPed->IsPlayer() ) + if (shooterPed->IsPlayer()) isPlayer = true; DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); } - if ( m_nAmmoInClip > 0 ) + if (m_nAmmoInClip > 0) m_nAmmoInClip--; - if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) && (!isPlayer || CStats::GetPercentageProgress() < 100.0f || m_eWeaponType == WEAPONTYPE_DETONATOR)) + if (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) && (!isPlayer || CStats::GetPercentageProgress() < 100.0f || m_eWeaponType == WEAPONTYPE_DETONATOR)) m_nAmmoTotal--; - if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) + if (m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER) DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); m_eWeaponState = WEAPONSTATE_FIRING; - } - if ( m_nAmmoInClip == 0 ) - { - if ( m_nAmmoTotal == 0 ) - return true; - - m_eWeaponState = WEAPONSTATE_RELOADING; - m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; - - if ( shooter == FindPlayerPed() ) + if (m_nAmmoInClip == 0) { - if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload ) - m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; + if (m_nAmmoTotal == 0) + return true; + + m_eWeaponState = WEAPONSTATE_RELOADING; + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + + if (shooter == FindPlayerPed()) + { + if (CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; + } + + return true; } - return true; - } + if (addFireRateAsDelay) + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nFiringRate; + else + m_nTimer = CTimer::GetTimeInMilliseconds(); - m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; - if ( shooter == FindPlayerPed() ) - CStats::RoundsFiredByPlayer++; + if (shooter == FindPlayerPed()) + CStats::RoundsFiredByPlayer++; + } } else { @@ -322,9 +338,15 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) { m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; m_eWeaponState = WEAPONSTATE_FIRING; +#ifndef AUDIO_NOT_READY + if (shooter->IsPed() && m_eWeaponType != WEAPONTYPE_CHAINSAW) + { + DMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, 188, m_eWeaponType << 8); + } +#endif } - FireMelee(shooter, *source); + fired = FireMelee(shooter, *source); } if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT ) @@ -372,7 +394,7 @@ CWeapon::FireFromCar(CVehicle *shooter, bool left) return true; } -// --MIAMI: Just a few lines is done +// --MIAMI: Done, except commented things bool CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { @@ -386,18 +408,31 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) CPed *shooterPed = (CPed*)shooter; + if (shooterPed == FindPlayerPed()) { + if (m_eWeaponType == WEAPONTYPE_GOLFCLUB || m_eWeaponType == WEAPONTYPE_NIGHTSTICK || + (m_eWeaponType >= WEAPONTYPE_BASEBALLBAT && m_eWeaponType <= WEAPONTYPE_CHAINSAW)) { + + // TODO(Miami): BreakGlassPhysically + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) { + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); + } + } + } + + int damageEntityRegistered = 0; + for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ ) { CPed *victimPed = shooterPed->m_nearPeds[i]; ASSERT(victimPed!=nil); if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget) - && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) ) + && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) + && (!shooterPed->IsGangMember() || victimPed->CanBeDamagedByThisGangMember(shooterPed)) ) { bool collided = false; - // TODO(Miami) - if (victimPed->m_nPedState == PED_DRIVING && (m_eWeaponType == WEAPONTYPE_UNARMED /*|| m_eWeaponType == WEAPONTYPE_BRASSKNUCKLES*/ + if (victimPed->m_nPedState == PED_DRIVING && (m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE || info->m_bFightMode)) continue; @@ -451,65 +486,115 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) int32 localDir = victimPed->GetLocalDirection(posOffset); - bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT; + bool isHeavy = m_eWeaponType >= WEAPONTYPE_GOLFCLUB && m_eWeaponType <= WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_HAMMER; + + if (shooterPed->m_fDamageImpulse == 0.0f) { + shooterPed->m_pDamageEntity = victimPed; + victimPed->RegisterReference(&shooterPed->m_pDamageEntity); + } + + damageEntityRegistered = 3; + // TODO(Miami): Bike if ( !victimPed->DyingOrDead() ) victimPed->ReactToAttack(shooterPed); uint8 hitLevel = HITLEVEL_HIGH; - if ( isBat && victimPed->OnGround() ) + if ( isHeavy && (victimPed->OnGround() || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE)) hitLevel = HITLEVEL_GROUND; victimPed->StartFightDefend(localDir, hitLevel, 10); if ( !victimPed->DyingOrDead() ) { - if ( shooterPed->IsPlayer() && isBat && anim2Playing ) + if ( shooterPed->IsPlayer() && isHeavy && anim2Playing ) victimPed->InflictDamage(shooterPed, m_eWeaponType, 100.0f, PEDPIECE_TORSO, localDir); else if ( shooterPed->IsPlayer() && ((CPlayerPed*)shooterPed)->m_bAdrenalineActive ) victimPed->InflictDamage(shooterPed, m_eWeaponType, 3.5f*info->m_nDamage, PEDPIECE_TORSO, localDir); else { - if ( victimPed->IsPlayer() && isBat ) // wtf, it's not fair + if ( victimPed->IsPlayer() && isHeavy ) // wtf, it's not fair victimPed->InflictDamage(shooterPed, m_eWeaponType, 2.0f*info->m_nDamage, PEDPIECE_TORSO, localDir); else victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir); } } - if ( CGame::nastyGame ) + if ( CGame::nastyGame && victimPed->GetIsOnScreen() ) { - if ( victimPed->GetIsOnScreen() ) + CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); + + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + if ( isHeavy ) { - CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); - - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - if ( isBat ) + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + } + + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + if (victimPed->m_nPedState != PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 1) + || victimPed->m_nPedState == PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 3)) { - dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - - dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_TEST, bloodPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f); } + CVector newDir(dir); + newDir.z += 0.2f; + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, bloodPos, newDir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir); + newDir.z = dir.z + 0.1f; + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir); + newDir.x = 0.0f; + newDir.y = 0.0f; + newDir.z = 0.01f; + CParticle::AddParticle(PARTICLE_DEBRIS2, bloodPos, newDir); + + // TODO(Miami): New particle + /* + v116.z = 0.0; + v116.x = CGeneral::GetRandomNumberInRange(-0.15f, 0.15f); + v116.y = CGeneral::GetRandomNumberInRange(0.1f, 0.35f); + v115.x = CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_X(50.0f), SCREEN_STRETCH_FROM_RIGHT(50.0f)); + v115.z = 1.0; + v115.y = CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_Y(50.0f), SCREEN_STRETCH_FROM_BOTTOM(50.0f)); + CParticle::AddParticle(41, v115, v116, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.15f), + CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 0); + + */ + } + if (info->m_AnimToPlay == ASSOCGRP_KNIFE) + { + dir.x += 0.1f * shooterPed->GetUp().x + 0.05f * shooterPed->GetRight().x; + dir.y += 0.1f * shooterPed->GetUp().y + 0.05f * shooterPed->GetRight().y; + dir.z += 0.1f * shooterPed->GetUp().z + 0.05f * shooterPed->GetRight().z; + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); } } if ( !victimPed->OnGround() ) { if ( victimPed->m_fHealth > 0.0f - && (victimPed->m_fHealth < 20.0f && victimPedHealth > 20.0f || isBat && !victimPed->IsPlayer()) ) + && (victimPed->m_fHealth < 30.0f && victimPedHealth > 20.0f || + (isHeavy || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) && !victimPed->IsPlayer()) ) { posOffset.Normalise(); victimPed->bIsStanding = false; - victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + if(m_eWeaponType == WEAPONTYPE_CHAINSAW) + victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 2.0f); + else + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); - if ( isBat && victimPed->IsPlayer() ) + if ( isHeavy && victimPed->IsPlayer() ) victimPed->SetFall(3000, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); else victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); @@ -522,21 +607,152 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { posOffset.Normalise(); victimPed->bIsStanding = false; - victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + if(m_eWeaponType == WEAPONTYPE_CHAINSAW) + victimPed->ApplyMoveForce(posOffset.x*-1.0f, posOffset.y*-1.0f, 1.0f); + else + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); } m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; - if ( victimPed->m_nPedType == PEDTYPE_COP ) - CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); - else - CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + if (m_eWeaponType != WEAPONTYPE_KNIFE && m_eWeaponType != WEAPONTYPE_MACHETE + && m_eWeaponType != WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_CHAINSAW) { + + if (victimPed->m_nPedType == PEDTYPE_COP) + CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + else + CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + } else { + if (victimPed->m_nPedType == PEDTYPE_COP) + CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + else + CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + } } } } } } } + CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, false, true, false, false, false, false); + if (nearVeh && nearVeh->IsCar()) + { + CAutomobile *nearCar = (CAutomobile*)nearVeh; + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; + if (shooterPed == FindPlayerPed()) + { + if (nearCar->IsLawEnforcementVehicle()) + { + FindPlayerPed()->SetWantedLevelNoDrop(1); + } + CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_VEHICLE, nearCar, shooterPed, 2000); + } + float oldHealth = nearCar->m_fHealth; + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + for(int i=0; i<4; i++) { + CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f)); + CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, gaTempSphereColPoints[0].normal * 0.1f); + } + } + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + nearCar->VehicleDamage(info->m_nDamage * (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB); + + // TODO(Miami): Particle not in III + // CParticle::AddParticle(81, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0); + } + else + { + nearCar->VehicleDamage(info->m_nDamage* (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB); + } + if (nearCar->m_fHealth < oldHealth) + { + nearCar->m_nLastWeaponDamage = m_eWeaponType; + nearCar->m_pLastDamageEntity = shooterPed; + } + if (shooterPed->m_fDamageImpulse == 0.0f) + { + shooterPed->m_pDamageEntity = nearCar; + nearCar->RegisterReference(&shooterPed->m_pDamageEntity); + } + damageEntityRegistered = 2; + if (FindPlayerPed()->GetWeapon() == this && nearCar->VehicleCreatedBy != MISSION_VEHICLE) + { + if (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH + && (CGeneral::GetRandomTrueFalse() || nearCar->AutoPilot.m_nCarMission != MISSION_CRUISE)) + { + int leaveCarDelay = 200; + CPed *driver = nearCar->pDriver; + if (driver && driver->CharCreatedBy != MISSION_CHAR) + { + if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear) + { + driver->SetObjective(OBJECTIVE_FLEE_TILL_SAFE); + } + else + { + driver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, FindPlayerPed()); + driver->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; + driver->m_prevObjective = OBJECTIVE_KILL_CHAR_ON_FOOT; + } + driver->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 200; + leaveCarDelay = 400; + } + for (int j = 0; j < nearCar->m_nNumPassengers; ++j) + { + CPed *passenger = nearCar->pPassengers[j]; + if (passenger && passenger->CharCreatedBy != MISSION_CHAR) + { + nearCar->pPassengers[j]->SetObjective(OBJECTIVE_FLEE_TILL_SAFE); + passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + leaveCarDelay; + leaveCarDelay += 200; + } + } + } + else + { + CPed *driver = nearCar->pDriver; + if (driver) + { + if (driver->m_objective != OBJECTIVE_LEAVE_VEHICLE && driver->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && + driver->m_objective != OBJECTIVE_FLEE_TILL_SAFE) + { + if (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH) + nearCar->AutoPilot.m_nCruiseSpeed = nearCar->AutoPilot.m_nCruiseSpeed * 1.5f; + + nearCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH; + } + } + } + } + } + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + CEntity *nearStatic = (CObject*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, true, false, false, true, false, false); + if (nearStatic) + { + for(int i=0; i < 4; i++) { + CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f), 0, 0.0f, 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, 0.1f * gaTempSphereColPoints[0].normal, 0, 0.0f, 0, 0, 0, 0); + } + + // TODO(Miami): Particle not in III + //CParticle::AddParticle(81, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0); + + if (!damageEntityRegistered) + { + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; + if (shooterPed->m_fDamageImpulse == 0.0f) + { + shooterPed->m_pDamageEntity = nearStatic; + nearStatic->RegisterReference(&shooterPed->m_pDamageEntity); + } + } + if (nearStatic->IsObject() && ((CObject*)nearStatic)->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY) + ((CObject*)nearStatic)->ObjectDamage(200.0f); + } + } return true; } @@ -2239,13 +2455,17 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) bool CWeapon::IsTypeMelee(void) { - return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT; + return CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE; } bool CWeapon::IsType2Handed(void) { - return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER; + // TODO(Miami): Uncomment + return m_eWeaponType == WEAPONTYPE_FLAMETHROWER || m_eWeaponType == WEAPONTYPE_HELICANNON || /* m_eWeaponType == WEAPONTYPE_M60 */ + m_eWeaponType == WEAPONTYPE_M16 || + (m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType < WEAPONTYPE_TEC9) || // Shotguns + m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_SNIPERRIFLE /*|| m_eWeaponType == WEAPONTYPE_LASERSCOPE*/; } void diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index 420171f2..d5e759b9 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -11,7 +11,7 @@ // Yeah... int32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; @@ -19,7 +19,17 @@ CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; // --MIAMI: Todo static char ms_aWeaponNames[][32] = { "Unarmed", + "BrassKnuckle", + "ScrewDriver", + "GolfClub", + "NightStick", + "Knife", "BaseballBat", + "Hammer", + "Cleaver", + "Machete", + "Katana", + "Chainsaw", "Grenade", "DetonateGrenade", "Molotov", @@ -61,8 +71,7 @@ CWeaponInfo::Initialise(void) ms_apWeaponInfos[i].m_fLifespan = 0.0f; ms_apWeaponInfos[i].m_fSpread = 0.0f; ms_apWeaponInfos[i].m_vecFireOffset = CVector(0.0f, 0.0f, 0.0f); - // TODO(Miami): ASSOCGRP_UNARMED - ms_apWeaponInfos[i].m_AnimToPlay = ASSOCGRP_STD; + ms_apWeaponInfos[i].m_AnimToPlay = ASSOCGRP_UNARMED; ms_apWeaponInfos[i].m_fAnimLoopStart = 0.0f; ms_apWeaponInfos[i].m_fAnimLoopEnd = 0.0f; ms_apWeaponInfos[i].m_fAnimFrameFire = 0.0f; diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h index 8c1f598d..6516828a 100644 --- a/src/weapons/WeaponType.h +++ b/src/weapons/WeaponType.h @@ -4,7 +4,17 @@ enum eWeaponType { WEAPONTYPE_UNARMED, + WEAPONTYPE_BRASSKNUCKLE, + WEAPONTYPE_SCREWDRIVER, + WEAPONTYPE_GOLFCLUB, + WEAPONTYPE_NIGHTSTICK, + WEAPONTYPE_KNIFE, WEAPONTYPE_BASEBALLBAT, + WEAPONTYPE_HAMMER, + WEAPONTYPE_CLEAVER, + WEAPONTYPE_MACHETE, + WEAPONTYPE_KATANA, + WEAPONTYPE_CHAINSAW, WEAPONTYPE_GRENADE, WEAPONTYPE_DETONATOR_GRENADE, WEAPONTYPE_MOLOTOV, From 4c822e8375268ac34f92af3f1960965446d32506 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 19 May 2020 20:54:05 +0300 Subject: [PATCH 064/148] script revision --- src/control/Script.cpp | 217 ++++++++++++++++-------------------- src/control/Script.h | 1 + src/peds/Ped.cpp | 38 ++++--- src/peds/Ped.h | 18 ++- src/vehicles/Automobile.cpp | 7 +- src/vehicles/Boat.cpp | 9 ++ src/vehicles/Vehicle.cpp | 1 + src/vehicles/Vehicle.h | 8 +- 8 files changed, 155 insertions(+), 144 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 2ad1e9de..4112acf4 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -57,6 +57,7 @@ #include "RoadBlocks.h" #include "RpAnimBlend.h" #include "Rubbish.h" +#include "SimpleModelInfo.h" #include "Shadows.h" #include "SpecialFX.h" #include "Sprite.h" @@ -1899,6 +1900,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) ped->CharCreatedBy = MISSION_CHAR; ped->bRespondsToThreats = false; ped->bAllowMedicsToReviveMe = false; + ped->bIsPlayerFriend = false; CVector pos = *(CVector*)&ScriptParams[2]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); @@ -1921,24 +1923,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) { CollectParameters(&m_nIp, 1); CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); - if (ped) { - if (ped->InVehicle()) { - if (ped->m_pMyVehicle->pDriver == ped) { - ped->m_pMyVehicle->RemoveDriver(); - ped->m_pMyVehicle->SetStatus(STATUS_ABANDONED); - if (ped->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) - ped->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - if (ped->m_nPedType == PEDTYPE_COP && ped->m_pMyVehicle->IsLawEnforcementVehicle()) - ped->m_pMyVehicle->ChangeLawEnforcerState(0); - } - else { - ped->m_pMyVehicle->RemovePassenger(ped); - } - } - CWorld::RemoveReferencesToDeletedObject(ped); - delete ped; - --CPopulation::ms_nTotalMissionPeds; - } + CTheScripts::RemoveThisPed(ped); if (m_bIsMissionScript) CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR); return 0; @@ -1955,19 +1940,26 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) ped->SetWanderPath(path); return 0; } - /* Not implemented. - case COMMAND_CHAR_WANDER_RANGE: - */ + //case COMMAND_CHAR_WANDER_RANGE: case COMMAND_CHAR_FOLLOW_PATH: { - CollectParameters(&m_nIp, 4); + CollectParameters(&m_nIp, 6); CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(ped); + if (ped->GetPedState() == PED_ATTACK || ped->GetPedState() == PED_FIGHT || !ped->IsPedInControl()) + return 0; CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + float radius = *(float*)&ScriptParams[4]; + eMoveState state; + switch (ScriptParams[5]) { + case 0: state = PEDMOVE_WALK; + case 1: state = PEDMOVE_SPRINT; + default: assert(0); + } ped->ClearAll(); - ped->SetFollowPath(pos); + ped->SetFollowPath(pos, radius, state, nil, nil, 999999); return 0; } case COMMAND_CHAR_SET_IDLE: @@ -2012,44 +2004,27 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - /* The following block was once again written - * by someone not familiar with virtual functions. - * It doesn't require any ifs at all. - * To keep as close to original as possible, I'll keep it. - * Maybe there was more commented out/debug - * stuff, but I doubt it. - */ + // removed dumb stuff again if (!vehicle) { pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel(); ped->Teleport(pos); CTheScripts::ClearSpaceForMissionEntity(pos, ped); - } - else if (vehicle->IsBoat()) { - pos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel(); - vehicle->Teleport(pos); - CTheScripts::ClearSpaceForMissionEntity(pos, vehicle); + for (int i = 0; i < ped->m_numNearPeds; i++) { + CPed* pNearPed = ped->m_nearPeds[i]; + if (pNearPed->m_leader == ped) { + pNearPed->Teleport(pos); + pNearPed->PositionPedOutOfCollision(); // TODO(MIAMI): this is PositionAnyPedOutOfCollision!!! + } + } } else { pos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel(); vehicle->Teleport(pos); CTheScripts::ClearSpaceForMissionEntity(pos, vehicle); } - /* Short version of this command. - * - * CollectParameters(&m_nIp, 4); - * CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); - * assert(ped); - * CEntity* entityToMove = ped->bInVehicle ? ped->m_pMyVehicle : ped; - * CVector pos = *(CVector*)&ScriptParams[1]; - * if (pos.z <= MAP_Z_LOW_LIMIT) - * pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - * pos.z += entityToMove->GetDistanceFromCentreOfMassToBaseOfModel(); - * entityToMove->Teleport(pos); - * CTheScripts::ClearSpaceForMissionEntity(pos, entityToMove); - * - */ return 0; } + /* case COMMAND_IS_CHAR_STILL_ALIVE: { CollectParameters(&m_nIp, 1); @@ -2057,6 +2032,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) UpdateCompareFlag(ped && ped->GetPedState() != PED_DEAD && ped->GetPedState() != PED_DIE); return 0; } + */ case COMMAND_IS_CHAR_IN_AREA_2D: { CollectParameters(&m_nIp, 6); @@ -2124,7 +2100,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) boat->SetStatus(STATUS_ABANDONED); boat->bIsLocked = true; boat->AutoPilot.m_nCarMission = MISSION_NONE; - boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */ + boat->AutoPilot.m_nTempAction = TEMPACT_NONE; boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f; if (m_bIsMissionScript) boat->bIsStaticWaitingForCollision = true; @@ -2147,7 +2123,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) car->bIsLocked = true; CCarCtrl::JoinCarWithRoadSystem(car); car->AutoPilot.m_nCarMission = MISSION_NONE; - car->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */ + car->AutoPilot.m_nTempAction = TEMPACT_NONE; car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0; @@ -2277,6 +2253,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) } return 0; } + /* case COMMAND_IS_CAR_STILL_ALIVE: { CollectParameters(&m_nIp, 1); @@ -2284,6 +2261,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) UpdateCompareFlag(car && car->GetStatus() != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater)); return 0; } + */ case COMMAND_SET_CAR_CRUISE_SPEED: { CollectParameters(&m_nIp, 2); @@ -2358,32 +2336,28 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) return 0; case COMMAND_PRINT_BIG: { - wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); - m_nIp += KEY_LENGTH_IN_SCRIPT; + wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp); CollectParameters(&m_nIp, 2); CMessages::AddBigMessage(key, ScriptParams[0], ScriptParams[1] - 1); return 0; } case COMMAND_PRINT: { - wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); - m_nIp += KEY_LENGTH_IN_SCRIPT; + wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp); CollectParameters(&m_nIp, 2); CMessages::AddMessage(key, ScriptParams[0], ScriptParams[1]); return 0; } case COMMAND_PRINT_NOW: { - wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); - m_nIp += KEY_LENGTH_IN_SCRIPT; + wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp); CollectParameters(&m_nIp, 2); CMessages::AddMessageJumpQ(key, ScriptParams[0], ScriptParams[1]); return 0; } case COMMAND_PRINT_SOON: { - wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); - m_nIp += KEY_LENGTH_IN_SCRIPT; + wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp); CollectParameters(&m_nIp, 2); CMessages::AddMessageSoon(key, ScriptParams[0], ScriptParams[1]); return 0; @@ -2420,15 +2394,15 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) case COMMAND_DEBUG_OFF: CTheScripts::DbgFlag = false; return 0; + /* case COMMAND_RETURN_TRUE: UpdateCompareFlag(true); return 0; case COMMAND_RETURN_FALSE: UpdateCompareFlag(false); return 0; - /* Special command only used by compiler. - case COMMAND_VAR_INT: */ + //case COMMAND_VAR_INT: default: assert(0); break; @@ -2481,8 +2455,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) { if (!m_bIsMissionScript) return 0; - if (strcmp(m_abScriptName, "love3") == 0) /* A Drop in the Ocean */ - CPickups::RemoveAllFloatingPickups(); CTheScripts::MissionCleanup.Process(); return 0; } @@ -2625,29 +2597,23 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) { CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(pPed->bInVehicle); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle); return 0; } case COMMAND_IS_PLAYER_IN_ANY_CAR: { CollectParameters(&m_nIp, 1); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - UpdateCompareFlag(pPed->bInVehicle); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle); return 0; } case COMMAND_IS_BUTTON_PRESSED: { CollectParameters(&m_nIp, 2); - bool value = GetPadState(ScriptParams[0], ScriptParams[1]) != 0; - if (CGame::playingIntro && ScriptParams[0] == 0 && ScriptParams[1] == 12) { - if (CPad::GetPad(0)->GetLeftMouseJustDown() || - CPad::GetPad(0)->GetEnterJustDown() || - CPad::GetPad(0)->GetCharJustDown(' ')) - value = true; - } - UpdateCompareFlag(value); + UpdateCompareFlag(GetPadState(ScriptParams[0], ScriptParams[1]) != 0); return 0; } + /* case COMMAND_GET_PAD_STATE: { CollectParameters(&m_nIp, 1); @@ -2655,6 +2621,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D: case COMMAND_LOCATE_PLAYER_ON_FOOT_2D: case COMMAND_LOCATE_PLAYER_IN_CAR_2D: @@ -2721,6 +2688,9 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pObj->SetOrientation(0.0f, 0.0f, 0.0f); pObj->GetMatrix().UpdateRW(); pObj->UpdateRwFrame(); + CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi); + if (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding) + pObj->SetupBigBuilding(); CTheScripts::ClearSpaceForMissionEntity(pos, pObj); CWorld::Add(pObj); ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj); @@ -2745,6 +2715,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) case COMMAND_ADD_SCORE: CollectParameters(&m_nIp, 2); CWorld::Players[ScriptParams[0]].m_nMoney += ScriptParams[1]; + if (CWorld::Players[ScriptParams[0]].m_nMoney < 0) + CWorld::Players[ScriptParams[0]].m_nMoney = 0; return 0; case COMMAND_IS_SCORE_GREATER: CollectParameters(&m_nIp, 2); @@ -2787,12 +2759,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) case COMMAND_HAS_DEATHARREST_BEEN_EXECUTED: UpdateCompareFlag(m_bDeatharrestExecuted); return 0; + /* case COMMAND_ADD_AMMO_TO_PLAYER: { CollectParameters(&m_nIp, 3); CWorld::Players[ScriptParams[0]].m_pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); return 0; } + */ case COMMAND_ADD_AMMO_TO_CHAR: { CollectParameters(&m_nIp, 3); @@ -2801,10 +2775,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); return 0; } - /* Not implemented - case COMMAND_ADD_AMMO_TO_CAR: - case COMMAND_IS_PLAYER_STILL_ALIVE: - */ + //case COMMAND_ADD_AMMO_TO_CAR: + //case COMMAND_IS_PLAYER_STILL_ALIVE: case COMMAND_IS_PLAYER_DEAD: CollectParameters(&m_nIp, 1); UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_WASTED); @@ -2813,14 +2785,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) { CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(!pPed || pPed->GetPedState() == PED_DIE || pPed->GetPedState() == PED_DEAD); + UpdateCompareFlag(!pPed || pPed->DyingOrDead()); return 0; } case COMMAND_IS_CAR_DEAD: { CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || !pVehicle->IsBoat() && pVehicle->bIsInWater); + UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->bIsDrowning); return 0; } case COMMAND_SET_CHAR_THREAT_SEARCH: @@ -2831,9 +2803,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPed->m_fearFlags |= ScriptParams[1]; return 0; } - /* Not implemented. - case COMMAND_SET_CHAR_THREAT_REACTION: - */ + //case COMMAND_SET_CHAR_THREAT_REACTION: case COMMAND_SET_CHAR_OBJ_NO_OBJ: { CollectParameters(&m_nIp, 1); @@ -2843,12 +2813,10 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPed->ClearObjective(); return 0; } - /* Not implemented. - case COMMAND_ORDER_DRIVER_OUT_OF_CAR: - case COMMAND_ORDER_CHAR_TO_DRIVE_CAR: - case COMMAND_ADD_PATROL_POINT: - case COMMAND_IS_PLAYER_IN_GANGZONE: - */ + //case COMMAND_ORDER_DRIVER_OUT_OF_CAR: + //case COMMAND_ORDER_CHAR_TO_DRIVE_CAR: + //case COMMAND_ADD_PATROL_POINT: + //case COMMAND_IS_PLAYER_IN_GANGZONE: case COMMAND_IS_PLAYER_IN_ZONE: { CollectParameters(&m_nIp, 1); @@ -2867,8 +2835,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) CollectParameters(&m_nIp, 1); UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_pPed->GetPedState() == PED_DRIVING && CPad::GetPad(ScriptParams[0])->GetHorn()); - /* Is it correct that same parameter is used both as index of Players */ - /* and as ID of pad? Pratically this parameter is always 0 anyway of course. */ return 0; case COMMAND_HAS_CHAR_SPOTTED_PLAYER: { @@ -2878,10 +2844,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) UpdateCompareFlag(pPed->OurPedCanSeeThisOne(CWorld::Players[ScriptParams[1]].m_pPed)); return 0; } - /* Not implemented. - case COMMAND_ORDER_CHAR_TO_BACKDOOR: - case COMMAND_ADD_CHAR_TO_GANG: - */ + //case COMMAND_ORDER_CHAR_TO_BACKDOOR: + //case COMMAND_ADD_CHAR_TO_GANG: case COMMAND_IS_CHAR_OBJECTIVE_PASSED: { CollectParameters(&m_nIp, 1); @@ -2937,6 +2901,9 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPed->CharCreatedBy = MISSION_CHAR; pPed->bRespondsToThreats = false; pPed->bAllowMedicsToReviveMe = false; + pPed->bIsPlayerFriend = false; + if (pVehicle->bIsBus) + pPed->bRenderPedInCar = false; pPed->SetPosition(pVehicle->GetPosition()); pPed->SetOrientation(0.0f, 0.0f, 0.0f); pPed->SetPedState(PED_DRIVING); @@ -2986,7 +2953,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPlayer->m_pPed->SetPedState(PED_IDLE); pPlayer->m_pPed->bUsesCollision = true; pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); - pPlayer->m_pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPlayer->m_pPed->GetWeapon()->m_eWeaponType)->m_nModelId); + pPlayer->m_pPed->ReplaceWeaponWhenExitingVehicle(); pPlayer->m_pPed->RemoveInCarAnims(); if (pPlayer->m_pPed->m_pVehicleAnim) pPlayer->m_pPed->m_pVehicleAnim->blendDelta = -1000.0f; @@ -3000,9 +2967,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) CTheScripts::ClearSpaceForMissionEntity(pos, pPlayer->m_pPed); return 0; } - /* Not implemented. - case COMMAND_MAKE_CHAR_DO_NOTHING: - */ + //case COMMAND_MAKE_CHAR_DO_NOTHING: default: assert(0); break; @@ -7035,28 +7000,16 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); if (pPed && pPed->CharCreatedBy == MISSION_CHAR){ CWorld::RemoveReferencesToDeletedObject(pPed); - if (pPed->bInVehicle){ - if (pPed->m_pMyVehicle){ - if (pPed == pPed->m_pMyVehicle->pDriver){ - pPed->m_pMyVehicle->RemoveDriver(); - pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); - if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) - pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle()) - pPed->m_pMyVehicle->ChangeLawEnforcerState(0); - }else{ - pPed->m_pMyVehicle->RemovePassenger(pPed); - } - } - delete pPed; - --CPopulation::ms_nTotalMissionPeds; - }else{ + if (pPed->bInVehicle && pPed->m_pMyVehicle) + CTheScripts::RemoveThisPed(pPed); + else{ pPed->CharCreatedBy = RANDOM_CHAR; pPed->bRespondsToThreats = true; pPed->bScriptObjectiveCompleted = false; pPed->ClearLeader(); --CPopulation::ms_nTotalMissionPeds; pPed->bFadeOut = true; + CWorld::RemoveReferencesToDeletedObject(pPed); } } if (m_bIsMissionScript) @@ -7252,7 +7205,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->m_nLastPedState = PED_NONE; pPed->bUsesCollision = true; pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); - pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId); + pPed->ReplaceWeaponWhenExitingVehicle(); pPed->RemoveInCarAnims(); if (pPed->m_pVehicleAnim) pPed->m_pVehicleAnim->blendDelta = -1000.0f; @@ -10543,7 +10496,9 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) pPed->CharCreatedBy = MISSION_CHAR; pPed->bRespondsToThreats = false; pPed->bAllowMedicsToReviveMe = false; - // TODO(MIAMI): two more flags and more stuff + pPed->bIsPlayerFriend = false; + if (pVehicle->bIsBus) + pPed->bRenderPedInCar = false; pPed->SetPosition(pVehicle->GetPosition()); pPed->SetOrientation(0.0f, 0.0f, 0.0f); pPed->SetPedState(PED_DRIVING); @@ -10572,7 +10527,9 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) pPed->CharCreatedBy = MISSION_CHAR; pPed->bRespondsToThreats = false; pPed->bAllowMedicsToReviveMe = false; - // TODO(MIAMI): two more flags and more stuff (ClearFollowPath) + pPed->bIsPlayerFriend = false; + if (pVehicle->bIsBus) + pPed->bRenderPedInCar = false; pPed->SetPosition(pVehicle->GetPosition()); pPed->SetOrientation(0.0f, 0.0f, 0.0f); CPopulation::ms_nTotalMissionPeds++; @@ -10585,9 +10542,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) pPed->m_pMyVehicle = pVehicle; pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); pPed->bInVehicle = true; - // TODO pPed->SetPedState(PED_DRIVING); - ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); StoreParameters(&m_nIp, 1); if (m_bIsMissionScript) @@ -10799,6 +10754,30 @@ bool CRunningScript::ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool f } } +void CTheScripts::RemoveThisPed(CPed* pPed) +{ + if (pPed) { + bool bWasMissionPed = pPed->CharCreatedBy == MISSION_CHAR; + if (pPed->InVehicle() && pPed->m_pMyVehicle) { + if (pPed->m_pMyVehicle->pDriver == pPed) { + pPed->m_pMyVehicle->RemoveDriver(); + pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); + if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) + pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle()) + pPed->m_pMyVehicle->ChangeLawEnforcerState(0); + } + else { + pPed->m_pMyVehicle->RemovePassenger(pPed); + } + } + CWorld::RemoveReferencesToDeletedObject(pPed); + delete pPed; + if (bWasMissionPed) + --CPopulation::ms_nTotalMissionPeds; + } +} + int32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index) { if (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1) diff --git a/src/control/Script.h b/src/control/Script.h index e84e76bf..3393467e 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -367,6 +367,7 @@ private: static int32 GetNewUniqueScriptSphereIndex(int32 index); static void RemoveScriptSphere(int32 index); static void RemoveScriptTextureDictionary(); + static void RemoveThisPed(CPed* pPed); friend class CRunningScript; friend class CHud; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 91dafbc2..f7140b2b 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -619,14 +619,15 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) #ifdef KANGAROO_CHEAT m_ped_flagI80 = false; #endif -#ifdef VC_PED_PORTS - bSomeVCflag1 = false; -#endif bReachedAttractorHeadingTarget = false; bTurnedAroundOnAttractor = false; bCarPassenger = false; bMiamiViceCop = false; +#ifdef VC_PED_PORTS + bHeadStuckInCollision = false; +#endif + bIsPlayerFriend = true; bDeadPedInFrontOfCar = false; if ((CGeneral::GetRandomNumber() & 3) == 0) @@ -10662,7 +10663,7 @@ CPed::ProcessControl(void) flyDir = 1; } - if (flyDir != 0 && !bSomeVCflag1) { + if (flyDir != 0 && !bHeadStuckInCollision) { SetPosition((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point)); GetMatrix().GetPosition().z += FEET_OFFSET; GetMatrix().UpdateRW(); @@ -10769,11 +10770,11 @@ CPed::ProcessControl(void) if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, nil)) { #ifdef VC_PED_PORTS - if (!bSomeVCflag1 || FEET_OFFSET + foundCol.point.z < GetPosition().z) { + if (!bHeadStuckInCollision || FEET_OFFSET + foundCol.point.z < GetPosition().z) { GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z; GetMatrix().UpdateRW(); - if (bSomeVCflag1) - bSomeVCflag1 = false; + if (bHeadStuckInCollision) + bHeadStuckInCollision = false; } #else GetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z; @@ -10843,15 +10844,15 @@ CPed::ProcessControl(void) if (IsPedInControl() && !bIsStanding && !m_pDamageEntity && CheckIfInTheAir()) { SetInTheAir(); #ifdef VC_PED_PORTS - bSomeVCflag1 = false; + bHeadStuckInCollision = false; #endif } #ifdef VC_PED_PORTS - if (bSomeVCflag1) { + if (bHeadStuckInCollision) { CVector posToCheck = GetPosition(); posToCheck.z += 0.9f; if (!CWorld::TestSphereAgainstWorld(posToCheck, 0.2f, this, true, true, false, true, false, false)) - bSomeVCflag1 = false; + bHeadStuckInCollision = false; } #endif ProcessObjective(); @@ -15339,10 +15340,10 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) { bStillOnValidPoly = true; #ifdef VC_PED_PORTS - if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { + if(!bHeadStuckInCollision || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; - if (bSomeVCflag1) - bSomeVCflag1 = false; + if (bHeadStuckInCollision) + bHeadStuckInCollision = false; } #else GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; @@ -15417,10 +15418,10 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) } } #ifdef VC_PED_PORTS - if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { + if (!bHeadStuckInCollision || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) { GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; - if (bSomeVCflag1) - bSomeVCflag1 = false; + if (bHeadStuckInCollision) + bHeadStuckInCollision = false; } #else GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; @@ -15507,7 +15508,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed); sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed); GetMatrix().GetPosition().z -= 0.05f; - bSomeVCflag1 = true; + bHeadStuckInCollision = true; } #endif sphereNormal.Normalise(); @@ -16038,8 +16039,9 @@ CPed::SetSolicit(uint32 time) } bool -CPed::SetFollowPath(CVector dest) +CPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* pFollowedPed, CEntity*, int time) { + // TODO(MIAMI): new follow if (m_nPedState == PED_FOLLOW_PATH) return false; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 1fa36b05..f34de765 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -418,9 +418,6 @@ public: uint32 bVehExitWillBeInstant : 1; uint32 bHasAlreadyBeenRecorded : 1; uint32 bFallenDown : 1; -#ifdef VC_PED_PORTS - uint32 bSomeVCflag1 : 1; -#endif #ifdef PED_SKIN uint32 bDontAcceptIKLookAts : 1; // TODO: find uses of this #endif @@ -433,6 +430,10 @@ public: uint32 bHasAlreadyUsedAttractor : 1; // 0x155 0x1 uint32 bCarPassenger : 1; // 0x155 0x4 uint32 bMiamiViceCop : 1; // 0x155 0x20 + uint32 bIsPlayerFriend : 1; // 0x156 0x10 +#ifdef VC_PED_PORTS + uint32 bHeadStuckInCollision : 1; // 0x156 0x20 +#endif uint32 bDeadPedInFrontOfCar : 1; // 0x156 0x40 uint8 CharCreatedBy; @@ -666,7 +667,9 @@ public: void SetPointGunAt(CEntity*); bool Seek(void); bool SetWanderPath(int8); - bool SetFollowPath(CVector); + bool SetFollowPath(CVector dest, float radius, eMoveState state, CEntity*, CEntity*, int); + bool SetFollowPathStatic(void); + bool SetFollowPathDynamic(void); void ClearAttackByRemovingAnim(void); void SetStoredState(void); void StopNonPartialAnims(void); @@ -873,7 +876,12 @@ public: CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } PedState GetPedState(void) { return m_nPedState; } - void SetPedState(PedState state) { m_nPedState = state; } + void SetPedState(PedState state) + { + if (GetPedState() == PED_FOLLOW_PATH) + ClearFollowPath(); + m_nPedState = state; + } bool Dead(void) { return m_nPedState == PED_DEAD; } bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index e0ee0296..524067ca 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -2853,6 +2853,7 @@ CAutomobile::ProcessBuoyancy(void) if(impulseRatio > 0.5f){ bIsInWater = true; + bIsDrowning = true; if(m_vecMoveSpeed.z < -0.1f) m_vecMoveSpeed.z = -0.1f; @@ -2867,8 +2868,11 @@ CAutomobile::ProcessBuoyancy(void) if(pPassengers[i]->IsPlayer() || !bWaterTight) pPassengers[i]->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); } - }else + } + else { bIsInWater = false; + bIsDrowning = false; + } static uint32 nGenerateRaindrops = 0; static uint32 nGenerateWaterCircles = 0; @@ -2950,6 +2954,7 @@ CAutomobile::ProcessBuoyancy(void) } }else{ bIsInWater = false; + bIsDrowning = false; bTouchingWater = false; static RwRGBA splashCol = {155, 155, 185, 196}; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 1e7f8ecf..c4ac94a2 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -273,9 +273,17 @@ CBoat::ProcessControl(void) if(0.1f * m_fMass * GRAVITY*CTimer::GetTimeStep() < buoyanceImpulse.z){ bBoatInWater = true; bIsInWater = true; + if (GetUp().z < -0.6f && Abs(GetMoveSpeed().x) < 0.05 && Abs(GetMoveSpeed().y) < 0.05) { + bIsDrowning = true; + if (pDriver) + pDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); + } + else + bIsDrowning = false; }else{ bBoatInWater = false; bIsInWater = false; + bIsDrowning = false; } m_fVolumeUnderWater = mod_Buoyancy.m_volumeUnderWater; @@ -519,6 +527,7 @@ CBoat::ProcessControl(void) }else{ bBoatInWater = false; bIsInWater = false; + bIsDrowning = false; } if(m_bIsAnchored){ diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index c5699d5e..90ffed50 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -104,6 +104,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_nCarHornPattern = 0; m_nCarHornDelay = 0; bPartOfConvoy = false; + bIsDrowning = false; bCreatedAsPoliceVehicle = false; bParking = false; m_nAlarmState = 0; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index c2cfa5e4..cce07410 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -182,10 +182,16 @@ public: uint8 bVehicleColProcessed : 1;// Has ProcessEntityCollision been processed for this car? uint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command uint8 bHasAlreadyBeenRecorded : 1; // Used for replays - uint8 bPartOfConvoy : 1; + //uint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really + //uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear + + uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water) + //uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc) + //uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed uint8 bParking : 1; + //uint8 bCanPark : 1; uint8 m_bombType : 3; From e967db4a3c18d3bf743afa4346ab29ee9ad6e7c2 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 19 May 2020 21:10:40 +0300 Subject: [PATCH 065/148] fixed annoying bug --- src/core/Zones.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 8e73a07b..0e8606f3 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -112,6 +112,7 @@ CTheZones::Init(void) memset(&MapZoneArray[i], 0, sizeof(CZone)); MapZoneArray[i].type = ZONE_MAPZONE; } + TotalNumberOfMapZones = 1; strcpy(MapZoneArray[0].name, "THEMAP"); MapZoneArray[0].minx = -2400.0f; MapZoneArray[0].miny = -2000.0f; From 46d1889344bc8837721b3eb102e2ea41dca6cfa4 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 19 May 2020 21:34:28 +0300 Subject: [PATCH 066/148] slightly restructured ped flags for convenience --- src/peds/Ped.h | 52 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index f34de765..c01e3630 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -421,21 +421,51 @@ public: #ifdef PED_SKIN uint32 bDontAcceptIKLookAts : 1; // TODO: find uses of this #endif + uint32 bReachedAttractorHeadingTarget : 1; + uint32 bTurnedAroundOnAttractor : 1; + + uint32 bHasAlreadyUsedAttractor : 1; + //uint32 b155_2 + uint32 bCarPassenger : 1; + //uint32 b155_8 + //uint32 b155_10 + uint32 bMiamiViceCop : 1; + //uint32 b155_40 + //uint32 b155_80 + + //uint32 b156_1 + //uint32 b156_2 + //uint32 b156_4 + //uint32 b156_8 + uint32 bIsPlayerFriend : 1; +#ifdef VC_PED_PORTS + uint32 bHeadStuckInCollision : 1; +#endif + uint32 bDeadPedInFrontOfCar : 1; + //uint32 b156_80 + + //uint32 b157_1 + //uint32 b157_2 + //uint32 b157_4 + //uint32 b157_8 + //uint32 b157_10 + //uint32 b157_20 + //uint32 b157_40 + //uint32 b157_80 + + //uint32 b158_1 + //uint32 b158_2 + //uint32 b158_4 + //uint32 b158_8 + //uint32 b158_10 + //uint32 b158_20 + //uint32 b158_40 + //uint32 b158_80 + // our own flags uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle - uint32 bReachedAttractorHeadingTarget : 1; // 0x154 0x40 - uint32 bTurnedAroundOnAttractor : 1; // 0x154 0x80 - uint32 bHasAlreadyUsedAttractor : 1; // 0x155 0x1 - uint32 bCarPassenger : 1; // 0x155 0x4 - uint32 bMiamiViceCop : 1; // 0x155 0x20 - uint32 bIsPlayerFriend : 1; // 0x156 0x10 -#ifdef VC_PED_PORTS - uint32 bHeadStuckInCollision : 1; // 0x156 0x20 -#endif - uint32 bDeadPedInFrontOfCar : 1; // 0x156 0x40 - uint8 CharCreatedBy; eObjective m_objective; eObjective m_prevObjective; From bdbe5d1080066073f063d653e80df6dbf4b326a2 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 19 May 2020 20:56:42 +0200 Subject: [PATCH 067/148] CEntity and friends --- src/control/Pickups.cpp | 73 ----- src/control/Script.cpp | 17 +- src/control/TrafficLights.cpp | 5 +- src/core/Camera.cpp | 11 +- src/core/Camera.h | 1 - src/core/Placeable.cpp | 2 - src/core/Placeable.h | 1 - src/core/World.cpp | 24 +- src/entities/Entity.cpp | 519 ++++++++++++++++++++------------- src/entities/Entity.h | 11 +- src/entities/Physical.cpp | 12 +- src/modelinfo/ModelIndices.cpp | 6 +- src/modelinfo/ModelIndices.h | 456 +++++++++++------------------ src/objects/Object.cpp | 10 +- src/objects/Object.h | 4 +- src/peds/Population.cpp | 22 +- src/render/2dEffect.h | 5 +- src/render/Clouds.cpp | 2 - src/render/Coronas.cpp | 11 +- src/render/Coronas.h | 6 +- src/render/Renderer.cpp | 12 +- src/render/WindModifiers.cpp | 8 + src/render/WindModifiers.h | 7 + src/vehicles/Automobile.cpp | 2 + src/vehicles/Cranes.cpp | 2 + src/vehicles/HandlingMgr.cpp | 2 + 26 files changed, 581 insertions(+), 650 deletions(-) create mode 100644 src/render/WindModifiers.cpp create mode 100644 src/render/WindModifiers.h diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 01a28193..86ae4440 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1148,45 +1148,6 @@ CPacManPickups::Update() void CPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, uint8 type) { - int i = 0; - while (count > 0) { - while (aPMPickUps[i].m_eType != PACMAN_NONE) - i++; - - bool bPickupCreated = false; - while (!bPickupCreated) { - CVector newPos = pos; - CColPoint colPoint; - CEntity *pRoad; - uint16 nRand = CGeneral::GetRandomNumber(); - newPos.x += ((nRand & 0xFF) - 128) * scrambleMult / 128.0f; - newPos.y += (((nRand >> 8) & 0xFF) - 128) * scrambleMult / 128.0f; - newPos.z = 1000.0f; - if (CWorld::ProcessVerticalLine(newPos, -1000.0f, colPoint, pRoad, true, false, false, false, true, false, nil) && pRoad->IsBuilding() && ((CBuilding*)pRoad)->GetIsATreadable()) { - newPos.z = 0.7f + colPoint.point.z; - aPMPickUps[i].m_eType = type; - aPMPickUps[i].m_vecPosn = newPos; - CObject *obj = new CObject(MI_BULLION, true); - if (obj != nil) { - obj->ObjectCreatedBy = MISSION_OBJECT; - obj->SetPosition(aPMPickUps[i].m_vecPosn); - obj->SetOrientation(0.0f, 0.0f, -HALFPI); - obj->GetMatrix().UpdateRW(); - obj->UpdateRwFrame(); - - obj->bAffectedByGravity = false; - obj->bExplosionProof = true; - obj->bUsesCollision = false; - obj->bIsPickup = false; - CWorld::Add(obj); - } - aPMPickUps[i].m_pObject = obj; - bPickupCreated = true; - } - } - count--; - } - bPMActive = true; } // diablo porn mission pickups @@ -1303,40 +1264,6 @@ static const CVector aRacePoints1[] = { void CPacManPickups::GeneratePMPickUpsForRace(int32 race) { - const CVector *pPos = nil; - int i = 0; - - if (race == 0) pPos = aRacePoints1; // there's only one available - assert(pPos != nil); - - while (!pPos->IsZero()) { - while (aPMPickUps[i].m_eType != PACMAN_NONE) - i++; - - aPMPickUps[i].m_eType = PACMAN_RACE; - aPMPickUps[i].m_vecPosn = *(pPos++); - if (race == 0) { - CObject* obj = new CObject(MI_DONKEYMAG, true); - if (obj != nil) { - obj->ObjectCreatedBy = MISSION_OBJECT; - - obj->SetPosition(aPMPickUps[i].m_vecPosn); - obj->SetOrientation(0.0f, 0.0f, -HALFPI); - obj->GetMatrix().UpdateRW(); - obj->UpdateRwFrame(); - - obj->bAffectedByGravity = false; - obj->bExplosionProof = true; - obj->bUsesCollision = false; - obj->bIsPickup = false; - - CWorld::Add(obj); - } - aPMPickUps[i].m_pObject = obj; - } else - aPMPickUps[i].m_pObject = nil; - } - bPMActive = true; } void diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 2ad1e9de..cc5c698b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -7167,12 +7167,13 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) } case COMMAND_CREATE_FLOATING_PACKAGE: { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - if (pos.z <= MAP_Z_LOW_LIMIT) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; - ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0); - StoreParameters(&m_nIp, 1); +// removed in MIAMI +// CollectParameters(&m_nIp, 3); +// CVector pos = *(CVector*)&ScriptParams[0]; +// if (pos.z <= MAP_Z_LOW_LIMIT) +// pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; +// ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0); +// StoreParameters(&m_nIp, 1); return 0; } case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR: @@ -8626,8 +8627,8 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) return 0; } case COMMAND_GET_BODY_CAST_HEALTH: - ScriptParams[0] = CObject::nBodyCastHealth; - StoreParameters(&m_nIp, 1); + // ScriptParams[0] = CObject::nBodyCastHealth; + // StoreParameters(&m_nIp, 1); return 0; case COMMAND_SET_CHARS_CHATTING: { diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 500d6af2..b1816936 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -145,7 +145,10 @@ CTrafficLights::ScanForLightsOnMap(void) CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES]; for(node = list.first; node; node = node->next){ CEntity *light = (CEntity*)node->item; - if(light->GetModelIndex() != MI_TRAFFICLIGHTS) + if(light->GetModelIndex() != MI_TRAFFICLIGHTS && + light->GetModelIndex() != MI_TRAFFICLIGHTS_VERTICAL && + light->GetModelIndex() != MI_TRAFFICLIGHTS_MIAMI && + light->GetModelIndex() != MI_TRAFFICLIGHTS_TWOVERTICAL) continue; // Check cars diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 1efe6bae..fa5e44bb 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -82,10 +82,6 @@ CCamera::CCamera(void) Init(); } -CCamera::CCamera(float) -{ -} - void CCamera::Init(void) { @@ -93,12 +89,7 @@ CCamera::Init(void) float fMouseAccelHorzntl = m_fMouseAccelHorzntl; float fMouseAccelVertical = m_fMouseAccelVertical; #endif -#ifdef FIX_BUGS - static const CCamera DummyCamera = CCamera(0.f); - *this = DummyCamera; -#else - memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh? -#endif + memset(this, 0, sizeof(CCamera)); // this is fine, no vtable #ifdef GTA3_1_1_PATCH m_fMouseAccelHorzntl = fMouseAccelHorzntl; m_fMouseAccelVertical = fMouseAccelVertical; diff --git a/src/core/Camera.h b/src/core/Camera.h index 8f2b6c51..135f9d8f 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -549,7 +549,6 @@ public: // High level and misc CCamera(void); - CCamera(float); void Init(void); void Process(void); void CamControl(void); diff --git a/src/core/Placeable.cpp b/src/core/Placeable.cpp index 69b3d3ea..6efc1540 100644 --- a/src/core/Placeable.cpp +++ b/src/core/Placeable.cpp @@ -7,8 +7,6 @@ CPlaceable::CPlaceable(void) m_matrix.SetScale(1.0f); } -CPlaceable::~CPlaceable(void) = default; - void CPlaceable::SetHeading(float angle) { diff --git a/src/core/Placeable.h b/src/core/Placeable.h index 970c0d48..22f7583c 100644 --- a/src/core/Placeable.h +++ b/src/core/Placeable.h @@ -9,7 +9,6 @@ public: CMatrix m_matrix; CPlaceable(void); - virtual ~CPlaceable(void); const CVector &GetPosition(void) { return m_matrix.GetPosition(); } void SetPosition(float x, float y, float z) { m_matrix.GetPosition().x = x; diff --git a/src/core/World.cpp b/src/core/World.cpp index f6817f8b..16e5e80d 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1813,18 +1813,22 @@ void CWorld::RepositionOneObject(CEntity *pEntity) { int16 modelId = pEntity->GetModelIndex(); - if (IsTrafficLight(modelId) || IsTreeModel(modelId) || modelId == MI_PARKINGMETER || - modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || modelId == MI_BIN || modelId == MI_POSTBOX1 || - modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || modelId == MI_DUMP1 || - modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || - modelId == MI_PHONESIGN || modelId == MI_TAXISIGN || modelId == MI_FISHSTALL01 || - modelId == MI_FISHSTALL02 || modelId == MI_FISHSTALL03 || modelId == MI_FISHSTALL04 || - modelId == MI_BAGELSTAND2 || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || - modelId == MI_PARKTABLE) { + if (modelId == MI_PARKINGMETER || modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || + modelId == MI_BIN || modelId == MI_POSTBOX1 || modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || + modelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || + modelId == MI_PHONESIGN || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || + modelId == MI_PARKTABLE || modelId == MI_PARKINGMETER2 || modelId == MI_TELPOLE02 || + modelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId) +// TODO(MIAMI): this is actually a different case +|| IsStreetLight(modelId) + ) { CVector &position = pEntity->GetMatrix().GetPosition(); - float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; + CColModel *pColModel = pEntity->GetColModel(); + float fBoundingBoxMinZ = pColModel->boundingBox.min.z; + float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; + if(fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z; position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, - position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - + position.z + fHeight, nil) - fBoundingBoxMinZ; pEntity->m_matrix.UpdateRW(); pEntity->UpdateRwFrame(); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index e83df204..efa67f36 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -30,6 +30,9 @@ #include "Renderer.h" #include "Ped.h" #include "Dummy.h" +#include "WindModifiers.h" + +//--MIAMI: file almost done (see TODO) int gBuildings; @@ -80,7 +83,7 @@ CEntity::CEntity(void) bIsStaticWaitingForCollision = false; m_flagE10 = false; bUnderwater = false; - m_flagE40 = false; + bHasPreRenderEffects = false; m_scanCode = 0; m_modelIndex = -1; @@ -276,6 +279,21 @@ CEntity::Remove(void) } } +void +CEntity::SetModelIndex(uint32 id) +{ + m_modelIndex = id; + bHasPreRenderEffects = HasPreRenderEffects(); + CreateRwObject(); +} + +void +CEntity::SetModelIndexNoCreate(uint32 id) +{ + m_modelIndex = id; + bHasPreRenderEffects = HasPreRenderEffects(); +} + void CEntity::CreateRwObject(void) { @@ -306,10 +324,8 @@ CEntity::DeleteRwObject(void) RpAtomicDestroy((RpAtomic*)m_rwObject); RwFrameDestroy(f); }else if(RwObjectGetType(m_rwObject) == rpCLUMP){ -#ifdef PED_SKIN if(IsClumpSkinned((RpClump*)m_rwObject)) RpClumpForAllAtomics((RpClump*)m_rwObject, AtomicRemoveAnimFromSkinCB, nil); -#endif RpClumpDestroy((RpClump*)m_rwObject); } m_rwObject = nil; @@ -330,7 +346,6 @@ CEntity::UpdateRwFrame(void) } } -//--MIAMI: done void CEntity::SetupBigBuilding(void) { @@ -370,19 +385,39 @@ CEntity::GetBoundRect(void) return rect; } +bool +CEntity::HasPreRenderEffects(void) +{ + return IsTreeModel(GetModelIndex()) || + GetModelIndex() == MI_COLLECTABLE1 || + GetModelIndex() == MI_MONEY || + GetModelIndex() == MI_CARMINE || + GetModelIndex() == MI_NAUTICALMINE || + GetModelIndex() == MI_BRIEFCASE || + GetModelIndex() == MI_GRENADE || + GetModelIndex() == MI_MOLOTOV || + GetModelIndex() == MI_MISSILE || + GetModelIndex() == MI_BEACHBALL || + IsGlass(GetModelIndex()) || + IsObject() && ((CObject*)this)->bIsPickup; + IsStreetLight(GetModelIndex()); +} + void CEntity::PreRender(void) { + if (CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects() != 0) + ProcessLightsForEntity(); + + if(!bHasPreRenderEffects) + return; + switch(m_type){ case ENTITY_TYPE_BUILDING: - if(GetModelIndex() == MI_RAILTRACKS){ - CShadows::StoreShadowForPole(this, 0.0f, -10.949f, 5.0f, 8.0f, 1.0f, 0); - CShadows::StoreShadowForPole(this, 0.0f, 10.949f, 5.0f, 8.0f, 1.0f, 1); - }else if(IsTreeModel(GetModelIndex())){ - CShadows::StoreShadowForTree(this); + if(IsTreeModel(GetModelIndex())){ + float dist = (TheCamera.GetPosition() - GetPosition()).Magnitude2D(); + CObject::fDistToNearestTree = Min(CObject::fDistToNearestTree, dist); ModifyMatrixForTreeInWind(); - }else if(IsBannerModel(GetModelIndex())){ - ModifyMatrixForBannerInWind(); } break; case ENTITY_TYPE_OBJECT: @@ -423,12 +458,11 @@ CEntity::PreRender(void) CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); }else if(IsGlass(GetModelIndex())){ - if(!((CSimpleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_isArtistGlass) - PreRenderForGlassWindow(); + PreRenderForGlassWindow(); }else if (((CObject*)this)->bIsPickup) { - CPickups::DoPickUpEffects(this); - GetMatrix().UpdateRW(); - UpdateRwFrame(); + CPickups::DoPickUpEffects(this); + GetMatrix().UpdateRW(); + UpdateRwFrame(); } else if (GetModelIndex() == MI_GRENADE) { CMotionBlurStreaks::RegisterStreak((uintptr)this, 100, 100, 100, @@ -439,12 +473,30 @@ CEntity::PreRender(void) 0, 100, 0, GetPosition() - 0.07f * TheCamera.GetRight(), GetPosition() + 0.07f * TheCamera.GetRight()); + }else if(GetModelIndex() == MI_BEACHBALL){ + CVector pos = GetPosition(); + CShadows::StoreShadowToBeRendered(SHADOWTYPE_DARK, + gpShadowPedTex, &pos, + 0.4f, 0.0f, 0.0f, -0.4f, + CTimeCycle::GetShadowStrength(), + CTimeCycle::GetShadowStrength(), + CTimeCycle::GetShadowStrength(), + CTimeCycle::GetShadowStrength(), + 20.0f, false, 1.0f); } // fall through case ENTITY_TYPE_DUMMY: if(GetModelIndex() == MI_TRAFFICLIGHTS){ CTrafficLights::DisplayActualLight(this); CShadows::StoreShadowForPole(this, 2.957f, 0.147f, 0.0f, 16.0f, 0.4f, 0); + }else if(GetModelIndex() == MI_TRAFFICLIGHTS_VERTICAL){ + CTrafficLights::DisplayActualLight(this); + }else if(GetModelIndex() == MI_TRAFFICLIGHTS_MIAMI){ + CTrafficLights::DisplayActualLight(this); + CShadows::StoreShadowForPole(this, 4.819f, 1.315f, 0.0f, 16.0f, 0.4f, 0); + }else if(GetModelIndex() == MI_TRAFFICLIGHTS_TWOVERTICAL){ + CTrafficLights::DisplayActualLight(this); + CShadows::StoreShadowForPole(this, 7.503f, 0.0f, 0.0f, 16.0f, 0.4f, 0); }else if(GetModelIndex() == MI_SINGLESTREETLIGHTS1) CShadows::StoreShadowForPole(this, 0.744f, 0.0f, 0.0f, 16.0f, 0.4f, 0); else if(GetModelIndex() == MI_SINGLESTREETLIGHTS2) @@ -453,19 +505,15 @@ CEntity::PreRender(void) CShadows::StoreShadowForPole(this, 1.143f, 0.145f, 0.0f, 16.0f, 0.4f, 0); else if(GetModelIndex() == MI_DOUBLESTREETLIGHTS) CShadows::StoreShadowForPole(this, 0.0f, -0.048f, 0.0f, 16.0f, 0.4f, 0); - else if(GetModelIndex() == MI_STREETLAMP1 || - GetModelIndex() == MI_STREETLAMP2) - CShadows::StoreShadowForPole(this, 0.0f, 0.0f, 0.0f, 16.0f, 0.4f, 0); break; } - - if (CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects() != 0) - ProcessLightsForEntity(); } void CEntity::PreRenderForGlassWindow(void) { + if(((CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_isArtistGlass) + return; CGlass::AskForObjectToBeRenderedInGlass(this); bIsVisible = false; } @@ -486,8 +534,6 @@ CEntity::Render(void) bool CEntity::SetupLighting(void) { - DeActivateDirectional(); - SetAmbientColours(); return false; } @@ -573,13 +619,12 @@ CEntity::PruneReferences(void) } } -#ifdef PED_SKIN void CEntity::UpdateRpHAnim(void) { - RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); - RpHAnimHierarchyUpdateMatrices(hier); - + if(IsClumpSkinned(GetClump())){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + RpHAnimHierarchyUpdateMatrices(hier); #if 0 int i; char buf[256]; @@ -608,8 +653,8 @@ CEntity::UpdateRpHAnim(void) void RenderSkeleton(RpHAnimHierarchy *hier); RenderSkeleton(hier); #endif + } } -#endif void CEntity::AddSteamsFromGround(CVector *unused) @@ -641,6 +686,15 @@ CEntity::AddSteamsFromGround(CVector *unused) case 4: CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false); break; +// TODO(MIAMI): enable this once we have the particle objects +/* + case 5: + CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_VERT, pos, effect->particle.dir, effect->particle.scale, false); + break; + case 6: + CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_HORIZ, pos, effect->particle.dir, effect->particle.scale, false); + break; +*/ } } } @@ -665,80 +719,66 @@ CEntity::ProcessLightsForEntity(void) for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){ effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i); - if(effect->type != EFFECT_LIGHT) - continue; + switch(effect->type){ + case EFFECT_LIGHT: + pos = GetMatrix() * effect->pos; - pos = GetMatrix() * effect->pos; - - lightOn = false; - lightFlickering = false; - switch(effect->light.lightType){ - case LIGHT_ON: - lightOn = true; - break; - case LIGHT_ON_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + lightOn = false; + lightFlickering = false; + switch(effect->light.lightType){ + case LIGHT_ON: lightOn = true; - break; - case LIGHT_FLICKER: - if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) - lightOn = true; - else - lightFlickering = true; - if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3) - lightOn = true; - break; - case LIGHT_FLICKER_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7){ + break; + case LIGHT_ON_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + lightOn = true; + break; + case LIGHT_FLICKER: if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) lightOn = true; else lightFlickering = true; if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3) lightOn = true; - } - break; - case LIGHT_FLASH1: - if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200) - lightOn = true; - break; - case LIGHT_FLASH1_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + break; + case LIGHT_FLICKER_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){ + if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) + lightOn = true; + else + lightFlickering = true; + if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3) + lightOn = true; + } + break; + case LIGHT_FLASH1: if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200) lightOn = true; - break; - case LIGHT_FLASH2: - if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400) - lightOn = true; - break; - case LIGHT_FLASH2_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + break; + case LIGHT_FLASH1_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200) + lightOn = true; + break; + case LIGHT_FLASH2: if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400) lightOn = true; - break; - case LIGHT_FLASH3: - if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800) - lightOn = true; - break; - case LIGHT_FLASH3_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + break; + case LIGHT_FLASH2_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400) + lightOn = true; + break; + case LIGHT_FLASH3: if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800) lightOn = true; - break; - case LIGHT_RANDOM_FLICKER: - if(m_randomSeed > 16) - lightOn = true; - else{ - if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60) - lightOn = true; - else - lightFlickering = true; - if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3) - lightOn = true; - } - break; - case LIGHT_RANDOM_FLICKER_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7){ + break; + case LIGHT_FLASH3_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7) + if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800) + lightOn = true; + break; + case LIGHT_RANDOM_FLICKER: if(m_randomSeed > 16) lightOn = true; else{ @@ -749,85 +789,143 @@ CEntity::ProcessLightsForEntity(void) if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3) lightOn = true; } + break; + case LIGHT_RANDOM_FLICKER_NIGHT: + if(CClock::GetHours() > 18 || CClock::GetHours() < 7){ + if(m_randomSeed > 16) + lightOn = true; + else{ + if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60) + lightOn = true; + else + lightFlickering = true; + if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3) + lightOn = true; + } + } + break; + case LIGHT_BRIDGE_FLASH1: + if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200) + lightOn = true; + break; + case LIGHT_BRIDGE_FLASH2: + if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60) + lightOn = true; + break; + } + + if(effect->light.flags & LIGHTFLAG_HIDE_OBJECT){ + if(lightOn) + bDoNotRender = false; + else + bDoNotRender = true; + return; + } + + // Corona + if(lightOn) + CCoronas::RegisterCorona((uintptr)this + i, + effect->col.r, effect->col.g, effect->col.b, 255, + pos, effect->light.size, effect->light.dist, + effect->light.corona, effect->light.flareType, effect->light.roadReflection, + effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f, + !!(effect->light.flags&LIGHTFLAG_LONG_DIST)); + else if(lightFlickering) + CCoronas::RegisterCorona((uintptr)this + i, + 0, 0, 0, 255, + pos, effect->light.size, effect->light.dist, + effect->light.corona, effect->light.flareType, effect->light.roadReflection, + effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f, + !!(effect->light.flags&LIGHTFLAG_LONG_DIST)); + + // Pointlight + bool alreadyProcessedFog; + alreadyProcessedFog = false; + if(effect->light.range != 0.0f && lightOn){ + if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){ + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos, CVector(0.0f, 0.0f, 0.0f), + effect->light.range, + 0.0f, 0.0f, 0.0f, + CPointLights::FOG_NONE, true); + }else{ + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos, CVector(0.0f, 0.0f, 0.0f), + effect->light.range, + effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f, + effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f, + effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f, + (effect->light.flags & LIGHTFLAG_FOG) >> 1, + true); + alreadyProcessedFog = true; + } + } + + if(!alreadyProcessedFog){ + if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){ + CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS, + pos, CVector(0.0f, 0.0f, 0.0f), + 0.0f, + effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, + CPointLights::FOG_ALWAYS, true); + }else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){ + CPointLights::AddLight(CPointLights::LIGHT_FOGONLY, + pos, CVector(0.0f, 0.0f, 0.0f), + 0.0f, + effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, + CPointLights::FOG_NORMAL, true); + } + } + + // Light shadow + if(effect->light.shadowRange != 0.0f){ + if(lightOn){ + CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, + effect->light.shadow, &pos, + effect->light.shadowRange, 0.0f, + 0.0f, -effect->light.shadowRange, + 128, + effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, + effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, + effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, + 15.0f, 1.0f, 40.0f, false, 0.0f); + }else if(lightFlickering){ + CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, + effect->light.shadow, &pos, + effect->light.shadowRange, 0.0f, + 0.0f, -effect->light.shadowRange, + 0, 0.0f, 0.0f, 0.0f, + 15.0f, 1.0f, 40.0f, false, 0.0f); + } } break; - case LIGHT_BRIDGE_FLASH1: - if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200) - lightOn = true; - break; - case LIGHT_BRIDGE_FLASH2: - if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60) - lightOn = true; - break; - } - // Corona - if(lightOn) - CCoronas::RegisterCorona((uintptr)this + i, - effect->col.r, effect->col.g, effect->col.b, 255, - pos, effect->light.size, effect->light.dist, - effect->light.corona, effect->light.flareType, effect->light.roadReflection, - effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f); - else if(lightFlickering) - CCoronas::RegisterCorona((uintptr)this + i, - 0, 0, 0, 255, - pos, effect->light.size, effect->light.dist, - effect->light.corona, effect->light.flareType, effect->light.roadReflection, - effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f); - - // Pointlight - if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){ - CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, - CPointLights::FOG_ALWAYS, true); - }else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){ - CPointLights::AddLight(CPointLights::LIGHT_FOGONLY, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f, - CPointLights::FOG_NORMAL, true); - }else if(lightOn && effect->light.range != 0.0f){ - if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){ - CPointLights::AddLight(CPointLights::LIGHT_POINT, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - 0.0f, 0.0f, 0.0f, - CPointLights::FOG_NONE, true); - }else{ - CPointLights::AddLight(CPointLights::LIGHT_POINT, - pos, CVector(0.0f, 0.0f, 0.0f), - effect->light.range, - effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f, - effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f, - effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f, - // half-useless because LIGHTFLAG_FOG_ALWAYS can't be on - (effect->light.flags & LIGHTFLAG_FOG) >> 1, - true); - } - } - - // Light shadow - if(effect->light.shadowRange != 0.0f){ - if(lightOn){ - CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, - effect->light.shadow, &pos, - effect->light.shadowRange, 0.0f, - 0.0f, -effect->light.shadowRange, - 128, - effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, - effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, - effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f, - 15.0f, 1.0f, 40.0f, false, 0.0f); - }else if(lightFlickering){ - CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE, - effect->light.shadow, &pos, - effect->light.shadowRange, 0.0f, - 0.0f, -effect->light.shadowRange, - 0, 0.0f, 0.0f, 0.0f, - 15.0f, 1.0f, 40.0f, false, 0.0f); + case EFFECT_SUNGLARE: + if(CWeather::SunGlare >= 0.0f){ + CVector pos = GetMatrix() * effect->pos; + CVector glareDir = pos - GetPosition(); + glareDir.Normalise(); + CVector camDir = TheCamera.GetPosition() - pos; + float dist = camDir.Magnitude(); + camDir *= 2.0f/dist; + glareDir += camDir; + glareDir.Normalise(); + float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunPosition()); + if(camAngle > 0.0f){ + float intens = Sqrt(camAngle) * CWeather::SunGlare; + pos += camDir; + CCoronas::RegisterCorona((uintptr)this + 33 + i, + intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f, + intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f, + intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f, + 255, + pos, 0.5f*CWeather::SunGlare*Sqrt(dist), 120.0f, + CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, + CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, + CCoronas::STREAK_OFF, 0.0f); + } } + break; } } } @@ -850,27 +948,31 @@ CEntity::ModifyMatrixForTreeInWind(void) CMatrix mat(GetMatrix().m_attachment); if(CWeather::Wind >= 0.5){ - t = m_randomSeed + 16*CTimer::GetTimeInMilliseconds(); + t = m_randomSeed + 8*CTimer::GetTimeInMilliseconds(); f = (t & 0xFFF)/(float)0x1000; flutter = f * WindTabel[(t>>12)+1 & 0xF] + (1.0f - f) * WindTabel[(t>>12) & 0xF] + 1.0f; - strength = CWeather::Wind < 0.8f ? 0.008f : 0.014f; + strength = -0.015f*CWeather::Wind; }else if(CWeather::Wind >= 0.2){ t = (uintptr)this + CTimer::GetTimeInMilliseconds(); f = (t & 0xFFF)/(float)0x1000; flutter = Sin(f * 6.28f); - strength = 0.008f; + strength = -0.008f; }else{ t = (uintptr)this + CTimer::GetTimeInMilliseconds(); f = (t & 0xFFF)/(float)0x1000; flutter = Sin(f * 6.28f); - strength = 0.005f; + strength = -0.005f; } mat.GetUp().x = strength * flutter; + if(IsPalmTreeModel(GetModelIndex())) + mat.GetUp().x += -0.07f*CWeather::Wind; mat.GetUp().y = mat.GetUp().x; + CWindModifiers::FindWindModifier(GetPosition(), &mat.GetUp().x, &mat.GetUp().y); + mat.UpdateRW(); UpdateRwFrame(); } @@ -882,6 +984,7 @@ float BannerWindTabel[] = { 0.28f, 0.28f, 0.22f, 0.1f, 0.0f, -0.1f, -0.17f, -0.12f }; +//--MIAMI: unused void CEntity::ModifyMatrixForBannerInWind(void) { @@ -929,7 +1032,6 @@ CEntity::AddSteamsFromGround(CPtrList& list) } #ifdef COMPATIBLE_SAVES -// TODO(MIAMI) void CEntity::SaveEntityFlags(uint8*& buf) { @@ -953,35 +1055,41 @@ CEntity::SaveEntityFlags(uint8*& buf) if (bRenderScorched) tmp |= BIT(20); if (bHasBlip) tmp |= BIT(21); if (bIsBIGBuilding) tmp |= BIT(22); - if (bRenderDamaged) tmp |= BIT(23); + if (bStreamBIGBuilding) tmp |= BIT(23); - if (bBulletProof) tmp |= BIT(24); - if (bFireProof) tmp |= BIT(25); - if (bCollisionProof) tmp |= BIT(26); - if (bMeleeProof) tmp |= BIT(27); - if (bOnlyDamagedByPlayer) tmp |= BIT(28); - if (bStreamingDontDelete) tmp |= BIT(29); - if (bRemoveFromWorld) tmp |= BIT(0); - if (bHasHitWall) tmp |= BIT(1); + if (bRenderDamaged) tmp |= BIT(24); + if (bBulletProof) tmp |= BIT(25); + if (bFireProof) tmp |= BIT(26); + if (bCollisionProof) tmp |= BIT(27); + if (bMeleeProof) tmp |= BIT(28); + if (bOnlyDamagedByPlayer) tmp |= BIT(29); + if (bStreamingDontDelete) tmp |= BIT(30); + if (bRemoveFromWorld) tmp |= BIT(31); WriteSaveBuf(buf, tmp); tmp = 0; - if (bImBeingRendered) tmp |= BIT(2); - if (bTouchingWater) tmp |= BIT(3); - if (bIsSubway) tmp |= BIT(4); - if (bDrawLast) tmp |= BIT(5); - if (bNoBrightHeadLights) tmp |= BIT(6); - if (bDoNotRender) tmp |= BIT(7); - if (bDistanceFade) tmp |= BIT(8); + if (bHasHitWall) tmp |= BIT(0); + if (bImBeingRendered) tmp |= BIT(1); + if (bTouchingWater) tmp |= BIT(2); + if (bIsSubway) tmp |= BIT(3); + if (bDrawLast) tmp |= BIT(4); + if (bNoBrightHeadLights) tmp |= BIT(5); + if (bDoNotRender) tmp |= BIT(6); + if (bDistanceFade) tmp |= BIT(7); + if (m_flagE1) tmp |= BIT(8); if (m_flagE2) tmp |= BIT(9); + if (bOffscreen) tmp |= BIT(10); + if (bIsStaticWaitingForCollision) tmp |= BIT(11); + if (m_flagE10) tmp |= BIT(12); + if (bUnderwater) tmp |= BIT(13); + if (bHasPreRenderEffects) tmp |= BIT(14); WriteSaveBuf(buf, tmp); } -// TODO(MIAMI) void CEntity::LoadEntityFlags(uint8*& buf) { @@ -1005,28 +1113,35 @@ CEntity::LoadEntityFlags(uint8*& buf) bRenderScorched = !!(tmp & BIT(20)); bHasBlip = !!(tmp & BIT(21)); bIsBIGBuilding = !!(tmp & BIT(22)); - bRenderDamaged = !!(tmp & BIT(23)); + bStreamBIGBuilding = !!(tmp & BIT(23)); - bBulletProof = !!(tmp & BIT(24)); - bFireProof = !!(tmp & BIT(25)); - bCollisionProof = !!(tmp & BIT(26)); - bMeleeProof = !!(tmp & BIT(27)); - bOnlyDamagedByPlayer = !!(tmp & BIT(28)); - bStreamingDontDelete = !!(tmp & BIT(29)); - bRemoveFromWorld = !!(tmp & BIT(0)); - bHasHitWall = !!(tmp & BIT(1)); + bRenderDamaged = !!(tmp & BIT(24)); + bBulletProof = !!(tmp & BIT(25)); + bFireProof = !!(tmp & BIT(26)); + bCollisionProof = !!(tmp & BIT(27)); + bMeleeProof = !!(tmp & BIT(28)); + bOnlyDamagedByPlayer = !!(tmp & BIT(29)); + bStreamingDontDelete = !!(tmp & BIT(30)); + bRemoveFromWorld = !!(tmp & BIT(31)); tmp = ReadSaveBuf(buf); - bImBeingRendered = !!(tmp & BIT(2)); - bTouchingWater = !!(tmp & BIT(3)); - bIsSubway = !!(tmp & BIT(4)); - bDrawLast = !!(tmp & BIT(5)); - bNoBrightHeadLights = !!(tmp & BIT(6)); - bDoNotRender = !!(tmp & BIT(7)); - bDistanceFade = !!(tmp & BIT(8)); + bHasHitWall = !!(tmp & BIT(0)); + bImBeingRendered = !!(tmp & BIT(1)); + bTouchingWater = !!(tmp & BIT(2)); + bIsSubway = !!(tmp & BIT(3)); + bDrawLast = !!(tmp & BIT(4)); + bNoBrightHeadLights = !!(tmp & BIT(5)); + bDoNotRender = !!(tmp & BIT(6)); + bDistanceFade = !!(tmp & BIT(7)); + m_flagE1 = !!(tmp & BIT(8)); m_flagE2 = !!(tmp & BIT(9)); + bOffscreen = !!(tmp & BIT(10)); + bIsStaticWaitingForCollision = !!(tmp & BIT(11)); + m_flagE10 = !!(tmp & BIT(12)); + bUnderwater = !!(tmp & BIT(13)); + bHasPreRenderEffects = !!(tmp & BIT(14)); } #endif diff --git a/src/entities/Entity.h b/src/entities/Entity.h index dc5378a5..ab7b6203 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -78,7 +78,7 @@ public: uint32 bIsSubway : 1; // set when subway, but maybe different meaning? uint32 bDrawLast : 1; // draw object last uint32 bNoBrightHeadLights : 1; - uint32 bDoNotRender : 1; + uint32 bDoNotRender : 1; //-- only applies to CObjects apparently uint32 bDistanceFade : 1; // Fade entity because it is far away // flagsE @@ -88,7 +88,7 @@ public: uint32 bIsStaticWaitingForCollision : 1; // this is used by script created entities - they are static until the collision is loaded below them uint32 m_flagE10 : 1; // probably bDontStream uint32 bUnderwater : 1; // this object is underwater change drawing order - uint32 m_flagE40 : 1; + uint32 bHasPreRenderEffects : 1; // Object has a prerender effects attached to it uint16 m_scanCode; uint16 m_randomSeed; @@ -112,12 +112,12 @@ public: #endif CEntity(void); - ~CEntity(void); + virtual ~CEntity(void); virtual void Add(void); virtual void Remove(void); - virtual void SetModelIndex(uint32 id) { m_modelIndex = id; CreateRwObject(); } - virtual void SetModelIndexNoCreate(uint32 id) { m_modelIndex = id; } + virtual void SetModelIndex(uint32 id); + virtual void SetModelIndexNoCreate(uint32 id); virtual void CreateRwObject(void); virtual void DeleteRwObject(void); virtual CRect GetBoundRect(void); @@ -160,6 +160,7 @@ public: int16 GetModelIndex(void) const { return m_modelIndex; } void UpdateRwFrame(void); void SetupBigBuilding(void); + bool HasPreRenderEffects(void); void AttachToRwObject(RwObject *obj); void DetachFromRwObject(void); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 22b391e8..423662f7 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1067,13 +1067,13 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) if(B->IsBuilding()) skipShift = false; - else if(IsTrafficLight(A->GetModelIndex()) && + else if(IsStreetLight(A->GetModelIndex()) && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f) skipShift = true; else if((A->IsVehicle() || A->IsPed()) && B->GetUp().z < 0.66f && - IsTrafficLight(B->GetModelIndex())) + IsStreetLight(B->GetModelIndex())) skipShift = true; // TODO: maybe flip some ifs here else if(A->IsObject() && B->IsVehicle()){ @@ -1398,7 +1398,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(B->IsBuilding()) skipCollision = false; - else if(IsTrafficLight(A->GetModelIndex()) && + else if(IsStreetLight(A->GetModelIndex()) && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f){ skipCollision = true; @@ -1406,12 +1406,12 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) Aobj->m_pCollidingEntity = B; }else if((A->IsVehicle() || A->IsPed()) && B->GetUp().z < 0.66f && - IsTrafficLight(B->GetModelIndex())){ + IsStreetLight(B->GetModelIndex())){ skipCollision = true; A->bSkipLineCol = true; Bobj->m_pCollidingEntity = A; }else if(A->IsObject() && B->IsVehicle()){ - if(A->GetModelIndex() == MI_CAR_BUMPER || A->GetModelIndex() == MI_FILES) + if(A->GetModelIndex() == MI_CAR_BUMPER)// || A->GetModelIndex() == MI_FILES) skipCollision = true; else if(Aobj->ObjectCreatedBy == TEMP_OBJECT || Aobj->bHasBeenDamaged || @@ -1430,7 +1430,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) } } }else if(B->IsObject() && A->IsVehicle()){ - if(B->GetModelIndex() == MI_CAR_BUMPER || B->GetModelIndex() == MI_FILES) + if(B->GetModelIndex() == MI_CAR_BUMPER)// || B->GetModelIndex() == MI_FILES) skipCollision = true; else if(Bobj->ObjectCreatedBy == TEMP_OBJECT || Bobj->bHasBeenDamaged || diff --git a/src/modelinfo/ModelIndices.cpp b/src/modelinfo/ModelIndices.cpp index 9a6a74d0..056c3733 100644 --- a/src/modelinfo/ModelIndices.cpp +++ b/src/modelinfo/ModelIndices.cpp @@ -3,14 +3,14 @@ #include "General.h" #include "ModelIndices.h" -#define X(name, var, addr) int16 var; +#define X(name, var) int16 var; MODELINDICES #undef X void InitModelIndices(void) { -#define X(name, var, addr) var = -1; +#define X(name, var) var = -1; MODELINDICES #undef X } @@ -18,7 +18,7 @@ InitModelIndices(void) void MatchModelString(const char *modelname, int16 id) { -#define X(name, var, addr) \ +#define X(name, var) \ if(!CGeneral::faststrcmp(name, modelname)){ \ var = id; \ return; \ diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 25ba0b7b..fc1eb62b 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -3,168 +3,144 @@ #include "ModelInfo.h" #define MODELINDICES \ - X("fire_hydrant", MI_FIRE_HYDRANT, 0x5F5A00) \ - X("bagelstnd02", MI_BAGELSTAND2, 0x5F59FC) \ - X("fish01", MI_FISHSTALL01, 0x5F59EC) \ - X("fishstall02", MI_FISHSTALL02, 0x5F59F0) \ - X("fishstall03", MI_FISHSTALL03, 0x5F59F4) \ - X("fishstall04", MI_FISHSTALL04, 0x5F59F8) \ - X("taxisign", MI_TAXISIGN, 0x5F59E8) \ - X("phonesign", MI_PHONESIGN, 0x5F59E4) \ - X("noparkingsign1", MI_NOPARKINGSIGN1, 0x5F59E0) \ - X("bussign1", MI_BUSSIGN1, 0x5F59DC) \ - X("roadworkbarrier1", MI_ROADWORKBARRIER1, 0x5F59D8) \ - X("dump1", MI_DUMP1, 0x5F59D4) \ - X("trafficcone", MI_TRAFFICCONE, 0x5F59D0) \ - X("newsstand1", MI_NEWSSTAND, 0x5F59CC) \ - X("postbox1", MI_POSTBOX1, 0x5F59C8) \ - X("bin1", MI_BIN, 0x5F59C4) \ - X("wastebin", MI_WASTEBIN, 0x5F59C0) \ - X("phonebooth1", MI_PHONEBOOTH1, 0x5F59BC) \ - X("parkingmeter", MI_PARKINGMETER, 0x5F59B8) \ - X("trafficlight1", MI_TRAFFICLIGHTS, 0x5F5958) \ - X("lamppost1", MI_SINGLESTREETLIGHTS1, 0x5F595C) \ - X("lamppost2", MI_SINGLESTREETLIGHTS2, 0x5F5960) \ - X("lamppost3", MI_SINGLESTREETLIGHTS3, 0x5F5964) \ - X("doublestreetlght1", MI_DOUBLESTREETLIGHTS, 0x5F5968) \ - X("rd_Road2A10", MI_ROADSFORROADBLOCKSSTART, 0x5F596C) \ - X("rd_Road1A30", MI_ROADSFORROADBLOCKSEND, 0x5F5970) \ - X("veg_tree1", MI_TREE1, 0x5F5974) \ - X("veg_tree3", MI_TREE2, 0x5F5978) \ - X("veg_treea1", MI_TREE3, 0x5F597C) \ - X("veg_treenew01", MI_TREE4, 0x5F5980) \ - X("veg_treenew05", MI_TREE5, 0x5F5984) \ - X("veg_treeb1", MI_TREE6, 0x5F5988) \ - X("veg_treenew10", MI_TREE7, 0x5F598C) \ - X("veg_treea3", MI_TREE8, 0x5F5990) \ - X("veg_treenew09", MI_TREE9, 0x5F5994) \ - X("veg_treenew08", MI_TREE10, 0x5F5998) \ - X("veg_treenew03", MI_TREE11, 0x5F599C) \ - X("veg_treenew16", MI_TREE12, 0x5F59A0) \ - X("veg_treenew17", MI_TREE13, 0x5F59A4) \ - X("veg_treenew06", MI_TREE14, 0x5F59A8) \ - X("doc_crane_cab", MODELID_CRANE_1, 0x5F59AC) \ - X("cranetopb", MODELID_CRANE_2, 0x5F59B0) \ - X("cranetopa", MODELID_CRANE_3, 0x5F59B4) \ - X("package1", MI_COLLECTABLE1, 0x5F5A04) \ - X("Money", MI_MONEY, 0x5F5A08) \ - X("barrel1", MI_CARMINE, 0x5F5A0C) \ - /*X("oddjgaragdoor", MI_GARAGEDOOR1, 0x5F5A10)*/ \ - X("dk_paynspraydoor", MI_GARAGEDOOR2, 0x5F5A14) \ - X("dk_waretankdoor1", MI_GARAGEDOOR3, 0x5F5A18) \ - X("hav_garagedoor1", MI_GARAGEDOOR4, 0x5F5A1C) \ - X("hav_garagedoor02", MI_GARAGEDOOR5, 0x5F5A20) \ - X("hav_garagedoor03", MI_GARAGEDOOR6, 0x5F5A24) \ - X("hav_garagedoor04", MI_GARAGEDOOR7, 0x5F5A28) \ - X("lh_showdoor03", MI_GARAGEDOOR9, 0x5F5A2C) \ - X("lh_showdoor1", MI_GARAGEDOOR10, 0x5F5A30) \ - X("lhtankdoor", MI_GARAGEDOOR11, 0x5F5A34) \ - X("nbtgardoor", MI_GARAGEDOOR12, 0x5F5A38) \ - X("dk_camjonesdoor", MI_GARAGEDOOR13, 0x5F5A3C) \ - X("nbtgardoor02", MI_GARAGEDOOR14, 0x5F5A40) \ - X("dt_savedra", MI_GARAGEDOOR15, 0x5F5A44) \ - X("dt_savedrb", MI_GARAGEDOOR16, 0x5F5A48) \ - /*X("dk_bombdoor", MI_GARAGEDOOR17, 0x5F5A4C)*/ \ - X("dk_bombdoor", MI_GARAGEDOOR18, 0x5F5A50) \ - X("haiwshpnsdoor", MI_GARAGEDOOR19, 0x5F5A54) \ - X("wshpnsdoor", MI_GARAGEDOOR20, 0x5F5A58) \ - X("nbecpnsdoor", MI_GARAGEDOOR21, 0x5F5A5C) \ - X("nbtgardoor03", MI_GARAGEDOOR22, 0x5F5A60) \ - X("dt_savedrc", MI_GARAGEDOOR23, 0x5F5A64) \ - X("dt_savedrd", MI_GARAGEDOOR24, 0x5F5A68) \ - X("man_frntstepGD", MI_GARAGEDOOR25, 0x5F5A6C) \ - X("svegrgedoor", MI_GARAGEDOOR26, 0x5F5A70) \ - /*X("towergaragedoor3", MI_GARAGEDOOR27, 0x5F5A74)*/ \ - /*X("plysve_gragedoor", MI_GARAGEDOOR28, 0x5F5A78)*/ \ - /*X("impexpsubgrgdoor", MI_GARAGEDOOR29, 0x5F5A7C)*/ \ - /*X("Sub_sprayshopdoor", MI_GARAGEDOOR30, 0x5F5A80)*/ \ - /*X("ind_plyrwoor", MI_GARAGEDOOR31, 0x5F5A84)*/ \ - /*X("8ballsuburbandoor", MI_GARAGEDOOR32, 0x5F5A88)*/ \ - X("barrel2", MI_NAUTICALMINE, 0x5F5A8C) \ - X("crushercrush", MI_CRUSHERBODY, 0x5F5A90) \ - X("crushertop", MI_CRUSHERLID, 0x5F5A94) \ - X("donkeymag", MI_DONKEYMAG, 0x5F5A98) \ - X("bullion", MI_BULLION, 0x5F5A9C) \ - X("floatpackge1", MI_FLOATPACKAGE1, 0x5F5AA0) \ - X("briefcase", MI_BRIEFCASE, 0x5F5AA4) \ - X("chinabanner1", MI_CHINABANNER1, 0x5F5AA8) \ - X("chinabanner2", MI_CHINABANNER2, 0x5F5AAC) \ - X("chinabanner3", MI_CHINABANNER3, 0x5F5AB0) \ - X("chinabanner4", MI_CHINABANNER4, 0x5F5AB4) \ - X("iten_chinatown5", MI_CHINABANNER5, 0x5F5AB8) \ - X("iten_chinatown7", MI_CHINABANNER6, 0x5F5ABC) \ - X("iten_chinatown3", MI_CHINABANNER7, 0x5F5AC0) \ - X("iten_chinatown2", MI_CHINABANNER8, 0x5F5AC4) \ - X("iten_chinatown4", MI_CHINABANNER9, 0x5F5AC8) \ - X("iten_washline01", MI_CHINABANNER10, 0x5F5ACC) \ - X("iten_washline02", MI_CHINABANNER11, 0x5F5AD0) \ - X("iten_washline03", MI_CHINABANNER12, 0x5F5AD4) \ - X("chinalanterns", MI_CHINALANTERN, 0x5F5AD8) \ - X("glassfx1", MI_GLASS1, 0x5F5ADC) \ - X("glassfx2", MI_GLASS2, 0x5F5AE0) \ - X("glassfx3", MI_GLASS3, 0x5F5AE4) \ - X("glassfx4", MI_GLASS4, 0x5F5AE8) \ - X("glassfx55", MI_GLASS5, 0x5F5AEC) \ - X("glassfxsub1", MI_GLASS6, 0x5F5AF0) \ - X("glassfxsub2", MI_GLASS7, 0x5F5AF4) \ - X("glassfx_composh", MI_GLASS8, 0x5F5AF8) \ - X("bridge_liftsec", MI_BRIDGELIFT, 0x5F5AFC) \ - X("bridge_liftweight", MI_BRIDGEWEIGHT, 0x5F5B00) \ - X("subbridge_lift", MI_BRIDGEROADSEGMENT, 0x5F5B04) \ - X("barrel4", MI_EXPLODINGBARREL, 0x5F5B08) \ - X("flagsitaly", MI_ITALYBANNER1, 0x5F5B0C) \ - X("adrenaline", MI_PICKUP_ADRENALINE, 0x5F5B10) \ - X("bodyarmour", MI_PICKUP_BODYARMOUR, 0x5F5B14) \ - X("info", MI_PICKUP_INFO, 0x5F5B18) \ - X("health", MI_PICKUP_HEALTH, 0x5F5B1C) \ - X("bonus", MI_PICKUP_BONUS, 0x5F5B20) \ - X("bribe", MI_PICKUP_BRIBE, 0x5F5B24) \ - X("killfrenzy", MI_PICKUP_KILLFRENZY, 0x5F5B28) \ - X("camerapickup", MI_PICKUP_CAMERA, 0x5F5B2C) \ - X("bollardlight", MI_BOLLARDLIGHT, 0x5F5B30) \ - X("magnet", MI_MAGNET, 0x5F5B34) \ - X("streetlamp1", MI_STREETLAMP1, 0x5F5B38) \ - X("streetlamp2", MI_STREETLAMP2, 0x5F5B3C) \ - X("railtrax_lo4b", MI_RAILTRACKS, 0x5F5B40) \ - X("bar_barrier10", MI_FENCE, 0x5F5B44) \ - X("bar_barrier12", MI_FENCE2, 0x5F5B48) \ - X("petrolpump", MI_PETROLPUMP, 0x5F5B4C) \ - X("bodycast", MI_BODYCAST, 0x5F5B50) \ - X("backdoor", MI_BACKDOOR, 0x5F5B54) \ - X("coffee", MI_COFFEE, 0x5F5B58) \ - X("bouy", MI_BUOY, 0x5F5B5C) \ - X("parktable1", MI_PARKTABLE, 0x5F5B60) \ - X("sbwy_tunl_start", MI_SUBWAY1, 0x5F5B64) \ - X("sbwy_tunl_bit", MI_SUBWAY2, 0x5F5B68) \ - X("sbwy_tunl_bend", MI_SUBWAY3, 0x5F5B6C) \ - X("sbwy_tunl_cstm6", MI_SUBWAY4, 0x5F5B70) \ - X("sbwy_tunl_cstm7", MI_SUBWAY5, 0x5F5B74) \ - X("sbwy_tunl_cstm8", MI_SUBWAY6, 0x5F5B78) \ - X("sbwy_tunl_cstm10", MI_SUBWAY7, 0x5F5B7C) \ - X("sbwy_tunl_cstm9", MI_SUBWAY8, 0x5F5B80) \ - X("sbwy_tunl_cstm11", MI_SUBWAY9, 0x5F5B84) \ - X("sbwy_tunl_cstm1", MI_SUBWAY10, 0x5F5B88) \ - X("sbwy_tunl_cstm2", MI_SUBWAY11, 0x5F5B8C) \ - X("sbwy_tunl_cstm4", MI_SUBWAY12, 0x5F5B90) \ - X("sbwy_tunl_cstm3", MI_SUBWAY13, 0x5F5B94) \ - X("sbwy_tunl_cstm5", MI_SUBWAY14, 0x5F5B98) \ - X("subplatform_n2", MI_SUBWAY15, 0x5F5B9C) \ - X("suby_tunl_start", MI_SUBWAY16, 0x5F5BA0) \ - X("sbwy_tunl_start2", MI_SUBWAY17, 0x5F5BA4) \ - X("indy_tunl_start", MI_SUBWAY18, 0x5F5BA8) \ - X("indsubway03", MI_SUBPLATFORM_IND, 0x5F5BAC) \ - X("comerside_subway", MI_SUBPLATFORM_COMS, 0x5F5BB0) \ - X("subplatform", MI_SUBPLATFORM_COMS2, 0x5F5BB4) \ - X("subplatform_n", MI_SUBPLATFORM_COMN, 0x5F5BB8) \ - X("Otherside_subway", MI_SUBPLATFORM_SUB, 0x5F5BBC) \ - X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \ - X("files", MI_FILES, 0x5F5BC4) \ - X("property_locked", MI_PICKUP_PROPERTY, 0x0) \ - X("property_fsale", MI_PICKUP_PROPERTY_FORSALE, 0x0) \ - X("clothesp", MI_PICKUP_CLOTHES, 0x0) \ - X("bigdollar", MI_PICKUP_REVENUE, 0x0) + X("fire_hydrant", MI_FIRE_HYDRANT) \ + X("phonesign", MI_PHONESIGN) \ + X("noparkingsign1", MI_NOPARKINGSIGN1) \ + X("bussign1", MI_BUSSIGN1) \ + X("roadworkbarrier1", MI_ROADWORKBARRIER1) \ + X("dump1", MI_DUMP1) \ + X("trafficcone", MI_TRAFFICCONE) \ + X("newsstand1", MI_NEWSSTAND) \ + X("postbox1", MI_POSTBOX1) \ + X("bin1", MI_BIN) \ + X("wastebin", MI_WASTEBIN) \ + X("phonebooth1", MI_PHONEBOOTH1) \ + X("parkingmeter", MI_PARKINGMETER) \ + X("parkingmeterg", MI_PARKINGMETER2) \ + X("mall_fans", MI_MALLFAN) \ + X("htl_fan_rotate_nt", MI_HOTELFAN_NIGHT) \ + X("htl_fan_rotate_dy", MI_HOTELFAN_DAY) \ + X("hotroomfan", MI_HOTROOMFAN) \ + X("trafficlight1", MI_TRAFFICLIGHTS) \ + X("MTraffic4", MI_TRAFFICLIGHTS_VERTICAL) \ + X("MTraffic1", MI_TRAFFICLIGHTS_MIAMI) \ + X("MTraffic2", MI_TRAFFICLIGHTS_TWOVERTICAL) \ + X("lamppost1", MI_SINGLESTREETLIGHTS1) \ + X("lamppost2", MI_SINGLESTREETLIGHTS2) \ + X("lamppost3", MI_SINGLESTREETLIGHTS3) \ + X("doublestreetlght1", MI_DOUBLESTREETLIGHTS) \ + X("Streetlamp1", MI_STREETLAMP1) \ + X("Streetlamp2", MI_STREETLAMP2) \ + X("veg_tree3", MI_TREE2) \ + X("veg_treea1", MI_TREE3) \ + X("veg_treeb1", MI_TREE6) \ + X("veg_treea3", MI_TREE8) \ + X("doc_crane_cab", MODELID_CRANE_1) \ + X("doc_crane_cab01", MODELID_CRANE_2) \ + X("doc_crane_cab02", MODELID_CRANE_3) \ + X("doc_crane_cab03", MODELID_CRANE_4) \ + X("boatcranelg0", MODELID_CRANE_5) \ + X("LODnetopa0", MODELID_CRANE_6) \ + X("package1", MI_COLLECTABLE1) \ + X("Money", MI_MONEY) \ + X("barrel1", MI_CARMINE) \ + X("dk_paynspraydoor", MI_GARAGEDOOR2) \ + X("dk_waretankdoor1", MI_GARAGEDOOR3) \ + X("hav_garagedoor1", MI_GARAGEDOOR4) \ + X("hav_garagedoor02", MI_GARAGEDOOR5) \ + X("hav_garagedoor03", MI_GARAGEDOOR6) \ + X("hav_garagedoor04", MI_GARAGEDOOR7) \ + X("lh_showdoor03", MI_GARAGEDOOR9) \ + X("lh_showdoor1", MI_GARAGEDOOR10) \ + X("lhtankdoor", MI_GARAGEDOOR11) \ + X("nbtgardoor", MI_GARAGEDOOR12) \ + X("dk_camjonesdoor", MI_GARAGEDOOR13) \ + X("nbtgardoor02", MI_GARAGEDOOR14) \ + X("dt_savedra", MI_GARAGEDOOR15) \ + X("dt_savedrb", MI_GARAGEDOOR16) \ + X("dk_bombdoor", MI_GARAGEDOOR18) \ + X("haiwshpnsdoor", MI_GARAGEDOOR19) \ + X("wshpnsdoor", MI_GARAGEDOOR20) \ + X("nbecpnsdoor", MI_GARAGEDOOR21) \ + X("nbtgardoor03", MI_GARAGEDOOR22) \ + X("dt_savedrc", MI_GARAGEDOOR23) \ + X("dt_savedrd", MI_GARAGEDOOR24) \ + X("man_frntstepGD", MI_GARAGEDOOR25) \ + X("svegrgedoor", MI_GARAGEDOOR26) \ + X("barrel2", MI_NAUTICALMINE) \ + X("briefcase", MI_BRIEFCASE) \ + X("wglasssmash", MI_GLASS1) \ + X("glassfx_composh", MI_GLASS8) \ + X("barrel4", MI_EXPLODINGBARREL) \ + X("adrenaline", MI_PICKUP_ADRENALINE) \ + X("bodyarmour", MI_PICKUP_BODYARMOUR) \ + X("info", MI_PICKUP_INFO) \ + X("health", MI_PICKUP_HEALTH) \ + X("bonus", MI_PICKUP_BONUS) \ + X("bribe", MI_PICKUP_BRIBE) \ + X("killfrenzy", MI_PICKUP_KILLFRENZY) \ + X("camerapickup", MI_PICKUP_CAMERA) \ + X("bigdollar", MI_PICKUP_REVENUE) \ + X("pickupsave", MI_PICKUP_SAVEGAME) \ + X("property_locked", MI_PICKUP_PROPERTY) \ + X("property_fsale", MI_PICKUP_PROPERTY_FORSALE) \ + X("clothesp", MI_PICKUP_CLOTHES) \ + X("bollardlight", MI_BOLLARDLIGHT) \ + X("bar_barrier10", MI_FENCE) \ + X("bar_barrier12", MI_FENCE2) \ + X("petrolpump", MI_PETROLPUMP) \ + X("washgaspump", MI_PETROLPUMP2) \ + X("bouy", MI_BUOY) \ + X("parktable1", MI_PARKTABLE) \ + X("lamppost1", MI_LAMPPOST1) \ + X("veg_palm04", MI_VEG_PALM01) \ + X("veg_palwee02", MI_VEG_PALM02) \ + X("veg_palmkbb11", MI_VEG_PALM03) \ + X("veg_palmkb4", MI_VEG_PALM04) \ + X("veg_palm02", MI_VEG_PALM05) \ + X("veg_palmkb3", MI_VEG_PALM06) \ + X("veg_palmbig14", MI_VEG_PALM07) \ + X("veg_palm01", MI_VEG_PALM08) \ + X("mlamppost", MI_MLAMPPOST) \ + X("roadworkbarrier1", MI_BARRIER1) \ + X("littleha_police", MI_LITTLEHA_POLICE) \ + X("telgrphpole02", MI_TELPOLE02) \ + X("trafficlight1", MI_TRAFFICLIGHT01) \ + X("parkbench1", MI_PARKBENCH) \ + X("plc_stinger", MI_PLC_STINGER) \ + X("od_lightbeam", MI_LIGHTBEAM) \ + X("ap_radar1_01", MI_AIRPORTRADAR) \ + X("rcbomb", MI_RCBOMB) \ + X("beachball", MI_BEACHBALL) \ + X("sandcastle1", MI_SANDCASTLE1) \ + X("sandcastle2", MI_SANDCASTLE2) \ + X("jellyfish", MI_JELLYFISH) \ + X("jellyfish01", MI_JELLYFISH01) \ + X("fish1single", MI_FISH1SINGLE) \ + X("fish1s", MI_FISH1S) \ + X("fish2single", MI_FISH2SINGLE) \ + X("fish2s", MI_FISH2S) \ + X("fish3single", MI_FISH3SINGLE) \ + X("fish3s", MI_FISH3S) \ + X("turtle", MI_TURTLE) \ + X("dolphin", MI_DOLPHIN) \ + X("shark", MI_SHARK) \ + X("submarine", MI_SUBMARINE) \ + X("Esc_step", MI_ESCALATORSTEP) \ + X("lounge_wood_up", MI_LOUNGE_WOOD_UP) \ + X("lounge_towel_up", MI_LOUNGE_TOWEL_UP) \ + X("lounge_wood_dn", MI_LOUNGE_WOOD_DN) \ + X("lotion", MI_LOTION) \ + X("beachtowel01", MI_BEACHTOWEL01) \ + X("beachtowel02", MI_BEACHTOWEL02) \ + X("beachtowel03", MI_BEACHTOWEL03) \ + X("beachtowel04", MI_BEACHTOWEL04) \ + X("blimp_night", MI_BLIMP_NIGHT) \ + X("blimp_day", MI_BLIMP_DAY) \ + X("yt_main_body", MI_YT_MAIN_BODY) \ + X("yt_main_body2", MI_YT_MAIN_BODY2) -#define X(name, var, addr) extern int16 var; +#define X(name, var) extern int16 var; MODELINDICES #undef X @@ -211,90 +187,10 @@ enum MI_WFYG2 = 106, // last regular ped MI_SPECIAL01 = 109, MI_SPECIAL21 = 129, -/* - MI_TAXI_D, - MI_PIMP, - MI_GANG01, - MI_GANG02, - MI_GANG03, - MI_GANG04, - MI_GANG05, - MI_GANG06, - MI_GANG07, - MI_GANG08, - MI_GANG09, - MI_GANG10, - MI_GANG11, - MI_GANG12, - MI_GANG13, - MI_GANG14, - MI_CRIMINAL01, - MI_CRIMINAL02, - MI_SPECIAL01, - MI_SPECIAL02, - MI_SPECIAL03, - MI_SPECIAL04, - MI_MALE02, - MI_MALE03, - MI_FATMALE01, - MI_FATMALE02, - MI_FEMALE01, - MI_FEMALE02, - MI_FEMALE03, - MI_FATFEMALE01, - MI_FATFEMALE02, - MI_PROSTITUTE, - MI_PROSTITUTE2, - MI_P_MAN1, - MI_P_MAN2, - MI_P_WOM1, - MI_P_WOM2, - MI_CT_MAN1, - MI_CT_MAN2, - MI_CT_WOM1, - MI_CT_WOM2, - MI_LI_MAN1, - MI_LI_MAN2, - MI_LI_WOM1, - MI_LI_WOM2, - MI_DOCKER1, - MI_DOCKER2, - MI_SCUM_MAN, - MI_SCUM_WOM, - MI_WORKER1, - MI_WORKER2, - MI_B_MAN1, - MI_B_MAN2, - MI_B_MAN3, - MI_B_WOM1, - MI_B_WOM2, - MI_B_WOM3, - MI_MOD_MAN, - MI_MOD_WOM, - MI_ST_MAN, - MI_ST_WOM, - MI_FAN_MAN1, - MI_FAN_MAN2, - MI_FAN_WOM, - MI_HOS_MAN, - MI_HOS_WOM, - MI_CONST1, - MI_CONST2, - MI_SHOPPER1, - MI_SHOPPER2, - MI_SHOPPER3, - MI_STUD_MAN, - MI_STUD_WOM, - MI_CAS_MAN, - MI_CAS_WOM, - MI_BUSKER1, - MI_BUSKER2, - MI_BUSKER3, - MI_BUSKER4, - // three more peds possible -*/ - MI_FIRST_VEHICLE = 130, + MI_LAST_PED = MI_SPECIAL21, + MI_FIRST_VEHICLE, + MI_LANDSTAL = MI_FIRST_VEHICLE, MI_IDAHO, MI_STINGER, @@ -440,9 +336,8 @@ enum MI_BODYPARTB, MI_AIRTRAIN_VLO = 257, -// MI_LOPOLYGUY, - NUM_DEFAULT_MODELS = 300 // MIAMI + NUM_DEFAULT_MODELS = 300 }; enum{ @@ -462,13 +357,16 @@ IsGlass(int16 id) } inline bool -IsTrafficLight(int16 id) +IsStreetLight(int16 id) { - return id == MI_TRAFFICLIGHTS || - id == MI_SINGLESTREETLIGHTS1 || + return id == MI_SINGLESTREETLIGHTS1 || id == MI_SINGLESTREETLIGHTS2 || id == MI_SINGLESTREETLIGHTS3 || - id == MI_DOUBLESTREETLIGHTS; + id == MI_TRAFFICLIGHTS_MIAMI || + id == MI_TRAFFICLIGHTS_TWOVERTICAL || + id == MI_MLAMPPOST || + id == MI_STREETLAMP1 || + id == MI_STREETLAMP2; } inline bool @@ -477,60 +375,32 @@ IsBodyPart(int16 id) return id == MI_BODYPARTA || id == MI_BODYPARTB; } -// This is bad and should perhaps not be used -/* -inline bool -IsBoatModel(int16 id) -{ - return id == MI_PREDATOR || - id == MI_REEFER || - id == MI_SPEEDER || - id == MI_GHOST; -} -*/ - inline bool IsPedModel(int16 id) { - return id >= 0 && id <= 89; + return id >= MI_PLAYER && id <= MI_LAST_PED; +} +inline bool +IsPalmTreeModel(int16 id) +{ + return id == MI_VEG_PALM01 || + id == MI_VEG_PALM02 || + id == MI_VEG_PALM03 || + id == MI_VEG_PALM04 || + id == MI_VEG_PALM05 || + id == MI_VEG_PALM06 || + id == MI_VEG_PALM07 || + id == MI_VEG_PALM08; } inline bool IsTreeModel(int16 id) { - return id == MI_TREE1 || - id == MI_TREE2 || + return id == MI_TREE2 || id == MI_TREE3 || - id == MI_TREE4 || - id == MI_TREE5 || id == MI_TREE6 || - id == MI_TREE7 || id == MI_TREE8 || - id == MI_TREE9 || - id == MI_TREE10 || - id == MI_TREE11 || - id == MI_TREE12 || - id == MI_TREE13 || - id == MI_TREE14; -} - -inline bool -IsBannerModel(int16 id) -{ - return id == MI_CHINABANNER1 || - id == MI_CHINABANNER2 || - id == MI_CHINABANNER3 || - id == MI_CHINABANNER4 || - id == MI_CHINABANNER5 || - id == MI_CHINABANNER6 || - id == MI_CHINABANNER7 || - id == MI_CHINABANNER8 || - id == MI_CHINABANNER9 || - id == MI_CHINABANNER10 || - id == MI_CHINABANNER11 || - id == MI_CHINABANNER12 || - id == MI_ITALYBANNER1 || - id == MI_CHINALANTERN; + IsPalmTreeModel(id); } inline bool diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 4a45050c..e6bb7aee 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -14,7 +14,8 @@ #include "soundlist.h" int16 CObject::nNoTempObjects; -int16 CObject::nBodyCastHealth = 1000; +//int16 CObject::nBodyCastHealth = 1000; +float CObject::fDistToNearestTree; void *CObject::operator new(size_t sz) { return CPools::GetObjectPool()->New(); } void *CObject::operator new(size_t sz, int handle) { return CPools::GetObjectPool()->New(handle);}; @@ -161,6 +162,7 @@ CObject::ObjectDamage(float amount) return; static int8 nFrameGen = 0; bool bBodyCastDamageEffect = false; +#if 0 if (GetModelIndex() == MI_BODYCAST) { if (amount > 50.0f) nBodyCastHealth = (int16)(nBodyCastHealth - 0.5f * amount); @@ -170,6 +172,7 @@ CObject::ObjectDamage(float amount) bBodyCastDamageEffect = true; amount = 0.0f; } +#endif if ((amount * m_fCollisionDamageMultiplier > 150.0f || bBodyCastDamageEffect) && m_nCollisionDamageEffect) { const CVector& vecPos = m_matrix.GetPosition(); const float fDirectionZ = 0.0002f * amount; @@ -335,9 +338,12 @@ CObject::Init(void) m_pCurSurface = outEntity; else m_pCurSurface = nil; +#if 0 if (GetModelIndex() == MI_BODYCAST) nBodyCastHealth = 1000; - else if (GetModelIndex() == MI_BUOY) + else +#endif + if (GetModelIndex() == MI_BUOY) bTouchingWater = true; } diff --git a/src/objects/Object.h b/src/objects/Object.h index 73f710f0..9ceffb2f 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -86,7 +86,9 @@ public: int8 m_colour1, m_colour2; static int16 nNoTempObjects; - static int16 nBodyCastHealth; +// static int16 nBodyCastHealth; + + static float fDistToNearestTree; static void *operator new(size_t); static void *operator new(size_t, int); diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 44bedab9..42abc2ab 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -853,18 +853,12 @@ CPopulation::ConvertToRealObject(CDummyObject *dummy) if (!obj) return; - bool makeInvisible; CWorld::Remove(dummy); delete dummy; CWorld::Add(obj); - int16 mi = obj->GetModelIndex(); - if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 || - mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8) - makeInvisible = true; - else - makeInvisible = false; - if (makeInvisible) { + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(obj->GetModelIndex()); + if (IsGlass(obj->GetModelIndex()) && !mi->m_isArtistGlass) { obj->bIsVisible = false; } else if (obj->GetModelIndex() == MI_BUOY) { obj->bIsStatic = false; @@ -883,17 +877,9 @@ CPopulation::ConvertToDummyObject(CObject *obj) dummy->GetMatrix().UpdateRW(); dummy->UpdateRwFrame(); - bool makeInvisible; - int16 mi = obj->GetModelIndex(); - if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 || - mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8) - makeInvisible = true; - else - makeInvisible = false; - - if (makeInvisible) { + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(obj->GetModelIndex()); + if (IsGlass(obj->GetModelIndex()) && !mi->m_isArtistGlass) dummy->bIsVisible = false; - } CWorld::Remove(obj); delete obj; diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index ed5ce5ba..504824c5 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -4,7 +4,8 @@ enum { EFFECT_LIGHT, EFFECT_PARTICLE, EFFECT_ATTRACTOR, - EFFECT_PED_ATTRACTOR + EFFECT_PED_ATTRACTOR, + EFFECT_SUNGLARE }; enum { @@ -35,6 +36,8 @@ enum { // same order as CPointLights flags, must start at 2 LIGHTFLAG_FOG_NORMAL = 2, // can have light and fog LIGHTFLAG_FOG_ALWAYS = 4, // fog only + LIGHTFLAG_HIDE_OBJECT = 8, // hide the object instead of rendering light (???) + LIGHTFLAG_LONG_DIST = 16, LIGHTFLAG_FOG = (LIGHTFLAG_FOG_NORMAL|LIGHTFLAG_FOG_ALWAYS) }; diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 05210c77..c6ba0f10 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -62,8 +62,6 @@ void CClouds::Update(void) { float s = Sin(TheCamera.Orientation - 0.85f); - CloudRotation += CWeather::Wind*s*0.001f; - IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f; #ifdef FIX_BUGS CloudRotation += CWeather::Wind*s*0.001f*CTimer::GetTimeStepFix(); IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f*CTimer::GetTimeStepFix()) * 60.0f; diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index e36bdf3d..8e832ab1 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -129,7 +129,8 @@ CCoronas::Update(void) void CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, const CVector &coors, float size, float drawDist, RwTexture *tex, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle) + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool longDist, float nearDist) { int i; @@ -192,11 +193,13 @@ CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 al void CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, - const CVector &coors, float size, float drawDist, uint8 type, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle) + const CVector &coors, float size, float drawDist, uint8 type, + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool longDist, float nearDist) { RegisterCorona(id, red, green, blue, alpha, coors, size, drawDist, - gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle); + gpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle, + longDist, nearDist); } void diff --git a/src/render/Coronas.h b/src/render/Coronas.h index 70e9ccd5..cb4e8583 100644 --- a/src/render/Coronas.h +++ b/src/render/Coronas.h @@ -90,10 +90,12 @@ public: static void Update(void); static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, const CVector &coors, float size, float drawDist, RwTexture *tex, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle); + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool longDist = false, float nearClip = 1.5f); static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha, const CVector &coors, float size, float drawDist, uint8 type, - int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle); + int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle, + bool longDist = false, float nearClip = 1.5f); static void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle); static void Render(void); static void RenderReflections(void); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 803f4cc1..f149c6fb 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1245,9 +1245,11 @@ CRenderer::ShouldModelBeStreamed(CEntity *ent, const CVector &campos) void CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset) { - if(ent->bRenderScorched) - return; - CPointLights::RemoveLightsAffectingObject(); - if(reset) - ReSetAmbientAndDirectionalColours(); + if(!ent->bRenderScorched){ + CPointLights::RemoveLightsAffectingObject(); + if(reset) + ReSetAmbientAndDirectionalColours(); + } + SetAmbientColours(); + DeActivateDirectional(); } diff --git a/src/render/WindModifiers.cpp b/src/render/WindModifiers.cpp new file mode 100644 index 00000000..d7405c7a --- /dev/null +++ b/src/render/WindModifiers.cpp @@ -0,0 +1,8 @@ +#include "common.h" +#include "WindModifiers.h" + +int32 +CWindModifiers::FindWindModifier(CVector pos, float *x, float *y) +{ + return 0; +} diff --git a/src/render/WindModifiers.h b/src/render/WindModifiers.h new file mode 100644 index 00000000..b4024343 --- /dev/null +++ b/src/render/WindModifiers.h @@ -0,0 +1,7 @@ +#pragma once + +class CWindModifiers +{ +public: + static int32 FindWindModifier(CVector pos, float *x, float *y); +}; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index e0ee0296..654feb5f 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -2192,6 +2192,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) phys->RegisterReference((CEntity**)&m_aGroundPhysical[i]); m_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition(); +#if 0 if(phys->GetModelIndex() == MI_BODYCAST && GetStatus() == STATUS_PLAYER){ // damage body cast float speed = m_vecMoveSpeed.MagnitudeSqr(); @@ -2208,6 +2209,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) phys->AddToMovingList(); } } +#endif } m_nSurfaceTouched = m_aWheelColPoints[i].surfaceB; diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 043f1c73..5a165c00 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -88,6 +88,7 @@ void CCranes::AddThisOneCrane(CEntity* pEntity) if (pCrane->m_nAudioEntity >= 0) DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1); pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex()); +#if 0 // Is this used to avoid military crane? if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) { CObject* pHook = new CObject(MI_MAGNET, false); @@ -100,6 +101,7 @@ void CCranes::AddThisOneCrane(CEntity* pEntity) pCrane->SetHookMatrix(); } else +#endif pCrane->m_pHook = nil; NumCranes++; } diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 51e2604c..3d5d4e77 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -4,6 +4,8 @@ #include "FileMgr.h" #include "HandlingMgr.h" +//--MIAMI: done + cHandlingDataMgr mod_HandlingManager; const char *HandlingFilename = "HANDLING.CFG"; From 0b0ba49abc34315f532f9adcdbc277d5275723c7 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 19 May 2020 21:42:55 +0200 Subject: [PATCH 068/148] small fixes --- src/core/World.cpp | 2 +- src/entities/Entity.cpp | 2 +- src/entities/Physical.cpp | 8 +- src/modelinfo/ModelIndices.cpp | 6 +- src/modelinfo/ModelIndices.h | 322 +++++++++++++++++---------------- src/peds/Population.cpp | 20 +- 6 files changed, 173 insertions(+), 187 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index c15c134d..edcfd865 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1823,7 +1823,7 @@ void CWorld::RepositionOneObject(CEntity *pEntity) { int16 modelId = pEntity->GetModelIndex(); - if (IsTrafficLight(modelId) || IsTreeModel(modelId) || modelId == MI_PARKINGMETER || + if (IsStreetLight(modelId) || IsTreeModel(modelId) || modelId == MI_PARKINGMETER || modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || modelId == MI_BIN || modelId == MI_POSTBOX1 || modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || modelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index ec50dd30..683a3571 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -683,7 +683,7 @@ CEntity::ProcessLightsForEntity(void) lightOn = true; break; case LIGHT_FLICKER_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7){ + if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){){ if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) lightOn = true; else diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 64358cbf..31f8fcbc 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1076,13 +1076,13 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) if(B->IsBuilding()) skipShift = false; - else if(IsTrafficLight(A->GetModelIndex()) && + else if(IsStreetLight(A->GetModelIndex()) && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f) skipShift = true; else if((A->IsVehicle() || A->IsPed()) && B->GetUp().z < 0.66f && - IsTrafficLight(B->GetModelIndex())) + IsStreetLight(B->GetModelIndex())) skipShift = true; // TODO: maybe flip some ifs here else if(A->IsObject() && B->IsVehicle()){ @@ -1407,7 +1407,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(B->IsBuilding()) skipCollision = false; - else if(IsTrafficLight(A->GetModelIndex()) && + else if(IsStreetLight(A->GetModelIndex()) && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f){ skipCollision = true; @@ -1415,7 +1415,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) Aobj->m_pCollidingEntity = B; }else if((A->IsVehicle() || A->IsPed()) && B->GetUp().z < 0.66f && - IsTrafficLight(B->GetModelIndex())){ + IsStreetLight(B->GetModelIndex())){ skipCollision = true; A->bSkipLineCol = true; Bobj->m_pCollidingEntity = A; diff --git a/src/modelinfo/ModelIndices.cpp b/src/modelinfo/ModelIndices.cpp index 9a6a74d0..056c3733 100644 --- a/src/modelinfo/ModelIndices.cpp +++ b/src/modelinfo/ModelIndices.cpp @@ -3,14 +3,14 @@ #include "General.h" #include "ModelIndices.h" -#define X(name, var, addr) int16 var; +#define X(name, var) int16 var; MODELINDICES #undef X void InitModelIndices(void) { -#define X(name, var, addr) var = -1; +#define X(name, var) var = -1; MODELINDICES #undef X } @@ -18,7 +18,7 @@ InitModelIndices(void) void MatchModelString(const char *modelname, int16 id) { -#define X(name, var, addr) \ +#define X(name, var) \ if(!CGeneral::faststrcmp(name, modelname)){ \ var = id; \ return; \ diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index cc6ed25c..c0f01929 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -1,164 +1,164 @@ #pragma once #define MODELINDICES \ - X("fire_hydrant", MI_FIRE_HYDRANT, 0x5F5A00) \ - X("bagelstnd02", MI_BAGELSTAND2, 0x5F59FC) \ - X("fish01", MI_FISHSTALL01, 0x5F59EC) \ - X("fishstall02", MI_FISHSTALL02, 0x5F59F0) \ - X("fishstall03", MI_FISHSTALL03, 0x5F59F4) \ - X("fishstall04", MI_FISHSTALL04, 0x5F59F8) \ - X("taxisign", MI_TAXISIGN, 0x5F59E8) \ - X("phonesign", MI_PHONESIGN, 0x5F59E4) \ - X("noparkingsign1", MI_NOPARKINGSIGN1, 0x5F59E0) \ - X("bussign1", MI_BUSSIGN1, 0x5F59DC) \ - X("roadworkbarrier1", MI_ROADWORKBARRIER1, 0x5F59D8) \ - X("dump1", MI_DUMP1, 0x5F59D4) \ - X("trafficcone", MI_TRAFFICCONE, 0x5F59D0) \ - X("newsstand1", MI_NEWSSTAND, 0x5F59CC) \ - X("postbox1", MI_POSTBOX1, 0x5F59C8) \ - X("bin1", MI_BIN, 0x5F59C4) \ - X("wastebin", MI_WASTEBIN, 0x5F59C0) \ - X("phonebooth1", MI_PHONEBOOTH1, 0x5F59BC) \ - X("parkingmeter", MI_PARKINGMETER, 0x5F59B8) \ - X("trafficlight1", MI_TRAFFICLIGHTS, 0x5F5958) \ - X("lamppost1", MI_SINGLESTREETLIGHTS1, 0x5F595C) \ - X("lamppost2", MI_SINGLESTREETLIGHTS2, 0x5F5960) \ - X("lamppost3", MI_SINGLESTREETLIGHTS3, 0x5F5964) \ - X("doublestreetlght1", MI_DOUBLESTREETLIGHTS, 0x5F5968) \ - X("rd_Road2A10", MI_ROADSFORROADBLOCKSSTART, 0x5F596C) \ - X("rd_Road1A30", MI_ROADSFORROADBLOCKSEND, 0x5F5970) \ - X("veg_tree1", MI_TREE1, 0x5F5974) \ - X("veg_tree3", MI_TREE2, 0x5F5978) \ - X("veg_treea1", MI_TREE3, 0x5F597C) \ - X("veg_treenew01", MI_TREE4, 0x5F5980) \ - X("veg_treenew05", MI_TREE5, 0x5F5984) \ - X("veg_treeb1", MI_TREE6, 0x5F5988) \ - X("veg_treenew10", MI_TREE7, 0x5F598C) \ - X("veg_treea3", MI_TREE8, 0x5F5990) \ - X("veg_treenew09", MI_TREE9, 0x5F5994) \ - X("veg_treenew08", MI_TREE10, 0x5F5998) \ - X("veg_treenew03", MI_TREE11, 0x5F599C) \ - X("veg_treenew16", MI_TREE12, 0x5F59A0) \ - X("veg_treenew17", MI_TREE13, 0x5F59A4) \ - X("veg_treenew06", MI_TREE14, 0x5F59A8) \ - X("doc_crane_cab", MODELID_CRANE_1, 0x5F59AC) \ - X("cranetopb", MODELID_CRANE_2, 0x5F59B0) \ - X("cranetopa", MODELID_CRANE_3, 0x5F59B4) \ - X("package1", MI_COLLECTABLE1, 0x5F5A04) \ - X("Money", MI_MONEY, 0x5F5A08) \ - X("barrel1", MI_CARMINE, 0x5F5A0C) \ - X("oddjgaragdoor", MI_GARAGEDOOR1, 0x5F5A10) \ - X("bombdoor", MI_GARAGEDOOR2, 0x5F5A14) \ - X("door_bombshop", MI_GARAGEDOOR3, 0x5F5A18) \ - X("vheistlocdoor", MI_GARAGEDOOR4, 0x5F5A1C) \ - X("door2_garage", MI_GARAGEDOOR5, 0x5F5A20) \ - X("ind_slidedoor", MI_GARAGEDOOR6, 0x5F5A24) \ - X("bankjobdoor", MI_GARAGEDOOR7, 0x5F5A28) \ - X("door_jmsgrage", MI_GARAGEDOOR9, 0x5F5A2C) \ - X("jamesgrge_kb", MI_GARAGEDOOR10, 0x5F5A30) \ - X("door_sfehousegrge", MI_GARAGEDOOR11, 0x5F5A34) \ - X("shedgaragedoor", MI_GARAGEDOOR12, 0x5F5A38) \ - X("door4_garage", MI_GARAGEDOOR13, 0x5F5A3C) \ - X("door_col_compnd_01", MI_GARAGEDOOR14, 0x5F5A40) \ - X("door_col_compnd_02", MI_GARAGEDOOR15, 0x5F5A44) \ - X("door_col_compnd_03", MI_GARAGEDOOR16, 0x5F5A48) \ - X("door_col_compnd_04", MI_GARAGEDOOR17, 0x5F5A4C) \ - X("door_col_compnd_05", MI_GARAGEDOOR18, 0x5F5A50) \ - X("impex_door", MI_GARAGEDOOR19, 0x5F5A54) \ - X("SalvGarage", MI_GARAGEDOOR20, 0x5F5A58) \ - X("door3_garage", MI_GARAGEDOOR21, 0x5F5A5C) \ - X("leveldoor2", MI_GARAGEDOOR22, 0x5F5A60) \ - X("double_garage_dr", MI_GARAGEDOOR23, 0x5F5A64) \ - X("amcogaragedoor", MI_GARAGEDOOR24, 0x5F5A68) \ - X("towergaragedoor1", MI_GARAGEDOOR25, 0x5F5A6C) \ - X("towergaragedoor2", MI_GARAGEDOOR26, 0x5F5A70) \ - X("towergaragedoor3", MI_GARAGEDOOR27, 0x5F5A74) \ - X("plysve_gragedoor", MI_GARAGEDOOR28, 0x5F5A78) \ - X("impexpsubgrgdoor", MI_GARAGEDOOR29, 0x5F5A7C) \ - X("Sub_sprayshopdoor", MI_GARAGEDOOR30, 0x5F5A80) \ - X("ind_plyrwoor", MI_GARAGEDOOR31, 0x5F5A84) \ - X("8ballsuburbandoor", MI_GARAGEDOOR32, 0x5F5A88) \ - X("barrel2", MI_NAUTICALMINE, 0x5F5A8C) \ - X("crushercrush", MI_CRUSHERBODY, 0x5F5A90) \ - X("crushertop", MI_CRUSHERLID, 0x5F5A94) \ - X("donkeymag", MI_DONKEYMAG, 0x5F5A98) \ - X("bullion", MI_BULLION, 0x5F5A9C) \ - X("floatpackge1", MI_FLOATPACKAGE1, 0x5F5AA0) \ - X("briefcase", MI_BRIEFCASE, 0x5F5AA4) \ - X("chinabanner1", MI_CHINABANNER1, 0x5F5AA8) \ - X("chinabanner2", MI_CHINABANNER2, 0x5F5AAC) \ - X("chinabanner3", MI_CHINABANNER3, 0x5F5AB0) \ - X("chinabanner4", MI_CHINABANNER4, 0x5F5AB4) \ - X("iten_chinatown5", MI_CHINABANNER5, 0x5F5AB8) \ - X("iten_chinatown7", MI_CHINABANNER6, 0x5F5ABC) \ - X("iten_chinatown3", MI_CHINABANNER7, 0x5F5AC0) \ - X("iten_chinatown2", MI_CHINABANNER8, 0x5F5AC4) \ - X("iten_chinatown4", MI_CHINABANNER9, 0x5F5AC8) \ - X("iten_washline01", MI_CHINABANNER10, 0x5F5ACC) \ - X("iten_washline02", MI_CHINABANNER11, 0x5F5AD0) \ - X("iten_washline03", MI_CHINABANNER12, 0x5F5AD4) \ - X("chinalanterns", MI_CHINALANTERN, 0x5F5AD8) \ - X("glassfx1", MI_GLASS1, 0x5F5ADC) \ - X("glassfx2", MI_GLASS2, 0x5F5AE0) \ - X("glassfx3", MI_GLASS3, 0x5F5AE4) \ - X("glassfx4", MI_GLASS4, 0x5F5AE8) \ - X("glassfx55", MI_GLASS5, 0x5F5AEC) \ - X("glassfxsub1", MI_GLASS6, 0x5F5AF0) \ - X("glassfxsub2", MI_GLASS7, 0x5F5AF4) \ - X("glassfx_composh", MI_GLASS8, 0x5F5AF8) \ - X("bridge_liftsec", MI_BRIDGELIFT, 0x5F5AFC) \ - X("bridge_liftweight", MI_BRIDGEWEIGHT, 0x5F5B00) \ - X("subbridge_lift", MI_BRIDGEROADSEGMENT, 0x5F5B04) \ - X("barrel4", MI_EXPLODINGBARREL, 0x5F5B08) \ - X("flagsitaly", MI_ITALYBANNER1, 0x5F5B0C) \ - X("adrenaline", MI_PICKUP_ADRENALINE, 0x5F5B10) \ - X("bodyarmour", MI_PICKUP_BODYARMOUR, 0x5F5B14) \ - X("info", MI_PICKUP_INFO, 0x5F5B18) \ - X("health", MI_PICKUP_HEALTH, 0x5F5B1C) \ - X("bonus", MI_PICKUP_BONUS, 0x5F5B20) \ - X("bribe", MI_PICKUP_BRIBE, 0x5F5B24) \ - X("killfrenzy", MI_PICKUP_KILLFRENZY, 0x5F5B28) \ - X("camerapickup", MI_PICKUP_CAMERA, 0x5F5B2C) \ - X("bollardlight", MI_BOLLARDLIGHT, 0x5F5B30) \ - X("magnet", MI_MAGNET, 0x5F5B34) \ - X("streetlamp1", MI_STREETLAMP1, 0x5F5B38) \ - X("streetlamp2", MI_STREETLAMP2, 0x5F5B3C) \ - X("railtrax_lo4b", MI_RAILTRACKS, 0x5F5B40) \ - X("bar_barrier10", MI_FENCE, 0x5F5B44) \ - X("bar_barrier12", MI_FENCE2, 0x5F5B48) \ - X("petrolpump", MI_PETROLPUMP, 0x5F5B4C) \ - X("bodycast", MI_BODYCAST, 0x5F5B50) \ - X("backdoor", MI_BACKDOOR, 0x5F5B54) \ - X("coffee", MI_COFFEE, 0x5F5B58) \ - X("bouy", MI_BUOY, 0x5F5B5C) \ - X("parktable1", MI_PARKTABLE, 0x5F5B60) \ - X("sbwy_tunl_start", MI_SUBWAY1, 0x5F5B64) \ - X("sbwy_tunl_bit", MI_SUBWAY2, 0x5F5B68) \ - X("sbwy_tunl_bend", MI_SUBWAY3, 0x5F5B6C) \ - X("sbwy_tunl_cstm6", MI_SUBWAY4, 0x5F5B70) \ - X("sbwy_tunl_cstm7", MI_SUBWAY5, 0x5F5B74) \ - X("sbwy_tunl_cstm8", MI_SUBWAY6, 0x5F5B78) \ - X("sbwy_tunl_cstm10", MI_SUBWAY7, 0x5F5B7C) \ - X("sbwy_tunl_cstm9", MI_SUBWAY8, 0x5F5B80) \ - X("sbwy_tunl_cstm11", MI_SUBWAY9, 0x5F5B84) \ - X("sbwy_tunl_cstm1", MI_SUBWAY10, 0x5F5B88) \ - X("sbwy_tunl_cstm2", MI_SUBWAY11, 0x5F5B8C) \ - X("sbwy_tunl_cstm4", MI_SUBWAY12, 0x5F5B90) \ - X("sbwy_tunl_cstm3", MI_SUBWAY13, 0x5F5B94) \ - X("sbwy_tunl_cstm5", MI_SUBWAY14, 0x5F5B98) \ - X("subplatform_n2", MI_SUBWAY15, 0x5F5B9C) \ - X("suby_tunl_start", MI_SUBWAY16, 0x5F5BA0) \ - X("sbwy_tunl_start2", MI_SUBWAY17, 0x5F5BA4) \ - X("indy_tunl_start", MI_SUBWAY18, 0x5F5BA8) \ - X("indsubway03", MI_SUBPLATFORM_IND, 0x5F5BAC) \ - X("comerside_subway", MI_SUBPLATFORM_COMS, 0x5F5BB0) \ - X("subplatform", MI_SUBPLATFORM_COMS2, 0x5F5BB4) \ - X("subplatform_n", MI_SUBPLATFORM_COMN, 0x5F5BB8) \ - X("Otherside_subway", MI_SUBPLATFORM_SUB, 0x5F5BBC) \ - X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \ - X("files", MI_FILES, 0x5F5BC4) + X("fire_hydrant", MI_FIRE_HYDRANT) \ + X("bagelstnd02", MI_BAGELSTAND2) \ + X("fish01", MI_FISHSTALL01) \ + X("fishstall02", MI_FISHSTALL02) \ + X("fishstall03", MI_FISHSTALL03) \ + X("fishstall04", MI_FISHSTALL04) \ + X("taxisign", MI_TAXISIGN) \ + X("phonesign", MI_PHONESIGN) \ + X("noparkingsign1", MI_NOPARKINGSIGN1) \ + X("bussign1", MI_BUSSIGN1) \ + X("roadworkbarrier1", MI_ROADWORKBARRIER1) \ + X("dump1", MI_DUMP1) \ + X("trafficcone", MI_TRAFFICCONE) \ + X("newsstand1", MI_NEWSSTAND) \ + X("postbox1", MI_POSTBOX1) \ + X("bin1", MI_BIN) \ + X("wastebin", MI_WASTEBIN) \ + X("phonebooth1", MI_PHONEBOOTH1) \ + X("parkingmeter", MI_PARKINGMETER) \ + X("trafficlight1", MI_TRAFFICLIGHTS) \ + X("lamppost1", MI_SINGLESTREETLIGHTS1) \ + X("lamppost2", MI_SINGLESTREETLIGHTS2) \ + X("lamppost3", MI_SINGLESTREETLIGHTS3) \ + X("doublestreetlght1", MI_DOUBLESTREETLIGHTS) \ + X("rd_Road2A10", MI_ROADSFORROADBLOCKSSTART) \ + X("rd_Road1A30", MI_ROADSFORROADBLOCKSEND) \ + X("veg_tree1", MI_TREE1) \ + X("veg_tree3", MI_TREE2) \ + X("veg_treea1", MI_TREE3) \ + X("veg_treenew01", MI_TREE4) \ + X("veg_treenew05", MI_TREE5) \ + X("veg_treeb1", MI_TREE6) \ + X("veg_treenew10", MI_TREE7) \ + X("veg_treea3", MI_TREE8) \ + X("veg_treenew09", MI_TREE9) \ + X("veg_treenew08", MI_TREE10) \ + X("veg_treenew03", MI_TREE11) \ + X("veg_treenew16", MI_TREE12) \ + X("veg_treenew17", MI_TREE13) \ + X("veg_treenew06", MI_TREE14) \ + X("doc_crane_cab", MODELID_CRANE_1) \ + X("cranetopb", MODELID_CRANE_2) \ + X("cranetopa", MODELID_CRANE_3) \ + X("package1", MI_COLLECTABLE1) \ + X("Money", MI_MONEY) \ + X("barrel1", MI_CARMINE) \ + X("oddjgaragdoor", MI_GARAGEDOOR1) \ + X("bombdoor", MI_GARAGEDOOR2) \ + X("door_bombshop", MI_GARAGEDOOR3) \ + X("vheistlocdoor", MI_GARAGEDOOR4) \ + X("door2_garage", MI_GARAGEDOOR5) \ + X("ind_slidedoor", MI_GARAGEDOOR6) \ + X("bankjobdoor", MI_GARAGEDOOR7) \ + X("door_jmsgrage", MI_GARAGEDOOR9) \ + X("jamesgrge_kb", MI_GARAGEDOOR10) \ + X("door_sfehousegrge", MI_GARAGEDOOR11) \ + X("shedgaragedoor", MI_GARAGEDOOR12) \ + X("door4_garage", MI_GARAGEDOOR13) \ + X("door_col_compnd_01", MI_GARAGEDOOR14) \ + X("door_col_compnd_02", MI_GARAGEDOOR15) \ + X("door_col_compnd_03", MI_GARAGEDOOR16) \ + X("door_col_compnd_04", MI_GARAGEDOOR17) \ + X("door_col_compnd_05", MI_GARAGEDOOR18) \ + X("impex_door", MI_GARAGEDOOR19) \ + X("SalvGarage", MI_GARAGEDOOR20) \ + X("door3_garage", MI_GARAGEDOOR21) \ + X("leveldoor2", MI_GARAGEDOOR22) \ + X("double_garage_dr", MI_GARAGEDOOR23) \ + X("amcogaragedoor", MI_GARAGEDOOR24) \ + X("towergaragedoor1", MI_GARAGEDOOR25) \ + X("towergaragedoor2", MI_GARAGEDOOR26) \ + X("towergaragedoor3", MI_GARAGEDOOR27) \ + X("plysve_gragedoor", MI_GARAGEDOOR28) \ + X("impexpsubgrgdoor", MI_GARAGEDOOR29) \ + X("Sub_sprayshopdoor", MI_GARAGEDOOR30) \ + X("ind_plyrwoor", MI_GARAGEDOOR31) \ + X("8ballsuburbandoor", MI_GARAGEDOOR32) \ + X("barrel2", MI_NAUTICALMINE) \ + X("crushercrush", MI_CRUSHERBODY) \ + X("crushertop", MI_CRUSHERLID) \ + X("donkeymag", MI_DONKEYMAG) \ + X("bullion", MI_BULLION) \ + X("floatpackge1", MI_FLOATPACKAGE1) \ + X("briefcase", MI_BRIEFCASE) \ + X("chinabanner1", MI_CHINABANNER1) \ + X("chinabanner2", MI_CHINABANNER2) \ + X("chinabanner3", MI_CHINABANNER3) \ + X("chinabanner4", MI_CHINABANNER4) \ + X("iten_chinatown5", MI_CHINABANNER5) \ + X("iten_chinatown7", MI_CHINABANNER6) \ + X("iten_chinatown3", MI_CHINABANNER7) \ + X("iten_chinatown2", MI_CHINABANNER8) \ + X("iten_chinatown4", MI_CHINABANNER9) \ + X("iten_washline01", MI_CHINABANNER10) \ + X("iten_washline02", MI_CHINABANNER11) \ + X("iten_washline03", MI_CHINABANNER12) \ + X("chinalanterns", MI_CHINALANTERN) \ + X("glassfx1", MI_GLASS1) \ + X("glassfx2", MI_GLASS2) \ + X("glassfx3", MI_GLASS3) \ + X("glassfx4", MI_GLASS4) \ + X("glassfx55", MI_GLASS5) \ + X("glassfxsub1", MI_GLASS6) \ + X("glassfxsub2", MI_GLASS7) \ + X("glassfx_composh", MI_GLASS8) \ + X("bridge_liftsec", MI_BRIDGELIFT) \ + X("bridge_liftweight", MI_BRIDGEWEIGHT) \ + X("subbridge_lift", MI_BRIDGEROADSEGMENT) \ + X("barrel4", MI_EXPLODINGBARREL) \ + X("flagsitaly", MI_ITALYBANNER1) \ + X("adrenaline", MI_PICKUP_ADRENALINE) \ + X("bodyarmour", MI_PICKUP_BODYARMOUR) \ + X("info", MI_PICKUP_INFO) \ + X("health", MI_PICKUP_HEALTH) \ + X("bonus", MI_PICKUP_BONUS) \ + X("bribe", MI_PICKUP_BRIBE) \ + X("killfrenzy", MI_PICKUP_KILLFRENZY) \ + X("camerapickup", MI_PICKUP_CAMERA) \ + X("bollardlight", MI_BOLLARDLIGHT) \ + X("magnet", MI_MAGNET) \ + X("streetlamp1", MI_STREETLAMP1) \ + X("streetlamp2", MI_STREETLAMP2) \ + X("railtrax_lo4b", MI_RAILTRACKS) \ + X("bar_barrier10", MI_FENCE) \ + X("bar_barrier12", MI_FENCE2) \ + X("petrolpump", MI_PETROLPUMP) \ + X("bodycast", MI_BODYCAST) \ + X("backdoor", MI_BACKDOOR) \ + X("coffee", MI_COFFEE) \ + X("bouy", MI_BUOY) \ + X("parktable1", MI_PARKTABLE) \ + X("sbwy_tunl_start", MI_SUBWAY1) \ + X("sbwy_tunl_bit", MI_SUBWAY2) \ + X("sbwy_tunl_bend", MI_SUBWAY3) \ + X("sbwy_tunl_cstm6", MI_SUBWAY4) \ + X("sbwy_tunl_cstm7", MI_SUBWAY5) \ + X("sbwy_tunl_cstm8", MI_SUBWAY6) \ + X("sbwy_tunl_cstm10", MI_SUBWAY7) \ + X("sbwy_tunl_cstm9", MI_SUBWAY8) \ + X("sbwy_tunl_cstm11", MI_SUBWAY9) \ + X("sbwy_tunl_cstm1", MI_SUBWAY10) \ + X("sbwy_tunl_cstm2", MI_SUBWAY11) \ + X("sbwy_tunl_cstm4", MI_SUBWAY12) \ + X("sbwy_tunl_cstm3", MI_SUBWAY13) \ + X("sbwy_tunl_cstm5", MI_SUBWAY14) \ + X("subplatform_n2", MI_SUBWAY15) \ + X("suby_tunl_start", MI_SUBWAY16) \ + X("sbwy_tunl_start2", MI_SUBWAY17) \ + X("indy_tunl_start", MI_SUBWAY18) \ + X("indsubway03", MI_SUBPLATFORM_IND) \ + X("comerside_subway", MI_SUBPLATFORM_COMS) \ + X("subplatform", MI_SUBPLATFORM_COMS2) \ + X("subplatform_n", MI_SUBPLATFORM_COMN) \ + X("Otherside_subway", MI_SUBPLATFORM_SUB) \ + X("subplatform_sub", MI_SUBPLATFORM_SUB2) \ + X("files", MI_FILES) -#define X(name, var, addr) extern int16 var; +#define X(name, var) extern int16 var; MODELINDICES #undef X @@ -255,7 +255,9 @@ enum MI_BUSKER4, // three more peds possible - MI_FIRST_VEHICLE = 90, + MI_LAST_PED = 89, + MI_FIRST_VEHICLE, + MI_LANDSTAL = MI_FIRST_VEHICLE, MI_IDAHO, MI_STINGER, @@ -382,7 +384,7 @@ IsGlass(int16 id) } inline bool -IsTrafficLight(int16 id) +IsStreetLight(int16 id) { return id == MI_TRAFFICLIGHTS || id == MI_SINGLESTREETLIGHTS1 || @@ -410,7 +412,7 @@ IsBoatModel(int16 id) inline bool IsPedModel(int16 id) { - return id >= 0 && id <= 89; + return id >= MI_PLAYER && id <= MI_LAST_PED; } inline bool diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 1566ba3d..e2257a28 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -966,18 +966,11 @@ CPopulation::ConvertToRealObject(CDummyObject *dummy) if (!obj) return; - bool makeInvisible; CWorld::Remove(dummy); delete dummy; CWorld::Add(obj); - int16 mi = obj->GetModelIndex(); - if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 || - mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8) - makeInvisible = true; - else - makeInvisible = false; - if (makeInvisible) { + if (IsGlass(obj->GetModelIndex())) { obj->bIsVisible = false; } else if (obj->GetModelIndex() == MI_BUOY) { obj->bIsStatic = false; @@ -996,17 +989,8 @@ CPopulation::ConvertToDummyObject(CObject *obj) dummy->GetMatrix().UpdateRW(); dummy->UpdateRwFrame(); - bool makeInvisible; - int16 mi = obj->GetModelIndex(); - if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 || - mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8) - makeInvisible = true; - else - makeInvisible = false; - - if (makeInvisible) { + if (IsGlass(obj->GetModelIndex())) dummy->bIsVisible = false; - } CWorld::Remove(obj); delete obj; From 50f0c7a1dcad33ac3d38d6e37faca3d16d222aaa Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 19 May 2020 22:01:28 +0200 Subject: [PATCH 069/148] bla --- src/entities/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 683a3571..a9b6b2b8 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -683,7 +683,7 @@ CEntity::ProcessLightsForEntity(void) lightOn = true; break; case LIGHT_FLICKER_NIGHT: - if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){){ + if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){ if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60) lightOn = true; else From 1b96e6c378b3e827c27444c38d207350ec0af66c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 19 May 2020 23:49:28 +0300 Subject: [PATCH 070/148] fixed script bug --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 864799f8..e8aa3266 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -2998,9 +2998,9 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) pCarGen->SwitchOff(); }else if (ScriptParams[1] <= 100){ pCarGen->SwitchOn(); + pCarGen->SetUsesRemaining(ScriptParams[1]); }else{ pCarGen->SwitchOn(); - pCarGen->SetUsesRemaining(ScriptParams[1]); } return 0; } From 2ab3fb5dd02aad980718f1ac176f06f7b7e25f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 20 May 2020 20:10:05 +0300 Subject: [PATCH 071/148] Fixes for melees and various things --- src/control/Pickups.cpp | 19 ++ src/control/Pickups.h | 1 + src/control/Script.h | 2 +- src/control/TrafficLights.cpp | 5 +- src/core/World.cpp | 5 +- src/core/config.h | 2 +- src/entities/Entity.cpp | 4 +- src/entities/Physical.cpp | 8 +- src/modelinfo/ModelIndices.h | 33 ++- src/objects/Object.cpp | 10 +- src/peds/CivilianPed.cpp | 2 +- src/peds/Ped.cpp | 376 +++++++++++++++++++--------------- src/peds/Ped.h | 5 +- src/peds/PlayerPed.cpp | 15 +- src/vehicles/Automobile.cpp | 6 +- 15 files changed, 297 insertions(+), 196 deletions(-) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index b5e20e41..9492e0e1 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1017,6 +1017,25 @@ CPickups::RenderPickUpText() NumMessages = 0; } +void +CPickups::CreateSomeMoney(CVector pos, int money) +{ + bool found; + + int pickupCount = Min(money / 20 + 1, 7); + int moneyPerPickup = money / pickupCount; + + for (int i = 0; i < pickupCount; i++) { + // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. + pos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128); + pos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128); + pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 0.5f; + if (found) { + CPickups::GenerateNewOne(CVector(pos.x, pos.y, pos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3)); + } + } +} + void CPickups::Load(uint8 *buf, uint32 size) { diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 810f3dff..0a73696a 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -91,6 +91,7 @@ public: static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex); static bool TestForPickupsInBubble(CVector pos, float range); static bool TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused); + static void CreateSomeMoney(CVector, int); static void Load(uint8 *buf, uint32 size); static void Save(uint8 *buf, uint32 *size); diff --git a/src/control/Script.h b/src/control/Script.h index 3393467e..f7aaa46c 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -232,7 +232,7 @@ enum { MAX_NUM_INTRO_RECTANGLES = 16, MAX_NUM_SCRIPT_SRPITES = 16, MAX_NUM_SCRIPT_SPHERES = 16, - MAX_NUM_USED_OBJECTS = 200, + MAX_NUM_USED_OBJECTS = 220, MAX_NUM_MISSION_SCRIPTS = 120, MAX_NUM_BUILDING_SWAPS = 25, MAX_NUM_INVISIBILITY_SETTINGS = 20, diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index b1816936..8487847f 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -145,10 +145,7 @@ CTrafficLights::ScanForLightsOnMap(void) CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES]; for(node = list.first; node; node = node->next){ CEntity *light = (CEntity*)node->item; - if(light->GetModelIndex() != MI_TRAFFICLIGHTS && - light->GetModelIndex() != MI_TRAFFICLIGHTS_VERTICAL && - light->GetModelIndex() != MI_TRAFFICLIGHTS_MIAMI && - light->GetModelIndex() != MI_TRAFFICLIGHTS_TWOVERTICAL) + if (!IsTrafficLight(light->GetModelIndex())) continue; // Check cars diff --git a/src/core/World.cpp b/src/core/World.cpp index 16e5e80d..433f9745 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1818,9 +1818,8 @@ CWorld::RepositionOneObject(CEntity *pEntity) modelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || modelId == MI_PHONESIGN || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || modelId == MI_PARKTABLE || modelId == MI_PARKINGMETER2 || modelId == MI_TELPOLE02 || - modelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId) -// TODO(MIAMI): this is actually a different case -|| IsStreetLight(modelId) + modelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId) || + IsLightThatNeedsRepositioning(modelId) ) { CVector &position = pEntity->GetMatrix().GetPosition(); CColModel *pColModel = pEntity->GetColModel(); diff --git a/src/core/config.h b/src/core/config.h index 548092f7..105454fa 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -95,7 +95,7 @@ enum Config { NUMPACMANPICKUPS = 256, NUMEVENTS = 64, - NUM_CARGENS = 160, + NUM_CARGENS = 185, NUM_PATH_NODES_IN_AUTOPILOT = 8, diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index efa67f36..a0c5c484 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -399,8 +399,8 @@ CEntity::HasPreRenderEffects(void) GetModelIndex() == MI_MISSILE || GetModelIndex() == MI_BEACHBALL || IsGlass(GetModelIndex()) || - IsObject() && ((CObject*)this)->bIsPickup; - IsStreetLight(GetModelIndex()); + IsObject() && ((CObject*)this)->bIsPickup || + IsLightWithPreRenderEffects(GetModelIndex()); } void diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 423662f7..92542071 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1067,13 +1067,13 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) if(B->IsBuilding()) skipShift = false; - else if(IsStreetLight(A->GetModelIndex()) && + else if(IsLightWithoutShift(A->GetModelIndex()) && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f) skipShift = true; else if((A->IsVehicle() || A->IsPed()) && B->GetUp().z < 0.66f && - IsStreetLight(B->GetModelIndex())) + IsLightWithoutShift(B->GetModelIndex())) skipShift = true; // TODO: maybe flip some ifs here else if(A->IsObject() && B->IsVehicle()){ @@ -1398,7 +1398,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(B->IsBuilding()) skipCollision = false; - else if(IsStreetLight(A->GetModelIndex()) && + else if(IsLightWithoutShift(A->GetModelIndex()) && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f){ skipCollision = true; @@ -1406,7 +1406,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) Aobj->m_pCollidingEntity = B; }else if((A->IsVehicle() || A->IsPed()) && B->GetUp().z < 0.66f && - IsStreetLight(B->GetModelIndex())){ + IsLightWithoutShift(B->GetModelIndex())){ skipCollision = true; A->bSkipLineCol = true; Bobj->m_pCollidingEntity = A; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 1d70be3d..b8c6964a 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -358,9 +358,38 @@ IsGlass(int16 id) } inline bool -IsStreetLight(int16 id) +IsTrafficLight(int16 id) { - return id == MI_SINGLESTREETLIGHTS1 || + return id == MI_TRAFFICLIGHTS || + id == MI_TRAFFICLIGHTS_VERTICAL || + id == MI_TRAFFICLIGHTS_MIAMI || + id == MI_TRAFFICLIGHTS_TWOVERTICAL; +} + +inline bool +IsLightWithoutShift(int16 id) +{ + return id == MI_TRAFFICLIGHTS || + id == MI_SINGLESTREETLIGHTS1 || + id == MI_SINGLESTREETLIGHTS2 || + id == MI_SINGLESTREETLIGHTS3 || + id == MI_DOUBLESTREETLIGHTS; +} + +inline bool +IsLightWithPreRenderEffects(int16 id) +{ + return IsTrafficLight(id) || + id == MI_SINGLESTREETLIGHTS1 || + id == MI_SINGLESTREETLIGHTS2 || + id == MI_SINGLESTREETLIGHTS3 || + id == MI_DOUBLESTREETLIGHTS; +} + +inline bool +IsLightThatNeedsRepositioning(int16 id) +{ + return id == MI_SINGLESTREETLIGHTS1 || id == MI_SINGLESTREETLIGHTS2 || id == MI_SINGLESTREETLIGHTS3 || id == MI_TRAFFICLIGHTS_MIAMI || diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index e6bb7aee..fd5a2aa3 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -338,13 +338,13 @@ CObject::Init(void) m_pCurSurface = outEntity; else m_pCurSurface = nil; -#if 0 - if (GetModelIndex() == MI_BODYCAST) - nBodyCastHealth = 1000; - else -#endif + if (GetModelIndex() == MI_BUOY) bTouchingWater = true; + + // TODO(Miami): Second flag set initialization + + m_area = AREA_EVERYWHERE; } bool diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 48b1f6cd..dd438a3f 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -103,7 +103,7 @@ CCivilianPed::CivilianAI(void) SetLookTimer(500); } else if (closestThreatFlag == PED_FLAG_DEADPEDS) { float eventDistSqr = (m_pEventEntity->GetPosition() - GetPosition()).MagnitudeSqr2D(); - if (IsGangMember() && m_nPedType == ((CPed*)m_pEventEntity)->m_nPedType) { + if (((CPed*)m_pEventEntity)->bIsDrowning || IsGangMember() && m_nPedType == ((CPed*)m_pEventEntity)->m_nPedType) { if (eventDistSqr < sq(5.0f)) { SetFindPathAndFlee(m_pEventEntity, 2000); SetMoveState(PEDMOVE_RUN); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 12870236..06012379 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -602,6 +602,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bTurnedAroundOnAttractor = false; bCarPassenger = false; bMiamiViceCop = false; + + bIsDrowning = false; + bCanDrownInWater = true; #ifdef VC_PED_PORTS bHeadStuckInCollision = false; #endif @@ -654,6 +657,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_nPedMoney = random % 25; if (m_nPedMoney == 23) m_nPedMoney = 400; + m_bleedCounter = 0; #ifdef PED_SKIN m_pWeaponModel = nil; #endif @@ -1285,7 +1289,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) } } -// --MIAMI: Done except melee weapons +// --MIAMI: Done except commented things void CPed::Attack(void) { @@ -1297,7 +1301,6 @@ CPed::Attack(void) float animLoopEnd; CWeaponInfo *ourWeapon; bool attackShouldContinue; - AnimationId reloadAnim; CAnimBlendAssociation *reloadAnimAssoc; CAnimBlendAssociation *throwAssoc; float delayBetweenAnimAndFire; @@ -1311,7 +1314,6 @@ CPed::Attack(void) attackShouldContinue = bIsAttacking; reloadAnimAssoc = nil; throwAssoc = nil; - reloadAnim = NUM_ANIMS; animLoopStart = ourWeapon->m_fAnimLoopStart; animLoopEnd = ourWeapon->m_fAnimLoopEnd; delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire; @@ -1462,66 +1464,104 @@ CPed::Attack(void) m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; } - // TODO(Miami): Chainsaw - if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) { - if (weaponAnimAssoc->speed < 1.0f) - weaponAnimAssoc->speed = 1.0f; + if (ourWeaponType != WEAPONTYPE_CHAINSAW + || !meleeAttackStarted && delayBetweenAnimAndFire - 0.5f >= weaponAnimAssoc->currentTime + || weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire) { - } else { - firePos = ourWeapon->m_vecFireOffset; + if (ourWeaponType == WEAPONTYPE_CHAINSAW) { +#ifndef AUDIO_NOT_READY + DMAudio.PlayOneShot(m_audioEntityId, 52, 0.0f); +#endif + } else if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) { + if (weaponAnimAssoc->speed < 1.0f) + weaponAnimAssoc->speed = 1.0f; - // TODO(Miami): Katana & Chainsaw - if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) { - firePos = GetMatrix() * firePos; } else { - TransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR); - } + firePos = ourWeapon->m_vecFireOffset; + + if (ourWeaponType != WEAPONTYPE_KATANA && ourWeaponType != WEAPONTYPE_CHAINSAW) { + if (ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE) { + TransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR); + } else { + firePos = GetMatrix() * firePos; + } + } else { + if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND) + firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f; + + firePos = GetMatrix() * firePos; + } + GetWeapon()->Fire(this, &firePos); + + // TODO(Miami): Teargas + if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE + /* ourWeaponType == WEAPONTYPE_TEARGAS*/) { + RemoveWeaponModel(ourWeapon->m_nModelId); + } + if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) { + SelectGunIfArmed(); + } + + if (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) { + int damagerType = ENTITY_TYPE_NOTHING; + if (m_pDamageEntity && (m_fDamageImpulse == 0.0f || !m_pDamageEntity->IsBuilding())) { + damagerType = m_pDamageEntity->GetType(); + } + switch (ourWeapon->m_AnimToPlay) { + case ASSOCGRP_UNARMED: + if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) { +#ifdef AUDIO_NOT_READY + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); +#else + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, (damagerType | (ourWeaponType << 8))); +#endif + } + break; + case ASSOCGRP_KNIFE: + case ASSOCGRP_BASEBALLBAT: + case ASSOCGRP_GOLFCLUB: + case ASSOCGRP_CHAINSAW: +#ifdef AUDIO_NOT_READY + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f); +#else + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (ourWeaponType << 8))); +#endif + break; + default: + break; + } + + if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) { + weaponAnimAssoc->callbackType = 0; + } + } + + attackShouldContinue = false; + } + } else { + CVector firePos = ourWeapon->m_vecFireOffset; + + if (weaponAnimAssoc->animId == 206) + firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f; + + firePos = GetMatrix() * firePos; GetWeapon()->Fire(this, &firePos); - - // TODO(Miami) - if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE - /* ourWeaponType == WEAPONTYPE_TEARGAS*/) { - RemoveWeaponModel(ourWeapon->m_nModelId); - } - if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) { - SelectGunIfArmed(); - } - if (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) { - int damagerType = 0; - if (m_pDamageEntity && (m_fDamageImpulse == 0.0f || !m_pDamageEntity->IsBuilding())) { + int damagerType = ENTITY_TYPE_PED; + if (m_pDamageEntity) damagerType = m_pDamageEntity->GetType(); - } - switch (ourWeapon->m_AnimToPlay) { - case ASSOCGRP_UNARMED: - if (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) { -#ifdef AUDIO_NOT_READY - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); -#else - DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, (damagerType | (ourWeaponType << 8))); -#endif - } - break; - case ASSOCGRP_KNIFE: - case ASSOCGRP_BASEBALLBAT: - case ASSOCGRP_GOLFCLUB: - case ASSOCGRP_CHAINSAW: -#ifdef AUDIO_NOT_READY - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f); -#else - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (ourWeaponType << 8))); -#endif - break; - default: - break; - } - if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) { - weaponAnimAssoc->callbackType = 0; + DMAudio.PlayOneShot(m_audioEntityId, 54, (float)damagerType); + if (IsPlayer()) { + CPad::GetPad(0)->StartShake(240, 180); + } + } else { + DMAudio.PlayOneShot(m_audioEntityId, 53, 0.0f); + if (IsPlayer()) { + CPad::GetPad(0)->StartShake(240, 90); } } - attackShouldContinue = false; } @@ -1614,12 +1654,12 @@ CPed::Attack(void) if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) && (GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING - /* || GetWeapon()->m_nWeaponType == WEAPONTYPE_MINIGUN */)) { + /* || GetWeapon()->m_nWeaponType == WEAPONTYPE_MINIGUN */)) { // TODO(Miami): Minigun PedOnGroundState pedOnGroundState; if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE && (CGame::nastyGame && ((pedOnGroundState = CheckForPedsOnGroundToAttack(this, nil)) > PED_IN_FRONT_OF_ATTACKER) - || GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) { + || ourWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) { AnimationId fireAnim = GetFireAnimGround(ourWeapon, false); if (weaponAnimAssoc->animId == fireAnim) @@ -1672,7 +1712,7 @@ CPed::Attack(void) break; } #else - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, ourWeaponType); #endif } @@ -1908,7 +1948,7 @@ CPed::BeingDraggedFromCar(void) #ifdef VC_PED_PORTS if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { if (m_pMyVehicle) { - m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f); + m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_STD_ANIMS, m_pVehicleAnim->currentTime * 5.0f); } } #endif @@ -4022,7 +4062,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) } m_nPedState = PED_DIE; - if (animId == NUM_ANIMS) { + if (animId == NUM_STD_ANIMS) { bIsPedDieAnimPlaying = false; } else { CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta); @@ -4045,6 +4085,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); } +// --MIAMI: Done except commented things bool CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction) { @@ -4056,17 +4097,28 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi bool willLinger = false; int random; + // TODO(Miami): PlayerInfo thingies here + if (player == this) { if (!player->m_bCanBeDamaged) return false; + if (damagedBy && damagedBy->IsPed() && ((CPed*)damagedBy)->m_nPedType == PEDTYPE_GANG7) + return false; + + if ((method == WEAPONTYPE_FLAMETHROWER || method == WEAPONTYPE_MOLOTOV) && CWorld::Players[CWorld::PlayerInFocus].m_bFireproof) + return false; + player->AnnoyPlayerPed(false); } if (DyingOrDead()) return false; - if (!bUsesCollision && method != WEAPONTYPE_DROWNING) + if (method == WEAPONTYPE_DROWNING && !bCanDrownInWater) + return false; + + if (!bUsesCollision && (!bInVehicle || m_nPedState != PED_DRIVING) && method != WEAPONTYPE_DROWNING) return false; if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() && @@ -4079,8 +4131,12 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi else healthImpact = damage * m_pedStats->m_defendWeakness; + if (!IsPlayer() && + (method == WEAPONTYPE_SCREWDRIVER || method == WEAPONTYPE_KNIFE || (method >= WEAPONTYPE_CLEAVER && method <= WEAPONTYPE_CHAINSAW))) + m_bleedCounter = 200; + bool detectDieAnim = true; - if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) { + if (m_nPedState == PED_GETUP) { if (!IsPedHeadAbovePos(-0.3f)) { if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) dieAnim = ANIM_FLOOR_HIT_F; @@ -4089,20 +4145,36 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi dieDelta *= 2.0f; dieSpeed = 0.5f; detectDieAnim = false; - } else if (m_nPedState == PED_FALL) { - dieAnim = NUM_ANIMS; - detectDieAnim = false; } + } else if (m_nPedState == PED_FALL) { + CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL); + if (!fallAssoc || fallAssoc->IsRunning()) { + if (fallAssoc && fallAssoc->blendDelta >= 0.0f) + dieAnim = NUM_STD_ANIMS; + else + dieAnim = ANIM_KO_SHOT_FRONT1; + } else { + if (fallAssoc->flags & ASSOC_FRONTAL) + dieAnim = ANIM_FLOOR_HIT_F; + else + dieAnim = ANIM_FLOOR_HIT; + + dieDelta *= 2.0f; + dieSpeed = 0.5f; + } + detectDieAnim = false; } + if (detectDieAnim) { switch (method) { case WEAPONTYPE_UNARMED: + case WEAPONTYPE_BRASSKNUCKLE: if (bMeleeProof) return false; if (m_nPedState == PED_FALL) { if (IsPedHeadAbovePos(-0.3f)) { - dieAnim = NUM_ANIMS; + dieAnim = NUM_STD_ANIMS; } else { if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) dieAnim = ANIM_FLOOR_HIT_F; @@ -4130,19 +4202,28 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi } } break; + case WEAPONTYPE_SCREWDRIVER: + case WEAPONTYPE_GOLFCLUB: + case WEAPONTYPE_NIGHTSTICK: + case WEAPONTYPE_KNIFE: case WEAPONTYPE_BASEBALLBAT: + case WEAPONTYPE_HAMMER: + case WEAPONTYPE_CLEAVER: + case WEAPONTYPE_MACHETE: + case WEAPONTYPE_KATANA: + case WEAPONTYPE_CHAINSAW: if (bMeleeProof) return false; -#ifdef VC_PED_PORTS - if (/*method != WEAPONTYPE_KATANA || */ + + if (method != WEAPONTYPE_KATANA || damagedBy != FindPlayerPed() || FindPlayerPed()->m_nPedState != PED_FIGHT - /*|| FindPlayerPed()->m_lastFightMove != 28 && FindPlayerPed()->m_lastFightMove != 29 */ + || FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE1 && FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE2 || CGeneral::GetRandomNumber() & 3) { if (m_nPedState == PED_FALL) { if (IsPedHeadAbovePos(-0.3f)) { - dieAnim = NUM_ANIMS; + dieAnim = NUM_STD_ANIMS; } else { if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) dieAnim = ANIM_FLOOR_HIT_F; @@ -4151,8 +4232,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi dieDelta = dieDelta * 2.0f; dieSpeed = 0.5f; } - } else if (damagedBy != FindPlayerPed()) { // || FindPlayerPed()->m_lastFightMove != 29) - //if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_lastFightMove != 30) { + } else if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE2) { + if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE3) { switch (direction) { case 0: dieAnim = ANIM_KO_SKID_FRONT; @@ -4169,82 +4250,46 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi default: break; } - //} else { - // dieAnim = ANIM_KO_SHOT_STOM; - //} + } else { + dieAnim = ANIM_KO_SHOT_STOM; + } } else { dieAnim = ANIM_KO_SHOT_FACE; } } else { dieAnim = ANIM_KO_SHOT_FACE; - // SpawnFlyingComponent in VC RemoveBodyPart(PED_HEAD, direction); headShot = true; willLinger = true; } -#else - if (m_nPedState == PED_FALL) { - if (IsPedHeadAbovePos(-0.3f)) { - dieAnim = NUM_ANIMS; - } else { - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) - dieAnim = ANIM_FLOOR_HIT_F; - else - dieAnim = ANIM_FLOOR_HIT; - dieDelta = dieDelta * 2.0f; - dieSpeed = 0.5f; - } - } else { - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - } -#endif break; case WEAPONTYPE_COLT45: - case WEAPONTYPE_UZI: + case WEAPONTYPE_SHOTGUN: + // TODO(Miami): Shotguns case WEAPONTYPE_TEC9: + case WEAPONTYPE_UZI: case WEAPONTYPE_SILENCED_INGRAM: case WEAPONTYPE_MP5: - case WEAPONTYPE_SHOTGUN: - case WEAPONTYPE_AK47: case WEAPONTYPE_M16: + case WEAPONTYPE_AK47: case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_UZI_DRIVEBY: + // TODO(Miami): Laserscope, M60, Minigun + if (bBulletProof) return false; bool dontRemoveLimb; if (IsPlayer() || bNoCriticalHits) dontRemoveLimb = true; - else { - switch (method) { - case WEAPONTYPE_SNIPERRIFLE: - dontRemoveLimb = false; - break; - case WEAPONTYPE_M16: - dontRemoveLimb = false; - break; - case WEAPONTYPE_SHOTGUN: - dontRemoveLimb = CGeneral::GetRandomNumber() & 7; - break; - default: - dontRemoveLimb = CGeneral::GetRandomNumber() & 15; - break; - } - } + else if (method != WEAPONTYPE_M16 && method != WEAPONTYPE_AK47 && method != WEAPONTYPE_SNIPERRIFLE + /* method != WEAPONTYPE_LASERSCOPE */) { // TODO(Miami): Laserscope + if (method == WEAPONTYPE_SHOTGUN) + dontRemoveLimb = CGeneral::GetRandomNumber() & 7; + else + dontRemoveLimb = CGeneral::GetRandomNumber() & 15; + } else + dontRemoveLimb = false; if (dontRemoveLimb) { if (method == WEAPONTYPE_SHOTGUN) { @@ -4309,8 +4354,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi } } break; - case WEAPONTYPE_ROCKETLAUNCHER: case WEAPONTYPE_GRENADE: + case WEAPONTYPE_ROCKETLAUNCHER: case WEAPONTYPE_EXPLOSION: if (bExplosionProof) return false; @@ -4407,7 +4452,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi default: break; } - if (damagedBy) { + if (damagedBy && pedPiece != PEDPIECE_TORSO) { CVehicle *vehicle = (CVehicle*)damagedBy; if (method == WEAPONTYPE_RAMMEDBYCAR) { float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude(); @@ -4466,6 +4511,16 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds(); m_lastWepDam = method; + m_lastDamEntity = damagedBy; + } + + if (method == WEAPONTYPE_FALL) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLOUT_LHS)) { + if (m_fHealth >= 1.0 && m_fHealth - healthImpact < 5.0f) { + m_fHealth = Min(m_fHealth, 5.0f); + return false; + } + } } if (m_fHealth - healthImpact >= 1.0f && !willLinger) { @@ -4477,6 +4532,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi if (method != WEAPONTYPE_DROWNING) { #ifdef VC_PED_PORTS if (m_pMyVehicle) { + + // TODO(Miami): Bikes if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) { if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) { m_pMyVehicle->SetStatus(STATUS_PHYSICS); @@ -4498,7 +4555,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi SetDie(dieAnim, dieDelta, dieSpeed); /* if (damagedBy == FindPlayerPed() && damagedBy != this) { - // PlayerInfo stuff + // TODO(Miami): PlayerInfo stuff } */ } @@ -4527,7 +4584,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi if (player == this) m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED); - SetDie(NUM_ANIMS, 4.0f, 0.0f); + SetDie(NUM_STD_ANIMS, 4.0f, 0.0f); return true; } else { m_fHealth = 0.0f; @@ -4535,7 +4592,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) { - // There are PlayerInfo stuff here in VC + // TODO(Miami): PlayerInfo stuff CDarkel::RegisterKillByPlayer(this, method, headShot); m_threatEntity = player; } else { @@ -4626,7 +4683,7 @@ CPed::SetGetUp(void) animAssoc->SetFinishCallback(PedGetupCB,this); } else { m_fHealth = 0.0f; - SetDie(NUM_ANIMS, 4.0f, 0.0f); + SetDie(NUM_STD_ANIMS, 4.0f, 0.0f); } } @@ -5037,7 +5094,7 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) else if (animType < 2) stepAnim = ANIM_EV_STEP; else - stepAnim = NUM_ANIMS; + stepAnim = NUM_STD_ANIMS; } if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) { CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f); @@ -5191,7 +5248,6 @@ CPed::SetAttack(CEntity *victim) return; } - // TODO(Miami): Brass knuckles if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || curWeapon->m_bFightMode || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) { if (IsPlayer() || (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL @@ -5795,7 +5851,7 @@ CPed::SetFlee(CVector2D const &from, int time) void CPed::SetWaitState(eWaitState state, void *time) { - AnimationId waitAnim = NUM_ANIMS; + AnimationId waitAnim = NUM_STD_ANIMS; CAnimBlendAssociation *animAssoc; if (!IsPedInControl()) @@ -5882,10 +5938,10 @@ CPed::SetWaitState(eWaitState state, void *time) case WAITSTATE_PLAYANIM_COWER: waitAnim = ANIM_HANDSCOWER; case WAITSTATE_PLAYANIM_HANDSUP: - if (waitAnim == NUM_ANIMS) + if (waitAnim == NUM_STD_ANIMS) waitAnim = ANIM_HANDSUP; case WAITSTATE_PLAYANIM_HANDSCOWER: - if (waitAnim == NUM_ANIMS) + if (waitAnim == NUM_STD_ANIMS) waitAnim = ANIM_HANDSCOWER; m_headingRate = 0.0f; if (time) @@ -5899,10 +5955,10 @@ CPed::SetWaitState(eWaitState state, void *time) case WAITSTATE_PLAYANIM_DUCK: waitAnim = ANIM_DUCK_DOWN; case WAITSTATE_PLAYANIM_TAXI: - if (waitAnim == NUM_ANIMS) + if (waitAnim == NUM_STD_ANIMS) waitAnim = ANIM_IDLE_TAXI; case WAITSTATE_PLAYANIM_CHAT: - if (waitAnim == NUM_ANIMS) + if (waitAnim == NUM_STD_ANIMS) waitAnim = ANIM_IDLE_CHAT; if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -6376,20 +6432,7 @@ CPed::CreateDeadPedMoney(void) return; CVector pickupPos = GetPosition(); - bool found; - - int pickupCount = Min(money / 20 + 1, 7); - int moneyPerPickup = money / pickupCount; - - for(int i = 0; i < pickupCount; i++) { - // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. - pickupPos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128); - pickupPos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128); - pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; - if (found) { - CPickups::GenerateNewOne(CVector(pickupPos.x, pickupPos.y, pickupPos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3)); - } - } + CPickups::CreateSomeMoney(pickupPos, money); m_nPedMoney = 0; } @@ -7683,7 +7726,7 @@ CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg) void CPed::Wait(void) { - AnimationId mustHaveAnim = NUM_ANIMS; + AnimationId mustHaveAnim = NUM_STD_ANIMS; CAnimBlendAssociation *animAssoc; CPed *pedWeLook; @@ -7853,7 +7896,7 @@ CPed::Wait(void) mustHaveAnim = ANIM_HANDSUP; case WAITSTATE_PLAYANIM_HANDSCOWER: - if (mustHaveAnim == NUM_ANIMS) + if (mustHaveAnim == NUM_STD_ANIMS) mustHaveAnim = ANIM_HANDSCOWER; animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim); @@ -7925,15 +7968,15 @@ CPed::Wait(void) mustHaveAnim = ANIM_HANDSCOWER; case WAITSTATE_PLAYANIM_DUCK: - if (mustHaveAnim == NUM_ANIMS) + if (mustHaveAnim == NUM_STD_ANIMS) mustHaveAnim = ANIM_DUCK_DOWN; case WAITSTATE_PLAYANIM_TAXI: - if (mustHaveAnim == NUM_ANIMS) + if (mustHaveAnim == NUM_STD_ANIMS) mustHaveAnim = ANIM_IDLE_TAXI; case WAITSTATE_PLAYANIM_CHAT: - if (mustHaveAnim == NUM_ANIMS) + if (mustHaveAnim == NUM_STD_ANIMS) mustHaveAnim = ANIM_IDLE_CHAT; if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { @@ -8721,14 +8764,22 @@ CPed::SetLanding(void) CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL); CAnimBlendAssociation *landAssoc; + if (fallAssoc && bIsDrowning) + return; + RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); - if (fallAssoc) { + if (fallAssoc || m_nPedType == PEDTYPE_COP && bKnockedUpIntoAir) { landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE); DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f); if (IsPlayer()) Say(SOUND_PED_LAND); + if (m_nPedType == PEDTYPE_COP) { + if (bKnockedUpIntoAir) + bKnockedUpIntoAir = false; + } + } else { landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND); DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f); @@ -9691,7 +9742,7 @@ CPed::MoveHeadToLook(void) bool notRocketLauncher = false; bool notTwoHanded = false; - AnimationId animToPlay = NUM_ANIMS; + AnimationId animToPlay = NUM_STD_ANIMS; if (!GetWeapon()->IsType2Handed()) notTwoHanded = true; @@ -9720,7 +9771,7 @@ CPed::MoveHeadToLook(void) animToPlay = ANIM_FUCKU; } - if (animToPlay != NUM_ANIMS) { + if (animToPlay != NUM_STD_ANIMS) { CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); if (newAssoc) { @@ -9912,6 +9963,7 @@ CPed::ProcessControl(void) bIsShooting = false; BuildPedLists(); bIsInWater = false; + bIsDrowning = false; ProcessBuoyancy(); if (m_nPedState != PED_ARRESTED) { @@ -11209,8 +11261,11 @@ CPed::ProcessControl(void) default: break; } SetMoveAnim(); - if (bPedIsBleeding) { + if (bPedIsBleeding || m_bleedCounter != 0) { if (CGame::nastyGame) { + if (m_bleedCounter != 0) + m_bleedCounter--; + if (!(CTimer::GetFrameCounter() & 3)) { CVector cameraDist = GetPosition() - TheCamera.GetPosition(); if (cameraDist.MagnitudeSqr() < sq(50.0f)) { @@ -15928,6 +15983,7 @@ CPed::ProcessBuoyancy(void) m_vecMoveSpeed.y *= speedMult; m_vecMoveSpeed.z *= speedMult; bIsStanding = false; + bIsDrowning = true; InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); } if (buoyancyImpulse.z / m_fMass > 0.002f * CTimer::GetTimeStep()) { diff --git a/src/peds/Ped.h b/src/peds/Ped.h index f5e6d95a..07c44fd5 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -444,8 +444,8 @@ public: //uint32 b155_40 //uint32 b155_80 - //uint32 b156_1 - //uint32 b156_2 + uint32 bIsDrowning : 1; + uint32 bCanDrownInWater : 1; // Originally bDrownsInWater //uint32 b156_4 //uint32 b156_8 uint32 bIsPlayerFriend : 1; @@ -578,6 +578,7 @@ public: uint8 m_fightButtonPressure; FightState m_fightState; bool m_takeAStepAfterAttack; + uint8 m_bleedCounter; CFire *m_pFire; CEntity *m_pLookTarget; float m_fLookDirection; diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 9f972882..f6f1cf05 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1026,7 +1026,7 @@ CPlayerPed::ProcessAnimGroups(void) if (m_fWalkAngle > 0.0f) { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETLEFT; - else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */ + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/ ) groupToSet = ASSOCGRP_CHAINSAWLEFT; @@ -1035,7 +1035,7 @@ CPlayerPed::ProcessAnimGroups(void) } else { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETRIGHT; - else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */ + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/) groupToSet = ASSOCGRP_CHAINSAWRIGHT; @@ -1045,7 +1045,7 @@ CPlayerPed::ProcessAnimGroups(void) } else { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETBACK; - else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */ + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/) groupToSet = ASSOCGRP_CHAINSAWBACK; @@ -1057,9 +1057,9 @@ CPlayerPed::ProcessAnimGroups(void) groupToSet = ASSOCGRP_PLAYERROCKET; } else { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT - /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MACHETE */) + || GetWeapon()->m_eWeaponType == WEAPONTYPE_MACHETE) groupToSet = ASSOCGRP_PLAYERBBBAT; - else if (/*GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || */ + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/) groupToSet = ASSOCGRP_PLAYERCHAINSAW; @@ -1067,10 +1067,9 @@ CPlayerPed::ProcessAnimGroups(void) // I hope this was inlined... /* && GetWeapon()->m_eWeaponType != WEAPONTYPE_PYTHON*/ && GetWeapon()->m_eWeaponType != WEAPONTYPE_TEC9 - && GetWeapon()->m_eWeaponType != WEAPONTYPE_SILENCED_INGRAM && GetWeapon()->m_eWeaponType != WEAPONTYPE_MP5 /* + && GetWeapon()->m_eWeaponType != WEAPONTYPE_SILENCED_INGRAM && GetWeapon()->m_eWeaponType != WEAPONTYPE_MP5 && GetWeapon()->m_eWeaponType != WEAPONTYPE_GOLFCLUB && GetWeapon()->m_eWeaponType != WEAPONTYPE_KATANA - && GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA - */) { + /* && GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA */) { if (!GetWeapon()->IsType2Handed()) { groupToSet = ASSOCGRP_PLAYER; } else { diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index ae78c93e..e260df93 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -3098,11 +3098,11 @@ CAutomobile::DoDriveByShootings(void) // TODO: what is this? if(!lookingLeft && m_weaponDoorTimerLeft > 0.0f){ m_weaponDoorTimerLeft = Max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f); - ProcessOpenDoor(CAR_DOOR_LF, NUM_ANIMS, m_weaponDoorTimerLeft); + ProcessOpenDoor(CAR_DOOR_LF, NUM_STD_ANIMS, m_weaponDoorTimerLeft); } if(!lookingRight && m_weaponDoorTimerRight > 0.0f){ m_weaponDoorTimerRight = Max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f); - ProcessOpenDoor(CAR_DOOR_RF, NUM_ANIMS, m_weaponDoorTimerRight); + ProcessOpenDoor(CAR_DOOR_RF, NUM_STD_ANIMS, m_weaponDoorTimerRight); } } @@ -3787,7 +3787,7 @@ CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) case ANIM_VAN_GETOUT: ProcessDoorOpenAnimation(this, component, door, time, 0.5f, 0.6f); break; - case NUM_ANIMS: + case NUM_STD_ANIMS: OpenDoor(component, door, time); break; } From d84650fbe5c9c90e4b1f2a68018fe246029b1dff Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 20 May 2020 20:40:04 +0300 Subject: [PATCH 072/148] script revision --- src/control/OnscreenTimer.cpp | 54 ++-- src/control/OnscreenTimer.h | 5 +- src/control/Script.cpp | 446 ++++++++++++++++++++++------------ src/control/Script.h | 8 +- src/weapons/WeaponType.h | 2 + 5 files changed, 328 insertions(+), 187 deletions(-) diff --git a/src/control/OnscreenTimer.cpp b/src/control/OnscreenTimer.cpp index d128efeb..d94e993e 100644 --- a/src/control/OnscreenTimer.cpp +++ b/src/control/OnscreenTimer.cpp @@ -20,8 +20,9 @@ void COnscreenTimer::Init() { } m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER; - m_sEntries[i].m_bTimerProcessed = 0; - m_sEntries[i].m_bCounterProcessed = 0; + m_sEntries[i].m_bTimerProcessed = false; + m_sEntries[i].m_bCounterProcessed = false; + m_sEntries[i].m_bTimerGoingDown = true; } } @@ -65,26 +66,21 @@ void COnscreenTimer::ClearClock(uint32 offset) { } } -void COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text) { - uint32 i = 0; - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - if(m_sEntries[i].m_nCounterOffset == 0) { - break; - } +void COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text, uint16 pos) { + + m_sEntries[pos].m_nCounterOffset = offset; + if (m_sEntries[pos].m_aCounterText[0] != '\0') return; - } - - m_sEntries[i].m_nCounterOffset = offset; if(text) { - strncpy(m_sEntries[i].m_aCounterText, text, 10); + strncpy(m_sEntries[pos].m_aCounterText, text, 10); } else { - m_sEntries[i].m_aCounterText[0] = 0; + m_sEntries[pos].m_aCounterText[0] = 0; } - m_sEntries[i].m_nType = type; + m_sEntries[pos].m_nType = type; } -void COnscreenTimer::AddClock(uint32 offset, char* text) { +void COnscreenTimer::AddClock(uint32 offset, char* text, bool bGoingDown) { uint32 i = 0; for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { if(m_sEntries[i].m_nTimerOffset == 0) { @@ -94,6 +90,7 @@ void COnscreenTimer::AddClock(uint32 offset, char* text) { } m_sEntries[i].m_nTimerOffset = offset; + m_sEntries[i].m_bTimerGoingDown = bGoingDown; if(text) { strncpy(m_sEntries[i].m_aTimerText, text, 10); } else { @@ -108,19 +105,24 @@ void COnscreenTimerEntry::Process() { int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nTimerOffset); int32 oldTime = *timerPtr; - int32 newTime = oldTime - int32(CTimer::GetTimeStepInSeconds() * 1000); - if(newTime < 0) { - *timerPtr = 0; - m_bTimerProcessed = 0; - m_nTimerOffset = 0; - m_aTimerText[0] = 0; - } else { - *timerPtr = newTime; - int32 oldTimeSeconds = oldTime / 1000; - if(oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds) { - DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000); + if (m_bTimerGoingDown) { + int32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds()); + if (newTime < 0) { + *timerPtr = 0; + m_bTimerProcessed = 0; + m_nTimerOffset = 0; + m_aTimerText[0] = 0; + } + else { + *timerPtr = newTime; + int32 oldTimeSeconds = oldTime / 1000; + if (oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds) { + DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000); + } } } + else + *timerPtr = oldTime + int32(CTimer::GetTimeStepInMilliseconds()); } bool COnscreenTimerEntry::ProcessForDisplay() { diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h index 3ef7764a..09473397 100644 --- a/src/control/OnscreenTimer.h +++ b/src/control/OnscreenTimer.h @@ -17,6 +17,7 @@ public: char m_bCounterBuffer[42]; char m_bTimerBuffer[42]; bool m_bTimerProcessed; + bool m_bTimerGoingDown; bool m_bCounterProcessed; void Process(); @@ -42,8 +43,8 @@ public: void ClearCounter(uint32 offset); void ClearClock(uint32 offset); - void AddCounter(uint32 offset, uint16 type, char* text); - void AddClock(uint32 offset, char* text); + void AddCounter(uint32 offset, uint16 type, char* text, uint16 pos); + void AddClock(uint32 offset, char* text, bool bGoingDown); }; VALIDATE_SIZE(COnscreenTimer, 0x78); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 0129b155..dd119c5a 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -75,7 +75,8 @@ #include "main.h" #define PICKUP_PLACEMENT_OFFSET 0.5f -#define PED_FIND_Z_OFFSET 10.0f +#define PED_FIND_Z_OFFSET 5.0f +#define COP_PED_FIND_Z_OFFSET 10.0f #define SPHERE_MARKER_R 0 #define SPHERE_MARKER_G 128 @@ -2978,22 +2979,21 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) int8 CRunningScript::ProcessCommands300To399(int32 command) { switch (command) { - /* Not implemented. - case COMMAND_SET_CHAR_INVINCIBLE: - case COMMAND_SET_PLAYER_INVINCIBLE: - case COMMAND_SET_CHAR_GRAPHIC_TYPE: - case COMMAND_SET_PLAYER_GRAPHIC_TYPE: - */ + //case COMMAND_SET_CHAR_INVINCIBLE: + //case COMMAND_SET_PLAYER_INVINCIBLE: + //case COMMAND_SET_CHAR_GRAPHIC_TYPE: + //case COMMAND_SET_PLAYER_GRAPHIC_TYPE: + /* case COMMAND_HAS_PLAYER_BEEN_ARRESTED: CollectParameters(&m_nIp, 1); UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED); return 0; - /* Not implemented. - case COMMAND_STOP_CHAR_DRIVING: - case COMMAND_KILL_CHAR: - case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR: - case COMMAND_SET_CHAR_OCCUPATION: */ + //case COMMAND_STOP_CHAR_DRIVING: + //case COMMAND_KILL_CHAR: + //case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR: + //case COMMAND_SET_CHAR_OCCUPATION: + /* case COMMAND_CHANGE_CAR_LOCK: { CollectParameters(&m_nIp, 2); @@ -3009,6 +3009,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) *(float*)&ScriptParams[2], *(float*)&ScriptParams[3]); return 0; + */ case COMMAND_IS_CAR_MODEL: { CollectParameters(&m_nIp, 2); @@ -3017,11 +3018,10 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]); return 0; } - /* Not implemented. - case COMMAND_IS_CAR_REMAP: - case COMMAND_HAS_CAR_JUST_SUNK: - case COMMAND_SET_CAR_NO_COLLIDE: - */ + //case COMMAND_IS_CAR_REMAP: + //case COMMAND_HAS_CAR_JUST_SUNK: + //case COMMAND_SET_CAR_NO_COLLIDE: + /* case COMMAND_IS_CAR_DEAD_IN_AREA_2D: { CollectParameters(&m_nIp, 6); @@ -3060,35 +3060,39 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; } - /* Not implemented. - case COMMAND_IS_TRAILER_ATTACHED: - case COMMAND_IS_CAR_ON_TRAILER: - case COMMAND_HAS_CAR_GOT_WEAPON: - case COMMAND_PARK: - case COMMAND_HAS_PARK_FINISHED: - case COMMAND_KILL_ALL_PASSENGERS: - case COMMAND_SET_CAR_BULLETPROOF: - case COMMAND_SET_CAR_FLAMEPROOF: - case COMMAND_SET_CAR_ROCKETPROOF: - case COMMAND_IS_CARBOMB_ACTIVE: - case COMMAND_GIVE_CAR_ALARM: - case COMMAND_PUT_CAR_ON_TRAILER: */ + //case COMMAND_IS_TRAILER_ATTACHED: + //case COMMAND_IS_CAR_ON_TRAILER: + //case COMMAND_HAS_CAR_GOT_WEAPON: + //case COMMAND_PARK: + //case COMMAND_HAS_PARK_FINISHED: + //case COMMAND_KILL_ALL_PASSENGERS: + //case COMMAND_SET_CAR_BULLETPROOF: + //case COMMAND_SET_CAR_FLAMEPROOF: + //case COMMAND_SET_CAR_ROCKETPROOF: + //case COMMAND_IS_CARBOMB_ACTIVE: + //case COMMAND_GIVE_CAR_ALARM: + //case COMMAND_PUT_CAR_ON_TRAILER: + /* case COMMAND_IS_CAR_CRUSHED: CollectParameters(&m_nIp, 1); UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0])); return 0; - /* Not implemented. - case COMMAND_CREATE_GANG_CAR: */ + //case COMMAND_CREATE_GANG_CAR: case COMMAND_CREATE_CAR_GENERATOR: + { CollectParameters(&m_nIp, 12); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z > MAP_Z_LOW_LIMIT) + pos.z += 0.015f; ScriptParams[0] = CTheCarGenerators::CreateCarGenerator( - *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], + pos.x, pos.y, pos.z, *(float*)&ScriptParams[3], ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]); StoreParameters(&m_nIp, 1); return 0; + } case COMMAND_SWITCH_CAR_GENERATOR: { CollectParameters(&m_nIp, 2); @@ -3097,12 +3101,13 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) pCarGen->SwitchOff(); }else if (ScriptParams[1] <= 100){ pCarGen->SwitchOn(); + pCarGen->SetUsesRemaining(ScriptParams[1]); }else{ pCarGen->SwitchOn(); - pCarGen->SetUsesRemaining(ScriptParams[1]); } return 0; } + /* case COMMAND_ADD_PAGER_MESSAGE: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -3110,11 +3115,14 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]); return 0; } + */ case COMMAND_DISPLAY_ONSCREEN_TIMER: { assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); m_nIp++; - CUserDisplay::OnscnTimer.AddClock(CTheScripts::Read2BytesFromScript(&m_nIp), nil); + uint32 offset = CTheScripts::Read2BytesFromScript(&m_nIp); + CollectParameters(&m_nIp, 1); + CUserDisplay::OnscnTimer.AddClock(offset, nil, ScriptParams[0] != 0); return 0; } case COMMAND_CLEAR_ONSCREEN_TIMER: @@ -3130,7 +3138,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) m_nIp++; int32 counter = CTheScripts::Read2BytesFromScript(&m_nIp); CollectParameters(&m_nIp, 1); - CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil); + CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil, 0); return 0; } case COMMAND_CLEAR_ONSCREEN_COUNTER: @@ -3166,9 +3174,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) } return 0; } - /* Not implemented. - case COMMAND_IS_CHAR_IN_GANG_ZONE: - */ + //case COMMAND_IS_CHAR_IN_GANG_ZONE: case COMMAND_IS_CHAR_IN_ZONE: { CollectParameters(&m_nIp, 1); @@ -3183,10 +3189,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetNavigationZone(zone))); return 0; } - /* Not implemented. - case COMMAND_SET_CAR_DENSITY: - case COMMAND_SET_PED_DENSITY: - */ + //case COMMAND_SET_CAR_DENSITY: + //case COMMAND_SET_PED_DENSITY: case COMMAND_POINT_CAMERA_AT_PLAYER: { CollectParameters(&m_nIp, 3); @@ -3198,24 +3202,26 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) { CollectParameters(&m_nIp, 3); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - assert(pVehicle); - TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); + if (pVehicle) + TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); return 0; } case COMMAND_POINT_CAMERA_AT_CHAR: { CollectParameters(&m_nIp, 3); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); - assert(pPed); - TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); + if (pPed) + TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT); return 0; } case COMMAND_RESTORE_CAMERA: TheCamera.Restore(); return 0; + /* case COMMAND_SHAKE_PAD: CPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]); return 0; + */ case COMMAND_SET_ZONE_PED_INFO: { char label[12]; @@ -3238,6 +3244,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 1); CTimer::SetTimeScale(*(float*)&ScriptParams[0]); return 0; + /* case COMMAND_IS_CAR_IN_AIR: { CollectParameters(&m_nIp, 1); @@ -3247,6 +3254,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) UpdateCompareFlag(pCar->GetAllWheelsOffGround()); return 0; } + */ case COMMAND_SET_FIXED_CAMERA_POSITION: { CollectParameters(&m_nIp, 6); @@ -3269,7 +3277,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 3); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - // Useless call. CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); StoreParameters(&m_nIp, 1); @@ -3280,23 +3287,23 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 3); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - // Useless call. CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_ADD_BLIP_FOR_OBJECT_OLD: { CollectParameters(&m_nIp, 3); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); assert(pObject); - // Useless call. CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]); StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_REMOVE_BLIP: CollectParameters(&m_nIp, 1); CRadar::ClearBlip(ScriptParams[0]); @@ -3315,7 +3322,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CVector pos = *(CVector*)&ScriptParams[0]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - // Useless call CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); ScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]); StoreParameters(&m_nIp, 1); @@ -3366,6 +3372,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CRestart::OverrideNextRestart(pos, angle); return 0; } + /* case COMMAND_DRAW_SHADOW: { CollectParameters(&m_nIp, 10); @@ -3384,11 +3391,11 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float frontY = y; float sideX = y; float sideY = x; - /* Not very nicely named intermediate variables. */ CShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY, ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]); return 0; } + */ case COMMAND_GET_PLAYER_HEADING: { CollectParameters(&m_nIp, 1); @@ -3402,10 +3409,9 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) { CollectParameters(&m_nIp, 2); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; - if (pPed->bInVehicle){ - // Is assertion required? + assert(pPed); + if (pPed->bInVehicle) return 0; - } pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]); pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); return 0; @@ -3425,10 +3431,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 2); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - if (pPed->bInVehicle) { - // Is assertion required? + if (pPed->bInVehicle) return 0; - } pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]); pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1])); return 0; @@ -3473,6 +3477,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CWorld::Add(pObject); return 0; } + /* case COMMAND_IS_PLAYER_TOUCHING_OBJECT: { CollectParameters(&m_nIp, 2); @@ -3494,12 +3499,14 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject)); return 0; } + */ case COMMAND_SET_PLAYER_AMMO: { CollectParameters(&m_nIp, 3); CWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); return 0; } + /* case COMMAND_SET_CHAR_AMMO: { CollectParameters(&m_nIp, 3); @@ -3507,16 +3514,16 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]); return 0; } - /* Not implemented. - case COMMAND_SET_CAR_AMMO: - case COMMAND_LOAD_CAMERA_SPLINE: - case COMMAND_MOVE_CAMERA_ALONG_SPLINE: - case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE: */ + //case COMMAND_SET_CAR_AMMO: + //case COMMAND_LOAD_CAMERA_SPLINE: + //case COMMAND_MOVE_CAMERA_ALONG_SPLINE: + //case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE: case COMMAND_DECLARE_MISSION_FLAG: CTheScripts::OnAMissionFlag = CTheScripts::Read2BytesFromScript(&++m_nIp); return 0; - //case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: + case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: + return 0; //case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT: case COMMAND_IS_PLAYER_HEALTH_GREATER: { @@ -3546,7 +3553,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - // Useless call. CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); int handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH); CRadar::ChangeBlipScale(handle, 3); @@ -3559,7 +3565,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - // Useless call. CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); int handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH); CRadar::ChangeBlipScale(handle, 3); @@ -3572,7 +3577,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CollectParameters(&m_nIp, 1); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); assert(pObject); - // Useless call. CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); int handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH); CRadar::ChangeBlipScale(handle, 3); @@ -3586,7 +3590,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CVector pos = *(CVector*)&ScriptParams[0]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - // Useless call CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 2, BLIP_DISPLAY_BOTH); CRadar::ChangeBlipScale(handle, 3); @@ -3600,7 +3603,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) CVector pos = *(CVector*)&ScriptParams[0]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - // Useless call CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp)); int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH); CRadar::ChangeBlipScale(handle, 3); @@ -3615,6 +3617,15 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) case COMMAND_ADD_ONE_OFF_SOUND: { CollectParameters(&m_nIp, 4); + // TODO(MIAMI) + // SOUND_PART_MISSION_COMPLETE == 1 + // SOUND_RACE_START_3 == 7 + // SOUND_RACE_START_2 == 8 + // SOUND_RACE_START_1 == 9 + // SOUND_RACE_START_GO == 10 + // SOUND_AMMUNATION_BUY_WEAPON == 13 + // SOUND_AMMUNATION_BUY_WEAPON_DENIED == 14 + // SOUND_AMMUNATION_IMRAN_ARM_BOMB == 16 switch (ScriptParams[3]) { case SCRIPT_SOUND_EVIDENCE_PICKUP: DMAudio.PlayFrontEndSound(SOUND_EVIDENCE_PICKUP, 0); @@ -3640,11 +3651,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) default: break; } -#ifdef FIX_BUGS - /* BUG: if audio is not initialized, this object will not be freed. */ if (!DMAudio.IsAudioInitialised()) return 0; -#endif cAudioScriptObject* obj = new cAudioScriptObject(); obj->Posn = *(CVector*)&ScriptParams[0]; obj->AudioId = ScriptParams[3]; @@ -3655,11 +3663,15 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) case COMMAND_ADD_CONTINUOUS_SOUND: { CollectParameters(&m_nIp, 4); - cAudioScriptObject* obj = new cAudioScriptObject(); - obj->Posn = *(CVector*)&ScriptParams[0]; - obj->AudioId = ScriptParams[3]; - obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj); - ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj); + if (DMAudio.IsAudioInitialised()) { + cAudioScriptObject* obj = new cAudioScriptObject(); + obj->Posn = *(CVector*)&ScriptParams[0]; + obj->AudioId = ScriptParams[3]; + obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj); + ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj); + } + else + ScriptParams[0] = -1; StoreParameters(&m_nIp, 1); return 0; } @@ -3738,6 +3750,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos); return 0; } + /* case COMMAND_SET_CHAR_OBJ_GUARD_AREA: { CollectParameters(&m_nIp, 5); @@ -3773,6 +3786,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_WAIT_IN_CAR); return 0; } + */ case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D: case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D: case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D: @@ -3821,11 +3835,10 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); pPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2])); - if (pPed->bInVehicle) + if (pPed->bInVehicle && pPed->m_pMyVehicle) pPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId); return 0; } - /* Not implemented */ //case COMMAND_GIVE_WEAPON_TO_CAR: case COMMAND_SET_PLAYER_CONTROL: { @@ -3833,14 +3846,10 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; if (ScriptParams[1]){ pPlayer->MakePlayerSafe(false); - // TODO(MIAMI): Four Iron hack + if (strcmp(m_abScriptName, "serg1") == 0) // Four Iron + pPlayer->m_pPed->ClearFollowPath(); }else{ pPlayer->MakePlayerSafe(true); - if (strcmp(m_abScriptName, "camera") == 0){ - pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); - pPlayer->m_pPed->SetTurnSpeed(0.0f, 0.0f, 0.0f); - CAnimManager::BlendAnimation((RpClump*)pPlayer->m_pPed->m_rwObject, pPlayer->m_pPed->m_animGroup, ANIM_IDLE_STANCE, 1000.0f); - } } return 0; } @@ -3875,7 +3884,6 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) } return 0; } - /* Not implemented */ //case COMMAND_SET_CURRENT_CAR_WEAPON: case COMMAND_GET_OBJECT_COORDINATES: { @@ -4065,9 +4073,11 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->CharCreatedBy = MISSION_CHAR; pPed->bRespondsToThreats = false; pPed->bAllowMedicsToReviveMe = false; + pPed->bIsPlayerFriend = false; + if (pVehicle->bIsBus) + pPed->bRenderPedInCar = false; pPed->SetPosition(pVehicle->GetPosition()); pPed->SetOrientation(0.0f, 0.0f, 0.0f); - pPed->SetPedState(PED_DRIVING); CPopulation::ms_nTotalMissionPeds++; if (ScriptParams[3] >= 0) pVehicle->AddPassenger(pPed, ScriptParams[3]); @@ -4076,8 +4086,8 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->m_pMyVehicle = pVehicle; pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); pPed->bInVehicle = true; - pPed->SetPedState(PED_DRIVING); pVehicle->SetStatus(STATUS_PHYSICS); + pPed->SetPedState(PED_DRIVING); pPed->bUsesCollision = false; pPed->AddInCarAnims(pVehicle, false); pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); @@ -4128,6 +4138,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget); return 0; } + /* case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE: { CollectParameters(&m_nIp, 2); @@ -4138,6 +4149,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget); return 0; } + */ case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE: { CollectParameters(&m_nIp, 2); @@ -4218,11 +4230,18 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle); return 0; } - /* Not implemented. - case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR: - case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE: + //case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR: + //case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE: case COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT: - */ + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_DESTROY_OBJ, pVehicle); + return 0; + } case COMMAND_SET_CHAR_OBJ_DESTROY_CAR: { CollectParameters(&m_nIp, 2); @@ -4233,6 +4252,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle); return 0; } + /* case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT: { CollectParameters(&m_nIp, 5); @@ -4259,11 +4279,10 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius); return 0; } - /* Not implemented. - case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR: - case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: - case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK: */ + //case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR: + //case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: + //case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK: case COMMAND_SET_CHAR_AS_LEADER: { CollectParameters(&m_nIp, 2); @@ -4326,9 +4345,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1); return 0; } - /* Not implemented. - case COMMAND_PRINT_WITH_NUMBER_SOON: - */ + //case COMMAND_PRINT_WITH_NUMBER_SOON: case COMMAND_SWITCH_ROADS_ON: { CollectParameters(&m_nIp, 6); @@ -4406,7 +4423,16 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - pVehicle->bIsHeavy = (ScriptParams[1] != 0); + if (ScriptParams[1] != 0) { + pVehicle->bIsHeavy = true; + pVehicle->m_fMass = 3.0f * pVehicle->pHandling->fMass; + pVehicle->m_fTurnMass = 5.0f * pVehicle->pHandling->fTurnMass; + } + else { + pVehicle->bIsHeavy = false; + pVehicle->m_fMass = pVehicle->pHandling->fMass; + pVehicle->m_fTurnMass = pVehicle->pHandling->fTurnMass; + } return 0; } case COMMAND_CLEAR_CHAR_THREAT_SEARCH: @@ -4417,6 +4443,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->m_fearFlags = 0; return 0; } + /* case COMMAND_ACTIVATE_CRANE: { CollectParameters(&m_nIp, 10); @@ -4444,16 +4471,15 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); return 0; } + */ case COMMAND_SET_MAX_WANTED_LEVEL: { CollectParameters(&m_nIp, 1); CWanted::SetMaximumWantedLevel(ScriptParams[0]); return 0; } - /* Debug commands? - case COMMAND_SAVE_VAR_INT: - case COMMAND_SAVE_VAR_FLOAT: - */ + //case COMMAND_SAVE_VAR_INT: + //case COMMAND_SAVE_VAR_FLOAT: case COMMAND_IS_CAR_IN_AIR_PROPER: { CollectParameters(&m_nIp, 1); @@ -4505,6 +4531,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) } return 0; } + /* case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -4513,6 +4540,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) ScriptParams[1], ScriptParams[2], ScriptParams[3]); return 0; } + */ case COMMAND_START_KILL_FRENZY: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -4657,7 +4685,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target); return 0; } - /* Not implemented*/ //case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR: case COMMAND_CREATE_PICKUP: { @@ -4697,6 +4724,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1); return 0; } + /* case COMMAND_PRINT_WITH_NUMBER_BIG_Q: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -4705,6 +4733,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) ScriptParams[0], -1, -1, -1, -1, -1); return 0; } + */ case COMMAND_SET_GARAGE: { CollectParameters(&m_nIp, 9); @@ -4720,6 +4749,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_SET_GARAGE_WITH_CAR_MODEL: { CollectParameters(&m_nIp, 10); @@ -4735,6 +4765,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE: { CollectParameters(&m_nIp, 2); @@ -4792,6 +4823,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) return 0; } #endif // GTA_PS2 + /* case COMMAND_SET_ALL_TAXI_LIGHTS: CollectParameters(&m_nIp, 1); CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0); @@ -4805,6 +4837,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) UpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum return 0; } + */ case COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR: CollectParameters(&m_nIp, 2); CPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0); @@ -4848,7 +4881,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - ScriptParams[0] = pPed->m_fHealth; // correct cast float to int + ScriptParams[0] = pPed->m_fHealth; StoreParameters(&m_nIp, 1); return 0; } @@ -4857,7 +4890,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - ScriptParams[0] = pPed->m_fHealth; // correct cast float to int + ScriptParams[0] = pPed->m_fHealth; StoreParameters(&m_nIp, 1); return 0; } @@ -4866,19 +4899,21 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - ScriptParams[0] = pVehicle->m_fHealth; // correct cast float to int + ScriptParams[0] = pVehicle->m_fHealth; StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_IS_CAR_ARMED_WITH_BOMB: { CollectParameters(&m_nIp, 2); CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pCar); assert(pCar->m_vehType == VEHICLE_TYPE_CAR); - UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); //TODO: enum + UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); return 0; } + */ case COMMAND_CHANGE_CAR_COLOUR: { CollectParameters(&m_nIp, 3); @@ -4992,14 +5027,15 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pSourcePed->RestorePreviousState(); return 0; } + /* case COMMAND_SWITCH_HELICOPTER: CollectParameters(&m_nIp, 1); CHeli::ActivateHeli(ScriptParams[0] != 0); return 0; - - //case COMMAND_SET_GANG_ATTITUDE: - //case COMMAND_SET_GANG_GANG_ATTITUDE: - //case COMMAND_SET_GANG_PLAYER_ATTITUDE: + */ + //case COMMAND_SET_GANG_ATTITUDE: + //case COMMAND_SET_GANG_GANG_ATTITUDE: + //case COMMAND_SET_GANG_PLAYER_ATTITUDE: case COMMAND_SET_GANG_PED_MODELS: CollectParameters(&m_nIp, 3); CGangs::SetGangPedModels(ScriptParams[0], ScriptParams[1], ScriptParams[2]); @@ -5012,6 +5048,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CollectParameters(&m_nIp, 3); CGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]); return 0; + /* case COMMAND_SET_CHAR_OBJ_RUN_TO_AREA: { CollectParameters(&m_nIp, 5); @@ -5038,6 +5075,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius); return 0; } + */ case COMMAND_SET_CHAR_OBJ_RUN_TO_COORD: { CollectParameters(&m_nIp, 3); @@ -5051,6 +5089,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos); return 0; } + /* case COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT: { CollectParameters(&m_nIp, 2); @@ -5079,6 +5118,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) UpdateCompareFlag(isTouching); return 0; } + */ case COMMAND_LOAD_SPECIAL_CHARACTER: { CollectParameters(&m_nIp, 1); @@ -5096,6 +5136,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) UpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1)); return 0; } + /* case COMMAND_FLASH_CAR: { CollectParameters(&m_nIp, 2); @@ -5120,10 +5161,12 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pObject->bHasBlip = (ScriptParams[1] != 0); return 0; } + */ case COMMAND_IS_PLAYER_IN_REMOTE_MODE: CollectParameters(&m_nIp, 1); UpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode()); return 0; + /* case COMMAND_ARM_CAR_WITH_BOMB: { CollectParameters(&m_nIp, 2); @@ -5134,6 +5177,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) ((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed(); return 0; } + */ case COMMAND_SET_CHAR_PERSONALITY: { CollectParameters(&m_nIp, 2); @@ -5154,6 +5198,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pPed->m_animGroup = (AssocGroupId)ScriptParams[1]; return 0; } + /* case COMMAND_SET_ANIM_GROUP_FOR_PLAYER: { CollectParameters(&m_nIp, 2); @@ -5162,6 +5207,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pPed->m_animGroup = (AssocGroupId)ScriptParams[1]; return 0; } + */ case COMMAND_REQUEST_MODEL: { CollectParameters(&m_nIp, 1); @@ -5196,6 +5242,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_SET_REPEATED_PHONE_MESSAGE: { CollectParameters(&m_nIp, 1); @@ -5216,6 +5263,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0])); return 0; } + */ case COMMAND_TURN_PHONE_OFF: { CollectParameters(&m_nIp, 1); @@ -5229,7 +5277,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], - 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f); + 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f); // TODO(MIAMI): more params return 0; } case COMMAND_DRAW_LIGHT: @@ -5249,6 +5297,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) case COMMAND_RESTORE_CLOCK: CClock::RestoreClock(); return 0; + /* case COMMAND_RESTART_CRITICAL_MISSION: { CollectParameters(&m_nIp, 4); @@ -5261,6 +5310,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission(); return 0; } + */ case COMMAND_IS_PLAYER_PLAYING: { CollectParameters(&m_nIp, 1); @@ -5369,6 +5419,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0); return 0; } + /* case COMMAND_IS_TAXI: { CollectParameters(&m_nIp, 1); @@ -5377,6 +5428,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) UpdateCompareFlag(pVehicle->IsTaxi()); return 0; } + */ case COMMAND_UNLOAD_SPECIAL_CHARACTER: CollectParameters(&m_nIp, 1); CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1); @@ -5389,6 +5441,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]); StoreParameters(&m_nIp, 1); return 0; + /* case COMMAND_ACTIVATE_GARAGE: CollectParameters(&m_nIp, 1); CGarages::ActivateGarage(ScriptParams[0]); @@ -5404,6 +5457,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) } return 0; } + */ case COMMAND_CREATE_OBJECT_NO_OFFSET: { CollectParameters(&m_nIp, 4); @@ -5417,6 +5471,9 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) pObj->SetOrientation(0.0f, 0.0f, 0.0f); pObj->GetMatrix().UpdateRW(); pObj->UpdateRwFrame(); + CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi); + if (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding) + pObj->SetupBigBuilding(); CTheScripts::ClearSpaceForMissionEntity(pos, pObj); CWorld::Add(pObj); ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj); @@ -5425,6 +5482,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT); return 0; } + /* case COMMAND_IS_BOAT: { CollectParameters(&m_nIp, 1); @@ -5459,6 +5517,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius); return 0; } + */ //case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS: case COMMAND_IS_PLAYER_STOPPED: { @@ -5466,7 +5525,9 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer)); return 0; + } + /* case COMMAND_IS_CHAR_STOPPED: { CollectParameters(&m_nIp, 1); @@ -5489,6 +5550,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0); return 0; } + */ case COMMAND_SWITCH_WIDESCREEN: CollectParameters(&m_nIp, 1); if (ScriptParams[0] != 0) @@ -5496,6 +5558,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) else TheCamera.SetWideScreenOff(); return 0; + /* case COMMAND_ADD_SPRITE_BLIP_FOR_CAR: { CollectParameters(&m_nIp, 2); @@ -5532,6 +5595,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT: { CollectParameters(&m_nIp, 4); @@ -5612,6 +5676,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D: PlayerInAngledAreaCheckCommand(command, &m_nIp); return 0; + /* case COMMAND_DEACTIVATE_GARAGE: CollectParameters(&m_nIp, 1); CGarages::DeActivateGarage(ScriptParams[0]); @@ -5625,6 +5690,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) CollectParameters(&m_nIp, 2); UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1)); return 0; + */ default: assert(0); } @@ -5634,6 +5700,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) int8 CRunningScript::ProcessCommands700To799(int32 command) { switch (command){ + /* case COMMAND_SET_SWAT_REQUIRED: CollectParameters(&m_nIp, 1); FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0); @@ -5646,6 +5713,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CollectParameters(&m_nIp, 1); FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0); return 0; + */ case COMMAND_IS_CAR_IN_WATER: { CollectParameters(&m_nIp, 1); @@ -5690,10 +5758,11 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE; pVehicle->SetStatus(STATUS_PHYSICS); pVehicle->bEngineOn = true; - pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); + pVehicle->AutoPilot.m_nCruiseSpeed = Max(1, pVehicle->AutoPilot.m_nCruiseSpeed); pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; } + /* case COMMAND_START_PACMAN_RACE: CollectParameters(&m_nIp, 1); CPacManPickups::StartPacManRace(ScriptParams[0]); @@ -5724,6 +5793,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED: CPacManPickups::ResetPowerPillsCarriedByPlayer(); return 0; + */ case COMMAND_IS_CAR_ON_SCREEN: { CollectParameters(&m_nIp, 1); @@ -5748,6 +5818,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius())); return 0; } + /* case COMMAND_GOSUB_FILE: { CollectParameters(&m_nIp, 2); @@ -5757,6 +5828,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) // ScriptParams[1] == filename return 0; } + */ case COMMAND_GET_GROUND_Z_FOR_3D_COORD: { CollectParameters(&m_nIp, 3); @@ -5784,6 +5856,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CollectParameters(&m_nIp, 1); gFireManager.RemoveScriptFire(ScriptParams[0]); return 0; + /* case COMMAND_SET_COMEDY_CONTROLS: { CollectParameters(&m_nIp, 2); @@ -5792,6 +5865,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pVehicle->bComedyControls = (ScriptParams[1] != 0); return 0; } + */ case COMMAND_BOAT_GOTO_COORDS: { CollectParameters(&m_nIp, 4); @@ -5805,7 +5879,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS; pBoat->AutoPilot.m_vecDestinationCoors = pos; pBoat->SetStatus(STATUS_PHYSICS); - pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed); + pBoat->AutoPilot.m_nCruiseSpeed = Max(1, pBoat->AutoPilot.m_nCruiseSpeed); pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; } @@ -5861,7 +5935,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CollectParameters(&m_nIp, 2); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType); + UpdateCompareFlag(ScriptParams[1] == pPed->GetWeapon()->m_eWeaponType); return 0; } case COMMAND_IS_CURRENT_CHAR_WEAPON: @@ -5869,9 +5943,10 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CollectParameters(&m_nIp, 2); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType); + UpdateCompareFlag(ScriptParams[1] == pPed->GetWeapon()->m_eWeaponType); return 0; } + /* case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN: CPacManPickups::ResetPowerPillsEatenInRace(); return 0; @@ -5884,6 +5959,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CPacManPickups::GenerateOnePMPickUp(pos); return 0; } + */ case COMMAND_SET_BOAT_CRUISE_SPEED: { CollectParameters(&m_nIp, 2); @@ -5894,6 +5970,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1]; return 0; } + /* case COMMAND_GET_RANDOM_CHAR_IN_AREA: { CollectParameters(&m_nIp, 4); @@ -5942,6 +6019,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_GET_RANDOM_CHAR_IN_ZONE: { char zone[KEY_LENGTH_IN_SCRIPT]; @@ -5950,6 +6028,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) if (nZone != -1) m_nIp += KEY_LENGTH_IN_SCRIPT; CZone* pZone = CTheZones::GetNavigationZone(nZone); + CollectParameters(&m_nIp, 3); int ped_handle = -1; CVector pos = FindPlayerCoors(); int i = CPools::GetPedPool()->GetSize(); @@ -5967,9 +6046,9 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) continue; if (pPed->bFadeOut) continue; -// if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN) -// continue; - if (!ThisIsAValidRandomPed(pPed->m_nPedType)) + if (pPed->m_nWaitState != WAITSTATE_FALSE) + continue; + if (!ThisIsAValidRandomPed(pPed->m_nPedType, ScriptParams[0], ScriptParams[1], ScriptParams[2])) continue; if (pPed->bIsLeader || pPed->m_leader) continue; @@ -5979,6 +6058,10 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) continue; if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) continue; + bool found; + CWorld::FindRoofZFor3DCoord(pos.x, pos.y, pos.z, &found); + if (found) + continue; ped_handle = CPools::GetPedPool()->GetIndex(pPed); CTheScripts::LastRandomPedId = ped_handle; pPed->CharCreatedBy = MISSION_CHAR; @@ -6099,6 +6182,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CollectParameters(&m_nIp, 1); CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0]; return 0; + /* case COMMAND_IS_PROJECTILE_IN_AREA: { CollectParameters(&m_nIp, 6); @@ -6169,6 +6253,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0); return 0; } + */ case COMMAND_IS_CHAR_MODEL: { CollectParameters(&m_nIp, 2); @@ -6188,16 +6273,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) m_nIp += KEY_LENGTH_IN_SCRIPT; return 0; } - case COMMAND_CREATE_CUTSCENE_HEAD: - { - assert(0); - return 0; - } - case COMMAND_SET_CUTSCENE_HEAD_ANIM: - { - assert(0); - return 0; - } + //case COMMAND_CREATE_CUTSCENE_HEAD: + //case COMMAND_SET_CUTSCENE_HEAD_ANIM: case COMMAND_SIN: CollectParameters(&m_nIp, 1); *(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0])); @@ -6230,6 +6307,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CollectParameters(&m_nIp, 2); CGarages::ChangeGarageType(ScriptParams[0], (eGarageType)ScriptParams[1], 0); return 0; + /* case COMMAND_ACTIVATE_CRUSHER_CRANE: { CollectParameters(&m_nIp, 10); @@ -6258,6 +6336,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); return 0; } + */ case COMMAND_PRINT_WITH_2_NUMBERS_NOW: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6265,6 +6344,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); return 0; } + /* case COMMAND_PRINT_WITH_2_NUMBERS_SOON: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6272,6 +6352,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); return 0; } + */ case COMMAND_PRINT_WITH_3_NUMBERS: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6279,6 +6360,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); return 0; } + /* case COMMAND_PRINT_WITH_3_NUMBERS_NOW: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6293,6 +6375,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1); return 0; } + */ case COMMAND_PRINT_WITH_4_NUMBERS: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6300,6 +6383,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1); return 0; } + /* case COMMAND_PRINT_WITH_4_NUMBERS_NOW: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6335,6 +6419,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1); return 0; } + */ case COMMAND_PRINT_WITH_6_NUMBERS: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6342,6 +6427,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); return 0; } + /* case COMMAND_PRINT_WITH_6_NUMBERS_NOW: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -6367,6 +6453,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pPed->SetFormation((eFormation)ScriptParams[2]); return 0; } + */ case COMMAND_PLAYER_MADE_PROGRESS: CollectParameters(&m_nIp, 1); CStats::ProgressMade += ScriptParams[0]; @@ -6374,6 +6461,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) case COMMAND_SET_PROGRESS_TOTAL: CollectParameters(&m_nIp, 1); CStats::TotalProgressInGame = ScriptParams[0]; + if (CGame::germanGame) + CStats::TotalProgressInGame -= 2; return 0; case COMMAND_REGISTER_JUMP_DISTANCE: CollectParameters(&m_nIp, 1); @@ -6420,6 +6509,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) strncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT); ++CStats::MissionsPassed; CStats::CheckPointReachedSuccessfully(); + CTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds(); + //CGameLogic::RemoveShortCutDropOffPointForMission() // TODO(MIAMI) return 0; } case COMMAND_SET_CHAR_RUNNING: @@ -6433,6 +6524,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) case COMMAND_REMOVE_ALL_SCRIPT_FIRES: gFireManager.RemoveAllScriptFires(); return 0; + /* case COMMAND_IS_FIRST_CAR_COLOUR: { CollectParameters(&m_nIp, 2); @@ -6449,22 +6541,37 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]); return 0; } + */ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON: { CollectParameters(&m_nIp, 2); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + bool result = false; if (!pPed) printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n"); - UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]); + else { + if (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON) + result = CheckDamagedWeaponType(ScriptParams[1], pPed->m_lastWepDam); + else + result = ScriptParams[1] == pPed->m_lastWepDam; + } + UpdateCompareFlag(result); return 0; } case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON: { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + bool result = false; if (!pVehicle) printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n"); - UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]); + else { + if (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON) + result = CheckDamagedWeaponType(ScriptParams[1], pVehicle->m_nLastWeaponDamage); + else + result = ScriptParams[1] == pVehicle->m_nLastWeaponDamage; + } + UpdateCompareFlag(result); return 0; } case COMMAND_IS_CHAR_IN_CHARS_GROUP: @@ -6501,17 +6608,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - if (pPed->m_nPedState == PED_DRIVING) { - pPed->SetDead(); - if (!pPed->IsPlayer()) - pPed->FlagToDestroyWhenNextProcessed(); - } - else if (CGame::nastyGame && pPed->IsPedInControl()) { - pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); - } - else { - pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } + pPed->InflictDamage(nil, WEAPONTYPE_SNIPERRIFLE, 1000.0f, PEDPIECE_HEAD, 0); return 0; } case COMMAND_EXPLODE_PLAYER_HEAD: @@ -6519,12 +6616,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - if (CGame::nastyGame) { - pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); - } - else { - pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } + pPed->InflictDamage(nil, WEAPONTYPE_SNIPERRIFLE, 1000.0f, PEDPIECE_HEAD, 0); return 0; } case COMMAND_ANCHOR_BOAT: @@ -6580,6 +6672,10 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); if (!pVehicle) continue; + if (pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR && pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE) + continue; + if (!pVehicle->bUsesCollision) + continue; if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0) continue; if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) @@ -6597,11 +6693,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE: { char zone[KEY_LENGTH_IN_SCRIPT]; CTheScripts::ReadTextLabelFromScript(&m_nIp, zone); -// TODO(MIAMI): just getting this to compile with new argument int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT); if (zone_id != -1) m_nIp += KEY_LENGTH_IN_SCRIPT; @@ -6630,6 +6726,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_HAS_RESPRAY_HAPPENED: { CollectParameters(&m_nIp, 1); @@ -6669,6 +6766,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CCarAI::TellCarToRamOtherCar(pVehicle, pTarget); return 0; } + /* case COMMAND_SET_CAR_BLOCK_CAR: { CollectParameters(&m_nIp, 2); @@ -6688,6 +6786,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->SetObjective(OBJECTIVE_CATCH_TRAIN); return 0; } + */ //case COMMAND_SET_COLL_OBJ_CATCH_TRAIN: case COMMAND_SET_PLAYER_NEVER_GETS_TIRED: { @@ -6711,6 +6810,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->bPedIsBleeding = (ScriptParams[1] != 0); return 0; } + /* case COMMAND_SET_CAR_FUNNY_SUSPENSION: { CollectParameters(&m_nIp, 2); @@ -6729,6 +6829,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pCar->bBigWheels = (ScriptParams[1] != 0); return 0; } + */ case COMMAND_SET_FREE_RESPRAYS: CollectParameters(&m_nIp, 1); CGarages::SetFreeResprays(ScriptParams[0] != 0); @@ -8111,10 +8212,11 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) { assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); int16 var = CTheScripts::Read2BytesFromScript(&m_nIp); + CollectParameters(&m_nIp, 1); wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); m_nIp += KEY_LENGTH_IN_SCRIPT; - CUserDisplay::OnscnTimer.AddClock(var, onscreen_str); + CUserDisplay::OnscnTimer.AddClock(var, onscreen_str, ScriptParams[0] != 0); return 0; } case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING: @@ -8125,7 +8227,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); m_nIp += KEY_LENGTH_IN_SCRIPT; - CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str); + CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str, 0); return 0; } case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK: @@ -9545,9 +9647,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) continue; if (!pPed->IsWithinArea(x1, y1, x2, y2)) continue; - if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + if (pos.z - COP_PED_FIND_Z_OFFSET > pPed->GetPosition().z) continue; - if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + if (pos.z + COP_PED_FIND_Z_OFFSET < pPed->GetPosition().z) continue; ped_handle = CPools::GetPedPool()->GetIndex(pPed); CTheScripts::LastRandomPedId = ped_handle; @@ -9593,9 +9695,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) continue; if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) continue; - if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + if (pos.z - COP_PED_FIND_Z_OFFSET > pPed->GetPosition().z) continue; - if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + if (pos.z + COP_PED_FIND_Z_OFFSET < pPed->GetPosition().z) continue; ped_handle = CPools::GetPedPool()->GetIndex(pPed); CTheScripts::LastRandomPedId = ped_handle; @@ -10753,6 +10855,36 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return -1; } +bool CRunningScript::CheckDamagedWeaponType(int32 type, int32 actual) +{ + if (type == -1) + return false; + if (type == WEAPONTYPE_ANYMELEE) { + switch (actual) { + case WEAPONTYPE_UNARMED: + case WEAPONTYPE_BRASSKNUCKLE: + case WEAPONTYPE_SCREWDRIVER: + case WEAPONTYPE_GOLFCLUB: + case WEAPONTYPE_NIGHTSTICK: + case WEAPONTYPE_KNIFE: + case WEAPONTYPE_BASEBALLBAT: + case WEAPONTYPE_HAMMER: + case WEAPONTYPE_CLEAVER: + case WEAPONTYPE_MACHETE: + case WEAPONTYPE_KATANA: + case WEAPONTYPE_CHAINSAW: + return true; + default: + return false; + } + } + if (type == WEAPONTYPE_ANYWEAPON) { + // TODO(MIAMI)! + return true; + } + return false; +} + bool CRunningScript::ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami) { switch (mi) diff --git a/src/control/Script.h b/src/control/Script.h index 3393467e..4f9f6b74 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -485,10 +485,11 @@ private: float LimitAngleOnCircle(float angle) { return angle < 0.0f ? angle + 360.0f : angle; } - bool ThisIsAValidRandomPed(uint32 pedtype) { + bool ThisIsAValidRandomPed(uint32 pedtype, int civ, int gang, int criminal) { switch (pedtype) { case PEDTYPE_CIVMALE: case PEDTYPE_CIVFEMALE: + return civ; case PEDTYPE_GANG1: case PEDTYPE_GANG2: case PEDTYPE_GANG3: @@ -498,13 +499,16 @@ private: case PEDTYPE_GANG7: case PEDTYPE_GANG8: case PEDTYPE_GANG9: + return gang; case PEDTYPE_CRIMINAL: case PEDTYPE_PROSTITUTE: - return true; + return criminal; default: return false; } } + + bool CheckDamagedWeaponType(int32 type, int32 actual); static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami); }; diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h index 6516828a..4b8be40f 100644 --- a/src/weapons/WeaponType.h +++ b/src/weapons/WeaponType.h @@ -44,6 +44,8 @@ enum eWeaponType WEAPONTYPE_UNIDENTIFIED, WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE, + WEAPONTYPE_ANYMELEE = 46, + WEAPONTYPE_ANYWEAPON = 47 }; enum { From c0c8278c635258fc72636db0bbf59d7c99c4ba61 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 20 May 2020 20:45:07 +0300 Subject: [PATCH 073/148] fixed ped comment --- src/audio/sampman_miles.cpp | 4 ++++ src/audio/sampman_oal.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index a2a206a4..ad2c512f 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -1469,6 +1469,10 @@ cSampleManager::_GetPedCommentSlot(uint32 nComment) for ( int32 i = 0; i < _TODOCONST(3); i++ ) { slot = nCurrentPedSlot - i - 1; +#ifdef FIX_BUGS + if (slot < 0) + slot += ARRAY_SIZE(nPedSlotSfx); +#endif if ( nComment == nPedSlotSfx[slot] ) return slot; } diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 30efd7f5..f16afbba 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -800,6 +800,10 @@ cSampleManager::_GetPedCommentSlot(uint32 nComment) for (int32 i = 0; i < _TODOCONST(3); i++) { slot = nCurrentPedSlot - i - 1; +#ifdef FIX_BUGS + if (slot < 0) + slot += ARRAY_SIZE(nPedSlotSfx); +#endif if (nComment == nPedSlotSfx[slot]) return slot; } From 5b953228b416ac894026fe9509a39a4e3b8850b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 20 May 2020 21:22:40 +0300 Subject: [PATCH 074/148] Pickup and audio fix --- src/audio/AudioLogic.cpp | 4 ++-- src/audio/sampman_miles.cpp | 4 ++++ src/audio/sampman_oal.cpp | 4 ++++ src/control/Pickups.cpp | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 9080a2dd..cc157389 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -3849,9 +3849,9 @@ cAudioManager::GetPedCommentSfx(CPed *ped, int32 sound) //if (ped->IsPlayer()) // return GetPlayerTalkSfx(sound); - // TODO: miami peds + // TODO(Miami): ped comments - return TOTAL_AUDIO_SAMPLES; + return NO_SAMPLE; } void diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index a2a206a4..ad2c512f 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -1469,6 +1469,10 @@ cSampleManager::_GetPedCommentSlot(uint32 nComment) for ( int32 i = 0; i < _TODOCONST(3); i++ ) { slot = nCurrentPedSlot - i - 1; +#ifdef FIX_BUGS + if (slot < 0) + slot += ARRAY_SIZE(nPedSlotSfx); +#endif if ( nComment == nPedSlotSfx[slot] ) return slot; } diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 30efd7f5..f16afbba 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -800,6 +800,10 @@ cSampleManager::_GetPedCommentSlot(uint32 nComment) for (int32 i = 0; i < _TODOCONST(3); i++) { slot = nCurrentPedSlot - i - 1; +#ifdef FIX_BUGS + if (slot < 0) + slot += ARRAY_SIZE(nPedSlotSfx); +#endif if (nComment == nPedSlotSfx[slot]) return slot; } diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 9492e0e1..4e4c02ab 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -136,6 +136,7 @@ CPickup::GiveUsAPickUpObject(int32 handle) object->bExplosionProof = true; object->bUsesCollision = false; object->bIsPickup = true; + object->bHasPreRenderEffects = true; object->m_nBonusValue = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0; From b7c1784dd274b88955763c5a3fa2acb4d202e934 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 20 May 2020 23:25:01 +0300 Subject: [PATCH 075/148] script fix --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index e8aa3266..8ade2c9b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8222,7 +8222,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3])); CTheScripts::ClearSpaceForMissionEntity(pos, car); car->SetStatus(STATUS_ABANDONED); - car->bIsLocked = true; + car->bIsLocked = false; car->bIsCarParkVehicle = true; CCarCtrl::JoinCarWithRoadSystem(car); car->AutoPilot.m_nCarMission = MISSION_NONE; From 0085ed894fe5fb5241c978c891ba4eadf4c02809 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 20 May 2020 23:47:44 +0300 Subject: [PATCH 076/148] script revision --- src/control/CarCtrl.cpp | 4 +- src/control/Script.cpp | 257 ++++++++++++++++++++++++++++++++-------- src/core/Stats.cpp | 2 + src/core/Stats.h | 1 + 4 files changed, 211 insertions(+), 53 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 920fba81..b250cb97 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -2995,7 +2995,9 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) CPathNode* pNode = &ThePaths.m_pathNodes[node]; if (node == pVehicle->AutoPilot.m_nNextRouteNode) continue; - float dist = CCollision::DistToLine(&pCurNode->GetPosition(), &pNode->GetPosition(), &pVehicle->GetPosition()); + CVector vCurPos = pCurNode->GetPosition(); + CVector vNextPos = pNode->GetPosition(); + float dist = CCollision::DistToLine(&vCurPos, &vNextPos, &pVehicle->GetPosition()); if (dist < md) { md = dist; closestLink = curLink; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 33642869..b5e81110 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -78,10 +78,10 @@ #define PED_FIND_Z_OFFSET 5.0f #define COP_PED_FIND_Z_OFFSET 10.0f -#define SPHERE_MARKER_R 0 -#define SPHERE_MARKER_G 128 -#define SPHERE_MARKER_B 255 -#define SPHERE_MARKER_A 128 +#define SPHERE_MARKER_R 252 +#define SPHERE_MARKER_G 138 +#define SPHERE_MARKER_B 242 +#define SPHERE_MARKER_A 228 #define SPHERE_MARKER_PULSE_PERIOD 2048 #define SPHERE_MARKER_PULSE_FRACTION 0.1f @@ -6850,6 +6850,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->bIsVisible = (ScriptParams[1] != 0); return 0; } + /* case COMMAND_SET_CAR_VISIBLE: { CollectParameters(&m_nIp, 2); @@ -6858,6 +6859,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pVehicle->bIsVisible = (ScriptParams[1] != 0); return 0; } + */ case COMMAND_IS_AREA_OCCUPIED: { CollectParameters(&m_nIp, 11); @@ -6885,6 +6887,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) UpdateCompareFlag(total > 0); return 0; } + /* case COMMAND_START_DRUG_RUN: CPlane::CreateIncomingCesna(); return 0; @@ -6898,6 +6901,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CollectParameters(&m_nIp, 1); gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f); return 0; + */ case COMMAND_DISPLAY_TEXT: { CollectParameters(&m_nIp, 2); @@ -6944,18 +6948,21 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0]; return 0; } + /* case COMMAND_SET_TEXT_CENTRE_SIZE: { CollectParameters(&m_nIp, 1); CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0]; return 0; } + */ case COMMAND_SET_TEXT_BACKGROUND: { CollectParameters(&m_nIp, 1); CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0); return 0; } + /* case COMMAND_SET_TEXT_BACKGROUND_COLOUR: { CollectParameters(&m_nIp, 4); @@ -6969,12 +6976,14 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0); return 0; } + */ case COMMAND_SET_TEXT_PROPORTIONAL: { CollectParameters(&m_nIp, 1); CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0); return 0; } + /* case COMMAND_SET_TEXT_FONT: { CollectParameters(&m_nIp, 1); @@ -6992,6 +7001,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) case COMMAND_SUBURBAN_PASSED: CStats::SuburbanPassed = true; return 0; + */ case COMMAND_ROTATE_OBJECT: { CollectParameters(&m_nIp, 4); @@ -7133,9 +7143,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0); return 0; } + /* case COMMAND_IS_NASTY_GAME: UpdateCompareFlag(CGame::nastyGame); return 0; + */ case COMMAND_UNDRESS_CHAR: { CollectParameters(&m_nIp, 1); @@ -7165,6 +7177,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CWorld::Add(pPed); return 0; } + /* case COMMAND_START_CHASE_SCENE: CollectParameters(&m_nIp, 1); CTimer::Suspend(); @@ -7229,15 +7242,15 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) } case COMMAND_CREATE_FLOATING_PACKAGE: { -// removed in MIAMI -// CollectParameters(&m_nIp, 3); -// CVector pos = *(CVector*)&ScriptParams[0]; -// if (pos.z <= MAP_Z_LOW_LIMIT) -// pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; -// ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0); -// StoreParameters(&m_nIp, 1); + CollectParameters(&m_nIp, 3); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET; + ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0); + StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR: { CollectParameters(&m_nIp, 5); @@ -7303,12 +7316,35 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); pPed->m_pMyVehicle->bEngineOn = false; pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f); + pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f); }else{ pPed->m_pMyVehicle->RemovePassenger(pPed); } - pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f); - pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f); + if (pPed->m_vehEnterType) { + if (pPed->GetPedState() == PED_EXIT_CAR || pPed->GetPedState() == PED_DRAG_FROM_CAR) { + uint8 flags = 0; + if (pPed->m_pMyVehicle->IsBike()) { + //TODO(MIAMI) + } + else { + switch (pPed->m_vehEnterType) { + case CAR_DOOR_LF: + flags = pPed->m_pMyVehicle->m_nNumMaxPassengers != 0 ? CAR_DOOR_FLAG_LF : CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR; + case CAR_DOOR_LR: + flags = pPed->m_pMyVehicle->m_nNumMaxPassengers != 0 ? CAR_DOOR_FLAG_RF : CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR; + case CAR_DOOR_RF: + flags = CAR_DOOR_FLAG_RF; + case CAR_DOOR_RR: + flags = CAR_DOOR_FLAG_RR; + } + } + pPed->m_pMyVehicle->m_nGettingOutFlags &= ~flags; + pPed->m_pMyVehicle->ProcessOpenDoor(pPed->m_vehEnterType, NUM_STD_ANIMS, 0.0f); + } + } } + pPed->RemoveInCarAnims(); pPed->bInVehicle = false; pPed->m_pMyVehicle = nil; pPed->SetPedState(PED_IDLE); @@ -7316,13 +7352,12 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->bUsesCollision = true; pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); pPed->ReplaceWeaponWhenExitingVehicle(); - pPed->RemoveInCarAnims(); if (pPed->m_pVehicleAnim) pPed->m_pVehicleAnim->blendDelta = -1000.0f; pPed->m_pVehicleAnim = nil; pPed->RestartNonPartialAnims(); pPed->SetMoveState(PEDMOVE_NONE); - CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 100.0f); + CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE, 1000.0f); pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel(); pPed->Teleport(pos); CTheScripts::ClearSpaceForMissionEntity(pos, pPed); @@ -7358,6 +7393,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) } return 0; } + /* case COMMAND_HAS_CHAR_SPOTTED_CHAR: { CollectParameters(&m_nIp, 2); @@ -7368,6 +7404,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget)); return 0; } + */ case COMMAND_SET_CHAR_OBJ_HAIL_TAXI: { CollectParameters(&m_nIp, 1); @@ -7385,6 +7422,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) UpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible); return 0; } + /* case COMMAND_START_KILL_FRENZY_HEADSHOT: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -7415,6 +7453,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); return 0; } + */ case COMMAND_WARP_PLAYER_INTO_CAR: { CollectParameters(&m_nIp, 2); @@ -7446,6 +7485,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1); return 0; } + /* case COMMAND_PRINT_WITH_3_NUMBERS_BIG: { wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); @@ -7474,6 +7514,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]); return 0; } + */ case COMMAND_SET_CHAR_WAIT_STATE: { CollectParameters(&m_nIp, 3); @@ -7485,6 +7526,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) case COMMAND_SET_CAMERA_BEHIND_PLAYER: TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString(); return 0; + /* case COMMAND_SET_MOTION_BLUR: CollectParameters(&m_nIp, 1); TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]); @@ -7497,6 +7539,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string); return 0; } + */ case COMMAND_CREATE_RANDOM_CHAR: { CollectParameters(&m_nIp, 3); @@ -7519,6 +7562,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) ped->CharCreatedBy = MISSION_CHAR; ped->bRespondsToThreats = false; ped->bAllowMedicsToReviveMe = false; + ped->bIsPlayerFriend = false; CVector pos = *(CVector*)&ScriptParams[0]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); @@ -7546,6 +7590,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR); return 0; } + /* case COMMAND_SET_2_REPEATED_PHONE_MESSAGES: { CollectParameters(&m_nIp, 1); @@ -7600,6 +7645,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil); return 0; } + */ case COMMAND_IS_SNIPER_BULLET_IN_AREA: { CollectParameters(&m_nIp, 6); @@ -7624,9 +7670,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ)); return 0; } + /* case COMMAND_GIVE_PLAYER_DETONATOR: CGarages::GivePlayerDetonator(); return 0; + */ //case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR: case COMMAND_SET_OBJECT_VELOCITY: { @@ -7676,6 +7724,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) return 0; } //case COMMAND_PRINT_STRING_IN_STRING_SOON: + /* case COMMAND_SET_5_REPEATED_PHONE_MESSAGES: { CollectParameters(&m_nIp, 1); @@ -7722,6 +7771,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6); return 0; } + */ case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY: { CollectParameters(&m_nIp, 6); @@ -7752,16 +7802,24 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) return 0; } case COMMAND_LOAD_ALL_MODELS_NOW: +#ifdef FIX_BUGS + CTimer::Suspend(); +#else CTimer::Stop(); +#endif CStreaming::LoadAllRequestedModels(false); +#ifdef FIX_BUGS + CTimer::Resume(); +#else CTimer::Update(); +#endif return 0; case COMMAND_ADD_TO_OBJECT_VELOCITY: { CollectParameters(&m_nIp, 4); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); assert(pObject); - pObject->SetMoveSpeed(pObject->GetMoveSpeed() + 0.02f * *(CVector*)&ScriptParams[1]); + pObject->SetMoveSpeed(pObject->GetMoveSpeed() + *(CVector*)&ScriptParams[1] / METERS_PER_SECOND_TO_GAME_SPEED); return 0; } case COMMAND_DRAW_SPRITE: @@ -7837,6 +7895,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) } return 0; } + /* case COMMAND_SET_CHAR_ANIM_SPEED: { CollectParameters(&m_nIp, 2); @@ -7847,6 +7906,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) pAssoc->speed = *(float*)&ScriptParams[1]; return 0; } + */ case COMMAND_PLAY_MISSION_PASSED_TUNE: { CollectParameters(&m_nIp, 1); @@ -7875,6 +7935,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) pVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0; return 0; } + /* case COMMAND_SWITCH_PED_ROADS_ON_ANGLED: { CollectParameters(&m_nIp, 7); @@ -7897,14 +7958,19 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0); return 0; + */ case COMMAND_SET_CAR_WATERTIGHT: { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); - CAutomobile* pCar = (CAutomobile*)pVehicle; - pCar->bWaterTight = ScriptParams[1] != 0; + if (pVehicle->IsBike()) { + //TODO(MIAMI) + } + else if (pVehicle->IsCar()) { + CAutomobile* pCar = (CAutomobile*)pVehicle; + pCar->bWaterTight = ScriptParams[1] != 0; + } return 0; } case COMMAND_ADD_MOVING_PARTICLE_EFFECT: @@ -7948,6 +8014,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) pVehicle->SetHeading(heading); return 0; } + /* case COMMAND_IS_CRANE_LIFTING_CAR: { CollectParameters(&m_nIp, 3); @@ -7955,6 +8022,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) UpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle)); return 0; } + */ case COMMAND_DRAW_SPHERE: { CollectParameters(&m_nIp, 4); @@ -7991,6 +8059,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) strncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT); return 0; } + /* case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL: { CollectParameters(&m_nIp, 3); @@ -8001,6 +8070,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) *(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates(); StoreParameters(&m_nIp, 3); return 0; + */ case COMMAND_SAVE_INT_TO_DEBUG_FILE: // TODO: implement something here CollectParameters(&m_nIp, 1); @@ -8028,7 +8098,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) return 0; case COMMAND_SWITCH_RUBBISH: CollectParameters(&m_nIp, 1); - CRubbish::SetVisibility(ScriptParams[0] != 0);; + CRubbish::SetVisibility(ScriptParams[0] != 0); return 0; case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA: { @@ -8067,6 +8137,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CollectParameters(&m_nIp, 1); UpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0])); return 0; + /* case COMMAND_START_CATALINA_HELI: CHeli::StartCatalinaFlyBy(); return 0; @@ -8079,6 +8150,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN: UpdateCompareFlag(CHeli::HasCatalinaBeenShotDown()); return 0; + */ case COMMAND_SWAP_NEAREST_BUILDING_MODEL: { CollectParameters(&m_nIp, 6); @@ -8125,6 +8197,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) pPed->ClearWeapons(); return 0; } + /* case COMMAND_GRAB_CATALINA_HELI: { CHeli* pHeli = CHeli::FindPointerToCatalinasHeli(); @@ -8132,6 +8205,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_CLEAR_AREA_OF_CARS: { CollectParameters(&m_nIp, 6); @@ -8176,9 +8250,11 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CollectParameters(&m_nIp, 1); CTheScripts::RemoveScriptSphere(ScriptParams[0]); return 0; + /* case COMMAND_CATALINA_HELI_FLY_AWAY: CHeli::MakeCatalinaHeliFlyAway(); return 0; + */ case COMMAND_SET_EVERYONE_IGNORE_PLAYER: { CollectParameters(&m_nIp, 2); @@ -8213,10 +8289,12 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_IS_PHONE_DISPLAYING_MESSAGE: CollectParameters(&m_nIp, 1); UpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0])); return 0; + */ case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING: { assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); @@ -8261,15 +8339,17 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) switch (model) { case MI_LANDSTAL: case MI_LINERUN: + case MI_RIO: case MI_FIRETRUCK: case MI_TRASH: case MI_STRETCH: + case MI_VOODOO: case MI_MULE: case MI_AMBULAN: case MI_FBICAR: case MI_MRWHOOP: case MI_BFINJECT: - // case MI_CORPSE: + case MI_HUNTER: case MI_POLICE: case MI_ENFORCER: case MI_SECURICA: @@ -8277,42 +8357,73 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) case MI_BUS: case MI_RHINO: case MI_BARRACKS: - case MI_TRAIN: + case MI_CUBAN: case MI_CHOPPER: - case MI_DODO: + case MI_ANGEL: case MI_COACH: case MI_RCBANDIT: - // case MI_BELLYUP: - // case MI_MRWONGS: - // case MI_MAFIA: - case MI_VOODOO: - // case MI_YAKUZA: - // case MI_DIABLOS: - // case MI_COLUMB: - // case MI_HOODS: + case MI_ROMERO: + case MI_PACKER: + case MI_SENTXS: + case MI_SQUALO: + case MI_SEASPAR: + case MI_PIZZABOY: + case MI_GANGBUR: case MI_AIRTRAIN: case MI_DEADDODO: case MI_SPEEDER: case MI_REEFER: - // case MI_PANLANT: + case MI_TROPIC: case MI_FLATBED: case MI_YANKEE: - // case MI_ESCAPE: + case MI_CADDY: case MI_ZEBRA: case MI_TOPFUN: - // case MI_GHOST: + case MI_SKIMMER: case MI_RCBARON: case MI_RCRAIDER: + case MI_SPARROW: + case MI_PATRIOT: + case MI_LOVEFIST: + case MI_COASTG: + case MI_DINGHY: + case MI_HERMES: + case MI_SABRETUR: + case MI_PHEONIX: + case MI_WALTON: + case MI_COMET: + case MI_DELUXO: + case MI_BURRITO: + case MI_SPAND: + case MI_MARQUIS: + case MI_BAGGAGE: + case MI_KAUFMAN: + case MI_MAVERICK: + case MI_VCNMAV: + case MI_RANCHER: + case MI_FBIRANCH: + case MI_JETMAX: + case MI_HOTRING: + case MI_SANDKING: + case MI_BLISTAC: + case MI_POLMAV: + case MI_BOXVILLE: + case MI_BENSON: + case MI_MESA: + case MI_RCGOBLIN: + case MI_HOTRINA: + case MI_HOTRINB: + case MI_BLOODRA: + case MI_BLOODRB: + case MI_VICECHEE: model = -1; break; case MI_IDAHO: case MI_STINGER: case MI_PEREN: case MI_SENTINEL: - case MI_PATRIOT: case MI_MANANA: case MI_INFERNUS: - // case MI_BLISTA: case MI_PONY: case MI_CHEETAH: case MI_MOONBEAM: @@ -8324,9 +8435,17 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) case MI_CABBIE: case MI_STALLION: case MI_RUMPO: -// case 151: -// case 152: -// case 153: + case MI_ADMIRAL: + case MI_PCJ600: + case MI_FAGGIO: + case MI_FREEWAY: + case MI_GLENDALE: + case MI_OCEANIC: + case MI_SANCHEZ: + case MI_SABRE: + case MI_REGINA: + case MI_VIRGO: + case MI_GREENWOO: break; default: printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]); @@ -8342,15 +8461,15 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) if (model == -1) return 0; CVehicle* car; - if (!CModelInfo::IsBikeModel(model)) - car = new CAutomobile(model, MISSION_VEHICLE); + //if (CModelInfo::IsBikeModel(model)) // TODO(MIAMI) + car = new CAutomobile(model, MISSION_VEHICLE); CVector pos = *(CVector*)&ScriptParams[0]; pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel(); car->SetPosition(pos); car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3])); CTheScripts::ClearSpaceForMissionEntity(pos, car); car->SetStatus(STATUS_ABANDONED); - car->bIsLocked = true; + car->bIsLocked = false; car->bIsCarParkVehicle = true; CCarCtrl::JoinCarWithRoadSystem(car); car->AutoPilot.m_nCarMission = MISSION_NONE; @@ -8363,10 +8482,12 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CWorld::Add(car); return 0; } + /* case COMMAND_IS_COLLISION_IN_MEMORY: CollectParameters(&m_nIp, 1); UpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]); return 0; + */ case COMMAND_SET_WANTED_MULTIPLIER: CollectParameters(&m_nIp, 1); FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0]; @@ -8374,6 +8495,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER: TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); return 0; + /* case COMMAND_IS_CAR_VISIBLY_DAMAGED: { CollectParameters(&m_nIp, 1); @@ -8382,6 +8504,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) UpdateCompareFlag(pVehicle->bIsDamaged); return 0; } + */ case COMMAND_DOES_OBJECT_EXIST: CollectParameters(&m_nIp, 1); UpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0])); @@ -8390,9 +8513,17 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) { CollectParameters(&m_nIp, 3); CVector pos = *(CVector*)&ScriptParams[0]; +#ifdef FIX_BUGS + CTimer::Suspend(); +#else CTimer::Stop(); +#endif CStreaming::LoadScene(pos); +#ifdef FIX_BUGS + CTimer::Suspend(); +#else CTimer::Update(); +#endif return 0; } case COMMAND_ADD_STUCK_CAR_CHECK: @@ -8414,12 +8545,20 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) UpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0])); return 0; case COMMAND_LOAD_MISSION_AUDIO: + { + CollectParameters(&m_nIp, 1); strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) str[i] = tolower(str[i]); + static bool bShowed = false; m_nIp += KEY_LENGTH_IN_SCRIPT; - DMAudio.PreloadMissionAudio(str); + if (!bShowed) { + debug("LOAD_MISSION_AUDIO not implemented\n"); + bShowed = true; + } + //DMAudio.PreloadMissionAudio(str); return 0; + } case COMMAND_HAS_MISSION_AUDIO_LOADED: { CollectParameters(&m_nIp, 1); @@ -8456,6 +8595,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); + // TODO(MIAMI): replace GetPosition with FindNodeCoorsForScript *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node); StoreParameters(&m_nIp, 4); @@ -8481,21 +8621,32 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) } case COMMAND_SET_MISSION_AUDIO_POSITION: { - CollectParameters(&m_nIp, 3); - CVector pos = *(CVector*)&ScriptParams[0]; - DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z); + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[1]; + static bool bShowed = false; + if (!bShowed) { + debug("SET_MISSION_AUDIO_POSITION not implemented\n"); + bShowed = true; + } + //DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z); return 0; } case COMMAND_ACTIVATE_SAVE_MENU: + { + CStats::SafeHouseVisits++; FrontEndMenuManager.m_bSaveMenuActive = true; + FindPlayerPed()->SetMoveSpeed(0.0f, 0.0f, 0.0f); + FindPlayerPed()->SetTurnSpeed(0.0f, 0.0f, 0.0f); return 0; + } case COMMAND_HAS_SAVE_GAME_FINISHED: - UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive); + UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive && !FrontEndMenuManager.m_bSaveMenuActive); return 0; case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE: CollectParameters(&m_nIp, 1); CGarages::SetLeaveCameraForThisGarage(ScriptParams[0]); return 0; + /* case COMMAND_ADD_BLIP_FOR_PICKUP_OLD: { CollectParameters(&m_nIp, 3); @@ -8505,6 +8656,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_ADD_BLIP_FOR_PICKUP: { CollectParameters(&m_nIp, 1); @@ -8516,6 +8668,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP: { CollectParameters(&m_nIp, 2); @@ -8527,6 +8680,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_SET_PED_DENSITY_MULTIPLIER: CollectParameters(&m_nIp, 1); CPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0]; @@ -8535,10 +8689,12 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CollectParameters(&m_nIp, 1); CPopulation::m_AllRandomPedsThisType = ScriptParams[0]; return 0; + /* case COMMAND_SET_TEXT_DRAW_BEFORE_FADE: CollectParameters(&m_nIp, 1); CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0; return 0; + */ case COMMAND_GET_COLLECTABLE1S_COLLECTED: ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages; StoreParameters(&m_nIp, 1); @@ -8565,8 +8721,8 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) if (CCamera::m_bUseMouse3rdPerson && ( strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 || strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 || - strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_3A", 7) == 0 || - strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_4A", 7) == 0)) { + strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2C", 7) == 0 || + strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2D", 7) == 0)) { m_nIp += KEY_LENGTH_IN_SCRIPT; return 0; } @@ -8589,9 +8745,6 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) int8 CRunningScript::ProcessCommands1000To1099(int32 command) { -#ifdef GTA_PS2 - char tmp[48]; -#endif switch (command) { //case COMMAND_FLASH_RADAR_BLIP: case COMMAND_IS_CHAR_IN_CONTROL: diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 32148476..f1770796 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -62,6 +62,7 @@ int32 CStats::Sprayings; float CStats::AutoPaintingBudget; int32 CStats::NoMoreHurricanes; float CStats::FashionBudget; +int32 CStats::SafeHouseVisits; void CStats::Init() { @@ -122,6 +123,7 @@ void CStats::Init() Sprayings = 0; AutoPaintingBudget = 0.0f; NoMoreHurricanes = 0; + SafeHouseVisits = 0; } void CStats::RegisterFastestTime(int32 index, int32 time) diff --git a/src/core/Stats.h b/src/core/Stats.h index 67ee86f7..be1f55ef 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -66,6 +66,7 @@ public: static float AutoPaintingBudget; static int32 NoMoreHurricanes; static float FashionBudget; + static int32 SafeHouseVisits; public: static void Init(void); From 3405cfffb76b1e0b7511e2fc394c0121f4aa43a8 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 20 May 2020 23:52:17 +0300 Subject: [PATCH 077/148] fixed dumb --- src/audio/sampman_miles.cpp | 4 ++-- src/audio/sampman_oal.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index ad2c512f..d625ac35 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -1445,7 +1445,7 @@ cSampleManager::IsSampleBankLoaded(uint8 nBank) bool cSampleManager::IsPedCommentLoaded(uint32 nComment) { - uint8 slot; + int8 slot; for ( int32 i = 0; i < _TODOCONST(3); i++ ) { @@ -1464,7 +1464,7 @@ cSampleManager::IsPedCommentLoaded(uint32 nComment) int32 cSampleManager::_GetPedCommentSlot(uint32 nComment) { - uint8 slot; + int8 slot; for ( int32 i = 0; i < _TODOCONST(3); i++ ) { diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index f16afbba..f6f3a393 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -775,7 +775,7 @@ cSampleManager::IsPedCommentLoaded(uint32 nComment) { ASSERT( nComment < TOTAL_AUDIO_SAMPLES ); - uint8 slot; + int8 slot; for ( int32 i = 0; i < _TODOCONST(3); i++ ) { @@ -795,7 +795,7 @@ cSampleManager::IsPedCommentLoaded(uint32 nComment) int32 cSampleManager::_GetPedCommentSlot(uint32 nComment) { - uint8 slot; + int8 slot; for (int32 i = 0; i < _TODOCONST(3); i++) { From 73ff01e35b2a0d14f06c1ac8121f59f73da7d994 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 21 May 2020 00:18:13 +0300 Subject: [PATCH 078/148] script fix --- src/control/Script.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 8ade2c9b..68b396f3 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8696,6 +8696,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CTimer::Resume(); pMissionScript->m_bIsMissionScript = true; pMissionScript->m_bMissionFlag = true; + CTheScripts::bAlreadyRunningAMissionScript = true; return 0; } case COMMAND_SET_OBJECT_DRAW_LAST: From 7e5342e9f0b27d69eaf0e3c6e1d14333ab5c4083 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 21 May 2020 11:22:25 +0300 Subject: [PATCH 079/148] script revision --- src/control/Script.cpp | 190 +++++++++++++++++++++++++++++------------ src/control/Script.h | 6 ++ src/peds/Ped.cpp | 1 + src/peds/Ped.h | 2 +- src/render/Shadows.cpp | 5 +- 5 files changed, 148 insertions(+), 56 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index b5e81110..eb94918e 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -78,13 +78,6 @@ #define PED_FIND_Z_OFFSET 5.0f #define COP_PED_FIND_Z_OFFSET 10.0f -#define SPHERE_MARKER_R 252 -#define SPHERE_MARKER_G 138 -#define SPHERE_MARKER_B 242 -#define SPHERE_MARKER_A 228 -#define SPHERE_MARKER_PULSE_PERIOD 2048 -#define SPHERE_MARKER_PULSE_FRACTION 0.1f - #ifdef USE_PRECISE_MEASUREMENT_CONVERTION #define METERS_IN_FOOT 0.3048f #define FEET_IN_METER 3.28084f @@ -8747,6 +8740,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) { switch (command) { //case COMMAND_FLASH_RADAR_BLIP: + /* case COMMAND_IS_CHAR_IN_CONTROL: { CollectParameters(&m_nIp, 1); @@ -8754,6 +8748,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) UpdateCompareFlag(pPed->IsPedInControl()); return 0; } + */ case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA: CollectParameters(&m_nIp, 1); CCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0); @@ -8761,9 +8756,11 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) case COMMAND_CLEAR_SMALL_PRINTS: CMessages::ClearSmallMessagesOnly(); return 0; + /* case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS: UpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()); return 0; + */ case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED: { CollectParameters(&m_nIp, 2); @@ -8829,6 +8826,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) return 0; } //case COMMAND_MAKE_PLAYER_UNSAFE: + /* case COMMAND_LOAD_COLLISION: { CollectParameters(&m_nIp, 1); @@ -8846,6 +8844,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) // ScriptParams[0] = CObject::nBodyCastHealth; // StoreParameters(&m_nIp, 1); return 0; + */ case COMMAND_SET_CHARS_CHATTING: { CollectParameters(&m_nIp, 3); @@ -8857,6 +8856,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) return 0; } //case COMMAND_MAKE_PLAYER_SAFE: + /* case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL: { CollectParameters(&m_nIp, 2); @@ -8879,18 +8879,33 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) pPed->m_nZoneLevel = LEVEL_NONE; return 0; } + */ case COMMAND_SET_DRUNK_INPUT_DELAY: - assert(0 && "SET_DRUNK_INPUT_DELAY not yet implemented"); + { + CollectParameters(&m_nIp, 2); + debug("SET_DRUNK_INPUT_DELAY not implemented\n"); return 0; + } case COMMAND_SET_CHAR_MONEY: - assert(0 && "SET_CHAR_MONEY not yet implemented"); - return 0; - case COMMAND_INCREASE_CHAR_MONEY: - assert(0 && "INCREASE_CHAR_MONEY not yet implemented"); + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->m_nPedMoney = ScriptParams[1]; + pPed->bMoneyHasBeenGivenByScript = true; return 0; + } + //case COMMAND_INCREASE_CHAR_MONEY: case COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS: - assert(0 && "GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS not yet implemented"); + { + CollectParameters(&m_nIp, 4); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + CVector result = pObject->GetPosition() + pObject->GetMatrix() * *(CVector*)&ScriptParams[1]; + *(CVector*)&ScriptParams[0] = result; + StoreParameters(&m_nIp, 3); return 0; + } case COMMAND_REGISTER_LIFE_SAVED: CStats::AnotherLifeSavedWithAmbulance(); return 0; @@ -8908,10 +8923,12 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 1); gPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9; return 0; + /* case COMMAND_REGISTER_LONGEST_DODO_FLIGHT: CollectParameters(&m_nIp, 1); CStats::RegisterLongestFlightInDodo(ScriptParams[0]); return 0; + */ case COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS: { CollectParameters(&m_nIp, 4); @@ -8929,10 +8946,12 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) case COMMAND_BLOW_UP_RC_BUGGY: CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(); return 0; + /* case COMMAND_REMOVE_CAR_FROM_CHASE: CollectParameters(&m_nIp, 1); CRecordDataForChase::RemoveCarFromChase(ScriptParams[0]); return 0; + */ case COMMAND_IS_FRENCH_GAME: UpdateCompareFlag(CGame::frenchGame); return 0; @@ -8940,8 +8959,13 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) UpdateCompareFlag(CGame::germanGame); return 0; case COMMAND_CLEAR_MISSION_AUDIO: - DMAudio.ClearMissionAudio(); + { + CollectParameters(&m_nIp, 1); + debug("CLEAR_MISSION_AUDIO not implemented\n"); + //DMAudio.ClearMissionAudio(); return 0; + } + /* case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST: CollectParameters(&m_nIp, 1); CRestart::bFadeInAfterNextArrest = !!ScriptParams[0]; @@ -8954,6 +8978,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 2); CGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]); return 0; + */ case COMMAND_SET_CHAR_USE_PEDNODE_SEEK: { CollectParameters(&m_nIp, 2); @@ -8964,6 +8989,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) pPed->bUsePedNodeSeek = !!ScriptParams[1]; return 0; } + /* case COMMAND_SWITCH_VEHICLE_WEAPONS: { CollectParameters(&m_nIp, 2); @@ -8976,10 +9002,12 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 2); CWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1]; return 0; + */ case COMMAND_SET_FREE_HEALTH_CARE: CollectParameters(&m_nIp, 2); CWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1]; return 0; + /* case COMMAND_IS_CAR_DOOR_CLOSED: { CollectParameters(&m_nIp, 2); @@ -8988,11 +9016,14 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) UpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1])); return 0; } + */ case COMMAND_LOAD_AND_LAUNCH_MISSION: return 0; case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL: { CollectParameters(&m_nIp, 1); + if (CTheScripts::NumberOfExclusiveMissionScripts > 0 && ScriptParams[0] <= UINT16_MAX - 2) + return 0; CTimer::Suspend(); int offset = CTheScripts::MultiScriptArray[ScriptParams[0]]; #ifdef USE_DEBUG_SCRIPT_LOADER @@ -9010,6 +9041,8 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CTimer::Resume(); pMissionScript->m_bIsMissionScript = true; pMissionScript->m_bMissionFlag = true; + CTheScripts::bAlreadyRunningAMissionScript = true; + //CGameLogic::ClearShortcut(); // TODO(MIAMI) return 0; } case COMMAND_SET_OBJECT_DRAW_LAST: @@ -9025,14 +9058,15 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 2); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]]; - if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1]) - ScriptParams[0] = pWeaponSlot->m_nAmmoTotal; - else - ScriptParams[0] = 0; + ScriptParams[0] = 0; + for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) { + if (pPed->GetWeapon(i).m_eWeaponType == (eWeaponType)ScriptParams[1]) + ScriptParams[0] = pPed->GetWeapon(i).m_nAmmoTotal; + } StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_GET_AMMO_IN_CHAR_WEAPON: { CollectParameters(&m_nIp, 2); @@ -9077,6 +9111,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) } return 0; } + */ case COMMAND_SET_NEAR_CLIP: CollectParameters(&m_nIp, 1); TheCamera.SetNearClipScript(*(float*)&ScriptParams[0]); @@ -9085,6 +9120,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 2); DMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]); return 0; + /* case COMMAND_OVERRIDE_HOSPITAL_LEVEL: CollectParameters(&m_nIp, 1); CRestart::OverrideHospitalLevel = ScriptParams[0]; @@ -9105,6 +9141,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) UpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle)); return 0; } + */ case COMMAND_SET_CAR_TRACTION: { CollectParameters(&m_nIp, 2); @@ -9114,9 +9151,8 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) if (pVehicle->m_vehType == VEHICLE_TYPE_CAR) ((CAutomobile*)pVehicle)->m_fTraction = fTraction; else - // this is certainly not a boat, trane, heli or plane field + // TODO(MIAMI) //((CBike*)pVehicle)->m_fTraction = fTraction; - *(float*)(((char*)pVehicle) + 1088) = fTraction; return 0; } case COMMAND_ARE_MEASUREMENTS_IN_METRES: @@ -9135,6 +9171,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) StoreParameters(&m_nIp, 1); return 0; } + /* case COMMAND_MARK_ROADS_BETWEEN_LEVELS: { CollectParameters(&m_nIp, 6); @@ -9183,6 +9220,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) ThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ); return 0; } + */ case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS: { CollectParameters(&m_nIp, 2); @@ -9191,6 +9229,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) pVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1]; return 0; } + /* case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS: { CollectParameters(&m_nIp, 2); @@ -9203,6 +9242,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 2); UpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1])); return 0; + */ case COMMAND_CLEAR_AREA_OF_CHARS: { CollectParameters(&m_nIp, 6); @@ -9229,7 +9269,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) } case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS: CollectParameters(&m_nIp, 1); - CStats::SetTotalNumberMissions(ScriptParams[0]); + CStats::SetTotalNumberMissions(CGame::germanGame ? ScriptParams[0] - 2 : ScriptParams[0]); return 0; case COMMAND_CONVERT_METRES_TO_FEET_INT: CollectParameters(&m_nIp, 1); @@ -9245,7 +9285,15 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]); return 0; //case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER: - //case COMMAND_IS_CAR_PASSENGER_SEAT_FREE: + case COMMAND_IS_CAR_PASSENGER_SEAT_FREE: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + UpdateCompareFlag(ScriptParams[1] < pVehicle->m_nNumMaxPassengers && pVehicle->pPassengers[ScriptParams[1]] == nil); + return 0; + } + /* case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT: { CollectParameters(&m_nIp, 2); @@ -9257,6 +9305,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL: { CollectParameters(&m_nIp, 2); @@ -9279,6 +9328,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1], *(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0); return 0; + /* case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS: { CollectParameters(&m_nIp, 2); @@ -9311,10 +9361,12 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix()); return 0; } + */ case COMMAND_SET_MUSIC_DOES_FADE: CollectParameters(&m_nIp, 1); TheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0); return 0; + /* case COMMAND_SET_INTRO_IS_PLAYING: CollectParameters(&m_nIp, 1); if (ScriptParams[0]) { @@ -9329,6 +9381,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CStreaming::LoadAllRequestedModels(false); } return 0; + */ case COMMAND_SET_PLAYER_HOOKER: { CollectParameters(&m_nIp, 2); @@ -9341,6 +9394,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]); assert(pHooker); pPlayerInfo->m_pHooker = (CCivilianPed*)pHooker; + pPlayerInfo->m_nSexFrequency = 1000; pPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000; pPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; } @@ -9368,8 +9422,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); - assert(pVehicle); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_VEHICLE && pPed->m_pMyVehicle == pVehicle); return 0; } case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR: @@ -9377,15 +9430,17 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 1); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_VEHICLE); return 0; } + /* case COMMAND_SET_SCRIPT_FIRE_AUDIO: CollectParameters(&m_nIp, 2); gFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]); return 0; + */ case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED: - UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3); + UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3); // TODO(MIAMI): more cheats! return 0; case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS: { @@ -9395,6 +9450,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) pPed->bNoCriticalHits = (ScriptParams[0] == 0); return 0; } + /* case COMMAND_IS_PLAYER_LIFTING_A_PHONE: { CollectParameters(&m_nIp, 1); @@ -9403,6 +9459,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) UpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL); return 0; } + */ case COMMAND_IS_CHAR_SITTING_IN_CAR: { CollectParameters(&m_nIp, 2); @@ -9410,7 +9467,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) assert(pPed); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); assert(pVehicle); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_VEHICLE && pPed->m_pMyVehicle == pVehicle); return 0; } case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR: @@ -9418,7 +9475,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING); + UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_VEHICLE); return 0; } case COMMAND_IS_PLAYER_ON_FOOT: @@ -9449,7 +9506,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) { char tmp[48]; switch (command) { - case COMMAND_LOAD_COLLISION_WITH_SCREEN: // NB: not actually implemented + /* + case COMMAND_LOAD_COLLISION_WITH_SCREEN: CollectParameters(&m_nIp, 1); CTimer::Stop(); CGame::currLevel = (eLevelName)ScriptParams[0]; @@ -9469,6 +9527,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) } CTimer::Update(); return 0; + */ case COMMAND_LOAD_SPLASH_SCREEN: CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp); for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) @@ -9476,7 +9535,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) m_nIp += 8; LoadSplash(tmp); return 0; - case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: // NB: not actually implemented + /* + case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS: { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9487,7 +9547,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); return 0; } - case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: // NB: not actually implemented + case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9497,6 +9557,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pCar->bMoreResistantToDamage = ScriptParams[1]; return 0; } + */ case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER: { CollectParameters(&m_nIp, 1); @@ -9511,9 +9572,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED); printf("End preload end of game audio\n"); return 0; - case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: // NB: not actually implemented + /* + case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA: CPad::GetPad(0)->DisablePlayerControls &= PLAYERCONTROL_DISABLED_1; return 0; + */ case COMMAND_SET_OBJECT_ROTATION: { CollectParameters(&m_nIp, 4); @@ -9533,11 +9596,12 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source; StoreParameters(&m_nIp, 3); return 0; - case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: // NB: not actually implemented + /* + case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR: *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front; StoreParameters(&m_nIp, 3); return 0; - case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: // NB: not actually implemented + case COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR: { CollectParameters(&m_nIp, 1); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; @@ -9546,6 +9610,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(pTarget && pTarget->IsPed()); return 0; } + */ case COMMAND_IS_PLAYER_TARGETTING_CHAR: { CollectParameters(&m_nIp, 2); @@ -9559,8 +9624,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) static int nCounter = 0; nCounter = Max(0, nCounter - 1); if (!pPed->GetWeapon()->IsTypeMelee() && !bTargetting) { - if ((pTarget->GetPosition() - TheCamera.GetPosition()).Magnitude() < 10.0f) { - CVector vTestedPos(pTarget->GetPosition().x, pTarget->GetPosition().y, pTarget->GetPosition().z + 0.4); + if ((pTestedPed->GetPosition() - TheCamera.GetPosition()).Magnitude() < 10.0f) { + CVector vTestedPos(pTestedPed->GetPosition().x, pTestedPed->GetPosition().y, pTestedPed->GetPosition().z + 0.4); CVector vScreenPos; float w, h; if (CSprite::CalcScreenCoors(vTestedPos, vScreenPos, &w, &h, false)) { @@ -9571,7 +9636,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CEntity* entity; if (!CWorld::ProcessLineOfSight(TheCamera.GetPosition() + 2.0f * TheCamera.GetForward(), vTestedPos, point, entity, true, true, true, true, true, false) || - entity == pTarget) { + entity == pTestedPed) { nCounter += 2; if (nCounter > 20) { bTargetting = true; @@ -9585,7 +9650,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(bTargetting); return 0; } - case COMMAND_IS_PLAYER_TARGETTING_OBJECT: // NB: not actually implemented + /* + case COMMAND_IS_PLAYER_TARGETTING_OBJECT: { CollectParameters(&m_nIp, 2); CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; @@ -9596,6 +9662,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject); return 0; } + */ case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME: { CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp); @@ -9638,8 +9705,10 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) case COMMAND_FAIL_CURRENT_MISSION: CTheScripts::FailCurrentMission = 2; return 0; - case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: // NB: actually does nothing + case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: { + return 0; +/* CollectParameters(&m_nIp, 5); CVector pos = *(CVector*)&ScriptParams[0]; if (pos.z <= MAP_Z_LOW_LIMIT) @@ -9683,8 +9752,10 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) } StoreParameters(&m_nIp, 1); return 0; +*/ } - case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: // NB: not actually implemented + /* + case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT: { CollectParameters(&m_nIp, 5); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); @@ -9695,6 +9766,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset); return 0; } + */ case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR: { CollectParameters(&m_nIp, 1); @@ -9707,7 +9779,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 2); TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 100.0f - *(float*)&ScriptParams[0], ScriptParams[1]); return 0; - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: // NB: not actually implemented + /* + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT: { CollectParameters(&m_nIp, 5); CVector pos = *(CVector*)&ScriptParams[0]; @@ -9722,7 +9795,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 4); return 0; } - case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: // NB: not actually implemented + case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT: { CollectParameters(&m_nIp, 5); CVector pos = *(CVector*)&ScriptParams[0]; @@ -9737,6 +9810,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 4); return 0; } + */ case COMMAND_GET_DEBUG_CAMERA_POINT_AT: *(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front; StoreParameters(&m_nIp, 3); @@ -9825,11 +9899,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 1); return 0; } - case COMMAND_GET_RANDOM_COP_IN_ZONE: // NB: not actually implemented + /* + case COMMAND_GET_RANDOM_COP_IN_ZONE: { char zone[KEY_LENGTH_IN_SCRIPT]; strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); -// TODO(MIAMI): just getting this to compile with new argument int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT); if (nZone != -1) m_nIp += KEY_LENGTH_IN_SCRIPT; @@ -9873,6 +9947,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) StoreParameters(&m_nIp, 1); return 0; } + */ case COMMAND_SET_CHAR_OBJ_FLEE_CAR: { CollectParameters(&m_nIp, 2); @@ -9959,7 +10034,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[2]; return 0; } - case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: // NB: not actually implemented + /* + case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT: { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9968,7 +10044,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; return 0; } - case COMMAND_SET_CAR_HANDBRAKE_STOP: // NB: not actually implemented + case COMMAND_SET_CAR_HANDBRAKE_STOP: { CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); @@ -9977,6 +10053,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1]; return 0; } + */ case COMMAND_IS_CHAR_ON_ANY_BIKE: { CollectParameters(&m_nIp, 1); @@ -9985,10 +10062,12 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE); return 0; } - case COMMAND_LOCATE_SNIPER_BULLET_2D: // NB: not actually implemented - case COMMAND_LOCATE_SNIPER_BULLET_3D: // NB: not actually implemented + /* + case COMMAND_LOCATE_SNIPER_BULLET_2D: + case COMMAND_LOCATE_SNIPER_BULLET_3D: LocateSniperBulletCommand(command, &m_nIp); return 0; + */ case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL: CollectParameters(&m_nIp, 1); ScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1; @@ -10002,7 +10081,8 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE); return 0; } - case COMMAND_IS_CHAR_LYING_DOWN: // NB: not actually implemented + /* + case COMMAND_IS_CHAR_LYING_DOWN: { CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); @@ -10010,6 +10090,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(pPed->bFallenDown); return 0; } + */ case COMMAND_CAN_CHAR_SEE_DEAD_CHAR: { CollectParameters(&m_nIp, 2); @@ -10062,7 +10143,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(CModelInfo::GetModelInfo(ScriptParams[0]) != nil); return 0; case COMMAND_SHUT_CHAR_UP: - assert("SHUT_CHAR_UP not implemented"); // TODO(MIAMI) + CollectParameters(&m_nIp, 1); + debug("SHUT_CHAR_UP not implemented"); // TODO(MIAMI) + return 0; case COMMAND_SET_ENABLE_RC_DETONATE: CollectParameters(&m_nIp, 1); CVehicle::bDisableRemoteDetonation = ScriptParams[0]; @@ -11019,7 +11102,7 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) bool CRunningScript::CheckDamagedWeaponType(int32 type, int32 actual) { - if (type == -1) + if (actual == -1) return false; if (type == WEAPONTYPE_ANYMELEE) { switch (actual) { @@ -11042,7 +11125,8 @@ bool CRunningScript::CheckDamagedWeaponType(int32 type, int32 actual) } if (type == WEAPONTYPE_ANYWEAPON) { // TODO(MIAMI)! - return true; + return actual != WEAPONTYPE_UNIDENTIFIED && actual != WEAPONTYPE_RAMMEDBYCAR && + actual != WEAPONTYPE_RUNOVERBYCAR && actual != WEAPONTYPE_FALL && actual != WEAPONTYPE_DROWNING; } return false; } diff --git a/src/control/Script.h b/src/control/Script.h index f335c148..811fbef5 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -15,6 +15,12 @@ class CPlayerInfo; class CRunningScript; #define KEY_LENGTH_IN_SCRIPT 8 +#define SPHERE_MARKER_R 252 +#define SPHERE_MARKER_G 138 +#define SPHERE_MARKER_B 242 +#define SPHERE_MARKER_A 228 +#define SPHERE_MARKER_PULSE_PERIOD 2048 +#define SPHERE_MARKER_PULSE_FRACTION 0.1f struct intro_script_rectangle { diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 06012379..539bbfaf 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -602,6 +602,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bTurnedAroundOnAttractor = false; bCarPassenger = false; bMiamiViceCop = false; + bMoneyHasBeenGivenByScript = false; bIsDrowning = false; bCanDrownInWater = true; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 07c44fd5..4452c13a 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -441,7 +441,7 @@ public: //uint32 b155_8 //uint32 b155_10 uint32 bMiamiViceCop : 1; - //uint32 b155_40 + uint32 bMoneyHasBeenGivenByScript : 1; // //uint32 b155_80 uint32 bIsDrowning : 1; diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 69f9dce0..c512f35c 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -18,6 +18,7 @@ #endif #include "PointLights.h" #include "SpecialFX.h" +#include "Script.h" #include "Shadows.h" #ifdef DEBUGMENU @@ -1766,6 +1767,6 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur ASSERT(pPosn != NULL); C3dMarkers::PlaceMarkerSet(nID, _TODOCONST(4), *pPosn, Max(fFrontX, -fSideY), - 0, 128, 255, 128, - 2048, 0.2f, 0); + SPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, + SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0); } From 6d32cf4a11fa5011d7966745f5281ecac440a21a Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 12:21:02 +0300 Subject: [PATCH 080/148] blip marker colors, also isolate crgba --- src/core/Radar.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 1267896a..6cff26ed 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -16,6 +16,11 @@ #include "Streaming.h" #include "SpecialFX.h" +CRGBA CARBLIP_COLOR(252, 138, 242, 255); +CRGBA CHARBLIP_COLOR(252, 138, 242, 255); +CRGBA OBJECTBLIP_COLOR(252, 138, 242, 255); +CRGBA COORDBLIP_COLOR(252, 138, 242, 255); + float CRadar::m_radarRange; sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS]; CVector2D vec2DRadarOrigin; @@ -431,7 +436,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, CARBLIP_COLOR.r, CARBLIP_COLOR.g, CARBLIP_COLOR.b, 1024, 0.2f, 5); } break; } @@ -445,7 +450,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += 3.0f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, CHARBLIP_COLOR.r, CHARBLIP_COLOR.g, CHARBLIP_COLOR.b, 1024, 0.2f, 5); } break; } @@ -455,7 +460,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, OBJECTBLIP_COLOR.r, OBJECTBLIP_COLOR.g, OBJECTBLIP_COLOR.b, 1024, 0.2f, 5); } break; } @@ -464,7 +469,7 @@ void CRadar::Draw3dMarkers() case BLIP_CONTACT_POINT: if (!CTheScripts::IsPlayerOnAMission()) { if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) - C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0); + C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, COORDBLIP_COLOR.r, COORDBLIP_COLOR.g, COORDBLIP_COLOR.b, 2048, 0.2f, 0); } break; } From 2db26d304f399fd6562747a5f205244025451ddd Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 12:45:45 +0300 Subject: [PATCH 081/148] approach separation differently --- src/core/Radar.cpp | 13 ++++--------- src/core/Radar.h | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 6cff26ed..4dd8e9c5 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -16,11 +16,6 @@ #include "Streaming.h" #include "SpecialFX.h" -CRGBA CARBLIP_COLOR(252, 138, 242, 255); -CRGBA CHARBLIP_COLOR(252, 138, 242, 255); -CRGBA OBJECTBLIP_COLOR(252, 138, 242, 255); -CRGBA COORDBLIP_COLOR(252, 138, 242, 255); - float CRadar::m_radarRange; sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS]; CVector2D vec2DRadarOrigin; @@ -436,7 +431,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, CARBLIP_COLOR.r, CARBLIP_COLOR.g, CARBLIP_COLOR.b, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, CARBLIP_MARKER_COLOR_R, CARBLIP_MARKER_COLOR_G, CARBLIP_MARKER_COLOR_B, CARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -450,7 +445,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += 3.0f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, CHARBLIP_COLOR.r, CHARBLIP_COLOR.g, CHARBLIP_COLOR.b, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, CHARBLIP_MARKER_COLOR_R, CHARBLIP_MARKER_COLOR_G, CHARBLIP_MARKER_COLOR_B, CHARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -460,7 +455,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, OBJECTBLIP_COLOR.r, OBJECTBLIP_COLOR.g, OBJECTBLIP_COLOR.b, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, OBJECTBLIP_MARKER_COLOR_R, OBJECTBLIP_MARKER_COLOR_G, OBJECTBLIP_MARKER_COLOR_B, OBJECTBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -469,7 +464,7 @@ void CRadar::Draw3dMarkers() case BLIP_CONTACT_POINT: if (!CTheScripts::IsPlayerOnAMission()) { if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) - C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, COORDBLIP_COLOR.r, COORDBLIP_COLOR.g, COORDBLIP_COLOR.b, 2048, 0.2f, 0); + C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, COORDBLIP_MARKER_COLOR_R, COORDBLIP_MARKER_COLOR_G, COORDBLIP_MARKER_COLOR_B, COORDBLIP_MARKER_COLOR_A, 2048, 0.2f, 0); } break; } diff --git a/src/core/Radar.h b/src/core/Radar.h index f68d290c..61d94d05 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -1,6 +1,26 @@ #pragma once #include "Sprite2d.h" +#define CARBLIP_MARKER_COLOR_R 252 +#define CARBLIP_MARKER_COLOR_G 138 +#define CARBLIP_MARKER_COLOR_B 242 +#define CARBLIP_MARKER_COLOR_A 255 + +#define CHARBLIP_MARKER_COLOR_R 252 +#define CHARBLIP_MARKER_COLOR_G 138 +#define CHARBLIP_MARKER_COLOR_B 242 +#define CHARBLIP_MARKER_COLOR_A 255 + +#define OBJECTBLIP_MARKER_COLOR_R 252 +#define OBJECTBLIP_MARKER_COLOR_G 138 +#define OBJECTBLIP_MARKER_COLOR_B 242 +#define OBJECTBLIP_MARKER_COLOR_A 255 + +#define COORDBLIP_MARKER_COLOR_R 252 +#define COORDBLIP_MARKER_COLOR_G 138 +#define COORDBLIP_MARKER_COLOR_B 242 +#define COORDBLIP_MARKER_COLOR_A 255 + #define MENU_MAP_LENGTH_UNIT 1190.0f // in game unit #define MENU_MAP_WIDTH_SCALE 1.112f // in game unit (originally 1.112494151260504f) #define MENU_MAP_HEIGHT_SCALE 1.119f // in game unit (originally 1.118714268907563f) From b4060a4789e8f079a86fc106b8a17ea66de23f8d Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 13:06:09 +0300 Subject: [PATCH 082/148] add freecam toggle in control settings comes with a free config save! --- src/core/Cam.cpp | 2 +- src/core/Frontend.cpp | 13 +++++++++++++ src/core/Frontend.h | 5 ++++- src/core/MenuScreens.h | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index afa153f9..e81031c2 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -29,7 +29,7 @@ bool PrintDebugCode = false; int16 DebugCamMode; #ifdef FREE_CAM -bool CCamera::bFreeCam = true; +bool CCamera::bFreeCam; int nPreviousMode = -1; #endif diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index dd840bdc..77eab0a0 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -3115,6 +3115,9 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); +#ifdef FREE_CAM + CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#endif } } @@ -3205,6 +3208,9 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); +#ifdef FREE_CAM + CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#endif } CFileMgr::CloseFile(fileHandle); @@ -4952,6 +4958,13 @@ CMenuManager::ProcessOnOffMenuOptions() DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); SaveSettings(); break; +#ifdef FREE_CAM + case MENUACTION_FREECAM: + TheCamera.bFreeCam = !TheCamera.bFreeCam; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SaveSettings(); + break; +#endif } } diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 114ea6ba..30ae0bb4 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -380,7 +380,10 @@ enum eMenuAction MENUACTION_LANG_JAP, #endif #ifdef IMPROVED_VIDEOMODE - MENUACTION_SCREENMODE + MENUACTION_SCREENMODE, +#endif +#ifdef FREE_CAM + MENUACTION_FREECAM #endif }; diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index 6c2ebdb8..c6708580 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -284,6 +284,9 @@ const CMenuScreen aScreens[] = { // MENUPAGE_CONTROLLER_PC = 35 { "FET_CTL", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, +#ifdef FREE_CAM + MENUACTION_FREECAM, "FREECAM", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, +#endif MENUACTION_CHANGEMENU, "FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, From 1cb7b9876fe8310d5f3f52324c6647874e4340aa Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 14:23:12 +0300 Subject: [PATCH 083/148] scuffed InitAfterFocusLoss implementation --- src/core/Game.cpp | 16 ++++++++++++++++ src/core/Game.h | 2 ++ src/skel/win/win.cpp | 7 +++++++ 3 files changed, 25 insertions(+) diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 3f4a3217..d2f23b17 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -664,6 +664,22 @@ void CGame::Process(void) } } +void +CGame::InitAfterFocusLoss() +{ + /* + byte_869656 = byte_86969D; + result = cDMAudio::SetCurrent3DProvider(byte_86969D); + if ( !bGameStarted && !bMenuVisible ) + byte_869642 = 1; + */ + + //cDMAudio::SetCurrent3DProvider( ? ? ? ); + + if (!FrontEndMenuManager.m_bGameNotLoaded && !FrontEndMenuManager.m_bMenuActive) + CMenuManager::m_bStartUpFrontEndRequested = true; +} + bool CGame::CanSeeOutSideFromCurrArea(void) { diff --git a/src/core/Game.h b/src/core/Game.h index 6efacf8d..7ad8d55e 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -59,6 +59,8 @@ public: static void InitialiseWhenRestarting(void); static void Process(void); + static void InitAfterFocusLoss(void); + static bool IsInInterior(void) { return currArea != AREA_MAIN_MAP; } static bool CanSeeOutSideFromCurrArea(void); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index f41b9ef8..8ae0ce6e 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1222,6 +1222,13 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) break; } + case 7: + { + debug("ALT TABBED! CGame::InitAfterFocusLoss() \n"); + CGame::InitAfterFocusLoss(); + break; + } + } /* From 3e75de970988fde8ebf2fd05a81399c2e7ba763b Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 15:46:53 +0300 Subject: [PATCH 084/148] radardisc shadow thank tomasak --- src/render/Hud.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 7289d70c..7c33ea5b 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -909,7 +909,17 @@ void CHud::Draw() #else rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #endif - rect.Grow(4.0f); + + // shadow, might not be exactly accurate numbers + rect.Translate(0.f, 4.f); + rect.Grow(6.0f); + rect.top += 2.f; + rect.bottom -= 2.f; + Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); + + rect.Translate(0.f, -4.f); + rect.top -= 2.f; + rect.bottom += 2.f; Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); CRadar::DrawBlips(); } From 46c6b0d29d218fdbea82a85939c6cef9f56437c6 Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 16:25:46 +0300 Subject: [PATCH 085/148] fancy HUD.TXD reloader TODO: make optional with defines, also add more reload options --- src/core/re3.cpp | 5 +++++ src/render/Hud.cpp | 22 ++++++++++++++++++++++ src/render/Hud.h | 1 + 3 files changed, 28 insertions(+) diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 0e62f3a5..7f69e0f1 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -385,6 +385,11 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); + DebugMenuAddCmd("Reload", "HUD.TXD", CHud::ReloadTXD); + DebugMenuAddCmd("Reload", "FONTS.TXD", NULL); + DebugMenuAddCmd("Reload", "FRONTEN1.TXD", NULL); + DebugMenuAddCmd("Reload", "FRONTEN2.TXD", NULL); + extern bool PrintDebugCode; extern int16 DebugCamMode; DebugMenuAddVarBool8("Cam", "Use mouse Cam", &CCamera::m_bUseMouse3rdPerson, nil); diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 7c33ea5b..a2eed48b 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -1476,6 +1476,28 @@ void CHud::GetRidOfAllHudMessages() } } +void CHud::ReloadTXD() +{ + for (int i = 0; i < NUM_HUD_SPRITES; ++i) { + Sprites[i].Delete(); + } + + int HudTXD = CTxdStore::FindTxdSlot("hud"); + CTxdStore::RemoveTxdSlot(HudTXD); + + debug("Reloading HUD.TXD...\n"); + + HudTXD = CTxdStore::AddTxdSlot("hud"); + CTxdStore::LoadTxd(HudTXD, "MODELS/HUD.TXD"); + CTxdStore::AddRef(HudTXD); + CTxdStore::PopCurrentTxd(); + CTxdStore::SetCurrentTxd(HudTXD); + + for (int i = 0; i < NUM_HUD_SPRITES; i++) { + Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); + } +} + void CHud::Initialise() { m_Wants_To_Draw_Hud = true; diff --git a/src/render/Hud.h b/src/render/Hud.h index bae19ee4..3f4b218e 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -124,6 +124,7 @@ public: static void Draw(); static void DrawAfterFade(); static void GetRidOfAllHudMessages(); + static void ReloadTXD(); static void Initialise(); static void ReInitialise(); static void SetBigMessage(wchar *message, int16 style); From 6912cfe98ac58d18445d0127d7b558dbe9d198dc Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 16:26:56 +0300 Subject: [PATCH 086/148] menu map color change --- src/core/Frontend.cpp | 3171 +++++++++++++++++++++-------------------- 1 file changed, 1652 insertions(+), 1519 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 77eab0a0..663c9323 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -48,6 +48,7 @@ CRGBA HEADER_COLOR(255, 150, 255, 255); CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); CRGBA SLIDERON_COLOR(97, 194, 247, 255); CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); +CRGBA MAPINFOBOX_COLOR(255, 150, 225, 150); #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 @@ -149,8 +150,8 @@ uint8 CMenuManager::m_PrefsPlayerBlue; // why?? CMenuManager FrontEndMenuManager; uint32 TimeToStopPadShaking; -char *pEditString; -int32 *pControlEdit; +char* pEditString; +int32* pControlEdit; bool DisplayComboButtonErrMsg; int32 MouseButtonJustClicked; int32 JoyButtonJustClicked; @@ -231,7 +232,8 @@ ScaleAndCenterX(float x) else { if (x > DEFAULT_SCREEN_WIDTH / 2) { return SCREEN_WIDTH / 2 + SCREEN_SCALE_X(x - DEFAULT_SCREEN_WIDTH / 2); - } else { + } + else { return SCREEN_WIDTH / 2 - SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH / 2 - x); } } @@ -314,7 +316,7 @@ ScaleAndCenterX(float x) // --- Functions not in the game/inlined starts inline void -CMenuManager::ScrollUpListByOne() +CMenuManager::ScrollUpListByOne() { if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { if (m_nFirstVisibleRowOnList > 0) { @@ -322,7 +324,8 @@ CMenuManager::ScrollUpListByOne() m_nFirstVisibleRowOnList--; m_nScrollbarTopMargin -= SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; } - } else { + } + else { m_nSelectedListRow--; } } @@ -336,7 +339,8 @@ CMenuManager::ScrollDownListByOne() m_nFirstVisibleRowOnList++; m_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; } - } else { + } + else { if (m_nSelectedListRow < m_nTotalListRow - 1) { m_nSelectedListRow++; } @@ -348,12 +352,13 @@ CMenuManager::PageUpList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { if (m_nFirstVisibleRowOnList > 0) { - if(playSoundOnSuccess) + if (playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); - } else { + } + else { m_nFirstVisibleRowOnList = 0; m_nSelectedListRow = 0; } @@ -366,12 +371,13 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { - if(playSoundOnSuccess) + if (playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList); - } else { + } + else { m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; m_nSelectedListRow = m_nTotalListRow - 1; } @@ -384,14 +390,16 @@ CMenuManager::ThingsToDoBeforeLeavingPage() { if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + } + else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { if (m_nPrefsAudio3DProviderIndex != -1) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); #ifdef TIDY_UP_PBP DMAudio.StopFrontEndTrack(); OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); #endif - } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + } + else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { m_nDisplayVideoMode = m_nPrefsVideoMode; #ifdef IMPROVED_VIDEOMODE m_nSelectedScreenMode = m_nPrefsWindowed; @@ -410,7 +418,7 @@ CMenuManager::ThingsToDoBeforeLeavingPage() // ------ Functions not in the game/inlined ends void -CMenuManager::BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2) +CMenuManager::BuildStatLine(Const char* text, void* stat, bool itsFloat, void* stat2) { if (!text) return; @@ -423,18 +431,20 @@ CMenuManager::BuildStatLine(Const char *text, void *stat, bool itsFloat, void *s sprintf(gString2, " %d/%d", *(int*)stat, *(int*)stat2); else #endif - if (stat2) { - if (itsFloat) - sprintf(gString2, " %.2f %s %.2f", *(float*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(float*)stat2); - else - sprintf(gString2, " %d %s %d", *(int*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(int*)stat2); - } else if (stat) { - if (itsFloat) - sprintf(gString2, " %.2f", *(float*)stat); + if (stat2) { + if (itsFloat) + sprintf(gString2, " %.2f %s %.2f", *(float*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(float*)stat2); + else + sprintf(gString2, " %d %s %d", *(int*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(int*)stat2); + } + else if (stat) { + if (itsFloat) + sprintf(gString2, " %.2f", *(float*)stat); + else + sprintf(gString2, " %d", *(int*)stat); + } else - sprintf(gString2, " %d", *(int*)stat); - } else - gString2[0] = '\0'; + gString2[0] = '\0'; UnicodeStrcpy(gUString, TheText.Get(text)); AsciiToUnicode(gString2, gUString2); @@ -467,50 +477,58 @@ CMenuManager::CheckCodesForControls(int typeOfControl) bool escPressed = false; eControllerType typeToSave; // GetStartOptionsCntrlConfigScreens(); - e_ControllerAction action = (e_ControllerAction) m_CurrCntrlAction; + e_ControllerAction action = (e_ControllerAction)m_CurrCntrlAction; if (typeOfControl == KEYBOARD) { if (*pControlEdit == rsESC) { escPressed = true; - } else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && + } + else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && *pControlEdit != rsLWIN && *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { typeToSave = KEYBOARD; if (ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD) != rsNULL && *pControlEdit != ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD)) { typeToSave = OPTIONAL_EXTRA; } - } else { + } + else { invalidKey = true; } - } else if (typeOfControl == MOUSE) { + } + else if (typeOfControl == MOUSE) { typeToSave = MOUSE; - } else if (typeOfControl == JOYSTICK) { + } + else if (typeOfControl == JOYSTICK) { typeToSave = JOYSTICK; if (ControlsManager.GetIsActionAButtonCombo(action)) DisplayComboButtonErrMsg = true; } #ifdef FIX_BUGS - if(!escPressed && !invalidKey) + if (!escPressed && !invalidKey) #endif ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); if (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) { if (typeOfControl == KEYBOARD) { ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD); ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, OPTIONAL_EXTRA); - } else { + } + else { if (typeOfControl == MOUSE) { ControlsManager.DeleteMatchingActionInitiators(action, MouseButtonJustClicked, MOUSE); - } else if (typeOfControl == JOYSTICK) { + } + else if (typeOfControl == JOYSTICK) { ControlsManager.DeleteMatchingActionInitiators(action, JoyButtonJustClicked, JOYSTICK); } } if (typeOfControl == KEYBOARD) { ControlsManager.SetControllerKeyAssociatedWithAction(action, *pControlEdit, typeToSave); - } else if (typeOfControl == MOUSE) { + } + else if (typeOfControl == MOUSE) { ControlsManager.SetControllerKeyAssociatedWithAction(action, MouseButtonJustClicked, typeToSave); - } else { + } + else { if (typeOfControl == JOYSTICK) { ControlsManager.SetControllerKeyAssociatedWithAction(action, JoyButtonJustClicked, typeToSave); } @@ -534,8 +552,8 @@ CMenuManager::CheckCodesForControls(int typeOfControl) bool CMenuManager::CheckHover(int x1, int x2, int y1, int y2) { - return m_nMousePosX > x1 && m_nMousePosX < x2 && - m_nMousePosY > y1 && m_nMousePosY < y2; + return m_nMousePosX > x1 && m_nMousePosX < x2&& + m_nMousePosY > y1 && m_nMousePosY < y2; } void @@ -543,11 +561,11 @@ CMenuManager::CheckSliderMovement(int value) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_BRIGHTNESS: - m_PrefsBrightness += value * (512/16); + m_PrefsBrightness += value * (512 / 16); m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 511); break; case MENUACTION_DRAWDIST: - if(value > 0) + if (value > 0) m_PrefsLOD += ((1.8f - 0.8f) / 16.0f); else m_PrefsLOD -= ((1.8f - 0.8f) / 16.0f); @@ -555,18 +573,18 @@ CMenuManager::CheckSliderMovement(int value) CRenderer::ms_lodDistScale = m_PrefsLOD; break; case MENUACTION_MUSICVOLUME: - m_PrefsMusicVolume += value * (128/16); + m_PrefsMusicVolume += value * (128 / 16); m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 127); DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); break; case MENUACTION_SFXVOLUME: - m_PrefsSfxVolume += value * (128/16); + m_PrefsSfxVolume += value * (128 / 16); m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 127); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); break; case MENUACTION_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // ??? - TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); + TheCamera.m_fMouseAccelHorzntl += value * 1.0f / 200.0f / 15.0f; // ??? + TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200.0f, 1.0f / 200.0f); TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; break; default: @@ -610,39 +628,39 @@ CMenuManager::DisplayHelperText() // TODO: name this cases? switch (m_nHelperTextMsgId) { - case 0: - { - int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if (action != MENUACTION_CHANGEMENU && action != MENUACTION_REDEFCTRL && action != MENUACTION_RESTOREDEF) { - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); - } - break; - } - case 1: + case 0: + { + int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; + if (action != MENUACTION_CHANGEMENU && action != MENUACTION_REDEFCTRL && action != MENUACTION_RESTOREDEF) { CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); - break; - case 2: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); - break; - case 3: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); - break; - case 4: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); - break; - default: - break; + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); + } + break; + } + case 1: + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); + break; + case 2: + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); + break; + case 3: + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); + break; + case 4: + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); + break; + default: + break; } CFont::SetRightJustifyOff(); } int -CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress) +CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress) { CRGBA color; float maxBarHeight; @@ -651,12 +669,13 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR float curBarX = 0.0f; float spacing = SCREEN_SCALE_X(4.0f); // TODO: find actual numbers used in the game for (int i = 0; i < 16; i++) { - curBarX = i * rectSize/32.0f + x; + curBarX = i * rectSize / 32.0f + x; if (i / 16.0f + 1 / 32.0f < progress) { color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); lastActiveBarX = curBarX; - } else + } + else color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255)); maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); @@ -716,16 +735,16 @@ CMenuManager::Draw() CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); switch (m_nCurrScreen) { - case MENUPAGE_STATS: - PrintStats(); - break; - case MENUPAGE_BRIEFS: - PrintBriefs(); - break; + case MENUPAGE_STATS: + PrintStats(); + break; + case MENUPAGE_BRIEFS: + PrintBriefs(); + break; #ifdef MENU_MAP - case MENUPAGE_MAP: - PrintMap(); - break; + case MENUPAGE_MAP: + PrintMap(); + break; #endif } @@ -734,20 +753,20 @@ CMenuManager::Draw() // Page name #ifdef PS2_SAVE_DIALOG - if(!m_bRenderGameInMenu) + if (!m_bRenderGameInMenu) #endif - if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { + if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - PREPARE_MENU_HEADER - CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + PREPARE_MENU_HEADER + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - // Weird place to put that. - nextYToUse += 24.0f + 10.0f; - } + // Weird place to put that. + nextYToUse += 24.0f + 10.0f; + } CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y)); @@ -755,7 +774,7 @@ CMenuManager::Draw() CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); // Label - wchar *str; + wchar* str; if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) { switch (m_nCurrScreen) { case MENUPAGE_LOAD_SLOT_CONFIRM: @@ -800,87 +819,87 @@ CMenuManager::Draw() int headerHeight; int columnWidth; switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_BRIEFS: - columnWidth = 320; - headerHeight = 240; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_SOUND_SETTINGS: - case MENUPAGE_GRAPHICS_SETTINGS: - case MENUPAGE_MULTIPLAYER_CREATE: - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_CONTROLLER_PC_OLD1: - case MENUPAGE_CONTROLLER_PC_OLD2: - case MENUPAGE_CONTROLLER_PC_OLD3: - case MENUPAGE_CONTROLLER_PC_OLD4: - case MENUPAGE_CONTROLLER_DEBUG: - case MENUPAGE_MOUSE_CONTROLS: - columnWidth = 50; - headerHeight = 0; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = MEDIUMTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = MEDIUMTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_CHOOSE_SAVE_SLOT: - columnWidth = 120; - headerHeight = 38; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_SAVE_OVERWRITE_CONFIRM: - case MENUPAGE_EXIT: - columnWidth = 320; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_START_MENU: - columnWidth = 320; - headerHeight = 110; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_PAUSE_MENU: - columnWidth = 320; - headerHeight = 117; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; + case MENUPAGE_STATS: + case MENUPAGE_BRIEFS: + columnWidth = 320; + headerHeight = 240; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; + case MENUPAGE_SOUND_SETTINGS: + case MENUPAGE_GRAPHICS_SETTINGS: + case MENUPAGE_MULTIPLAYER_CREATE: + case MENUPAGE_SKIN_SELECT_OLD: + case MENUPAGE_CONTROLLER_PC_OLD1: + case MENUPAGE_CONTROLLER_PC_OLD2: + case MENUPAGE_CONTROLLER_PC_OLD3: + case MENUPAGE_CONTROLLER_PC_OLD4: + case MENUPAGE_CONTROLLER_DEBUG: + case MENUPAGE_MOUSE_CONTROLS: + columnWidth = 50; + headerHeight = 0; + lineHeight = 20; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = MEDIUMTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = MEDIUMTEXT_Y_SCALE)); + CFont::SetRightJustifyOff(); + break; + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + columnWidth = 120; + headerHeight = 38; + lineHeight = 20; + CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE)); + CFont::SetRightJustifyOff(); + break; + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + case MENUPAGE_SAVE_OVERWRITE_CONFIRM: + case MENUPAGE_EXIT: + columnWidth = 320; + headerHeight = 60; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; + case MENUPAGE_START_MENU: + columnWidth = 320; + headerHeight = 110; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; + case MENUPAGE_PAUSE_MENU: + columnWidth = 320; + headerHeight = 117; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; #ifdef PS2_SAVE_DIALOG - case MENUPAGE_SAVE: - columnWidth = 180; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - break; + case MENUPAGE_SAVE: + columnWidth = 180; + headerHeight = 60; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + break; #endif - default: - columnWidth = 320; - headerHeight = 40; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; + default: + columnWidth = 320; + headerHeight = 40; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; } #ifdef PS2_LIKE_MENU @@ -888,18 +907,18 @@ CMenuManager::Draw() #endif switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD1: - case MENUPAGE_CONTROLLER_PC_OLD2: - case MENUPAGE_CONTROLLER_PC_OLD3: - case MENUPAGE_CONTROLLER_PC_OLD4: - case MENUPAGE_CONTROLLER_DEBUG: - if (m_bWaitingForNewKeyBind) - itemsAreSelectable = false; + case MENUPAGE_CONTROLLER_PC_OLD1: + case MENUPAGE_CONTROLLER_PC_OLD2: + case MENUPAGE_CONTROLLER_PC_OLD3: + case MENUPAGE_CONTROLLER_PC_OLD4: + case MENUPAGE_CONTROLLER_DEBUG: + if (m_bWaitingForNewKeyBind) + itemsAreSelectable = false; - DrawControllerScreenExtraText(nextYToUse - 8.0f, MENU_X_LEFT_ALIGNED(350), lineHeight); - break; - default: - break; + DrawControllerScreenExtraText(nextYToUse - 8.0f, MENU_X_LEFT_ALIGNED(350), lineHeight); + break; + default: + break; } float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider @@ -911,7 +930,7 @@ CMenuManager::Draw() #ifdef MENU_MAP if (m_nCurrScreen == MENUPAGE_MAP) { // Back button - wchar *backTx = TheText.Get("FEDS_TB"); + wchar* backTx = TheText.Get("FEDS_TB"); CFont::SetDropShadowPosition(1); CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(MENU_X(60.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), backTx); @@ -919,7 +938,8 @@ CMenuManager::Draw() if (!CheckHover(MENU_X(30.0f), MENU_X(30.0f) + CFont::GetStringWidth(backTx), SCREEN_SCALE_FROM_BOTTOM(125.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f))) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; m_nCurrOption = m_nPrevOption = 0; - } else { + } + else { m_nHoverOption = HOVEROPTION_RANDOM_ITEM; m_nCurrOption = m_nPrevOption = 1; } @@ -929,8 +949,8 @@ CMenuManager::Draw() for (int i = 0; i < NUM_MENUROWS; ++i) { if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { - wchar *rightText = nil; - wchar *leftText; + wchar* rightText = nil; + wchar* leftText; if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { CFont::SetRightJustifyOff(); @@ -943,75 +963,76 @@ CMenuManager::Draw() sprintf(gString, "FEM_SL%d", i); leftText = TheText.Get(gString); } - } else { + } + else { leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { case MENUACTION_CHANGEMENU: { switch (aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu) { - case MENUPAGE_MULTIPLAYER_MAP: - switch (m_SelectedMap) { - case 0: - rightText = TheText.Get("FEM_MA0"); - break; - case 1: - rightText = TheText.Get("FEM_MA1"); - break; - case 2: - rightText = TheText.Get("FEM_MA2"); - break; - case 3: - rightText = TheText.Get("FEM_MA3"); - break; - case 4: - rightText = TheText.Get("FEM_MA4"); - break; - case 5: - rightText = TheText.Get("FEM_MA5"); - break; - case 6: - rightText = TheText.Get("FEM_MA6"); - break; - case 7: - rightText = TheText.Get("FEM_MA7"); - break; - default: - break; - } + case MENUPAGE_MULTIPLAYER_MAP: + switch (m_SelectedMap) { + case 0: + rightText = TheText.Get("FEM_MA0"); break; - case MENUPAGE_MULTIPLAYER_MODE: - switch (m_SelectedGameType) { - case 0: - rightText = TheText.Get("FEN_TY0"); - break; - case 1: - rightText = TheText.Get("FEN_TY1"); - break; - case 2: - rightText = TheText.Get("FEN_TY2"); - break; - case 3: - rightText = TheText.Get("FEN_TY3"); - break; - case 4: - rightText = TheText.Get("FEN_TY4"); - break; - case 5: - rightText = TheText.Get("FEN_TY5"); - break; - case 6: - rightText = TheText.Get("FEN_TY6"); - break; - case 7: - rightText = TheText.Get("FEN_TY7"); - break; - default: - break; - } + case 1: + rightText = TheText.Get("FEM_MA1"); + break; + case 2: + rightText = TheText.Get("FEM_MA2"); + break; + case 3: + rightText = TheText.Get("FEM_MA3"); + break; + case 4: + rightText = TheText.Get("FEM_MA4"); + break; + case 5: + rightText = TheText.Get("FEM_MA5"); + break; + case 6: + rightText = TheText.Get("FEM_MA6"); + break; + case 7: + rightText = TheText.Get("FEM_MA7"); break; default: break; + } + break; + case MENUPAGE_MULTIPLAYER_MODE: + switch (m_SelectedGameType) { + case 0: + rightText = TheText.Get("FEN_TY0"); + break; + case 1: + rightText = TheText.Get("FEN_TY1"); + break; + case 2: + rightText = TheText.Get("FEN_TY2"); + break; + case 3: + rightText = TheText.Get("FEN_TY3"); + break; + case 4: + rightText = TheText.Get("FEN_TY4"); + break; + case 5: + rightText = TheText.Get("FEN_TY5"); + break; + case 6: + rightText = TheText.Get("FEN_TY6"); + break; + case 7: + rightText = TheText.Get("FEN_TY7"); + break; + default: + break; + } + break; + default: + break; } break; } @@ -1125,11 +1146,12 @@ CMenuManager::Draw() if (m_nPrefsAudio3DProviderIndex == -1) rightText = TheText.Get("FEA_NAH"); else { - char *provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); + char* provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); if (!strcmp(strupr(provider), "DIRECTSOUND3D HARDWARE SUPPORT")) { strcpy(provider, "DSOUND3D HARDWARE SUPPORT"); - } else if (!strcmp(strupr(provider), "DIRECTSOUND3D SOFTWARE EMULATION")) { + } + else if (!strcmp(strupr(provider), "DIRECTSOUND3D SOFTWARE EMULATION")) { strcpy(provider, "DSOUND3D SOFTWARE EMULATION"); } AsciiToUnicode(provider, unicodeTemp); @@ -1176,10 +1198,10 @@ CMenuManager::Draw() float nextItemY = headerHeight + nextYToUse; float bitAboveNextItemY = nextItemY - 2.0f; int nextYToCheck = bitAboveNextItemY; - + if (!foundTheHoveringItem) { for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) { - if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) + if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) break; int extraOffset = 0; @@ -1197,13 +1219,13 @@ CMenuManager::Draw() m_nMousePosY < MENU_Y((nextYToCheck + 2) + usableLineHeight)) { static int oldOption = -99; - static int oldScreen = m_nCurrScreen; + static int oldScreen = m_nCurrScreen; - m_nPrevOption = rowToCheck; - if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { - m_nCurrOption = rowToCheck; - m_bShowMouse = true; - } + m_nPrevOption = rowToCheck; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrOption = rowToCheck; + m_bShowMouse = true; + } if (oldOption != m_nCurrOption) { if (oldScreen == m_nCurrScreen && m_bShowMouse) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); @@ -1227,17 +1249,17 @@ CMenuManager::Draw() #ifdef PS2_SAVE_DIALOG if (!m_bRenderGameInMenu) #endif - if (i == m_nCurrOption && itemsAreSelectable) { - // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background - CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), - SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); - } + if (i == m_nCurrOption && itemsAreSelectable) { + // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background + CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), + SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); + } CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); // Button and it's shadow - for(int textLayer = 0; textLayer < 2; textLayer++) { + for (int textLayer = 0; textLayer < 2; textLayer++) { if (!CFont::Details.centre) CFont::SetRightJustifyOff(); @@ -1247,22 +1269,23 @@ CMenuManager::Draw() if (rightText) { if (!CFont::Details.centre) CFont::SetRightJustifyOn(); - - if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") + + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") && !m_bGameNotLoaded && textLayer == 1) { CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); } - if (i == m_nCurrOption && itemsAreSelectable){ + if (i == m_nCurrOption && itemsAreSelectable) { CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); - } else { + } + else { CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } } if (m_nPrefsAudio3DProviderIndex == DMAudio.GetCurrent3DProviderIndex()) { - if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) ResetHelperText(); } if (m_nDisplayVideoMode == m_nPrefsVideoMode) { @@ -1304,21 +1327,21 @@ CMenuManager::Draw() // Sliders int lastActiveBarX; switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case MENUACTION_BRIGHTNESS: - ProcessSlider(m_PrefsBrightness / 512.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_DRAWDIST: - ProcessSlider((m_PrefsLOD - 0.8f) * 1.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_MUSICVOLUME: - ProcessSlider(m_PrefsMusicVolume / 128.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_SFXVOLUME: - ProcessSlider(m_PrefsSfxVolume / 128.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_MOUSESENS: - ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); - break; + case MENUACTION_BRIGHTNESS: + ProcessSlider(m_PrefsBrightness / 512.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_DRAWDIST: + ProcessSlider((m_PrefsLOD - 0.8f) * 1.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_MUSICVOLUME: + ProcessSlider(m_PrefsMusicVolume / 128.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_SFXVOLUME: + ProcessSlider(m_PrefsSfxVolume / 128.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_MOUSESENS: + ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); + break; } // 60.0 is silly @@ -1369,22 +1392,22 @@ CMenuManager::GetNumOptionsCntrlConfigScreens(void) { int number = 0; switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD3: - number = 2; + case MENUPAGE_CONTROLLER_PC_OLD3: + number = 2; + break; + case MENUPAGE_CONTROLLER_DEBUG: + number = 4; + break; + case MENUPAGE_KEYBOARD_CONTROLS: + switch (m_ControlMethod) { + case CONTROL_STANDARD: + number = 25; break; - case MENUPAGE_CONTROLLER_DEBUG: - number = 4; - break; - case MENUPAGE_KEYBOARD_CONTROLS: - switch (m_ControlMethod) { - case CONTROL_STANDARD: - number = 25; - break; - case CONTROL_CLASSIC: - number = 30; - break; - } + case CONTROL_CLASSIC: + number = 30; break; + } + break; } return number; } @@ -1398,14 +1421,14 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 int bindingMargin = MENU_X(3.0f); float rowHeight; switch (m_ControlMethod) { - case CONTROL_STANDARD: - rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; - break; - case CONTROL_CLASSIC: - rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; - break; - default: - break; + case CONTROL_STANDARD: + rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; + break; + case CONTROL_CLASSIC: + rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; + break; + default: + break; } // MENU_Y(rowHeight * 0.0f + yStart); @@ -1416,163 +1439,164 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (column == CONTSETUP_PED_COLUMN) { switch (optionIdx) { - case 0: - controllerAction = PED_FIREWEAPON; - break; - case 1: - controllerAction = PED_CYCLE_WEAPON_RIGHT; - break; - case 2: - controllerAction = PED_CYCLE_WEAPON_LEFT; - break; - case 3: - controllerAction = GO_FORWARD; - break; - case 4: - controllerAction = GO_BACK; - break; - case 5: - controllerAction = GO_LEFT; - break; - case 6: - controllerAction = GO_RIGHT; - break; - case 7: - controllerAction = PED_SNIPER_ZOOM_IN; - break; - case 8: - controllerAction = PED_SNIPER_ZOOM_OUT; - break; - case 9: - controllerAction = VEHICLE_ENTER_EXIT; - break; - case 10: - case 11: - case 12: - case 16: - case 18: - case 19: - case 20: - case 21: + case 0: + controllerAction = PED_FIREWEAPON; + break; + case 1: + controllerAction = PED_CYCLE_WEAPON_RIGHT; + break; + case 2: + controllerAction = PED_CYCLE_WEAPON_LEFT; + break; + case 3: + controllerAction = GO_FORWARD; + break; + case 4: + controllerAction = GO_BACK; + break; + case 5: + controllerAction = GO_LEFT; + break; + case 6: + controllerAction = GO_RIGHT; + break; + case 7: + controllerAction = PED_SNIPER_ZOOM_IN; + break; + case 8: + controllerAction = PED_SNIPER_ZOOM_OUT; + break; + case 9: + controllerAction = VEHICLE_ENTER_EXIT; + break; + case 10: + case 11: + case 12: + case 16: + case 18: + case 19: + case 20: + case 21: + controllerAction = -1; + break; + case 13: + controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; + break; + case 14: + controllerAction = PED_JUMPING; + break; + case 15: + controllerAction = PED_SPRINT; + break; + case 17: + controllerAction = PED_LOCK_TARGET; + break; + case 22: + controllerAction = PED_LOOKBEHIND; + break; + case 23: + if (m_ControlMethod == CONTROL_STANDARD) controllerAction = -1; - break; - case 13: - controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; - break; - case 14: - controllerAction = PED_JUMPING; - break; - case 15: - controllerAction = PED_SPRINT; - break; - case 17: - controllerAction = PED_LOCK_TARGET; - break; - case 22: - controllerAction = PED_LOOKBEHIND; - break; - case 23: - if (m_ControlMethod == CONTROL_STANDARD) - controllerAction = -1; - else - controllerAction = PED_1RST_PERSON_LOOK_LEFT; - break; - case 24: - if (m_ControlMethod == CONTROL_STANDARD) - controllerAction = -1; - else - controllerAction = PED_1RST_PERSON_LOOK_RIGHT; - break; - case 25: - controllerAction = PED_1RST_PERSON_LOOK_UP; - break; - case 26: - controllerAction = PED_1RST_PERSON_LOOK_DOWN; - break; - case 27: - controllerAction = PED_CYCLE_TARGET_LEFT; - break; - case 28: - controllerAction = PED_CYCLE_TARGET_RIGHT; - break; - case 29: - controllerAction = PED_CENTER_CAMERA_BEHIND_PLAYER; - break; - default: - break; + else + controllerAction = PED_1RST_PERSON_LOOK_LEFT; + break; + case 24: + if (m_ControlMethod == CONTROL_STANDARD) + controllerAction = -1; + else + controllerAction = PED_1RST_PERSON_LOOK_RIGHT; + break; + case 25: + controllerAction = PED_1RST_PERSON_LOOK_UP; + break; + case 26: + controllerAction = PED_1RST_PERSON_LOOK_DOWN; + break; + case 27: + controllerAction = PED_CYCLE_TARGET_LEFT; + break; + case 28: + controllerAction = PED_CYCLE_TARGET_RIGHT; + break; + case 29: + controllerAction = PED_CENTER_CAMERA_BEHIND_PLAYER; + break; + default: + break; } - } else if (column == CONTSETUP_VEHICLE_COLUMN) { + } + else if (column == CONTSETUP_VEHICLE_COLUMN) { switch (optionIdx) { - case 0: - controllerAction = PED_FIREWEAPON; - break; - case 1: - case 2: - case 7: - case 8: - case 14: - case 15: - case 17: - case 25: - case 26: - case 27: - case 28: - case 29: - controllerAction = -1; - break; - case 3: - controllerAction = VEHICLE_ACCELERATE; - break; - case 4: - controllerAction = VEHICLE_BRAKE; - break; - case 5: - controllerAction = GO_LEFT; - break; - case 6: - controllerAction = GO_RIGHT; - break; - case 9: - controllerAction = VEHICLE_ENTER_EXIT; - break; - case 10: - controllerAction = VEHICLE_CHANGE_RADIO_STATION; - break; - case 11: - controllerAction = VEHICLE_HORN; - break; - case 12: - controllerAction = TOGGLE_SUBMISSIONS; - break; - case 13: - controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; - break; - case 16: - controllerAction = VEHICLE_HANDBRAKE; - break; - case 18: - controllerAction = VEHICLE_TURRETLEFT; - break; - case 19: - controllerAction = VEHICLE_TURRETRIGHT; - break; - case 20: - controllerAction = VEHICLE_TURRETUP; - break; - case 21: - controllerAction = VEHICLE_TURRETDOWN; - break; - case 22: - controllerAction = -2; - break; - case 23: - controllerAction = VEHICLE_LOOKLEFT; - break; - case 24: - controllerAction = VEHICLE_LOOKRIGHT; - break; - default: - break; + case 0: + controllerAction = PED_FIREWEAPON; + break; + case 1: + case 2: + case 7: + case 8: + case 14: + case 15: + case 17: + case 25: + case 26: + case 27: + case 28: + case 29: + controllerAction = -1; + break; + case 3: + controllerAction = VEHICLE_ACCELERATE; + break; + case 4: + controllerAction = VEHICLE_BRAKE; + break; + case 5: + controllerAction = GO_LEFT; + break; + case 6: + controllerAction = GO_RIGHT; + break; + case 9: + controllerAction = VEHICLE_ENTER_EXIT; + break; + case 10: + controllerAction = VEHICLE_CHANGE_RADIO_STATION; + break; + case 11: + controllerAction = VEHICLE_HORN; + break; + case 12: + controllerAction = TOGGLE_SUBMISSIONS; + break; + case 13: + controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; + break; + case 16: + controllerAction = VEHICLE_HANDBRAKE; + break; + case 18: + controllerAction = VEHICLE_TURRETLEFT; + break; + case 19: + controllerAction = VEHICLE_TURRETRIGHT; + break; + case 20: + controllerAction = VEHICLE_TURRETUP; + break; + case 21: + controllerAction = VEHICLE_TURRETDOWN; + break; + case 22: + controllerAction = -2; + break; + case 23: + controllerAction = VEHICLE_LOOKLEFT; + break; + case 24: + controllerAction = VEHICLE_LOOKRIGHT; + break; + default: + break; } } int bindingWhite = 155; @@ -1587,7 +1611,8 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (controllerAction == -1) { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); - } else { + } + else { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); } @@ -1595,7 +1620,8 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (controllerAction == -1) { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); - } else { + } + else { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); } @@ -1603,19 +1629,22 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); bindingWhite = 0; - } else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { + } + else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { #ifdef FIX_BUGS if (controllerAction == -1) { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); - } else { + } + else { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); } #else if (controllerAction == -1) { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(235, 170, 50, FadeIn(150))); - } else { + } + else { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(255, 217, 106, FadeIn(210))); } #endif @@ -1628,11 +1657,11 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 // Print bindings, including seperator (-) between them CFont::SetScale(MENU_X(0.25f), MENU_Y(0.6f)); for (int contSetOrder = SETORDER_1; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) { - wchar *settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); + wchar* settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); if (settingText) { ++bindingsForThisOpt; if (bindingsForThisOpt > 1) { - wchar *seperator = TheText.Get("FEC_IBT"); + wchar* seperator = TheText.Get("FEC_IBT"); CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); CFont::PrintString(nextX, nextY, seperator); CFont::SetColor(CRGBA(bindingWhite, bindingWhite, bindingWhite, FadeIn(255))); @@ -1650,19 +1679,23 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (controllerAction == -1) { CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_NUS")); // not used - } else if (controllerAction == -2) { + } + else if (controllerAction == -2) { CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_CMP")); // combo: l+r - } else if (bindingsForThisOpt == 0) { + } + else if (bindingsForThisOpt == 0) { if (m_nSelectedListRow != optionIdx) { CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound - } else if (m_bWaitingForNewKeyBind) { + } + else if (m_bWaitingForNewKeyBind) { if (column != m_nSelectedContSetupColumn) { CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound } - } else { + } + else { if (column != m_nSelectedContSetupColumn) { CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); } @@ -1674,11 +1707,11 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { if (optionIdx == m_nSelectedListRow && controllerAction != -1 && controllerAction != -2) { - m_CurrCntrlAction = controllerAction; + m_CurrCntrlAction = controllerAction; if (m_bWaitingForNewKeyBind) { static bool showWaitingText = false; if (bindingsForThisOpt > 0) { - wchar *seperator = TheText.Get("FEC_IBT"); + wchar* seperator = TheText.Get("FEC_IBT"); CFont::PrintString(nextX, nextY, seperator); nextX += CFont::GetStringWidth(seperator, true) + bindingMargin; } @@ -1697,10 +1730,11 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); if (m_bKeyChangeNotProcessed) { CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_CIG")); // BACKSPACE TO CLEAR - LMB,RETURN TO CHANGE - } else { + } + else { CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_RIG")); // SELECT A NEW CONTROL FOR THIS ACTION OR ESC TO CANCEL } - + CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); @@ -1708,7 +1742,8 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); m_bKeyIsOK = true; - } else { + } + else { CFont::SetCentreOn(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -1720,7 +1755,8 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 m_bKeyIsOK = false; m_bKeyChangeNotProcessed = false; } - } else if (optionIdx == m_nSelectedListRow) { + } + else if (optionIdx == m_nSelectedListRow) { CFont::SetCentreOn(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -1744,7 +1780,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig int numTextsPrinted = 0; int nextX = xStart; for (int j = 1; j < 5; j++) { - wchar *text = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)i, (eContSetOrder)j); + wchar* text = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)i, (eContSetOrder)j); if (text) ++numTextsPrinted; @@ -1780,7 +1816,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig } yStart += lineHeight; } - wchar *error = nil; + wchar* error = nil; if (DisplayComboButtonErrMsg) error = ControlsManager.GetButtonComboText((e_ControllerAction)(m_nCurrOption + extraTextStart)); @@ -1795,14 +1831,14 @@ CMenuManager::DrawControllerSetupScreen() { float rowHeight; switch (m_ControlMethod) { - case CONTROL_STANDARD: - rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; - break; - case CONTROL_CLASSIC: - rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; - break; - default: - break; + case CONTROL_STANDARD: + rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; + break; + case CONTROL_CLASSIC: + rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; + break; + default: + break; } CFont::SetBackgroundOff(); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); @@ -1816,15 +1852,15 @@ CMenuManager::DrawControllerSetupScreen() PREPARE_MENU_HEADER - switch (m_ControlMethod) { + switch (m_ControlMethod) { case CONTROL_STANDARD: CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), - TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), + TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); break; case CONTROL_CLASSIC: CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); @@ -1832,13 +1868,13 @@ CMenuManager::DrawControllerSetupScreen() TheText.Get("FET_CTI")); PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), - TheText.Get("FET_CTI")); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), + TheText.Get("FET_CTI")); break; default: break; - } - wchar *actionTexts[31]; + } + wchar* actionTexts[31]; actionTexts[0] = TheText.Get("FEC_FIR"); actionTexts[1] = TheText.Get("FEC_NWE"); actionTexts[2] = TheText.Get("FEC_PWE"); @@ -1871,7 +1907,8 @@ CMenuManager::DrawControllerSetupScreen() actionTexts[28] = TheText.Get("FEC_PTT"); actionTexts[29] = TheText.Get("FEC_CEN"); actionTexts[30] = nil; - } else { + } + else { actionTexts[18] = TheText.Get("FEC_TFL"); actionTexts[19] = TheText.Get("FEC_TFR"); actionTexts[20] = TheText.Get("FEC_TFU"); @@ -1909,7 +1946,7 @@ CMenuManager::DrawControllerSetupScreen() yStart = CONTSETUP_LIST_HEADER_HEIGHT + 34; for (int i = 0; i < ARRAY_SIZE(actionTexts); ++i) { - wchar *actionText = actionTexts[i]; + wchar* actionText = actionTexts[i]; if (!actionText) break; @@ -1918,47 +1955,50 @@ CMenuManager::DrawControllerSetupScreen() float curOptY = i * rowHeight + yStart; if (m_nMousePosY > MENU_Y(curOptY) && m_nMousePosY < MENU_Y(rowHeight + curOptY)) { - if (m_nPrevOption != i && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + if (m_nPrevOption != i && m_nCurrExLayer == HOVEROPTION_LIST) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nPrevOption = i; - if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_nSelectedListRow = i; + m_nPrevOption = i; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_nSelectedListRow = i; - // why different number for 3rd column hovering X?? this function is a mess + // why different number for 3rd column hovering X?? this function is a mess #ifdef FIX_BUGS - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { #else - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { #endif - if (m_nSelectedContSetupColumn != CONTSETUP_PED_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + if (m_nSelectedContSetupColumn != CONTSETUP_PED_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; + m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; #ifdef FIX_BUGS - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { -#else - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { -#endif - if (m_nSelectedContSetupColumn != CONTSETUP_VEHICLE_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - - m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; - } } - // what?? - if (m_nHoverOption == HOVEROPTION_SKIN) { - if (i == m_nSelectedListRow) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - } - } else + else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { +#else + } + else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { +#endif + if (m_nSelectedContSetupColumn != CONTSETUP_VEHICLE_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + + m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + } + } + // what?? + if (m_nHoverOption == HOVEROPTION_SKIN) { + if (i == m_nSelectedListRow) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + } + else + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } } - } if (m_nSelectedListRow != 35) CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); else if (m_nCurrExLayer == HOVEROPTION_LIST) @@ -1971,7 +2011,7 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetScale(MENU_X(0.32f), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(i * rowHeight + yStart), actionText); - } + } DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), rowHeight, CONTSETUP_PED_COLUMN); DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), rowHeight, CONTSETUP_VEHICLE_COLUMN); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); @@ -1981,11 +2021,13 @@ CMenuManager::DrawControllerSetupScreen() && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - CONTSETUP_BACK_HEIGHT)) || m_nCurrExLayer == HOVEROPTION_BACK) { m_nHoverOption = HOVEROPTION_BACK; - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) + } + else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosY > MENU_Y(CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM + 5.0f)) { m_nHoverOption = HOVEROPTION_LIST; - } else { + } + else { m_nHoverOption = HOVEROPTION_NOT_HOVERING; } @@ -2003,7 +2045,7 @@ CMenuManager::DrawControllerSetupScreen() else CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } -} + } void CMenuManager::DrawFrontEnd() @@ -2022,7 +2064,8 @@ CMenuManager::DrawFrontEnd() bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT }; bbTabCount = 6; } - } else { + } + else { if (bbTabCount != 8) { bbNames[0] = { "FEB_STA",MENUPAGE_STATS }; bbNames[1] = { "FEB_SAV",MENUPAGE_NEW_GAME }; @@ -2043,7 +2086,8 @@ CMenuManager::DrawFrontEnd() if (m_nCurrScreen == MENUPAGE_NONE) { if (m_bGameNotLoaded) { m_nCurrScreen = MENUPAGE_START_MENU; - } else { + } + else { m_nCurrScreen = MENUPAGE_PAUSE_MENU; } } @@ -2053,7 +2097,7 @@ CMenuManager::DrawFrontEnd() m_nCurrOption = 1; #ifdef PS2_SAVE_DIALOG - if(m_bRenderGameInMenu) + if (m_bRenderGameInMenu) DrawFrontEndSaveZone(); else #endif @@ -2093,11 +2137,12 @@ CMenuManager::DrawFrontEndSaveZone() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ + if (field_518 == 4) { m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ + } + else { m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); @@ -2115,9 +2160,10 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); if (!m_bGameNotLoaded) { - CSprite2d *bg = LoadSplash(nil); + CSprite2d* bg = LoadSplash(nil); bg->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - } else { + } + else { CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } @@ -2130,44 +2176,44 @@ CMenuManager::DrawFrontEndNormal() m_aFrontEndSprites[FE2_MAINPANEL_UR].Draw(CRect(SCREEN_WIDTH / 2, 0.0f, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE2_MAINPANEL_DL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), SCREEN_HEIGHT / 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE2_MAINPANEL_DR].Draw(CRect(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); eFrontendSprites currentSprite; switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - case MENUPAGE_EXIT: - currentSprite = FE_ICONSTATS; - break; - case MENUPAGE_LANGUAGE_SETTINGS: - currentSprite = FE_ICONLANGUAGE; - break; - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - currentSprite = FE_ICONSAVE; - break; - case MENUPAGE_GRAPHICS_SETTINGS: - currentSprite = FE_ICONDISPLAY; - break; - case MENUPAGE_SOUND_SETTINGS: - currentSprite = FE_ICONAUDIO; - break; - case MENUPAGE_CONTROLLER_PC: - case MENUPAGE_OPTIONS: - case MENUPAGE_CONTROLLER_SETTINGS: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - currentSprite = FE_ICONCONTROLS; - break; - default: - /*case MENUPAGE_NEW_GAME: */ - /*case MENUPAGE_BRIEFS: */ - currentSprite = FE_ICONBRIEF; - break; + case MENUPAGE_STATS: + case MENUPAGE_START_MENU: + case MENUPAGE_PAUSE_MENU: + case MENUPAGE_EXIT: + currentSprite = FE_ICONSTATS; + break; + case MENUPAGE_LANGUAGE_SETTINGS: + currentSprite = FE_ICONLANGUAGE; + break; + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + currentSprite = FE_ICONSAVE; + break; + case MENUPAGE_GRAPHICS_SETTINGS: + currentSprite = FE_ICONDISPLAY; + break; + case MENUPAGE_SOUND_SETTINGS: + currentSprite = FE_ICONAUDIO; + break; + case MENUPAGE_CONTROLLER_PC: + case MENUPAGE_OPTIONS: + case MENUPAGE_CONTROLLER_SETTINGS: + case MENUPAGE_KEYBOARD_CONTROLS: + case MENUPAGE_MOUSE_CONTROLS: + currentSprite = FE_ICONCONTROLS; + break; + default: + /*case MENUPAGE_NEW_GAME: */ + /*case MENUPAGE_BRIEFS: */ + currentSprite = FE_ICONBRIEF; + break; } m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); @@ -2183,7 +2229,8 @@ CMenuManager::DrawFrontEndNormal() if (m_nMenuFadeAlpha <= 0 && reverseAlpha) { reverseAlpha = false; ChangeScreen(pendingScreen, pendingOption, true, false); - } else { + } + else { // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) if (!reverseAlpha) fadeAlpha += (frameTime) * 20.f / 33.f; @@ -2191,9 +2238,10 @@ CMenuManager::DrawFrontEndNormal() fadeAlpha = max(0.0f, fadeAlpha - (frameTime) * 30.f / 33.f); m_nMenuFadeAlpha = fadeAlpha; - } + } lastState = 0; - } else { + } + else { if (lastState == 0) fadeAlpha = 255.f; if (reverseAlpha) { @@ -2204,8 +2252,8 @@ CMenuManager::DrawFrontEndNormal() lastState = 1; // TODO: what is this? waiting mouse? - if(field_518 == 4){ - if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || + if (field_518 == 4) { + if (m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) field_518 = 2; @@ -2218,28 +2266,28 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); switch (m_nCurrScreen) { - case MENUPAGE_SKIN_SELECT: - DrawPlayerSetupScreen(); - break; - case MENUPAGE_KEYBOARD_CONTROLS: - DrawControllerSetupScreen(); - break; - default: - Draw(); - break; + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + default: + Draw(); + break; } - #define optionWidth MENU_X(66.0f) - #define rawOptionHeight 22.0f - #define optionBottom SCREEN_SCALE_FROM_BOTTOM(20.0f) - #define optionTop SCREEN_SCALE_FROM_BOTTOM(20.0f + rawOptionHeight) - #define leftPadding MENU_X_LEFT_ALIGNED(90.0f) - wchar *str; +#define optionWidth MENU_X(66.0f) +#define rawOptionHeight 22.0f +#define optionBottom SCREEN_SCALE_FROM_BOTTOM(20.0f) +#define optionTop SCREEN_SCALE_FROM_BOTTOM(20.0f + rawOptionHeight) +#define leftPadding MENU_X_LEFT_ALIGNED(90.0f) + wchar* str; hoveredBottomBarOption = -1; if (curBottomBarOption != -1) { // This active tab sprite is needlessly big - m_aFrontEndSprites[FE2_TABACTIVE].Draw(CRect(leftPadding - MENU_X(2.0f) + (optionWidth) * curBottomBarOption, optionTop, + m_aFrontEndSprites[FE2_TABACTIVE].Draw(CRect(leftPadding - MENU_X(2.0f) + (optionWidth)*curBottomBarOption, optionTop, leftPadding - MENU_X(5.0f) + optionWidth * (curBottomBarOption + 2), optionBottom + MENU_Y(rawOptionHeight - 9.0f)), CRGBA(CRGBA(255, 255, 255, 255))); @@ -2254,23 +2302,23 @@ CMenuManager::DrawFrontEndNormal() if (hoveredBottomBarOption == i && hoveredBottomBarOption != curBottomBarOption) CFont::SetColor(CRGBA(235, 170, 50, 255)); else { - if(bottomBarActive || curBottomBarOption == i) + if (bottomBarActive || curBottomBarOption == i) CFont::SetColor(CRGBA(0, 0, 0, 255)); else CFont::SetColor(CRGBA(0, 0, 0, 110)); } str = TheText.Get(bbNames[i].name); - + CFont::PrintString(xStart + MENU_X(4.0f), SCREEN_SCALE_FROM_BOTTOM(39.0f), str); - + } } - #undef optionBottom - #undef optionTop - #undef leftPadding - #undef optionWidth - #undef rawOptionHeight +#undef optionBottom +#undef optionTop +#undef leftPadding +#undef optionWidth +#undef rawOptionHeight CFont::DrawFonts(); @@ -2287,11 +2335,12 @@ CMenuManager::DrawFrontEndNormal() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ + if (field_518 == 4) { m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ + } + else { m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); @@ -2307,7 +2356,7 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); LoadSplash(nil); - + eMenuSprites previousSprite = MENUSPRITE_BACKGROUND; if (m_nMenuFadeAlpha < 255) { @@ -2323,29 +2372,29 @@ CMenuManager::DrawFrontEndNormal() eMenuSprites currentSprite = MENUSPRITE_BACKGROUND; // actually uninitialized switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - case MENUPAGE_NEW_GAME: - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_EXIT: - case MENUPAGE_MULTIPLAYER_MAIN: - case MENUPAGE_MULTIPLAYER_MAP: - case MENUPAGE_MULTIPLAYER_FIND_GAME: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - case MENUPAGE_MULTIPLAYER_CONNECTION: - case MENUPAGE_MULTIPLAYER_MODE: - case MENUPAGE_MULTIPLAYER_CREATE: - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - currentSprite = MENUSPRITE_BACKGROUND; - break; + case MENUPAGE_STATS: + case MENUPAGE_START_MENU: + case MENUPAGE_PAUSE_MENU: + case MENUPAGE_NEW_GAME: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + case MENUPAGE_EXIT: + case MENUPAGE_MULTIPLAYER_MAIN: + case MENUPAGE_MULTIPLAYER_MAP: + case MENUPAGE_MULTIPLAYER_FIND_GAME: + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_KEYBOARD_CONTROLS: + case MENUPAGE_MOUSE_CONTROLS: + case MENUPAGE_MULTIPLAYER_CONNECTION: + case MENUPAGE_MULTIPLAYER_MODE: + case MENUPAGE_MULTIPLAYER_CREATE: + case MENUPAGE_SKIN_SELECT_OLD: + case MENUPAGE_OPTIONS: + currentSprite = MENUSPRITE_BACKGROUND; + break; } if (m_nMenuFadeAlpha < 255) { @@ -2361,23 +2410,25 @@ CMenuManager::DrawFrontEndNormal() #else static uint32 LastFade = 0; - if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10) { m_nMenuFadeAlpha += 20; LastFade = CTimer::GetTimeInMillisecondsPauseMode(); } #endif - - if (m_nMenuFadeAlpha > 255){ + + if (m_nMenuFadeAlpha > 255) { m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - } else { + } + else { RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); } - } else { + } + else { m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); // TODO: what is this? waiting mouse? - if(field_518 == 4){ - if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || + if (field_518 == 4) { + if (m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) field_518 = 2; @@ -2405,15 +2456,15 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); switch (m_nCurrScreen) { - case MENUPAGE_SKIN_SELECT: - DrawPlayerSetupScreen(); - break; - case MENUPAGE_KEYBOARD_CONTROLS: - DrawControllerSetupScreen(); - break; - default: - Draw(); - break; + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + default: + Draw(); + break; } CFont::DrawFonts(); @@ -2431,11 +2482,12 @@ CMenuManager::DrawFrontEndNormal() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ + if (field_518 == 4) { m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ + } + else { m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); @@ -2459,7 +2511,7 @@ CMenuManager::DrawPlayerSetupScreen() PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // lstrcpy's changed with strcpy @@ -2540,17 +2592,18 @@ CMenuManager::DrawPlayerSetupScreen() } } } - } + } OutputDebugString("Finished enumerating skin files."); m_bSkinsEnumerated = true; - } + } CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(200, 200, 50, FadeIn(50))); // Header (Skin - Date) if (m_nCurrExLayer == HOVEROPTION_LIST) { CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } else { + } + else { CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -2558,13 +2611,13 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetRightJustifyOn(); CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_DAT")); switch (m_PrefsLanguage) { - case LANGUAGE_FRENCH: - case LANGUAGE_SPANISH: - CFont::SetScale(MENU_X(0.6f), MENU_Y(MENUACTION_SCALE_MULT)); - break; - default: - CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); - break; + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + CFont::SetScale(MENU_X(0.6f), MENU_Y(MENUACTION_SCALE_MULT)); + break; + default: + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); + break; } CFont::SetRightJustifyOff(); CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_SKN")); @@ -2581,7 +2634,7 @@ CMenuManager::DrawPlayerSetupScreen() int orderInVisibles = 0; int rowEndY = PLAYERSETUP_LIST_BODY_TOP + PLAYERSETUP_ROW_HEIGHT + 1; int rowStartY = PLAYERSETUP_LIST_BODY_TOP; - for (int rowIdx = m_nFirstVisibleRowOnList; + for (int rowIdx = m_nFirstVisibleRowOnList; rowIdx < m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW && m_pSelectedSkin; ) { if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)) { @@ -2599,7 +2652,8 @@ CMenuManager::DrawPlayerSetupScreen() CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); } - } else { + } + else { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_nCurrExLayer = HOVEROPTION_LIST; m_nSelectedListRow = rowIdx; @@ -2618,9 +2672,11 @@ CMenuManager::DrawPlayerSetupScreen() CWorld::Players[0].SetPlayerSkin(m_aSkinName); } lastSelectedSkin = m_nSelectedListRow; - } else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) { + } + else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) { CFont::SetColor(CRGBA(255, 255, 155, FadeIn(255))); - } else { + } + else { CFont::SetColor(CRGBA(155, 155, 155, FadeIn(255))); } wchar unicodeTemp[80]; @@ -2646,9 +2702,9 @@ CMenuManager::DrawPlayerSetupScreen() // Scrollbar background CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205))); - + // Scrollbar - float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float) MAX_VISIBLE_LIST_ROW; + float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float)MAX_VISIBLE_LIST_ROW; float scrollbarBottom, scrollbarTop; if (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) { scrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f); @@ -2657,7 +2713,8 @@ CMenuManager::DrawPlayerSetupScreen() // Shadow CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255))); - } else { + } + else { #ifdef FIX_BUGS scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight); scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin); @@ -2688,7 +2745,8 @@ CMenuManager::DrawPlayerSetupScreen() MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), CRGBA(255, 255, 255, FadeIn(255))); #endif - } else { + } + else { #ifdef FIX_BUGS m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), @@ -2707,10 +2765,11 @@ CMenuManager::DrawPlayerSetupScreen() CRGBA(255, 255, 255, FadeIn(255))); #else m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), - MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), + MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), CRGBA(255, 255, 255, FadeIn(255))); #endif - } else { + } + else { #ifdef FIX_BUGS m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), @@ -2728,19 +2787,19 @@ CMenuManager::DrawPlayerSetupScreen() if (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); switch (m_PrefsLanguage) { - case LANGUAGE_FRENCH: - CFont::SetScale(MENU_X(1.1f), MENU_Y(1.9f)); - break; - case LANGUAGE_GERMAN: - CFont::SetScale(MENU_X(0.85f), MENU_Y(1.9f)); - break; - case LANGUAGE_ITALIAN: - case LANGUAGE_SPANISH: - CFont::SetScale(MENU_X(1.4f), MENU_Y(1.9f)); - break; - default: - CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); - break; + case LANGUAGE_FRENCH: + CFont::SetScale(MENU_X(1.1f), MENU_Y(1.9f)); + break; + case LANGUAGE_GERMAN: + CFont::SetScale(MENU_X(0.85f), MENU_Y(1.9f)); + break; + case LANGUAGE_ITALIAN: + case LANGUAGE_SPANISH: + CFont::SetScale(MENU_X(1.4f), MENU_Y(1.9f)); + break; + default: + CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); + break; } CFont::SetColor(CRGBA(255, 217, 106, FadeIn(120))); CFont::SetRightJustifyOff(); @@ -2760,7 +2819,8 @@ CMenuManager::DrawPlayerSetupScreen() m_nHoverOption = HOVEROPTION_BACK; - } else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0 + } + else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0 && m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) + CFont::GetStringWidth(TheText.Get("FES_SET"), true) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3) @@ -2771,31 +2831,35 @@ CMenuManager::DrawPlayerSetupScreen() m_nHoverOption = HOVEROPTION_USESKIN; - } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } + else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_TOP) && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3)) { if (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN) m_nHoverOption = HOVEROPTION_OVER_SCROLL_UP; - } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } + else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) { if (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN) m_nHoverOption = HOVEROPTION_OVER_SCROLL_DOWN; - } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } + else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) - && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3) + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3) #ifdef FIX_BUGS - && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)) { + && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)) { #else - && m_nMousePosY < MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)) { + && m_nMousePosY < MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)) { #endif m_nHoverOption = HOVEROPTION_PAGEUP; - } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } + else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) #ifdef FIX_BUGS && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight) @@ -2805,7 +2869,8 @@ CMenuManager::DrawPlayerSetupScreen() && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1)) { m_nHoverOption = HOVEROPTION_PAGEDOWN; - } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4) + } + else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH) #ifdef FIX_BUGS && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin) @@ -2816,14 +2881,16 @@ CMenuManager::DrawPlayerSetupScreen() #endif m_nHoverOption = HOVEROPTION_HOLDING_SCROLLBAR; - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT) + } + else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT) && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + 1) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) { m_nHoverOption = HOVEROPTION_LIST; - } else { + } + else { m_nHoverOption = HOVEROPTION_NOT_HOVERING; } - } + } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); CFont::SetRightJustifyOn(); @@ -2834,7 +2901,8 @@ CMenuManager::DrawPlayerSetupScreen() CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - i), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FEDS_TB")); if (m_nHoverOption == HOVEROPTION_BACK) { CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } else { + } + else { CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } } @@ -2846,14 +2914,16 @@ CMenuManager::DrawPlayerSetupScreen() CFont::PrintString(MENU_X_LEFT_ALIGNED(i + PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FES_SET")); if (!strcmp(m_aSkinName, m_PrefsSkinFile)) { CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); - } else if (m_nHoverOption == HOVEROPTION_USESKIN) { + } + else if (m_nHoverOption == HOVEROPTION_USESKIN) { CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } else { + } + else { CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } } -} + } int CMenuManager::FadeIn(int alpha) @@ -2867,27 +2937,28 @@ CMenuManager::FadeIn(int alpha) } void -CMenuManager::FilterOutColorMarkersFromString(wchar *str, CRGBA &newColor) +CMenuManager::FilterOutColorMarkersFromString(wchar * str, CRGBA & newColor) { int newIdx = 0; - wchar copy[256], *c; + wchar copy[256], * c; UnicodeStrcpy(copy, str); for (c = copy; *c != '\0'; c++) { if (*c == '~') { c++; switch (*c) { - case 'b': newColor = CRGBA(40, 40, 255, 255); break; - case 'g': newColor = CRGBA(40, 235, 40, 255); break; + case 'b': newColor = CRGBA(40, 40, 255, 255); break; + case 'g': newColor = CRGBA(40, 235, 40, 255); break; // There is no case for "h", is that a mistake? - case 'l': newColor = CRGBA(0, 0, 0, 255); break; - case 'p': newColor = CRGBA(255, 0, 255, 255); break; - case 'r': newColor = CRGBA(255, 0, 0, 255); break; - case 'w': newColor = CRGBA(255, 255, 255, 255); break; - case 'y': newColor = CRGBA(255, 255, 0, 255); break; + case 'l': newColor = CRGBA(0, 0, 0, 255); break; + case 'p': newColor = CRGBA(255, 0, 255, 255); break; + case 'r': newColor = CRGBA(255, 0, 0, 255); break; + case 'w': newColor = CRGBA(255, 255, 255, 255); break; + case 'y': newColor = CRGBA(255, 255, 0, 255); break; } while (*c != '~') c++; - } else { + } + else { str[newIdx++] = *c; } } @@ -2899,17 +2970,17 @@ CMenuManager::GetStartOptionsCntrlConfigScreens() { int number = 0; switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD3: - number = 34; - break; - case MENUPAGE_CONTROLLER_DEBUG: - number = 35; - break; - case MENUPAGE_KEYBOARD_CONTROLS: - number = 0; - break; - default: - break; + case MENUPAGE_CONTROLLER_PC_OLD3: + number = 34; + break; + case MENUPAGE_CONTROLLER_DEBUG: + number = 35; + break; + case MENUPAGE_KEYBOARD_CONTROLS: + number = 0; + break; + default: + break; } return number; } @@ -2980,9 +3051,10 @@ CMenuManager::LoadAllTextures() if (DMAudio.IsMP3RadioChannelAvailable()) { if (m_PrefsRadioStation > USERTRACK) m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; - } else if (m_PrefsRadioStation > CHATTERBOX) + } + else if (m_PrefsRadioStation > CHATTERBOX) m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; - + CFileMgr::SetDir(""); //CFileMgr::SetDir(""); CTimer::Stop(); @@ -2992,7 +3064,7 @@ CMenuManager::LoadAllTextures() CTxdStore::PushCurrentTxd(); int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1"); - if(frontendTxdSlot1 == -1) + if (frontendTxdSlot1 == -1) frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1"); printf("LOAD frontend1\n"); @@ -3074,7 +3146,7 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, (char*)&m_nPrefsDepth, sizeof(m_nPrefsDepth)); CFileMgr::Read(fileHandle, (char*)&m_nPrefsWindowed, sizeof(m_nPrefsWindowed)); CFileMgr::Read(fileHandle, (char*)&m_nPrefsSubsystem, sizeof(m_nPrefsSubsystem)); - if(m_nPrefsWindowed != 0 && m_nPrefsWindowed != 1){ + if (m_nPrefsWindowed != 0 && m_nPrefsWindowed != 1) { // garbage data from vanilla settings file // let skeleton find something m_nPrefsWidth = 0; @@ -3143,7 +3215,7 @@ CMenuManager::LoadSettings() } WIN32_FIND_DATA FindFileData; - char skinfile[256+16]; // Stack analysis shows 16 bits gap, but I don't trust it. It may very well be MAX_PATH(260). + char skinfile[256 + 16]; // Stack analysis shows 16 bits gap, but I don't trust it. It may very well be MAX_PATH(260). bool SkinFound = false; HANDLE handle = FindFirstFile("skins\\*.bmp", &FindFileData); for (int i = 1; handle != INVALID_HANDLE_VALUE && i; i = FindNextFile(handle, &FindFileData)) { @@ -3221,9 +3293,9 @@ bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 Bo void DoRWStuffEndOfFrame(void); void -CMenuManager::MessageScreen(const char *text) +CMenuManager::MessageScreen(const char* text) { - CSprite2d *splash = LoadSplash(nil); + CSprite2d* splash = LoadSplash(nil); if (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)) return; @@ -3279,7 +3351,7 @@ CMenuManager::PrintBriefs() float nextY = BRIEFS_TOP_MARGIN; CRGBA newColor; for (int i = 4; i >= 0; i--) { - tPreviousBrief &brief = CMessages::PreviousBriefs[i]; + tPreviousBrief& brief = CMessages::PreviousBriefs[i]; if (brief.m_pText) { CMessages::InsertNumberInString(brief.m_pText, brief.m_nNumber[0], brief.m_nNumber[1], @@ -3360,7 +3432,8 @@ CMenuManager::PrintStats() if (CPad::GetPad(0)->GetLeftMouse()) { scrollY += (m_nMouseOldPosY - m_nMousePosY); lastChange = CTimer::GetTimeInMillisecondsPauseMode(); - } else { + } + else { scrollY += MENU_Y(STATS_SLIDE_Y_PER_SECOND) / 1000.0f * (CTimer::GetTimeInMillisecondsPauseMode() - lastChange); lastChange = CTimer::GetTimeInMillisecondsPauseMode(); } @@ -3386,13 +3459,15 @@ CMenuManager::PrintStats() else alphaMult = (y - MENU_Y(STATS_BOTTOM_MARGIN)) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); - // About to dim from bottom - } else if (y > SCREEN_SCALE_FROM_BOTTOM(STATS_TOP_DIMMING_AREA_LENGTH) - MENU_Y(STATS_BOTTOM_DIMMING_AREA_LENGTH)) { + // About to dim from bottom + } + else if (y > SCREEN_SCALE_FROM_BOTTOM(STATS_TOP_DIMMING_AREA_LENGTH) - MENU_Y(STATS_BOTTOM_DIMMING_AREA_LENGTH)) { if ((SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH) < 0.0f) alphaMult = 0.0f; else alphaMult = (SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); - } else + } + else alphaMult = 1.0f; CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255.0f * alphaMult))); @@ -3466,7 +3541,7 @@ CMenuManager::Process(void) SlotPopulated = true; } - if (SlotPopulated) + if (SlotPopulated) ChangeScreen(MENUPAGE_DELETE_SUCCESS, 0, true, false); else SaveLoadFileError_SetUpErrorScreen(); @@ -3492,7 +3567,8 @@ CMenuManager::Process(void) DMAudio.SetEffectsFadeVol(0); DMAudio.SetMusicFadeVol(0); DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); - } else + } + else SaveLoadFileError_SetUpErrorScreen(); } @@ -3542,12 +3618,14 @@ CMenuManager::Process(void) m_bWaitingForNewKeyBind = false; m_KeyPressedCode = -1; m_bStartWaitingForKeyBind = false; - } else if (!m_bKeyChangeNotProcessed) { + } + else if (!m_bKeyChangeNotProcessed) { if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) CheckCodesForControls(TypeOfControl); field_535 = true; - } else { + } + else { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); for (int i = 0; i < 4; i++) ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); @@ -3572,7 +3650,8 @@ CMenuManager::Process(void) TimeToStopPadShaking = 0; } - } else { + } + else { UnloadTextures(); m_bRenderGameInMenu = false; // byte_5F33E4 = 1; // unused @@ -3641,7 +3720,8 @@ CMenuManager::ProcessButtonPresses(void) m_bKeyChangeNotProcessed = true; pControlEdit = &m_KeyPressedCode; } - } else { + } + else { field_535 = false; } @@ -3660,15 +3740,15 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_bShowMouse = false; switch (m_nCurrExLayer) { - case HOVEROPTION_BACK: - default: - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case HOVEROPTION_LIST: - m_nCurrExLayer = HOVEROPTION_USESKIN; - break; - case HOVEROPTION_USESKIN: - m_nCurrExLayer = HOVEROPTION_BACK; + case HOVEROPTION_BACK: + default: + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case HOVEROPTION_LIST: + m_nCurrExLayer = HOVEROPTION_USESKIN; + break; + case HOVEROPTION_USESKIN: + m_nCurrExLayer = HOVEROPTION_BACK; } if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { m_nCurrExLayer = HOVEROPTION_BACK; @@ -3682,7 +3762,8 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; pressed = true; - } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { + } + else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { m_bShowMouse = true; pressed = true; } @@ -3696,7 +3777,8 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); ScrollUpListByOne(); } - } else { + } + else { m_bPressedUpOnList = false; } @@ -3704,7 +3786,8 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; pressed = true; - } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + } + else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { m_bShowMouse = true; pressed = true; } @@ -3718,14 +3801,16 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); ScrollDownListByOne(); } - } else { + } + else { m_bPressedDownOnList = false; } if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { if (!CPad::GetPad(0)->GetPageUp()) { m_bPressedPgUpOnList = false; - } else { + } + else { m_nCurrExLayer = HOVEROPTION_LIST; if (!m_bPressedPgUpOnList) { m_bPressedPgUpOnList = true; @@ -3737,7 +3822,8 @@ CMenuManager::ProcessButtonPresses(void) } if (!CPad::GetPad(0)->GetPageDown()) { m_bPressedPgDnOnList = false; - } else { + } + else { m_nCurrExLayer = HOVEROPTION_LIST; if (!m_bPressedPgDnOnList) { m_bPressedPgDnOnList = true; @@ -3778,50 +3864,53 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetLeftMouseJustDown()) { switch (m_nHoverOption) { - case HOVEROPTION_BACK: - goBack = true; - break; - case HOVEROPTION_PAGEUP: - PageUpList(true); - break; - case HOVEROPTION_PAGEDOWN: - PageDownList(true); - break; - case HOVEROPTION_USESKIN: - if (m_nSkinsTotal > 0) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - m_pSelectedSkin = m_pSkinListHead.nextSkin; - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - SaveSettings(); - } + case HOVEROPTION_BACK: + goBack = true; + break; + case HOVEROPTION_PAGEUP: + PageUpList(true); + break; + case HOVEROPTION_PAGEDOWN: + PageDownList(true); + break; + case HOVEROPTION_USESKIN: + if (m_nSkinsTotal > 0) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + m_pSelectedSkin = m_pSkinListHead.nextSkin; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } } } if (CPad::GetPad(0)->GetLeftMouseJustDown()) { switch (m_nHoverOption) { - case HOVEROPTION_OVER_SCROLL_UP: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; - break; - case HOVEROPTION_OVER_SCROLL_DOWN: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; - break; - case HOVEROPTION_LIST: - m_nHoverOption = HOVEROPTION_SKIN; + case HOVEROPTION_OVER_SCROLL_UP: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; + break; + case HOVEROPTION_LIST: + m_nHoverOption = HOVEROPTION_SKIN; } - } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) + } + else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; } if (!CPad::GetPad(0)->GetLeftMouse()) { holdingScrollBar = false; - } else { + } + else { if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { holdingScrollBar = true; // TODO: This part is a bit hard to reverse. Not much code tho assert(0 && "Holding scrollbar isn't done yet"); - } else { + } + else { switch (m_nHoverOption) { case HOVEROPTION_OVER_SCROLL_UP: case HOVEROPTION_CLICKED_SCROLL_UP: @@ -3844,7 +3933,8 @@ CMenuManager::ProcessButtonPresses(void) } } } - } else if (isPlainTextScreen(m_nCurrScreen)) { + } + else if (isPlainTextScreen(m_nCurrScreen)) { #ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) { optionSelected = true; @@ -3855,12 +3945,14 @@ CMenuManager::ProcessButtonPresses(void) } } #endif - } else { + } + else { if (CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); goDown = true; - } else if (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + } + else if (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); goUp = true; @@ -3872,7 +3964,8 @@ CMenuManager::ProcessButtonPresses(void) m_bShowMouse = false; optionSelected = true; } - } else { + } + else { if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { m_bShowMouse = false; optionSelected = true; @@ -3888,9 +3981,10 @@ CMenuManager::ProcessButtonPresses(void) #endif (m_nHoverOption == HOVEROPTION_RANDOM_ITEM)) { m_nCurrOption = m_nPrevOption; - optionSelected = true; + optionSelected = true; } - } else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + } + else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { #ifdef TIDY_UP_PBP if (m_nHoverOption >= HOVEROPTION_RADIO_0 && m_nHoverOption <= HOVEROPTION_RADIO_9) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); @@ -3899,7 +3993,8 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); OutputDebugString("FRONTEND RADIO STATION CHANGED"); - } else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM + } + else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESUME) { m_nCurrOption = m_nPrevOption; optionSelected = true; @@ -4082,26 +4177,26 @@ CMenuManager::ProcessButtonPresses(void) TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; - } + } #else switch (m_nHoverOption) { - case HOVEROPTION_INCREASE_BRIGHTNESS: - case HOVEROPTION_INCREASE_DRAWDIST: - case HOVEROPTION_INCREASE_MUSICVOLUME: - case HOVEROPTION_INCREASE_SFXVOLUME: - case HOVEROPTION_INCREASE_MOUSESENS: - CheckSliderMovement(1); - break; - case HOVEROPTION_DECREASE_BRIGHTNESS: - case HOVEROPTION_DECREASE_DRAWDIST: - case HOVEROPTION_DECREASE_MUSICVOLUME: - case HOVEROPTION_DECREASE_SFXVOLUME: - case HOVEROPTION_DECREASE_MOUSESENS: - CheckSliderMovement(-1); - break; + case HOVEROPTION_INCREASE_BRIGHTNESS: + case HOVEROPTION_INCREASE_DRAWDIST: + case HOVEROPTION_INCREASE_MUSICVOLUME: + case HOVEROPTION_INCREASE_SFXVOLUME: + case HOVEROPTION_INCREASE_MOUSESENS: + CheckSliderMovement(1); + break; + case HOVEROPTION_DECREASE_BRIGHTNESS: + case HOVEROPTION_DECREASE_DRAWDIST: + case HOVEROPTION_DECREASE_MUSICVOLUME: + case HOVEROPTION_DECREASE_SFXVOLUME: + case HOVEROPTION_DECREASE_MOUSESENS: + CheckSliderMovement(-1); + break; } #endif - } + } if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp() || CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp() @@ -4135,7 +4230,7 @@ CMenuManager::ProcessButtonPresses(void) goBack = false; } #endif - } + } // Centralized enter/back (except some conditions) #ifdef TIDY_UP_PBP @@ -4148,7 +4243,8 @@ CMenuManager::ProcessButtonPresses(void) optionSelected = true; } - } else { + } + else { if (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) { m_bShowMouse = false; optionSelected = true; @@ -4161,7 +4257,8 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustUp()) { goBack = true; } - } else { + } + else { if (CPad::GetPad(0)->GetEscapeJustDown() || (m_nCurrScreen != MENUPAGE_PAUSE_MENU && CPad::GetPad(0)->GetBackJustDown())) { m_bShowMouse = false; goBack = true; @@ -4178,7 +4275,8 @@ CMenuManager::ProcessButtonPresses(void) curBottomBarOption = hoveredBottomBarOption; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, false); return; - } else if (bottomBarActive) { + } + else if (bottomBarActive) { if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); bottomBarActive = false; @@ -4187,7 +4285,8 @@ CMenuManager::ProcessButtonPresses(void) if (reverseAlpha) m_nMenuFadeAlpha = 0; return; - } else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown() + } + else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown() || CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); @@ -4195,11 +4294,12 @@ CMenuManager::ProcessButtonPresses(void) curBottomBarOption--; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); return; - } else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown() + } + else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown() || CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - if (curBottomBarOption < bbTabCount-1) + if (curBottomBarOption < bbTabCount - 1) curBottomBarOption++; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); return; @@ -4222,7 +4322,8 @@ CMenuManager::ProcessButtonPresses(void) && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption + 1].m_Action != MENUACTION_NOTHING) { m_nCurrOption++; } - } else { + } + else { m_nCurrOption--; } } @@ -4238,9 +4339,11 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); else DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - } else + } + else DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_COMPLETED, 0); - } else { + } + else { // This is duplicate, back button already processed below #ifndef TIDY_UP_PBP DMAudio.PlayFrontEndSound(SOUND_FRONTEND_EXIT, 0); @@ -4250,15 +4353,18 @@ CMenuManager::ProcessButtonPresses(void) } #endif } - } else if (option == MENUACTION_CHECKSAVE) { + } + else if (option == MENUACTION_CHECKSAVE) { if (Slots[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot - 1] == SLOT_EMPTY) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - } else { + } + else { if (m_nCurrScreen != MENUPAGE_NEW_GAME_RELOAD) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); } } - } else if (option != MENUACTION_CHANGEMENU && option != MENUACTION_BRIGHTNESS && option != MENUACTION_DRAWDIST + } + else if (option != MENUACTION_CHANGEMENU && option != MENUACTION_BRIGHTNESS && option != MENUACTION_DRAWDIST && option != MENUACTION_MUSICVOLUME && option != MENUACTION_SFXVOLUME && option != MENUACTION_CHECKSAVE && option != MENUACTION_UNK24 && option != MENUACTION_MOUSESENS && option != MENUACTION_SCREENRES) { @@ -4268,382 +4374,392 @@ CMenuManager::ProcessButtonPresses(void) if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) || (m_nCurrScreen == MENUPAGE_SKIN_SELECT)) { switch (m_nCurrExLayer) { - default: - goBack = true; - break; - case HOVEROPTION_LIST: - if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - } - if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - m_nCurrExLayer = HOVEROPTION_BACK; - SaveSettings(); - } - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - break; - case HOVEROPTION_USESKIN: - m_nHoverOption = HOVEROPTION_NOT_HOVERING; + default: + goBack = true; + break; + case HOVEROPTION_LIST: + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); m_nCurrExLayer = HOVEROPTION_BACK; SaveSettings(); - break; + } + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + break; + case HOVEROPTION_USESKIN: + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + m_nCurrExLayer = HOVEROPTION_BACK; + SaveSettings(); + break; } - } else if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { + } + else if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { DoSettingsBeforeStartingAGame(); -/* } else if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - // .. either empty or there was some outer if. :shrug: pointless anyway, keyboard_controls is handled in first if. -*/ - } else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + /* } else if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + // .. either empty or there was some outer if. :shrug: pointless anyway, keyboard_controls is handled in first if. + */ + } + else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { if (m_nSkinsTotal > 0) { m_pSelectedSkin = m_pSkinListHead.nextSkin; strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); - } else { + } + else { if (!m_bGameNotLoaded) ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); else ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); } - } else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { + } + else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; switch (option) { - case MENUACTION_RADIO: + case MENUACTION_RADIO: #ifdef TIDY_UP_PBP - assumeIncrease = true; + assumeIncrease = true; #else - ++m_PrefsRadioStation; - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; - } else if (m_PrefsRadioStation > CHATTERBOX) { - m_PrefsRadioStation = USERTRACK; + ++m_PrefsRadioStation; + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = HEAD_RADIO; + } + else if (m_PrefsRadioStation > CHATTERBOX) { + m_PrefsRadioStation = USERTRACK; + } + SaveSettings(); + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("FRONTEND RADIO STATION CHANGED"); +#endif + break; + case MENUACTION_LANG_ENG: + m_PrefsLanguage = LANGUAGE_AMERICAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_FRE: + m_PrefsLanguage = LANGUAGE_FRENCH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_GER: + m_PrefsLanguage = LANGUAGE_GERMAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_ITA: + m_PrefsLanguage = LANGUAGE_ITALIAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_SPA: + m_PrefsLanguage = LANGUAGE_SPANISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; +#ifdef MORE_LANGUAGES + case MENUACTION_LANG_PL: + m_PrefsLanguage = LANGUAGE_POLISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_RUS: + m_PrefsLanguage = LANGUAGE_RUSSIAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + CMenuManager::InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_JAP: + m_PrefsLanguage = LANGUAGE_JAPANESE; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; +#endif + case MENUACTION_POPULATESLOTS_CHANGEMENU: + PcSaveHelper.PopulateSlotInfo(); + + // fall through + case MENUACTION_CHANGEMENU: + { + bool changeMenu = true; + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + // This should be unused. + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = saveSlot - 2; + switch (m_nCurrScreen) { + case MENUPAGE_CHOOSE_LOAD_SLOT: + if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY) + changeMenu = false; + + break; + case MENUPAGE_CHOOSE_DELETE_SLOT: + if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY) + changeMenu = false; + + break; + } + } + if (changeMenu) { + if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) { +#ifndef TIDY_UP_PBP + ResetHelperText(); + if (!m_bGameNotLoaded) + ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); + else + ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); +#else + goBack = true; + break; +#endif + } + else { +#ifdef MENU_MAP + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { + bMapLoaded = false; + } + +#endif + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + } + } + break; + } + case MENUACTION_CHECKSAVE: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = saveSlot - 2; + if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY && Slots[m_nCurrSaveSlot + 1] != SLOT_CORRUPTED) { + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + } + } + break; + } + case MENUACTION_NEWGAME: + DoSettingsBeforeStartingAGame(); + break; + case MENUACTION_RELOADIDE: + CFileLoader::ReloadObjectTypes("GTA3.IDE"); + break; + case MENUACTION_RELOADIPL: + CGame::ReloadIPLs(); + break; + case MENUACTION_SHOWCULL: + // REMOVED(MIAMI) + break; + case MENUACTION_MEMCARDSAVECONFIRM: + return; + case MENUACTION_RESUME_FROM_SAVEZONE: + RequestFrontEndShutDown(); + break; + case MENUACTION_MPMAP_LIBERTY: + case MENUACTION_MPMAP_REDLIGHT: + case MENUACTION_MPMAP_CHINATOWN: + case MENUACTION_MPMAP_TOWER: + case MENUACTION_MPMAP_SEWER: + case MENUACTION_MPMAP_INDUSTPARK: + case MENUACTION_MPMAP_DOCKS: + case MENUACTION_MPMAP_STAUNTON: + m_SelectedMap = option - MENUACTION_MPMAP_LIBERTY; + SaveSettings(); + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + break; + case MENUACTION_MPMAP_DEATHMATCH1: + case MENUACTION_MPMAP_DEATHMATCH2: + case MENUACTION_MPMAP_TEAMDEATH1: + case MENUACTION_MPMAP_TEAMDEATH2: + case MENUACTION_MPMAP_STASH: + case MENUACTION_MPMAP_CAPTURE: + case MENUACTION_MPMAP_RATRACE: + case MENUACTION_MPMAP_DOMINATION: + m_SelectedGameType = option - MENUACTION_MPMAP_DEATHMATCH1; + SaveSettings(); + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + break; + case MENUACTION_REDEFCTRL: + ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); + m_nSelectedListRow = 0; + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case MENUACTION_GETKEY: + m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; + m_bKeyIsOK = true; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + break; + case MENUACTION_CANCELGAME: + DMAudio.Service(); + RsEventHandler(rsQUITAPP, nil); + break; + case MENUACTION_RESUME: +#ifndef TIDY_UP_PBP + if (m_PrefsVsyncDisp != m_PrefsVsync) { + m_PrefsVsync = m_PrefsVsyncDisp; + } + RequestFrontEndShutDown(); +#else + goBack = true; +#endif + break; + case MENUACTION_DONTCANCEL: + ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); + break; + case MENUACTION_SCREENRES: + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + m_nPrefsVideoMode = m_nDisplayVideoMode; + _psSelectScreenVM(m_nPrefsVideoMode); + SetHelperText(0); + SaveSettings(); + } + break; +#ifdef IMPROVED_VIDEOMODE + case MENUACTION_SCREENMODE: + if (m_nSelectedScreenMode != m_nPrefsWindowed) { + m_nPrefsWindowed = m_nSelectedScreenMode; + _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution + SetHelperText(0); + SaveSettings(); + } + break; +#endif + case MENUACTION_AUDIOHW: + { + int selectedProvider = m_nPrefsAudio3DProviderIndex; + if (selectedProvider != -1) { + m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + if (selectedProvider == m_nPrefsAudio3DProviderIndex) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SetHelperText(0); + } + else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + SetHelperText(4); } SaveSettings(); + } + break; + } + case MENUACTION_SPEAKERCONF: +#ifndef TIDY_UP_PBP + if (m_nPrefsAudio3DProviderIndex != -1) { + if (--m_PrefsSpeakers < 0) + m_PrefsSpeakers = 2; + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); + SaveSettings(); + } +#else + assumeIncrease = true; +#endif + break; + case MENUACTION_PLAYERSETUP: + CPlayerSkin::BeginFrontendSkinEdit(); + ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); + m_nCurrExLayer = HOVEROPTION_LIST; + m_bSkinsEnumerated = false; + break; + case MENUACTION_RESTOREDEF: + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + m_PrefsSfxVolume = 102; + m_PrefsSpeakers = 0; + m_PrefsMusicVolume = 102; + m_PrefsStereoMono = 0; + m_PrefsRadioStation = HEAD_RADIO; + DMAudio.SetMusicMasterVolume(102); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); -#endif - break; - case MENUACTION_LANG_ENG: - m_PrefsLanguage = LANGUAGE_AMERICAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); SaveSettings(); - break; - case MENUACTION_LANG_FRE: - m_PrefsLanguage = LANGUAGE_FRENCH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_GER: - m_PrefsLanguage = LANGUAGE_GERMAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_ITA: - m_PrefsLanguage = LANGUAGE_ITALIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_SPA: - m_PrefsLanguage = LANGUAGE_SPANISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; -#ifdef MORE_LANGUAGES - case MENUACTION_LANG_PL: - m_PrefsLanguage = LANGUAGE_POLISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_RUS: - m_PrefsLanguage = LANGUAGE_RUSSIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - CMenuManager::InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_JAP: - m_PrefsLanguage = LANGUAGE_JAPANESE; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; -#endif - case MENUACTION_POPULATESLOTS_CHANGEMENU: - PcSaveHelper.PopulateSlotInfo(); - - // fall through - case MENUACTION_CHANGEMENU: - { - bool changeMenu = true; - int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; - - // This should be unused. - if (saveSlot >= 2 && saveSlot <= 9) { - m_nCurrSaveSlot = saveSlot - 2; - switch (m_nCurrScreen) { - case MENUPAGE_CHOOSE_LOAD_SLOT: - if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY) - changeMenu = false; - - break; - case MENUPAGE_CHOOSE_DELETE_SLOT: - if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY) - changeMenu = false; - - break; - } - } - if (changeMenu) { - if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) { -#ifndef TIDY_UP_PBP - ResetHelperText(); - if (!m_bGameNotLoaded) - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - else - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); -#else - goBack = true; - break; -#endif - } else { -#ifdef MENU_MAP - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { - bMapLoaded = false; - } - -#endif - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } - break; } - case MENUACTION_CHECKSAVE: - { - int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; - - if (saveSlot >= 2 && saveSlot <= 9) { - m_nCurrSaveSlot = saveSlot - 2; - if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY && Slots[m_nCurrSaveSlot + 1] != SLOT_CORRUPTED) { - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } - break; - } - case MENUACTION_NEWGAME: - DoSettingsBeforeStartingAGame(); - break; - case MENUACTION_RELOADIDE: - CFileLoader::ReloadObjectTypes("GTA3.IDE"); - break; - case MENUACTION_RELOADIPL: - CGame::ReloadIPLs(); - break; - case MENUACTION_SHOWCULL: - // REMOVED(MIAMI) - break; - case MENUACTION_MEMCARDSAVECONFIRM: - return; - case MENUACTION_RESUME_FROM_SAVEZONE: - RequestFrontEndShutDown(); - break; - case MENUACTION_MPMAP_LIBERTY: - case MENUACTION_MPMAP_REDLIGHT: - case MENUACTION_MPMAP_CHINATOWN: - case MENUACTION_MPMAP_TOWER: - case MENUACTION_MPMAP_SEWER: - case MENUACTION_MPMAP_INDUSTPARK: - case MENUACTION_MPMAP_DOCKS: - case MENUACTION_MPMAP_STAUNTON: - m_SelectedMap = option - MENUACTION_MPMAP_LIBERTY; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_MPMAP_DEATHMATCH1: - case MENUACTION_MPMAP_DEATHMATCH2: - case MENUACTION_MPMAP_TEAMDEATH1: - case MENUACTION_MPMAP_TEAMDEATH2: - case MENUACTION_MPMAP_STASH: - case MENUACTION_MPMAP_CAPTURE: - case MENUACTION_MPMAP_RATRACE: - case MENUACTION_MPMAP_DOMINATION: - m_SelectedGameType = option - MENUACTION_MPMAP_DEATHMATCH1; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_REDEFCTRL: - ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); - m_nSelectedListRow = 0; - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case MENUACTION_GETKEY: - m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; - m_bKeyIsOK = true; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - break; - case MENUACTION_CANCELGAME: - DMAudio.Service(); - RsEventHandler(rsQUITAPP, nil); - break; - case MENUACTION_RESUME: -#ifndef TIDY_UP_PBP - if (m_PrefsVsyncDisp != m_PrefsVsync) { - m_PrefsVsync = m_PrefsVsyncDisp; - } - RequestFrontEndShutDown(); -#else - goBack = true; -#endif - break; - case MENUACTION_DONTCANCEL: - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - break; - case MENUACTION_SCREENRES: - if (m_nDisplayVideoMode != m_nPrefsVideoMode) { - m_nPrefsVideoMode = m_nDisplayVideoMode; - _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); - SaveSettings(); - } - break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - m_nPrefsWindowed = m_nSelectedScreenMode; - _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution - SetHelperText(0); - SaveSettings(); - } - break; -#endif - case MENUACTION_AUDIOHW: - { - int selectedProvider = m_nPrefsAudio3DProviderIndex; - if (selectedProvider != -1) { - m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); - if (selectedProvider == m_nPrefsAudio3DProviderIndex) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - SetHelperText(0); - } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - SetHelperText(4); - } - SaveSettings(); - } - break; - } - case MENUACTION_SPEAKERCONF: -#ifndef TIDY_UP_PBP - if (m_nPrefsAudio3DProviderIndex != -1) { - if (--m_PrefsSpeakers < 0) - m_PrefsSpeakers = 2; - DMAudio.SetSpeakerConfig(m_PrefsSpeakers); - SaveSettings(); - } -#else - assumeIncrease = true; -#endif - break; - case MENUACTION_PLAYERSETUP: - CPlayerSkin::BeginFrontendSkinEdit(); - ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); - m_nCurrExLayer = HOVEROPTION_LIST; - m_bSkinsEnumerated = false; - break; - case MENUACTION_RESTOREDEF: - if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - m_PrefsSfxVolume = 102; - m_PrefsSpeakers = 0; - m_PrefsMusicVolume = 102; - m_PrefsStereoMono = 0; - m_PrefsRadioStation = HEAD_RADIO; - DMAudio.SetMusicMasterVolume(102); - DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - SaveSettings(); - } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_PrefsFrameLimiter = true; - m_PrefsBrightness = 256; - m_PrefsVsyncDisp = true; - m_PrefsLOD = 1.2f; - m_PrefsVsync = true; - CRenderer::ms_lodDistScale = 1.2f; - m_PrefsUseWideScreen = false; - m_PrefsShowSubtitles = true; - m_nDisplayVideoMode = m_nPrefsVideoMode; + else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + m_PrefsFrameLimiter = true; + m_PrefsBrightness = 256; + m_PrefsVsyncDisp = true; + m_PrefsLOD = 1.2f; + m_PrefsVsync = true; + CRenderer::ms_lodDistScale = 1.2f; + m_PrefsUseWideScreen = false; + m_PrefsShowSubtitles = true; + m_nDisplayVideoMode = m_nPrefsVideoMode; #ifdef GTA3_1_1_PATCH - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } - else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } -#else + if (_dwOperatingSystemVersion == OS_WIN98) { + CMBlur::BlurOn = false; + CMBlur::MotionBlurClose(); + } + else { CMBlur::BlurOn = true; -#endif - SaveSettings(); - } else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { - ControlsManager.MakeControllerActionsBlank(); - ControlsManager.InitDefaultControlConfiguration(); - ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); -#if !defined RW_GL3 - if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { - DIDEVCAPS devCaps; - devCaps.dwSize = sizeof(DIDEVCAPS); - PSGLOBAL(joy1)->GetCapabilities(&devCaps); - ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); - } + CMBlur::MotionBlurOpen(Scene.camera); + } #else - if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { - int count; - glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); - ControlsManager.InitDefaultControlConfigJoyPad(count); - } + CMBlur::BlurOn = true; #endif - m_ControlMethod = CONTROL_STANDARD; - MousePointerStateHelper.bInvertVertically = false; - TheCamera.m_fMouseAccelHorzntl = 0.0025f; - CVehicle::m_bDisableMouseSteering = true; - TheCamera.m_bHeadBob = false; - SaveSettings(); - } - SetHelperText(2); - break; - case MENUACTION_CTRLMETHOD: -#ifndef TIDY_UP_PBP - if (m_ControlMethod == CONTROL_CLASSIC) { - CCamera::m_bUseMouse3rdPerson = true; - m_ControlMethod = CONTROL_STANDARD; - } else { - CCamera::m_bUseMouse3rdPerson = false; - m_ControlMethod = CONTROL_CLASSIC; - } SaveSettings(); + } + else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { + ControlsManager.MakeControllerActionsBlank(); + ControlsManager.InitDefaultControlConfiguration(); + ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); +#if !defined RW_GL3 + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { + DIDEVCAPS devCaps; + devCaps.dwSize = sizeof(DIDEVCAPS); + PSGLOBAL(joy1)->GetCapabilities(&devCaps); + ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); + } #else - assumeIncrease = true; + if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + ControlsManager.InitDefaultControlConfigJoyPad(count); + } #endif - break; - case MENUACTION_LOADRADIO: - ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); - break; + m_ControlMethod = CONTROL_STANDARD; + MousePointerStateHelper.bInvertVertically = false; + TheCamera.m_fMouseAccelHorzntl = 0.0025f; + CVehicle::m_bDisableMouseSteering = true; + TheCamera.m_bHeadBob = false; + SaveSettings(); + } + SetHelperText(2); + break; + case MENUACTION_CTRLMETHOD: +#ifndef TIDY_UP_PBP + if (m_ControlMethod == CONTROL_CLASSIC) { + CCamera::m_bUseMouse3rdPerson = true; + m_ControlMethod = CONTROL_STANDARD; + } + else { + CCamera::m_bUseMouse3rdPerson = false; + m_ControlMethod = CONTROL_CLASSIC; + } + SaveSettings(); +#else + assumeIncrease = true; +#endif + break; + case MENUACTION_LOADRADIO: + ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); + break; } } ProcessOnOffMenuOptions(); @@ -4694,7 +4810,8 @@ CMenuManager::ProcessButtonPresses(void) if (!bottomBarActive && (oldScreen == MENUPAGE_NONE || oldScreen == MENUPAGE_OPTIONS)) { bottomBarActive = true; - } else + } + else #endif { ChangeScreen(oldScreen, oldOption, true, true); @@ -4705,7 +4822,7 @@ CMenuManager::ProcessButtonPresses(void) return; #endif } - } + } #ifdef PS2_LIKE_MENU if (bottomBarActive) @@ -4725,7 +4842,8 @@ CMenuManager::ProcessButtonPresses(void) CheckSliderMovement(-1); lastSliderDecrease = CTimer::GetTimeInMillisecondsPauseMode(); } - } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { + } + else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { static uint32 lastSliderIncrease = 0; if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) { CheckSliderMovement(1); @@ -4736,7 +4854,8 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) { m_bShowMouse = false; increase = true; - } else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + } + else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { increase = true; CheckSliderMovement(1); m_bShowMouse = true; @@ -4750,7 +4869,8 @@ CMenuManager::ProcessButtonPresses(void) m_bShowMouse = true; } } - } else { + } + else { m_bShowMouse = false; decrease = true; } @@ -4762,101 +4882,105 @@ CMenuManager::ProcessButtonPresses(void) if (changeValueBy != 0) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { - case MENUACTION_RADIO: - m_PrefsRadioStation += changeValueBy; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = USERTRACK; - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; - } else { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = CHATTERBOX; - if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = HEAD_RADIO; - } - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; + case MENUACTION_RADIO: + m_PrefsRadioStation += changeValueBy; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < HEAD_RADIO) + m_PrefsRadioStation = USERTRACK; + if (m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = HEAD_RADIO; + } + else { + if (m_PrefsRadioStation < HEAD_RADIO) + m_PrefsRadioStation = CHATTERBOX; + if (m_PrefsRadioStation > CHATTERBOX) + m_PrefsRadioStation = HEAD_RADIO; + } + SaveSettings(); + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("FRONTEND RADIO STATION CHANGED"); + break; #ifdef ASPECT_RATIO_SCALE - case MENUACTION_WIDESCREEN: + case MENUACTION_WIDESCREEN: + if (changeValueBy > 0) { + m_PrefsUseWideScreen++; + if (m_PrefsUseWideScreen > 2) + m_PrefsUseWideScreen = 2; + } + else { + m_PrefsUseWideScreen--; + if (m_PrefsUseWideScreen < 0) + m_PrefsUseWideScreen = 0; + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SaveSettings(); + break; +#endif + case MENUACTION_SCREENRES: + if (m_bGameNotLoaded) { + RwChar** videoMods = _psGetVideoModeList(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); if (changeValueBy > 0) { - m_PrefsUseWideScreen++; - if (m_PrefsUseWideScreen > 2) - m_PrefsUseWideScreen = 2; - } else { - m_PrefsUseWideScreen--; - if (m_PrefsUseWideScreen < 0) - m_PrefsUseWideScreen = 0; - } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - SaveSettings(); - break; -#endif - case MENUACTION_SCREENRES: - if (m_bGameNotLoaded) { - RwChar** videoMods = _psGetVideoModeList(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - if (changeValueBy > 0) { - do { - ++m_nDisplayVideoMode; + do { + ++m_nDisplayVideoMode; - if (m_nDisplayVideoMode >= _psGetNumVideModes()) - m_nDisplayVideoMode = 0; - } while (!videoMods[m_nDisplayVideoMode]); - } else { - do { - --m_nDisplayVideoMode; - - if (m_nDisplayVideoMode < 0) - m_nDisplayVideoMode = _psGetNumVideModes() - 1; - } while (!videoMods[m_nDisplayVideoMode]); - } + if (m_nDisplayVideoMode >= _psGetNumVideModes()) + m_nDisplayVideoMode = 0; + } while (!videoMods[m_nDisplayVideoMode]); } - break; + else { + do { + --m_nDisplayVideoMode; + + if (m_nDisplayVideoMode < 0) + m_nDisplayVideoMode = _psGetNumVideModes() - 1; + } while (!videoMods[m_nDisplayVideoMode]); + } + } + break; #ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nSelectedScreenMode = !m_nSelectedScreenMode; - break; + case MENUACTION_SCREENMODE: + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + m_nSelectedScreenMode = !m_nSelectedScreenMode; + break; #endif - case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex != -1) { - m_nPrefsAudio3DProviderIndex += changeValueBy; - m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); - } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - break; - case MENUACTION_SPEAKERCONF: - if (m_nPrefsAudio3DProviderIndex != -1) { - m_PrefsSpeakers -= changeValueBy; - m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); - DMAudio.SetSpeakerConfig(m_PrefsSpeakers); - SaveSettings(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - } - break; - case MENUACTION_CTRLMETHOD: - m_ControlMethod = !m_ControlMethod; - CCamera::m_bUseMouse3rdPerson = !m_ControlMethod; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + case MENUACTION_AUDIOHW: + if (m_nPrefsAudio3DProviderIndex != -1) { + m_nPrefsAudio3DProviderIndex += changeValueBy; + m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + break; + case MENUACTION_SPEAKERCONF: + if (m_nPrefsAudio3DProviderIndex != -1) { + m_PrefsSpeakers -= changeValueBy; + m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); SaveSettings(); - break; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + } + break; + case MENUACTION_CTRLMETHOD: + m_ControlMethod = !m_ControlMethod; + CCamera::m_bUseMouse3rdPerson = !m_ControlMethod; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SaveSettings(); + break; } ProcessOnOffMenuOptions(); if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { if (changeValueBy < 1) { m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; - } else { + } + else { m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); } } -} + } void CMenuManager::ProcessOnOffMenuOptions() @@ -4982,7 +5106,7 @@ CMenuManager::RequestFrontEndStartUp() } void -CMenuManager::ResetHelperText() +CMenuManager::ResetHelperText() { m_nHelperTextMsgId = 0; m_nHelperTextAlpha = 300; @@ -4992,25 +5116,25 @@ void CMenuManager::SaveLoadFileError_SetUpErrorScreen() { switch (PcSaveHelper.nErrorCode) { - case SAVESTATUS_ERR_SAVE_CREATE: - case SAVESTATUS_ERR_SAVE_WRITE: - case SAVESTATUS_ERR_SAVE_CLOSE: - ChangeScreen(MENUPAGE_SAVE_FAILED, 0, true, false); - break; - case SAVESTATUS_ERR_LOAD_OPEN: - case SAVESTATUS_ERR_LOAD_READ: - case SAVESTATUS_ERR_LOAD_CLOSE: - ChangeScreen(MENUPAGE_LOAD_FAILED, 0, true, false); - break; - case SAVESTATUS_ERR_DATA_INVALID: - ChangeScreen(MENUPAGE_LOAD_FAILED_2, 0, true, false); - break; - case SAVESTATUS_DELETEFAILED8: - case SAVESTATUS_DELETEFAILED9: - case SAVESTATUS_DELETEFAILED10: - ChangeScreen(MENUPAGE_DELETE_FAILED, 0, true, false); - break; - default: break; + case SAVESTATUS_ERR_SAVE_CREATE: + case SAVESTATUS_ERR_SAVE_WRITE: + case SAVESTATUS_ERR_SAVE_CLOSE: + ChangeScreen(MENUPAGE_SAVE_FAILED, 0, true, false); + break; + case SAVESTATUS_ERR_LOAD_OPEN: + case SAVESTATUS_ERR_LOAD_READ: + case SAVESTATUS_ERR_LOAD_CLOSE: + ChangeScreen(MENUPAGE_LOAD_FAILED, 0, true, false); + break; + case SAVESTATUS_ERR_DATA_INVALID: + ChangeScreen(MENUPAGE_LOAD_FAILED_2, 0, true, false); + break; + case SAVESTATUS_DELETEFAILED8: + case SAVESTATUS_DELETEFAILED9: + case SAVESTATUS_DELETEFAILED10: + ChangeScreen(MENUPAGE_DELETE_FAILED, 0, true, false); + break; + default: break; } } @@ -5053,7 +5177,7 @@ CMenuManager::SwitchMenuOnAndOff() bool menuWasActive = GetIsMenuActive(); // Reminder: You need REGISTER_START_BUTTON defined to make it work. - if (CPad::GetPad(0)->GetStartJustDown() + if (CPad::GetPad(0)->GetStartJustDown() #ifdef FIX_BUGS && !m_bGameNotLoaded #endif @@ -5068,7 +5192,8 @@ CMenuManager::SwitchMenuOnAndOff() if (m_bMenuActive) { CTimer::StartUserPause(); - } else { + } + else { #ifdef PS2_LIKE_MENU bottomBarActive = false; #endif @@ -5112,14 +5237,14 @@ CMenuManager::SwitchMenuOnAndOff() PcSaveHelper.PopulateSlotInfo(); m_nCurrOption = 0; } -/* // PS2 leftover - if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) - { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); - gMusicPlaying = 0; - } -*/ + /* // PS2 leftover + if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) + { + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); + gMusicPlaying = 0; + } + */ if (m_bMenuActive != menuWasActive) m_bMenuStateChanged = true; @@ -5154,8 +5279,8 @@ CMenuManager::UnloadTextures() void CMenuManager::WaitForUserCD() { - CSprite2d *splash; - char *splashscreen = nil; + CSprite2d* splash; + char* splashscreen = nil; #if (!(defined RANDOMSPLASH) && !(defined GTA3_1_1_PATCH)) if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) @@ -5215,189 +5340,190 @@ CMenuManager::PrintController(void) if (m_DisplayControllerOnFoot) { switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - default: - return; + case 0: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + case 1: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + case 2: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + case 3: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + default: + return; } - } else { + } + else { switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_RS3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_SMT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_ACC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_BRA")); - break; - default: - return; + case 0: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + break; + case 1: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HOR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + break; + case 2: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_RS3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HOR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + break; + case 3: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_SMT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_ACC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_BRA")); + break; + default: + return; } } @@ -5512,7 +5638,8 @@ CMenuManager::PrintMap(void) if (m_bShowMouse) { bMapMouseShownOnce = true; - } else if (!bMapMouseShownOnce) { + } + else if (!bMapMouseShownOnce) { mapPoint.x = SCREEN_WIDTH / 2; mapPoint.y = SCREEN_HEIGHT / 2; } @@ -5540,19 +5667,24 @@ CMenuManager::PrintMap(void) if (CPad::GetPad(0)->GetLeftMouse()) { fMapCenterX += m_nMousePosX - m_nMouseOldPosX; fMapCenterY += m_nMousePosY - m_nMouseOldPosY; - } else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { + } + else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { fMapCenterX += 15.0f; - } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { + } + else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { fMapCenterX -= 15.0f; - } else if (CPad::GetPad(0)->GetLeftStickX()) { + } + else if (CPad::GetPad(0)->GetLeftStickX()) { fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; } if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetDPadUp()) { fMapCenterY += 15.0f; - } else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { + } + else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { fMapCenterY -= 15.0f; - } else if (CPad::GetPad(0)->GetLeftStickY()) { + } + else if (CPad::GetPad(0)->GetLeftStickY()) { fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; } @@ -5561,13 +5693,14 @@ CMenuManager::PrintMap(void) ZOOM(mapPoint.x, mapPoint.y, false); else ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false); - } else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { + } + else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { if (CPad::GetPad(0)->GetMouseWheelUp()) ZOOM(mapPoint.x, mapPoint.y, true); else ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); } - + if (fMapCenterX - fMapSize > SCREEN_WIDTH / 2) fMapCenterX = fMapSize + SCREEN_WIDTH / 2; @@ -5576,7 +5709,7 @@ CMenuManager::PrintMap(void) if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; - + if (fMapCenterY - fMapSize > SCREEN_HEIGHT / 2) fMapCenterY = SCREEN_HEIGHT / 2 + fMapSize; @@ -5587,14 +5720,14 @@ CMenuManager::PrintMap(void) CSprite2d::DrawRect(CRect(MENU_X(14.0f), SCREEN_STRETCH_FROM_BOTTOM(95.0f), SCREEN_STRETCH_FROM_RIGHT(11.0f), SCREEN_STRETCH_FROM_BOTTOM(59.0f)), - CRGBA(235, 170, 50, 255)); + CRGBA(MAPINFOBOX_COLOR.r, MAPINFOBOX_COLOR.g, MAPINFOBOX_COLOR.b, MAPINFOBOX_COLOR.a)); CFont::SetScale(MENU_X(0.4f), MENU_Y(0.7f)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); float nextX = MENU_X(30.0f), nextY = 95.0f; - wchar *text; + wchar* text; #ifdef MORE_LANGUAGES #define TEXT_PIECE(key,extraSpace) \ text = TheText.Get(key);\ @@ -5656,8 +5789,8 @@ CMenuManager::ConstructStatLine(int rowIdx) if (CGame::nastyGame) { STAT_LINE("FEST_RP", &CStats::NumberKillFrenziesPassed, false, &CStats::TotalNumberKillFrenzies); } - - CPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus]; + + CPlayerInfo& player = CWorld::Players[CWorld::PlayerInFocus]; float packagesPercent = 0.0f; if (player.m_nTotalPackages != 0) packagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; @@ -5674,16 +5807,16 @@ CMenuManager::ConstructStatLine(int rowIdx) STAT_LINE("TM_BUST", &CStats::TimesArrested, false, nil); STAT_LINE("TM_DED", &CStats::TimesDied, false, nil); STAT_LINE("GNG_WST", &(nTemp = CStats::PedsKilledOfThisType[PEDTYPE_GANG9] + CStats::PedsKilledOfThisType[PEDTYPE_GANG8] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]), false, nil); + + CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6] + + CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4] + + CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2] + + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]), false, nil); STAT_LINE("DED_CRI", &(nTemp = CStats::PedsKilledOfThisType[PEDTYPE_CRIMINAL]), false, nil); STAT_LINE("HEL_DST", &CStats::HelisDestroyed, false, nil); STAT_LINE("KGS_EXP", &CStats::KgsOfExplosivesUsed, false, nil); STAT_LINE("ACCURA", &(nTemp = (CStats::InstantHitsFiredByPlayer == 0 ? 0 : - CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)), false, nil); - + CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)), false, nil); + if (CStats::ElBurroTime > 0) { STAT_LINE("ELBURRO", &CStats::ElBurroTime, false, nil); } @@ -5728,33 +5861,33 @@ CMenuManager::ConstructStatLine(int rowIdx) } switch (m_PrefsLanguage) { - case LANGUAGE_AMERICAN: + case LANGUAGE_AMERICAN: #ifndef USE_MEASUREMENTS_IN_METERS - float fTemp; - STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); - STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); - STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); - STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); - break; + float fTemp; + STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); + STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); + STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); + STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); + STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); + break; #endif - case LANGUAGE_FRENCH: - case LANGUAGE_GERMAN: - case LANGUAGE_ITALIAN: - case LANGUAGE_SPANISH: + case LANGUAGE_FRENCH: + case LANGUAGE_GERMAN: + case LANGUAGE_ITALIAN: + case LANGUAGE_SPANISH: #ifdef MORE_LANGUAGES - case LANGUAGE_POLISH: - case LANGUAGE_RUSSIAN: - case LANGUAGE_JAPANESE: + case LANGUAGE_POLISH: + case LANGUAGE_RUSSIAN: + case LANGUAGE_JAPANESE: #endif - STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); - STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); - STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); - STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); - break; - default: - break; + STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); + STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); + STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); + STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); + STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); + break; + default: + break; } STAT_LINE("MXFLIP", &CStats::MaximumJumpFlips, false, nil); @@ -5764,33 +5897,33 @@ CMenuManager::ConstructStatLine(int rowIdx) if (counter == rowIdx) { gUString[0] = '\0'; switch (CStats::BestStuntJump) { - case 1: - UnicodeStrcpy(gUString2, TheText.Get("INSTUN")); - return 0; - case 2: - UnicodeStrcpy(gUString2, TheText.Get("PRINST")); - return 0; - case 3: - UnicodeStrcpy(gUString2, TheText.Get("DBINST")); - return 0; - case 4: - UnicodeStrcpy(gUString2, TheText.Get("DBPINS")); - return 0; - case 5: - UnicodeStrcpy(gUString2, TheText.Get("TRINST")); - return 0; - case 6: - UnicodeStrcpy(gUString2, TheText.Get("PRTRST")); - return 0; - case 7: - UnicodeStrcpy(gUString2, TheText.Get("QUINST")); - return 0; - case 8: - UnicodeStrcpy(gUString2, TheText.Get("PQUINS")); - return 0; - default: - UnicodeStrcpy(gUString2, TheText.Get("NOSTUC")); - return 0; + case 1: + UnicodeStrcpy(gUString2, TheText.Get("INSTUN")); + return 0; + case 2: + UnicodeStrcpy(gUString2, TheText.Get("PRINST")); + return 0; + case 3: + UnicodeStrcpy(gUString2, TheText.Get("DBINST")); + return 0; + case 4: + UnicodeStrcpy(gUString2, TheText.Get("DBPINS")); + return 0; + case 5: + UnicodeStrcpy(gUString2, TheText.Get("TRINST")); + return 0; + case 6: + UnicodeStrcpy(gUString2, TheText.Get("PRTRST")); + return 0; + case 7: + UnicodeStrcpy(gUString2, TheText.Get("QUINST")); + return 0; + case 8: + UnicodeStrcpy(gUString2, TheText.Get("PQUINS")); + return 0; + default: + UnicodeStrcpy(gUString2, TheText.Get("NOSTUC")); + return 0; } } counter++; From 6692f5b2aa11e5cac51a61b41164316030152b16 Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 16:47:48 +0300 Subject: [PATCH 087/148] make reloadables optional --- src/core/config.h | 3 +++ src/core/re3.cpp | 2 ++ src/render/Hud.cpp | 2 ++ src/render/Hud.h | 2 ++ 4 files changed, 9 insertions(+) diff --git a/src/core/config.h b/src/core/config.h index 105454fa..1d7e760a 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -204,6 +204,9 @@ enum Config { #else #define AUDIO_OAL #endif +#ifdef DEBUGMENU +#define RELOADABLES // some debug menu options to reload TXD files +#endif // Particle //#define PC_PARTICLE diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 7f69e0f1..c7fade52 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -385,10 +385,12 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); +#ifdef RELOADABLES DebugMenuAddCmd("Reload", "HUD.TXD", CHud::ReloadTXD); DebugMenuAddCmd("Reload", "FONTS.TXD", NULL); DebugMenuAddCmd("Reload", "FRONTEN1.TXD", NULL); DebugMenuAddCmd("Reload", "FRONTEN2.TXD", NULL); +#endif extern bool PrintDebugCode; extern int16 DebugCamMode; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index a2eed48b..4e12ceb5 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -1476,6 +1476,7 @@ void CHud::GetRidOfAllHudMessages() } } +#ifdef RELOADABLES void CHud::ReloadTXD() { for (int i = 0; i < NUM_HUD_SPRITES; ++i) { @@ -1497,6 +1498,7 @@ void CHud::ReloadTXD() Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); } } +#endif void CHud::Initialise() { diff --git a/src/render/Hud.h b/src/render/Hud.h index 3f4b218e..9d2c5f8b 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -124,7 +124,9 @@ public: static void Draw(); static void DrawAfterFade(); static void GetRidOfAllHudMessages(); +#ifdef RELOADABLES static void ReloadTXD(); +#endif static void Initialise(); static void ReInitialise(); static void SetBigMessage(wchar *message, int16 style); From 1c00e3cf2c184809d4ed814640eedcf0ef997b1c Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 17:28:03 +0300 Subject: [PATCH 088/148] vehicle cheats and debug cheat string display --- src/core/Pad.cpp | 2007 +++++++++++++++++++++++---------------------- src/core/Pad.h | 2 +- src/core/main.cpp | 22 + src/core/re3.cpp | 4 +- 4 files changed, 1047 insertions(+), 988 deletions(-) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index ae7fcdb4..6804b938 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -49,7 +49,7 @@ CKeyboardState CPad::OldKeyState; CKeyboardState CPad::NewKeyState; CKeyboardState CPad::TempKeyState; -char CPad::KeyBoardCheatString[20]; +char CPad::KeyBoardCheatString[30]; CMouseControllerState CPad::OldMouseControllerState; CMouseControllerState CPad::NewMouseControllerState; @@ -108,31 +108,31 @@ void HealthCheat() } } -void TankCheat() +void VehicleCheat(bool something, int model) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - CStreaming::RequestModel(MI_RHINO, 0); - CStreaming::LoadAllRequestedModels(false); - if (CStreaming::ms_aInfoForModel[MI_RHINO].m_loadState == STREAMSTATE_LOADED) { + CStreaming::RequestModel(model, 0); + CStreaming::LoadAllRequestedModels(something); + if (CStreaming::ms_aInfoForModel[model].m_loadState == STREAMSTATE_LOADED) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f); if (node < 0) return; - + #ifdef FIX_BUGS - CAutomobile* tank = new CAutomobile(MI_RHINO, RANDOM_VEHICLE); + CAutomobile* vehicle = new CAutomobile(model, RANDOM_VEHICLE); #else - CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE); + CAutomobile* vehicle = new CAutomobile(MI_RHINO, MISSION_VEHICLE); #endif - if (tank != nil) { + if (vehicle != nil) { CVector pos = ThePaths.m_pathNodes[node].GetPosition(); pos.z += 4.0f; - tank->SetPosition(pos); - tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f)); + vehicle->SetPosition(pos); + vehicle->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f)); - tank->SetStatus(STATUS_ABANDONED); - tank->m_nDoorLock = CARLOCK_UNLOCKED; - CWorld::Add(tank); + vehicle->SetStatus(STATUS_ABANDONED); + vehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CWorld::Add(vehicle); } } } @@ -143,7 +143,7 @@ void BlowUpCarsCheat() int i = CPools::GetVehiclePool()->GetSize(); while (i-- > 0) { - if (CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i)) + if (CVehicle* veh = CPools::GetVehiclePool()->GetSlot(i)) veh->BlowUpCar(nil); } } @@ -154,18 +154,18 @@ void ChangePlayerCheat() if (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo("player", nil)) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - CPlayerPed *ped = FindPlayerPed(); + CPlayerPed* ped = FindPlayerPed(); AssocGroupId AnimGrp = ped->m_animGroup; do { do - modelId = CGeneral::GetRandomNumberInRange(0, MI_WFYG2+1); + modelId = CGeneral::GetRandomNumberInRange(0, MI_WFYG2 + 1); while (!CModelInfo::GetModelInfo(modelId)); } while (modelId == MI_TAXI_D); uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags; ped->DeleteRwObject(); - CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_DONT_REMOVE); CStreaming::LoadAllRequestedModels(false); ped->m_modelIndex = -1; ped->SetModelIndex(modelId); @@ -185,7 +185,7 @@ void MayhemCheat() PED_FLAG_CIVMALE | PED_FLAG_CIVFEMALE | PED_FLAG_COP | PED_FLAG_GANG1 | PED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 | PED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 | - PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL ); + PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL); } void EverybodyAttacksPlayerCheat() @@ -311,14 +311,15 @@ void PinkCarsCheat() #ifdef KANGAROO_CHEAT void KangarooCheat() { - wchar *string; - CPed *playerPed = FindPlayerPed(); + wchar* string; + CPed* playerPed = FindPlayerPed(); int m_fMass; if (playerPed->m_ped_flagI80) { string = TheText.Get("CHEATOF"); m_fMass = 70.0f; - } else { + } + else { string = TheText.Get("CHEAT1"); m_fMass = 15.0f; } @@ -367,8 +368,8 @@ bool CControllerState::IsAnyButtonPressed(void) { return !!LeftStickX || !!LeftStickY || !!RightStickX || !!RightStickY || !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2 || - !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight || !!Start || !!Select || !!Square || !!Triangle || !!Cross || !!Circle || !!LeftShock || - !!RightShock || !!NetworkTalk; + !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight || !!Start || !!Select || !!Square || !!Triangle || !!Cross || !!Circle || !!LeftShock || + !!RightShock || !!NetworkTalk; } #endif @@ -386,24 +387,24 @@ CControllerState::Clear(void) void CKeyboardState::Clear() { - for ( int32 i = 0; i < 12; i++ ) + for (int32 i = 0; i < 12; i++) F[i] = 0; - - for ( int32 i = 0; i < 256; i++ ) + + for (int32 i = 0; i < 256; i++) VK_KEYS[i] = 0; ESC = INS = DEL = HOME = END = PGUP = PGDN = 0; - + UP = DOWN = LEFT = RIGHT = 0; - + NUMLOCK = 0; - + DIV = MUL = SUB = ADD = 0; - + DECIMAL = NUM1 = NUM2 = NUM3 = NUM4 = 0; - + NUM5 = NUM6 = NUM7 = NUM8 = 0; - + NUM9 = NUM0 = SCROLLLOCK = PAUSE = 0; BACKSP = TAB = CAPSLOCK = EXTENTER = 0; @@ -421,10 +422,10 @@ void CPad::Initialise(void) CPad::GetPad(i)->Clear(true); CPad::GetPad(i)->Mode = 0; } - - bObsoleteControllerMessage = false; + + bObsoleteControllerMessage = false; bOldDisplayNoControllerMessage = false; - bDisplayNoControllerMessage = false; + bDisplayNoControllerMessage = false; } #endif @@ -432,37 +433,37 @@ void CPad::Clear(bool bResetPlayerControls) { NewState.Clear(); OldState.Clear(); - + PCTempKeyState.Clear(); PCTempJoyState.Clear(); PCTempMouseState.Clear(); - + NewKeyState.Clear(); OldKeyState.Clear(); TempKeyState.Clear(); - + NewMouseControllerState.Clear(); OldMouseControllerState.Clear(); PCTempMouseControllerState.Clear(); - + Phase = 0; ShakeFreq = 0; ShakeDur = 0; - - if ( bResetPlayerControls ) + + if (bResetPlayerControls) DisablePlayerControls = PLAYERCONTROL_ENABLED; - + bApplyBrakes = false; - - - for ( int32 i = 0; i < HORNHISTORY_SIZE; i++ ) + + + for (int32 i = 0; i < HORNHISTORY_SIZE; i++) bHornHistory[i] = false; - + iCurrHornHistory = 0; - - for ( int32 i = 0; i < ARRAY_SIZE(CheatString); i++ ) + + for (int32 i = 0; i < ARRAY_SIZE(CheatString); i++) CheatString[i] = ' '; - + LastTimeTouched = CTimer::GetTimeInMilliseconds(); AverageWeapon = 0; AverageEntries = 0; @@ -484,7 +485,7 @@ CMouseControllerState::CMouseControllerState() WHEELDN = 0; MXB1 = 0; MXB2 = 0; - + x = 0.0f; y = 0.0f; } @@ -503,35 +504,35 @@ void CMouseControllerState::Clear() CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() { CMouseControllerState state; - + #if defined RW_D3D9 || defined RWLIBS - if ( PSGLOBAL(mouse) == nil ) + if (PSGLOBAL(mouse) == nil) _InputInitialiseMouse(); - - if ( PSGLOBAL(mouse) != nil ) + + if (PSGLOBAL(mouse) != nil) { DIDEVCAPS devCaps; devCaps.dwSize = sizeof(DIDEVCAPS); - + PSGLOBAL(mouse)->GetCapabilities(&devCaps); - switch ( devCaps.dwButtons ) + switch (devCaps.dwButtons) { - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - state.MMB = true; - - case 2: - state.RMB = true; - - case 1: - state.LMB = true; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + state.MMB = true; + + case 2: + state.RMB = true; + + case 1: + state.LMB = true; } - - if ( devCaps.dwAxes == 3 ) + + if (devCaps.dwAxes == 3) { state.WHEELDN = true; state.WHEELUP = true; @@ -556,29 +557,29 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() void CPad::UpdateMouse() { - if ( IsForegroundApp() ) + if (IsForegroundApp()) { #if defined RW_D3D9 || defined RWLIBS - if ( PSGLOBAL(mouse) == nil ) + if (PSGLOBAL(mouse) == nil) _InputInitialiseMouse(); - + DIMOUSESTATE2 state; - - if ( PSGLOBAL(mouse) != nil && SUCCEEDED(_InputGetMouseState(&state)) ) + + if (PSGLOBAL(mouse) != nil && SUCCEEDED(_InputGetMouseState(&state))) { int32 signX = 1; int32 signy = 1; - if ( !FrontEndMenuManager.m_bMenuActive ) + if (!FrontEndMenuManager.m_bMenuActive) { - if ( MousePointerStateHelper.bInvertVertically ) + if (MousePointerStateHelper.bInvertVertically) signy = -1; - if ( MousePointerStateHelper.bInvertHorizontally ) + if (MousePointerStateHelper.bInvertHorizontally) signX = -1; } - + PCTempMouseControllerState.Clear(); - + PCTempMouseControllerState.x = (float)(signX * state.lX); PCTempMouseControllerState.y = (float)(signy * state.lY); PCTempMouseControllerState.LMB = state.rgbButtons[0] & 128; @@ -586,12 +587,12 @@ void CPad::UpdateMouse() PCTempMouseControllerState.MMB = state.rgbButtons[2] & 128; PCTempMouseControllerState.MXB1 = state.rgbButtons[3] & 128; PCTempMouseControllerState.MXB2 = state.rgbButtons[4] & 128; - - if ( state.lZ > 0 ) + + if (state.lZ > 0) PCTempMouseControllerState.WHEELUP = 1; - else if ( state.lZ < 0 ) + else if (state.lZ < 0) PCTempMouseControllerState.WHEELDN = 1; - + OldMouseControllerState = NewMouseControllerState; NewMouseControllerState = PCTempMouseControllerState; } @@ -637,15 +638,15 @@ void CPad::UpdateMouse() } } -CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2) +CControllerState CPad::ReconcileTwoControllersInput(CControllerState const& State1, CControllerState const& State2) { static CControllerState ReconState; - + ReconState.Clear(); #define _RECONCILE_BUTTON(button) \ { if ( State1.button || State2.button ) ReconState.button = 255; } - + #define _RECONCILE_AXIS_POSITIVE(axis) \ { if ( State1.axis >= 0 && State2.axis >= 0 ) ReconState.axis = Max(State1.axis, State2.axis); } @@ -654,10 +655,10 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &Stat #define _RECONCILE_AXIS(axis) \ { _RECONCILE_AXIS_POSITIVE(axis); _RECONCILE_AXIS_NEGATIVE(axis); } - + #define _FIX_AXIS_DIR(axis) \ { if ( State1.axis > 0 && State2.axis < 0 || State1.axis < 0 && State2.axis > 0 ) ReconState.axis = 0; } - + #define _FIX_RECON_DIR(pos, neg, axis) \ { if ( (ReconState.pos || ReconState.axis < 0) && (ReconState.neg || ReconState.axis > 0) ) { ReconState.pos = 0; ReconState.neg = 0; ReconState.axis = 0; } } @@ -690,7 +691,7 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &Stat _FIX_RECON_DIR(DPadLeft, DPadRight, LeftStickX); return ReconState; - + #undef _RECONCILE_BUTTON #undef _RECONCILE_AXIS_POSITIVE #undef _RECONCILE_AXIS_NEGATIVE @@ -701,20 +702,20 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &Stat void CPad::StartShake(int16 nDur, uint8 nFreq) { - if ( !CMenuManager::m_PrefsUseVibration ) + if (!CMenuManager::m_PrefsUseVibration) return; - - if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) + + if (CCutsceneMgr::IsRunning() || CGame::playingIntro) return; - - if ( nFreq == 0 ) + + if (nFreq == 0) { ShakeDur = 0; ShakeFreq = 0; return; } - - if ( nDur > ShakeDur ) + + if (nDur > ShakeDur) { ShakeDur = nDur; ShakeFreq = nFreq; @@ -723,24 +724,24 @@ void CPad::StartShake(int16 nDur, uint8 nFreq) void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fZ) { - if ( !CMenuManager::m_PrefsUseVibration ) + if (!CMenuManager::m_PrefsUseVibration) return; - - if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) + + if (CCutsceneMgr::IsRunning() || CGame::playingIntro) return; - - float fDist = ( TheCamera.GetPosition() - CVector(fX, fY, fZ) ).Magnitude(); - - if ( fDist < 70.0f ) + + float fDist = (TheCamera.GetPosition() - CVector(fX, fY, fZ)).Magnitude(); + + if (fDist < 70.0f) { - if ( nFreq == 0 ) + if (nFreq == 0) { ShakeDur = 0; ShakeFreq = 0; return; } - - if ( nDur > ShakeDur ) + + if (nDur > ShakeDur) { ShakeDur = nDur; ShakeFreq = nFreq; @@ -750,22 +751,22 @@ void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, floa void CPad::StartShake_Train(float fX, float fY) { - if ( !CMenuManager::m_PrefsUseVibration ) + if (!CMenuManager::m_PrefsUseVibration) return; - - if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) + + if (CCutsceneMgr::IsRunning() || CGame::playingIntro) return; - - if (FindPlayerVehicle() != nil && FindPlayerVehicle()->IsTrain() ) + + if (FindPlayerVehicle() != nil && FindPlayerVehicle()->IsTrain()) return; - - float fDist = ( TheCamera.GetPosition() - CVector(fX, fY, 0.0f) ).Magnitude2D(); - - if ( fDist < 70.0f ) + + float fDist = (TheCamera.GetPosition() - CVector(fX, fY, 0.0f)).Magnitude2D(); + + if (fDist < 70.0f) { int32 freq = (int32)((70.0f - fDist) * 70.0f / 70.0f + 30.0f); - if ( ShakeDur < 100 ) + if (ShakeDur < 100) { ShakeDur = 100; ShakeFreq = freq; @@ -776,102 +777,102 @@ void CPad::StartShake_Train(float fX, float fY) #ifdef GTA_PS2_STUFF void CPad::AddToCheatString(char c) { - for ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- ) + for (int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i--) CheatString[i + 1] = CheatString[i]; - + CheatString[0] = c; #define _CHEATCMP(str) strncmp(str, CheatString, sizeof(str)-1) // "4414LDRULDRU" - R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - if ( !_CHEATCMP("URDLURDL4144") ) + if (!_CHEATCMP("URDLURDL4144")) WeaponCheat(); // "4411LDRULDRU" - R2 R2 L1 L1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - else if ( !_CHEATCMP("URDLURDL1144") ) + else if (!_CHEATCMP("URDLURDL1144")) MoneyCheat(); - + // "4412LDRULDRU" - R2 R2 L1 L2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - else if ( !_CHEATCMP("URDLURDL2144") ) + else if (!_CHEATCMP("URDLURDL2144")) ArmourCheat(); - + // "4413LDRULDRU" - R2 R2 L1 R1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - else if ( !_CHEATCMP("URDLURDL3144") ) + else if (!_CHEATCMP("URDLURDL3144")) HealthCheat(); // "4414LRLRLR" - R2 R2 L1 R2 LEFT RIGHT LEFT RIGHT LEFT RIGHT - else if ( !_CHEATCMP("RLRLRL4144") ) + else if (!_CHEATCMP("RLRLRL4144")) WantedLevelUpCheat(); - + // "4414UDUDUD" - R2 R2 L1 R2 UP DOWN UP DOWN UP DOWN - else if ( !_CHEATCMP("DUDUDU4144") ) + else if (!_CHEATCMP("DUDUDU4144")) WantedLevelDownCheat(); - + // "1234432T" - L1 L2 R1 R2 R2 R1 L2 TRIANGLE - else if ( !_CHEATCMP("T2344321") ) + else if (!_CHEATCMP("T2344321")) SunnyWeatherCheat(); - + // "1234432S" - L1 L2 R1 R2 R2 R1 L2 SQUARE - else if ( !_CHEATCMP("S2344321") ) + else if (!_CHEATCMP("S2344321")) CloudyWeatherCheat(); - + // "1234432C" - L1 L2 R1 R2 R2 R1 L2 CIRCLE - else if ( !_CHEATCMP("C2344321") ) + else if (!_CHEATCMP("C2344321")) RainyWeatherCheat(); - + // "1234432X" - L1 L2 R1 R2 R2 R1 L2 CROSS - else if ( !_CHEATCMP("X2344321") ) + else if (!_CHEATCMP("X2344321")) FoggyWeatherCheat(); - + // "CCCCCC321TCT" - CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE - else if ( !_CHEATCMP("TCT123CCCCCC") ) - TankCheat(); - + else if (!_CHEATCMP("TCT123CCCCCC")) + VehicleCheat(true, MI_RHINO); + // "CCCSSSSS1TCT" - CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE - else if ( !_CHEATCMP("TCT1SSSSSCCC") ) + else if (!_CHEATCMP("TCT1SSSSSCCC")) FastWeatherCheat(); - + // "241324TSCT21" - L2 R2 L1 R1 L2 R2 TRIANGLE SQUARE CIRCLE TRIANGLE L2 L1 - else if ( !_CHEATCMP("12TCST423142") ) + else if (!_CHEATCMP("12TCST423142")) BlowUpCarsCheat(); - + // "RDLU12ULDR" - RIGHT DOWN LEFT UP L1 L2 UP LEFT DOWN RIGHT - else if ( !_CHEATCMP("RDLU21ULDR") ) + else if (!_CHEATCMP("RDLU21ULDR")) ChangePlayerCheat(); - + // "DULUX3421" - DOWN UP LEFT UP CROSS R1 R2 L2 L1 - else if ( !_CHEATCMP("1243XULUD") ) + else if (!_CHEATCMP("1243XULUD")) MayhemCheat(); - + // "DULUX3412" - DOWN UP LEFT UP CROSS R1 R2 L1 L2 - else if ( !_CHEATCMP("2143XULUD") ) + else if (!_CHEATCMP("2143XULUD")) EverybodyAttacksPlayerCheat(); - + // "43TX21UD" - R2 R1 TRIANGLE CROSS L2 L1 UP DOWN - else if ( !_CHEATCMP("DU12XT34") ) + else if (!_CHEATCMP("DU12XT34")) WeaponsForAllCheat(); - + // "TURDS12" - TRIANGLE UP RIGHT DOWN SQUARE L1 L2 - else if ( !_CHEATCMP("21SDRUT") ) + else if (!_CHEATCMP("21SDRUT")) FastTimeCheat(); - + // "TURDS34" - TRIANGLE UP RIGHT DOWN SQUARE R1 R2 - else if ( !_CHEATCMP("43SDRUT") ) + else if (!_CHEATCMP("43SDRUT")) SlowTimeCheat(); // "11S4T1T" - L1 L1 SQUARE R2 TRIANGLE L1 TRIANGLE - else if ( !_CHEATCMP("T1T4S11") ) + else if (!_CHEATCMP("T1T4S11")) OnlyRenderWheelsCheat(); - + // "R4C32D13" - RIGHT R2 CIRCLE R1 L2 DOWN L1 R1 - else if ( !_CHEATCMP("31D23C4R") ) + else if (!_CHEATCMP("31D23C4R")) ChittyChittyBangBangCheat(); - + // "3141L33T" - R1 L1 R2 L1 LEFT R1 R1 TRIANGLE - else if ( !_CHEATCMP("T33L1413") ) + else if (!_CHEATCMP("T33L1413")) StrongGripCheat(); - + // "S1CD13TR1X" - SQUARE L1 CIRCLE DOWN L1 R1 TRIANGLE RIGHT L1 CROSS - else if ( !_CHEATCMP("X1RT31DC1S") ) + else if (!_CHEATCMP("X1RT31DC1S")) NastyLimbsCheat(); #undef _CHEATCMP } @@ -879,117 +880,153 @@ void CPad::AddToCheatString(char c) void CPad::AddToPCCheatString(char c) { - for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- ) + for (int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i--) KeyBoardCheatString[i + 1] = KeyBoardCheatString[i]; - + KeyBoardCheatString[0] = c; - - #define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) - + +#define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) + // "GUNSGUNSGUNS" - if ( !_CHEATCMP("SNUGSNUGSNUG") ) + if (!_CHEATCMP("SNUGSNUGSNUG")) WeaponCheat(); // "IFIWEREARICHMAN" - if ( !_CHEATCMP("NAMHCIRAEREWIFI") ) + if (!_CHEATCMP("NAMHCIRAEREWIFI")) MoneyCheat(); - + // "GESUNDHEIT" - if ( !_CHEATCMP("TIEHDNUSEG") ) + if (!_CHEATCMP("TIEHDNUSEG")) HealthCheat(); - + // "MOREPOLICEPLEASE" - if ( !_CHEATCMP("ESAELPECILOPEROM") ) + if (!_CHEATCMP("ESAELPECILOPEROM")) WantedLevelUpCheat(); - + // "NOPOLICEPLEASE" - if ( !_CHEATCMP("ESAELPECILOPON") ) + if (!_CHEATCMP("ESAELPECILOPON")) WantedLevelDownCheat(); - - // "GIVEUSATANK" - if ( !_CHEATCMP("KNATASUEVIG") ) - TankCheat(); - + + // "PANZER" + if (!_CHEATCMP("REZNAP")) + VehicleCheat(true, MI_RHINO); + + // "TRAVELINSTYLE" + if (!_CHEATCMP("ELYTSNILEVART")) + VehicleCheat(true, MI_BLOODRA); + + // "GETTHEREQUICKLY" + if (!_CHEATCMP("YLKCIUQEREHTTEG")) + VehicleCheat(true, MI_BLOODRB); + + // "GETTHEREFAST" + if (!_CHEATCMP("TSAFEREHTTEG")) + VehicleCheat(true, MI_SABRETUR); + + // "GETTHEREVERYFASTINDEED" + if (!_CHEATCMP("DEEDNITSAFYREVEREHTTEG")) + VehicleCheat(true, MI_HOTRINA); + + // "GETTHEREAMAZINGLYFAST" + if (!_CHEATCMP("TSAFYLGNIZAMAEREHTTEG")) + VehicleCheat(true, MI_HOTRINB); + + // "THELASTRIDE" + if (!_CHEATCMP("EDIRTSALEHT")) + VehicleCheat(true, MI_ROMERO); + + // "ROCKANDROLLCAR" + if (!_CHEATCMP("RACLLORDNAKCOR")) + VehicleCheat(true, MI_LOVEFIST); + + // "RUBBISHCAR" + if (!_CHEATCMP("RACHSIBBUR")) + VehicleCheat(true, MI_TRASH); + + // "BETTERTHANWALKING" + if (!_CHEATCMP("GNIKLAWNAHTRETTEB")) + VehicleCheat(true, MI_CADDY); + // "BANGBANGBANG" - if ( !_CHEATCMP("GNABGNABGNAB") ) + if (!_CHEATCMP("GNABGNABGNAB")) BlowUpCarsCheat(); - + // "ILIKEDRESSINGUP" - if ( !_CHEATCMP("PUGNISSERDEKILI") ) + if (!_CHEATCMP("PUGNISSERDEKILI")) ChangePlayerCheat(); - + // "ITSALLGOINGMAAAD" - if ( !_CHEATCMP("DAAAMGNIOGLLASTI") ) + if (!_CHEATCMP("DAAAMGNIOGLLASTI")) MayhemCheat(); - + // "NOBODYLIKESME" - if ( !_CHEATCMP("EMSEKILYDOBON") ) + if (!_CHEATCMP("EMSEKILYDOBON")) EverybodyAttacksPlayerCheat(); - + // "WEAPONSFORALL" - if ( !_CHEATCMP("LLAROFSNOPAEW") ) + if (!_CHEATCMP("LLAROFSNOPAEW")) WeaponsForAllCheat(); - + // "TIMEFLIESWHENYOU" - if ( !_CHEATCMP("UOYNEHWSEILFEMIT") ) + if (!_CHEATCMP("UOYNEHWSEILFEMIT")) FastTimeCheat(); - + // "BOOOOORING" - if ( !_CHEATCMP("GNIROOOOOB") ) + if (!_CHEATCMP("GNIROOOOOB")) SlowTimeCheat(); - + #ifndef GTA3_1_1_PATCH // "TURTOISE" - if ( !_CHEATCMP("ESIOTRUT") ) + if (!_CHEATCMP("ESIOTRUT")) ArmourCheat(); #else // "TORTOISE" - if ( !_CHEATCMP("ESIOTROT") ) + if (!_CHEATCMP("ESIOTROT")) ArmourCheat(); #endif - + // "SKINCANCERFORME" - if ( !_CHEATCMP("EMROFRECNACNIKS") ) + if (!_CHEATCMP("EMROFRECNACNIKS")) SunnyWeatherCheat(); - + // "ILIKESCOTLAND" - if ( !_CHEATCMP("DNALTOCSEKILI") ) + if (!_CHEATCMP("DNALTOCSEKILI")) CloudyWeatherCheat(); - + // "ILOVESCOTLAND" - if ( !_CHEATCMP("DNALTOCSEVOLI") ) + if (!_CHEATCMP("DNALTOCSEVOLI")) RainyWeatherCheat(); - + // "PEASOUP" - if ( !_CHEATCMP("PUOSAEP") ) + if (!_CHEATCMP("PUOSAEP")) FoggyWeatherCheat(); - + // "MADWEATHER" - if ( !_CHEATCMP("REHTAEWDAM") ) + if (!_CHEATCMP("REHTAEWDAM")) FastWeatherCheat(); - + // "ANICESETOFWHEELS" - if ( !_CHEATCMP("SLEEHWFOTESECINA") ) + if (!_CHEATCMP("SLEEHWFOTESECINA")) OnlyRenderWheelsCheat(); - + // "CHITTYCHITTYBB" - if ( !_CHEATCMP("BBYTTIHCYTTIHC") ) + if (!_CHEATCMP("BBYTTIHCYTTIHC")) ChittyChittyBangBangCheat(); - + // "CORNERSLIKEMAD" - if ( !_CHEATCMP("DAMEKILSRENROC") ) + if (!_CHEATCMP("DAMEKILSRENROC")) StrongGripCheat(); - + // "NASTYLIMBSCHEAT" - if ( !_CHEATCMP("TAEHCSBMILYTSAN") ) + if (!_CHEATCMP("TAEHCSBMILYTSAN")) NastyLimbsCheat(); // "IWANTITPAINTEDBLACK" - if ( !_CHEATCMP("KCALBDETNIAPTITNAWI") ) + if (!_CHEATCMP("KCALBDETNIAPTITNAWI")) BlackCarsCheat(); // "AHAIRDRESSERSCAR" - if ( !_CHEATCMP("RACSRESSERDRIAHA") ) + if (!_CHEATCMP("RACSRESSERDRIAHA")) PinkCarsCheat(); #ifdef KANGAROO_CHEAT @@ -1015,8 +1052,8 @@ void CPad::AddToPCCheatString(char c) if (!_CHEATCMP("ODODRETSAMOTTNAWI")) AltDodoCheat(); #endif - - #undef _CHEATCMP + +#undef _CHEATCMP } #ifdef XINPUT @@ -1066,7 +1103,7 @@ void CPad::AffectFromXinput(uint32 pad) uint16 iLeftMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff); uint16 iRightMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff); - + if (ShakeDur < CTimer::GetTimeStepInMilliseconds()) ShakeDur = 0; else @@ -1081,10 +1118,10 @@ void CPad::AffectFromXinput(uint32 pad) } #endif -void CPad::UpdatePads(void) +void CPad::UpdatePads(void) { bool bUpdate = true; - + GetPad(0)->UpdateMouse(); #ifdef XINPUT GetPad(0)->AffectFromXinput(0); @@ -1106,11 +1143,11 @@ void CPad::UpdatePads(void) if (IsAffectedByController && (GetPad(0)->PCTempKeyState.IsAnyButtonPressed() || GetPad(0)->PCTempMouseState.IsAnyButtonPressed())) IsAffectedByController = false; #endif - - if ( CReplay::IsPlayingBackFromFile() ) + + if (CReplay::IsPlayingBackFromFile()) bUpdate = false; - - if ( bUpdate ) + + if (bUpdate) { GetPad(0)->Update(0); GetPad(1)->Update(0); @@ -1120,7 +1157,7 @@ void CPad::UpdatePads(void) GetPad(1)->NewState.Clear(); GetPad(1)->OldState.Clear(); #endif - + OldKeyState = NewKeyState; NewKeyState = TempKeyState; } @@ -1133,7 +1170,7 @@ void CPad::ProcessPCSpecificStuff(void) void CPad::Update(int16 unk) { OldState = NewState; - + #if (defined GTA_PS2 || defined FIX_BUGS) if (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(unk)) #endif @@ -1145,16 +1182,16 @@ void CPad::Update(int16 unk) PCTempJoyState.Clear(); PCTempKeyState.Clear(); PCTempMouseState.Clear(); - + ProcessPCSpecificStuff(); - - if ( ++iCurrHornHistory >= HORNHISTORY_SIZE ) + + if (++iCurrHornHistory >= HORNHISTORY_SIZE) iCurrHornHistory = 0; bHornHistory[iCurrHornHistory] = GetHorn(); - if ( !bDisplayNoControllerMessage ) + if (!bDisplayNoControllerMessage) CGame::bDemoMode = false; } @@ -1169,40 +1206,40 @@ void CPad::DoCheats(void) void CPad::DoCheats(int16 unk) { #ifdef GTA_PS2_STUFF - if ( GetTriangleJustDown() ) + if (GetTriangleJustDown()) AddToCheatString('T'); - - if ( GetCircleJustDown() ) + + if (GetCircleJustDown()) AddToCheatString('C'); - - if ( GetCrossJustDown() ) + + if (GetCrossJustDown()) AddToCheatString('X'); - - if ( GetSquareJustDown() ) + + if (GetSquareJustDown()) AddToCheatString('S'); - - if ( GetDPadUpJustDown() ) + + if (GetDPadUpJustDown()) AddToCheatString('U'); - - if ( GetDPadDownJustDown() ) + + if (GetDPadDownJustDown()) AddToCheatString('D'); - - if ( GetDPadLeftJustDown() ) + + if (GetDPadLeftJustDown()) AddToCheatString('L'); - - if ( GetDPadRightJustDown() ) + + if (GetDPadRightJustDown()) AddToCheatString('R'); - - if ( GetLeftShoulder1JustDown() ) + + if (GetLeftShoulder1JustDown()) AddToCheatString('1'); - - if ( GetLeftShoulder2JustDown() ) + + if (GetLeftShoulder2JustDown()) AddToCheatString('2'); - - if ( GetRightShoulder1JustDown() ) + + if (GetRightShoulder1JustDown()) AddToCheatString('3'); - - if ( GetRightShoulder2JustDown() ) + + if (GetRightShoulder2JustDown()) AddToCheatString('4'); #endif } @@ -1217,7 +1254,7 @@ void CPad::StopShaking(int16 unk) ; } -CPad *CPad::GetPad(int32 pad) +CPad* CPad::GetPad(int32 pad) { return &Pads[pad]; } @@ -1230,188 +1267,188 @@ CPad *CPad::GetPad(int32 pad) int16 CPad::GetSteeringLeftRight(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickX; - int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - - if ( Abs(axis) > Abs(dpad) ) - return axis; - else - return dpad; - - break; - } - - case 1: - case 3: - { - return NewState.LeftStickX; + case 0: + case 2: + { + int16 axis = NewState.LeftStickX; + int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - break; - } + if (Abs(axis) > Abs(dpad)) + return axis; + else + return dpad; + + break; } - + + case 1: + case 3: + { + return NewState.LeftStickX; + + break; + } + } + return 0; } int16 CPad::GetSteeringUpDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; - - if ( Abs(axis) > Abs(dpad) ) - return axis; - else - return dpad; - - break; - } - - case 1: - case 3: - { - return NewState.LeftStickY; + case 0: + case 2: + { + int16 axis = NewState.LeftStickY; + int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; - break; - } + if (Abs(axis) > Abs(dpad)) + return axis; + else + return dpad; + + break; } - + + case 1: + case 3: + { + return NewState.LeftStickY; + + break; + } + } + return 0; } int16 CPad::GetCarGunUpDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return NewState.RightStickY; - - break; - } - - case 3: - { - return (NewState.DPadUp - NewState.DPadDown) / 2; - - break; - } + case 0: + case 1: + case 2: + { + return NewState.RightStickY; + + break; } - + + case 3: + { + return (NewState.DPadUp - NewState.DPadDown) / 2; + + break; + } + } + return 0; } int16 CPad::GetCarGunLeftRight(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return NewState.RightStickX; - - break; - } - - case 3: - { - return (NewState.DPadRight - NewState.DPadLeft) / 2; - - break; - } + case 0: + case 1: + case 2: + { + return NewState.RightStickX; + + break; } - + + case 3: + { + return (NewState.DPadRight - NewState.DPadLeft) / 2; + + break; + } + } + return 0; } int16 CPad::GetPedWalkLeftRight(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickX; - int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - - if ( Abs(axis) > Abs(dpad) ) - return axis; - else - return dpad; - - break; - } - - case 1: - case 3: - { - return NewState.LeftStickX; + case 0: + case 2: + { + int16 axis = NewState.LeftStickX; + int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - break; - } + if (Abs(axis) > Abs(dpad)) + return axis; + else + return dpad; + + break; } - + + case 1: + case 3: + { + return NewState.LeftStickX; + + break; + } + } + return 0; } int16 CPad::GetPedWalkUpDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; - - if ( Abs(axis) > Abs(dpad) ) - return axis; - else - return dpad; - - break; - } - - case 1: - case 3: - { - return NewState.LeftStickY; + case 0: + case 2: + { + int16 axis = NewState.LeftStickY; + int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; - break; - } + if (Abs(axis) > Abs(dpad)) + return axis; + else + return dpad; + + break; } - + + case 1: + case 3: + { + return NewState.LeftStickY; + + break; + } + } + return 0; } @@ -1419,43 +1456,43 @@ int16 CPad::GetAnalogueUpDown(void) { switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; - - if ( Abs(axis) > Abs(dpad) ) - return axis; - else - return dpad; - - break; - } - - case 1: - case 3: - { - return NewState.LeftStickY; + case 0: + case 2: + { + int16 axis = NewState.LeftStickY; + int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; - break; - } + if (Abs(axis) > Abs(dpad)) + return axis; + else + return dpad; + + break; } - + + case 1: + case 3: + { + return NewState.LeftStickY; + + break; + } + } + return 0; } bool CPad::GetLookLeft(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; - + return !!(NewState.LeftShoulder2 && !NewState.RightShoulder2); } bool CPad::GetLookRight(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; return !!(NewState.RightShoulder2 && !NewState.LeftShoulder2); @@ -1464,7 +1501,7 @@ bool CPad::GetLookRight(void) bool CPad::GetLookBehindForCar(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; return !!(NewState.RightShoulder2 && NewState.LeftShoulder2); @@ -1472,7 +1509,7 @@ bool CPad::GetLookBehindForCar(void) bool CPad::GetLookBehindForPed(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; return !!NewState.RightShock; @@ -1480,363 +1517,363 @@ bool CPad::GetLookBehindForPed(void) bool CPad::GetHorn(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - { - return !!NewState.LeftShock; + case 0: + { + return !!NewState.LeftShock; - break; - } - - case 1: - { - return !!NewState.LeftShoulder1; - - break; - } - - case 2: - { - return !!NewState.RightShoulder1; - - break; - } - - case 3: - { - return !!NewState.LeftShock; - - break; - } + break; } - + + case 1: + { + return !!NewState.LeftShoulder1; + + break; + } + + case 2: + { + return !!NewState.RightShoulder1; + + break; + } + + case 3: + { + return !!NewState.LeftShock; + + break; + } + } + return false; } bool CPad::HornJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - { - return !!(NewState.LeftShock && !OldState.LeftShock); + case 0: + { + return !!(NewState.LeftShock && !OldState.LeftShock); - break; - } - - case 1: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } - - case 2: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } - - case 3: - { - return !!(NewState.LeftShock && !OldState.LeftShock); - - break; - } + break; } - + + case 1: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } + + case 2: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } + + case 3: + { + return !!(NewState.LeftShock && !OldState.LeftShock); + + break; + } + } + return false; } bool CPad::GetCarGunFired(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!NewState.Circle; + case 0: + case 1: + case 2: + { + return !!NewState.Circle; - break; - } - - case 3: - { - return !!NewState.RightShoulder1; - - break; - } + break; } - + + case 3: + { + return !!NewState.RightShoulder1; + + break; + } + } + return false; } bool CPad::CarGunJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!(NewState.Circle && !OldState.Circle); + case 0: + case 1: + case 2: + { + return !!(NewState.Circle && !OldState.Circle); - break; - } - - case 3: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } + break; } - + + case 3: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } + } + return false; } int16 CPad::GetHandBrake(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 1: - { - return NewState.RightShoulder1; - - break; - } - - case 2: - { - return NewState.Triangle; - - break; - } - - case 3: - { - return NewState.LeftShoulder1; - - break; - } + case 0: + case 1: + { + return NewState.RightShoulder1; + + break; } - + + case 2: + { + return NewState.Triangle; + + break; + } + + case 3: + { + return NewState.LeftShoulder1; + + break; + } + } + return 0; } int16 CPad::GetBrake(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 2: - { - return NewState.Square; - - break; - } - - case 1: - { - return NewState.Square; + case 0: + case 2: + { + return NewState.Square; - break; - } - - case 3: - { - int16 axis = 2 * NewState.RightStickY; - - if ( axis < 0 ) - return 0; - else - return axis; - - break; - } + break; } - + + case 1: + { + return NewState.Square; + + break; + } + + case 3: + { + int16 axis = 2 * NewState.RightStickY; + + if (axis < 0) + return 0; + else + return axis; + + break; + } + } + return 0; } bool CPad::GetExitVehicle(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Triangle; - - break; - } - - case 2: - { - return !!NewState.LeftShoulder1; - - break; - } + case 0: + case 1: + case 3: + { + return !!NewState.Triangle; + + break; } - + + case 2: + { + return !!NewState.LeftShoulder1; + + break; + } + } + return false; } bool CPad::ExitVehicleJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!(NewState.Triangle && !OldState.Triangle); - - break; - } - - case 2: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } + case 0: + case 1: + case 3: + { + return !!(NewState.Triangle && !OldState.Triangle); + + break; } - + + case 2: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } + } + return false; } int32 CPad::GetWeapon(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - { - return NewState.Circle; - - break; - } - - case 2: - { - return NewState.Cross; - - break; - } - - case 3: - { - return NewState.RightShoulder1; - - break; - } + case 0: + case 1: + { + return NewState.Circle; + + break; } - + + case 2: + { + return NewState.Cross; + + break; + } + + case 3: + { + return NewState.RightShoulder1; + + break; + } + } + return false; } bool CPad::WeaponJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - { - return !!(NewState.Circle && !OldState.Circle); - - break; - } - - case 2: - { - return !!(NewState.Cross && !OldState.Cross); - - break; - } - - case 3: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } + case 0: + case 1: + { + return !!(NewState.Circle && !OldState.Circle); + + break; } - + + case 2: + { + return !!(NewState.Cross && !OldState.Cross); + + break; + } + + case 3: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } + } + return false; } int16 CPad::GetAccelerate(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return 0; switch (CURMODE) { - case 0: - case 2: - { - return NewState.Cross; - - break; - } - - case 1: - { - return NewState.Cross; - - break; - } - - case 3: - { - int16 axis = -2 * NewState.RightStickY; - - if ( axis < 0 ) - return 0; - else - return axis; - - break; - } + case 0: + case 2: + { + return NewState.Cross; + + break; } - + + case 1: + { + return NewState.Cross; + + break; + } + + case 3: + { + int16 axis = -2 * NewState.RightStickY; + + if (axis < 0) + return 0; + else + return axis; + + break; + } + } + return 0; } @@ -1844,23 +1881,23 @@ bool CPad::CycleCameraModeUpJustDown(void) { switch (CURMODE) { - case 0: - case 2: - case 3: - { - return !!(NewState.Select && !OldState.Select); - - break; - } - - case 1: - { - return !!(NewState.DPadUp && !OldState.DPadUp); - - break; - } + case 0: + case 2: + case 3: + { + return !!(NewState.Select && !OldState.Select); + + break; } - + + case 1: + { + return !!(NewState.DPadUp && !OldState.DPadUp); + + break; + } + } + return false; } @@ -1868,77 +1905,77 @@ bool CPad::CycleCameraModeDownJustDown(void) { switch (CURMODE) { - case 0: - case 2: - case 3: - { - return false; - - break; - } - - case 1: - { - return !!(NewState.DPadDown && !OldState.DPadDown); - - break; - } + case 0: + case 2: + case 3: + { + return false; + + break; } - + + case 1: + { + return !!(NewState.DPadDown && !OldState.DPadDown); + + break; + } + } + return false; } bool CPad::ChangeStationJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } - - case 1: - { - return !!(NewState.Select && !OldState.Select); - - break; - } - - case 2: - { - return !!(NewState.LeftShock && !OldState.LeftShock); - - break; - } - - case 3: - { - return !!(NewState.Circle && !OldState.Circle); - - break; - } + case 0: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; } - + + case 1: + { + return !!(NewState.Select && !OldState.Select); + + break; + } + + case 2: + { + return !!(NewState.LeftShock && !OldState.LeftShock); + + break; + } + + case 3: + { + return !!(NewState.Circle && !OldState.Circle); + + break; + } + } + return false; } bool CPad::CycleWeaponLeftJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; - + return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); } bool CPad::CycleWeaponRightJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); @@ -1946,96 +1983,96 @@ bool CPad::CycleWeaponRightJustDown(void) bool CPad::GetTarget(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!NewState.RightShoulder1; - - break; - } - - case 3: - { - return !!NewState.LeftShoulder1; - - break; - } + case 0: + case 1: + case 2: + { + return !!NewState.RightShoulder1; + + break; } - + + case 3: + { + return !!NewState.LeftShoulder1; + + break; + } + } + return false; } bool CPad::TargetJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } - - case 3: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } + case 0: + case 1: + case 2: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; } - + + case 3: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } + } + return false; } bool CPad::JumpJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; - + return !!(NewState.Square && !OldState.Square); } bool CPad::GetSprint(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Cross; - - break; - } - - case 2: - { - return !!NewState.Circle; - - break; - } + case 0: + case 1: + case 3: + { + return !!NewState.Cross; + + break; } - + + case 2: + { + return !!NewState.Circle; + + break; + } + } + return false; } bool CPad::ShiftTargetLeftJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); @@ -2043,7 +2080,7 @@ bool CPad::ShiftTargetLeftJustDown(void) bool CPad::ShiftTargetRightJustDown(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); @@ -2052,10 +2089,10 @@ bool CPad::ShiftTargetRightJustDown(void) bool CPad::GetAnaloguePadUp(void) { static int16 oldfStickY = 0; - + int16 Y = CPad::GetPad(0)->GetAnalogueUpDown(); - - if ( Y < 0 && oldfStickY >= 0 ) + + if (Y < 0 && oldfStickY >= 0) { oldfStickY = Y; return true; @@ -2070,10 +2107,10 @@ bool CPad::GetAnaloguePadUp(void) bool CPad::GetAnaloguePadDown(void) { static int16 oldfStickY = 0; - + int16 Y = CPad::GetPad(0)->GetAnalogueUpDown(); - - if ( Y > 0 && oldfStickY <= 0 ) + + if (Y > 0 && oldfStickY <= 0) { oldfStickY = Y; return true; @@ -2088,10 +2125,10 @@ bool CPad::GetAnaloguePadDown(void) bool CPad::GetAnaloguePadLeft(void) { static int16 oldfStickX = 0; - + int16 X = CPad::GetPad(0)->GetPedWalkLeftRight(); - - if ( X < 0 && oldfStickX >= 0 ) + + if (X < 0 && oldfStickX >= 0) { oldfStickX = X; return true; @@ -2106,10 +2143,10 @@ bool CPad::GetAnaloguePadLeft(void) bool CPad::GetAnaloguePadRight(void) { static int16 oldfStickX = 0; - + int16 X = CPad::GetPad(0)->GetPedWalkLeftRight(); - - if ( X > 0 && oldfStickX <= 0 ) + + if (X > 0 && oldfStickX <= 0) { oldfStickX = X; return true; @@ -2124,19 +2161,19 @@ bool CPad::GetAnaloguePadRight(void) bool CPad::GetAnaloguePadLeftJustUp(void) { static int16 oldfStickX = 0; - + int16 X = GetPad(0)->GetPedWalkLeftRight(); - - if ( X == 0 && oldfStickX < 0 ) + + if (X == 0 && oldfStickX < 0) { oldfStickX = X; - + return true; } else { oldfStickX = X; - + return false; } } @@ -2144,107 +2181,107 @@ bool CPad::GetAnaloguePadLeftJustUp(void) bool CPad::GetAnaloguePadRightJustUp(void) { static int16 oldfStickX = 0; - + int16 X = GetPad(0)->GetPedWalkLeftRight(); - - if ( X == 0 && oldfStickX > 0 ) + + if (X == 0 && oldfStickX > 0) { oldfStickX = X; - + return true; } else { oldfStickX = X; - + return false; } } bool CPad::ForceCameraBehindPlayer(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - { - return !!NewState.LeftShoulder1; - - break; - } - - case 2: - { - return !!NewState.Triangle; - - break; - } - - case 3: - { - return !!NewState.Circle; - - break; - } + case 0: + case 1: + { + return !!NewState.LeftShoulder1; + + break; } - + + case 2: + { + return !!NewState.Triangle; + + break; + } + + case 3: + { + return !!NewState.Circle; + + break; + } + } + return false; } bool CPad::SniperZoomIn(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Square; + case 0: + case 1: + case 3: + { + return !!NewState.Square; - break; - } - - case 2: - { - return !!NewState.Triangle; - - break; - } + break; } - + + case 2: + { + return !!NewState.Triangle; + + break; + } + } + return false; } bool CPad::SniperZoomOut(void) { - if ( ArePlayerControlsDisabled() ) + if (ArePlayerControlsDisabled()) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Cross; + case 0: + case 1: + case 3: + { + return !!NewState.Cross; - break; - } - - case 2: - { - return !!NewState.Square; - - break; - } + break; } - + + case 2: + { + return !!NewState.Square; + + break; + } + } + return false; } @@ -2254,8 +2291,8 @@ int16 CPad::SniperModeLookLeftRight(void) { int16 axis = NewState.LeftStickX; int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - - if ( Abs(axis) > Abs(dpad) ) + + if (Abs(axis) > Abs(dpad)) return axis; else return dpad; @@ -2268,8 +2305,8 @@ int16 CPad::SniperModeLookUpDown(void) axis = -axis; #endif int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; - - if ( Abs(axis) > Abs(dpad) ) + + if (Abs(axis) > Abs(dpad)) return axis; else return dpad; @@ -2278,15 +2315,15 @@ int16 CPad::SniperModeLookUpDown(void) int16 CPad::LookAroundLeftRight(void) { float axis = GetPad(0)->NewState.RightStickX; - - if ( Abs(axis) > 85 && !GetLookBehindForPed() ) - return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) ) - * (127.0f / 32.0f) ); // 3.96875f - else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 10 ) - return (int16) ( (axis + ( ( axis > 0 ) ? -10 : 10) ) - * (127.0f / 64.0f) ); // 1.984375f - + if (Abs(axis) > 85 && !GetLookBehindForPed()) + return (int16)((axis + ((axis > 0) ? -85 : 85)) + * (127.0f / 32.0f)); // 3.96875f + + else if (TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 10) + return (int16)((axis + ((axis > 0) ? -10 : 10)) + * (127.0f / 64.0f)); // 1.984375f + return 0; } @@ -2298,13 +2335,13 @@ int16 CPad::LookAroundUpDown(void) axis = -axis; #endif - if ( Abs(axis) > 85 && !GetLookBehindForPed() ) - return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) ) - * (127.0f / 32.0f) ); // 3.96875f + if (Abs(axis) > 85 && !GetLookBehindForPed()) + return (int16)((axis + ((axis > 0) ? -85 : 85)) + * (127.0f / 32.0f)); // 3.96875f - else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 40 ) - return (int16) ( (axis + ( ( axis > 0 ) ? -40 : 40) ) - * (127.0f / 64.0f) ); // 1.984375f + else if (TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 40) + return (int16)((axis + ((axis > 0) ? -40 : 40)) + * (127.0f / 64.0f)); // 1.984375f return 0; } @@ -2318,7 +2355,7 @@ void CPad::ResetAverageWeapon(void) void CPad::PrintErrorMessage(void) { - if ( bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive ) + if (bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive) { CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); @@ -2330,12 +2367,12 @@ void CPad::PrintErrorMessage(void) CFont::SetFontStyle(FONT_BANK); CFont::PrintString ( - SCREEN_WIDTH / 2, + SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, TheText.Get("NOCONT") // Please reconnect an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). to controller port 1 to continue - ); + ); } - else if ( bObsoleteControllerMessage ) + else if (bObsoleteControllerMessage) { CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); @@ -2347,31 +2384,31 @@ void CPad::PrintErrorMessage(void) CFont::SetFontStyle(FONT_BANK); CFont::PrintString ( - SCREEN_WIDTH / 2, + SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, TheText.Get("WRCONT") // The controller connected to controller port 1 is an unsupported controller. Grand Theft Auto III requires an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). - ); + ); } - + } void LittleTest(void) { static int32 Cunt = 0; - + Cunt++; // ??? } void CPad::ResetCheats(void) { CWeather::ReleaseWeather(); - + CPopulation::ms_bGivePedsWeapons = false; - + CPed::bNastyLimbsCheat = false; CPed::bPedCheat2 = false; CPed::bPedCheat3 = false; - + CVehicle::bWheelsOnlyCheat = false; CVehicle::bAllDodosCheat = false; CVehicle::bCheat3 = false; @@ -2379,210 +2416,210 @@ void CPad::ResetCheats(void) CVehicle::bCheat5 = false; gbBlackCars = false; gbPinkCars = false; - + gbFastTime = false; CTimer::SetTimeScale(1.0f); } -char *CPad::EditString(char *pStr, int32 nSize) +char* CPad::EditString(char* pStr, int32 nSize) { int32 pos = strlen(pStr); - + // letters - for ( int32 i = 0; i < ('Z' - 'A' + 1); i++ ) + for (int32 i = 0; i < ('Z' - 'A' + 1); i++) { - if ( GetPad(0)->GetCharJustDown(i + 'A') && pos < nSize - 1 ) + if (GetPad(0)->GetCharJustDown(i + 'A') && pos < nSize - 1) { pStr[pos++] = i + 'A'; pStr[pos] = '\0'; } - - if ( GetPad(0)->GetCharJustDown(i + 'a') && pos < nSize - 1 ) + + if (GetPad(0)->GetCharJustDown(i + 'a') && pos < nSize - 1) { pStr[pos++] = i + 'a'; pStr[pos] = '\0'; } } - + // numbers - for ( int32 i = 0; i < ('9' - '0' + 1); i++ ) + for (int32 i = 0; i < ('9' - '0' + 1); i++) { - if ( GetPad(0)->GetCharJustDown(i + '0') && pos < nSize - 1 ) + if (GetPad(0)->GetCharJustDown(i + '0') && pos < nSize - 1) { pStr[pos++] = i + '0'; pStr[pos] = '\0'; } } - + // space - if ( GetPad(0)->GetCharJustDown(' ') && pos < nSize - 1 ) + if (GetPad(0)->GetCharJustDown(' ') && pos < nSize - 1) { pStr[pos++] = ' '; pStr[pos] = '\0'; } - - + + // del - if ( GetPad(0)->GetDeleteJustDown() || GetPad(0)->GetBackspaceJustDown() ) + if (GetPad(0)->GetDeleteJustDown() || GetPad(0)->GetBackspaceJustDown()) { - if ( pos > 0 ) + if (pos > 0) pStr[pos - 1] = '\0'; } // extenter/up/down - if ( GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown() ) + if (GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown()) return nil; - + return pStr; } -int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize) +int32* CPad::EditCodesForControls(int32* pRsKeys, int32 nSize) { *pRsKeys = rsNULL; - for ( int32 i = 0; i < 255; i++ ) + for (int32 i = 0; i < 255; i++) { - if ( GetPad(0)->GetCharJustDown(i) ) + if (GetPad(0)->GetCharJustDown(i)) *pRsKeys = i; } - - for ( int32 i = 0; i < 12; i++ ) + + for (int32 i = 0; i < 12; i++) { - if ( GetPad(0)->GetFJustDown(i) ) + if (GetPad(0)->GetFJustDown(i)) *pRsKeys = i + rsF1; } - - if ( GetPad(0)->GetEscapeJustDown() ) + + if (GetPad(0)->GetEscapeJustDown()) *pRsKeys = rsESC; - - if ( GetPad(0)->GetInsertJustDown() ) + + if (GetPad(0)->GetInsertJustDown()) *pRsKeys = rsINS; - - if ( GetPad(0)->GetDeleteJustDown() ) + + if (GetPad(0)->GetDeleteJustDown()) *pRsKeys = rsDEL; - - if ( GetPad(0)->GetHomeJustDown() ) + + if (GetPad(0)->GetHomeJustDown()) *pRsKeys = rsHOME; - - if ( GetPad(0)->GetEndJustDown() ) + + if (GetPad(0)->GetEndJustDown()) *pRsKeys = rsEND; - - if ( GetPad(0)->GetPageUpJustDown() ) + + if (GetPad(0)->GetPageUpJustDown()) *pRsKeys = rsPGUP; - - if ( GetPad(0)->GetPageDownJustDown() ) + + if (GetPad(0)->GetPageDownJustDown()) *pRsKeys = rsPGDN; - - if ( GetPad(0)->GetUpJustDown() ) + + if (GetPad(0)->GetUpJustDown()) *pRsKeys = rsUP; - - if ( GetPad(0)->GetDownJustDown() ) + + if (GetPad(0)->GetDownJustDown()) *pRsKeys = rsDOWN; - - if ( GetPad(0)->GetLeftJustDown() ) + + if (GetPad(0)->GetLeftJustDown()) *pRsKeys = rsLEFT; - - if ( GetPad(0)->GetRightJustDown() ) + + if (GetPad(0)->GetRightJustDown()) *pRsKeys = rsRIGHT; - - if ( GetPad(0)->GetScrollLockJustDown() ) + + if (GetPad(0)->GetScrollLockJustDown()) *pRsKeys = rsSCROLL; - - if ( GetPad(0)->GetPauseJustDown() ) + + if (GetPad(0)->GetPauseJustDown()) *pRsKeys = rsPAUSE; - - if ( GetPad(0)->GetNumLockJustDown() ) + + if (GetPad(0)->GetNumLockJustDown()) *pRsKeys = rsNUMLOCK; - - if ( GetPad(0)->GetDivideJustDown() ) + + if (GetPad(0)->GetDivideJustDown()) *pRsKeys = rsDIVIDE; - - if ( GetPad(0)->GetTimesJustDown() ) + + if (GetPad(0)->GetTimesJustDown()) *pRsKeys = rsTIMES; - - if ( GetPad(0)->GetMinusJustDown() ) + + if (GetPad(0)->GetMinusJustDown()) *pRsKeys = rsMINUS; - - if ( GetPad(0)->GetPlusJustDown() ) + + if (GetPad(0)->GetPlusJustDown()) *pRsKeys = rsPLUS; - if ( GetPad(0)->GetPadEnterJustDown() ) + if (GetPad(0)->GetPadEnterJustDown()) *pRsKeys = rsPADENTER; - if ( GetPad(0)->GetPadDelJustDown() ) + if (GetPad(0)->GetPadDelJustDown()) *pRsKeys = rsPADDEL; - if ( GetPad(0)->GetPad1JustDown() ) + if (GetPad(0)->GetPad1JustDown()) *pRsKeys = rsPADEND; - - if ( GetPad(0)->GetPad2JustDown() ) + + if (GetPad(0)->GetPad2JustDown()) *pRsKeys = rsPADDOWN; - - if ( GetPad(0)->GetPad3JustDown() ) + + if (GetPad(0)->GetPad3JustDown()) *pRsKeys = rsPADPGDN; - - if ( GetPad(0)->GetPad4JustDown() ) + + if (GetPad(0)->GetPad4JustDown()) *pRsKeys = rsPADLEFT; - - if ( GetPad(0)->GetPad5JustDown() ) + + if (GetPad(0)->GetPad5JustDown()) *pRsKeys = rsPAD5; - - if ( GetPad(0)->GetPad6JustDown() ) + + if (GetPad(0)->GetPad6JustDown()) *pRsKeys = rsPADRIGHT; - - if ( GetPad(0)->GetPad7JustDown() ) + + if (GetPad(0)->GetPad7JustDown()) *pRsKeys = rsPADHOME; - - if ( GetPad(0)->GetPad8JustDown() ) + + if (GetPad(0)->GetPad8JustDown()) *pRsKeys = rsPADUP; - - if ( GetPad(0)->GetPad9JustDown() ) + + if (GetPad(0)->GetPad9JustDown()) *pRsKeys = rsPADPGUP; - - if ( GetPad(0)->GetPad0JustDown() ) + + if (GetPad(0)->GetPad0JustDown()) *pRsKeys = rsPADINS; - if ( GetPad(0)->GetBackspaceJustDown() ) + if (GetPad(0)->GetBackspaceJustDown()) *pRsKeys = rsBACKSP; - - if ( GetPad(0)->GetTabJustDown() ) + + if (GetPad(0)->GetTabJustDown()) *pRsKeys = rsTAB; - - if ( GetPad(0)->GetCapsLockJustDown() ) + + if (GetPad(0)->GetCapsLockJustDown()) *pRsKeys = rsCAPSLK; - - if ( GetPad(0)->GetReturnJustDown() ) + + if (GetPad(0)->GetReturnJustDown()) *pRsKeys = rsENTER; - - if ( GetPad(0)->GetLeftShiftJustDown() ) + + if (GetPad(0)->GetLeftShiftJustDown()) *pRsKeys = rsLSHIFT; - - if ( GetPad(0)->GetShiftJustDown() ) + + if (GetPad(0)->GetShiftJustDown()) *pRsKeys = rsSHIFT; - - if ( GetPad(0)->GetRightShiftJustDown() ) + + if (GetPad(0)->GetRightShiftJustDown()) *pRsKeys = rsRSHIFT; - - if ( GetPad(0)->GetLeftCtrlJustDown() ) + + if (GetPad(0)->GetLeftCtrlJustDown()) *pRsKeys = rsLCTRL; - - if ( GetPad(0)->GetRightCtrlJustDown() ) + + if (GetPad(0)->GetRightCtrlJustDown()) *pRsKeys = rsRCTRL; - - if ( GetPad(0)->GetLeftAltJustDown() ) + + if (GetPad(0)->GetLeftAltJustDown()) *pRsKeys = rsLALT; - - if ( GetPad(0)->GetRightAltJustDown() ) + + if (GetPad(0)->GetRightAltJustDown()) *pRsKeys = rsRALT; - - if ( GetPad(0)->GetLeftWinJustDown() ) + + if (GetPad(0)->GetLeftWinJustDown()) *pRsKeys = rsLWIN; - - if ( GetPad(0)->GetRightWinJustDown() ) + + if (GetPad(0)->GetRightWinJustDown()) *pRsKeys = rsRWIN; - - if ( GetPad(0)->GetAppsJustDown() ) + + if (GetPad(0)->GetAppsJustDown()) *pRsKeys = rsAPPS; - + return pRsKeys; } diff --git a/src/core/Pad.h b/src/core/Pad.h index ea771f81..ad93fb49 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -176,7 +176,7 @@ public: static CKeyboardState OldKeyState; static CKeyboardState NewKeyState; static CKeyboardState TempKeyState; - static char KeyBoardCheatString[20]; + static char KeyBoardCheatString[30]; static CMouseControllerState OldMouseControllerState; static CMouseControllerState NewMouseControllerState; static CMouseControllerState PCTempMouseControllerState; diff --git a/src/core/main.cpp b/src/core/main.cpp index 9b40b81d..531a30d3 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -689,11 +689,13 @@ DisplayGameDebugText() { static bool bDisplayPosn = false; static bool bDisplayRate = false; + static bool bDisplayCheatStr = false; { SETTWEAKPATH("GameDebugText"); TWEAKBOOL(bDisplayPosn); TWEAKBOOL(bDisplayRate); + TWEAKBOOL(bDisplayCheatStr); } @@ -781,6 +783,26 @@ DisplayGameDebugText() CFont::SetColor(CRGBA(255, 108, 0, 255)); CFont::PrintString(40.0f, 40.0f, ustr); } + + if (bDisplayCheatStr) + { + sprintf(str, "%s", CPad::KeyBoardCheatString); + AsciiToUnicode(str, ustr); + + CFont::SetPropOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(0.7f, 1.5f); + CFont::SetCentreOn(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetWrapx(640.0f); + CFont::SetFontStyle(FONT_HEADING); + + CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.5f)+2.f, SCREEN_SCALE_FROM_BOTTOM(20.0f)+2.f, ustr); + + CFont::SetColor(CRGBA(255, 150, 225, 255)); + CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.5f), SCREEN_SCALE_FROM_BOTTOM(20.0f), ustr); + } } #endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index c7fade52..8f808b61 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -69,7 +69,7 @@ mysrand(unsigned int seed) #ifdef DEBUGMENU void WeaponCheat(); void HealthCheat(); -void TankCheat(); +void VehicleCheat(bool something, int model); void BlowUpCarsCheat(); void ChangePlayerCheat(); void MayhemCheat(); @@ -293,7 +293,7 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Cheats", "Health", HealthCheat); DebugMenuAddCmd("Cheats", "Wanted level up", WantedLevelUpCheat); DebugMenuAddCmd("Cheats", "Wanted level down", WantedLevelDownCheat); - DebugMenuAddCmd("Cheats", "Tank", TankCheat); + DebugMenuAddCmd("Cheats", "Tank", []() { VehicleCheat(true, MI_TAXI); }); DebugMenuAddCmd("Cheats", "Blow up cars", BlowUpCarsCheat); DebugMenuAddCmd("Cheats", "Change player", ChangePlayerCheat); DebugMenuAddCmd("Cheats", "Mayhem", MayhemCheat); From 0db3d03c3c9c40ba09391f2dab492d9a49acb9bd Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 17:36:12 +0300 Subject: [PATCH 089/148] sorry my bad --- src/core/Frontend.cpp | 3180 ++++++++++++++++++++--------------------- src/core/Pad.cpp | 1953 +++++++++++++------------ 2 files changed, 2500 insertions(+), 2633 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 663c9323..228168b2 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -150,8 +150,8 @@ uint8 CMenuManager::m_PrefsPlayerBlue; // why?? CMenuManager FrontEndMenuManager; uint32 TimeToStopPadShaking; -char* pEditString; -int32* pControlEdit; +char *pEditString; +int32 *pControlEdit; bool DisplayComboButtonErrMsg; int32 MouseButtonJustClicked; int32 JoyButtonJustClicked; @@ -232,8 +232,7 @@ ScaleAndCenterX(float x) else { if (x > DEFAULT_SCREEN_WIDTH / 2) { return SCREEN_WIDTH / 2 + SCREEN_SCALE_X(x - DEFAULT_SCREEN_WIDTH / 2); - } - else { + } else { return SCREEN_WIDTH / 2 - SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH / 2 - x); } } @@ -316,7 +315,7 @@ ScaleAndCenterX(float x) // --- Functions not in the game/inlined starts inline void -CMenuManager::ScrollUpListByOne() +CMenuManager::ScrollUpListByOne() { if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { if (m_nFirstVisibleRowOnList > 0) { @@ -324,8 +323,7 @@ CMenuManager::ScrollUpListByOne() m_nFirstVisibleRowOnList--; m_nScrollbarTopMargin -= SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; } - } - else { + } else { m_nSelectedListRow--; } } @@ -339,8 +337,7 @@ CMenuManager::ScrollDownListByOne() m_nFirstVisibleRowOnList++; m_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow; } - } - else { + } else { if (m_nSelectedListRow < m_nTotalListRow - 1) { m_nSelectedListRow++; } @@ -352,13 +349,12 @@ CMenuManager::PageUpList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { if (m_nFirstVisibleRowOnList > 0) { - if (playSoundOnSuccess) + if(playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); - } - else { + } else { m_nFirstVisibleRowOnList = 0; m_nSelectedListRow = 0; } @@ -371,13 +367,12 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { - if (playSoundOnSuccess) + if(playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList); - } - else { + } else { m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; m_nSelectedListRow = m_nTotalListRow - 1; } @@ -390,16 +385,14 @@ CMenuManager::ThingsToDoBeforeLeavingPage() { if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - } - else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { if (m_nPrefsAudio3DProviderIndex != -1) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); #ifdef TIDY_UP_PBP DMAudio.StopFrontEndTrack(); OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); #endif - } - else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { m_nDisplayVideoMode = m_nPrefsVideoMode; #ifdef IMPROVED_VIDEOMODE m_nSelectedScreenMode = m_nPrefsWindowed; @@ -418,7 +411,7 @@ CMenuManager::ThingsToDoBeforeLeavingPage() // ------ Functions not in the game/inlined ends void -CMenuManager::BuildStatLine(Const char* text, void* stat, bool itsFloat, void* stat2) +CMenuManager::BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2) { if (!text) return; @@ -431,20 +424,18 @@ CMenuManager::BuildStatLine(Const char* text, void* stat, bool itsFloat, void* s sprintf(gString2, " %d/%d", *(int*)stat, *(int*)stat2); else #endif - if (stat2) { - if (itsFloat) - sprintf(gString2, " %.2f %s %.2f", *(float*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(float*)stat2); - else - sprintf(gString2, " %d %s %d", *(int*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(int*)stat2); - } - else if (stat) { - if (itsFloat) - sprintf(gString2, " %.2f", *(float*)stat); - else - sprintf(gString2, " %d", *(int*)stat); - } + if (stat2) { + if (itsFloat) + sprintf(gString2, " %.2f %s %.2f", *(float*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(float*)stat2); + else + sprintf(gString2, " %d %s %d", *(int*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(int*)stat2); + } else if (stat) { + if (itsFloat) + sprintf(gString2, " %.2f", *(float*)stat); else - gString2[0] = '\0'; + sprintf(gString2, " %d", *(int*)stat); + } else + gString2[0] = '\0'; UnicodeStrcpy(gUString, TheText.Get(text)); AsciiToUnicode(gString2, gUString2); @@ -477,58 +468,50 @@ CMenuManager::CheckCodesForControls(int typeOfControl) bool escPressed = false; eControllerType typeToSave; // GetStartOptionsCntrlConfigScreens(); - e_ControllerAction action = (e_ControllerAction)m_CurrCntrlAction; + e_ControllerAction action = (e_ControllerAction) m_CurrCntrlAction; if (typeOfControl == KEYBOARD) { if (*pControlEdit == rsESC) { escPressed = true; - } - else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && + } else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && *pControlEdit != rsLWIN && *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { typeToSave = KEYBOARD; if (ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD) != rsNULL && *pControlEdit != ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD)) { typeToSave = OPTIONAL_EXTRA; } - } - else { + } else { invalidKey = true; } - } - else if (typeOfControl == MOUSE) { + } else if (typeOfControl == MOUSE) { typeToSave = MOUSE; - } - else if (typeOfControl == JOYSTICK) { + } else if (typeOfControl == JOYSTICK) { typeToSave = JOYSTICK; if (ControlsManager.GetIsActionAButtonCombo(action)) DisplayComboButtonErrMsg = true; } #ifdef FIX_BUGS - if (!escPressed && !invalidKey) + if(!escPressed && !invalidKey) #endif ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); if (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) { if (typeOfControl == KEYBOARD) { ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD); ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, OPTIONAL_EXTRA); - } - else { + } else { if (typeOfControl == MOUSE) { ControlsManager.DeleteMatchingActionInitiators(action, MouseButtonJustClicked, MOUSE); - } - else if (typeOfControl == JOYSTICK) { + } else if (typeOfControl == JOYSTICK) { ControlsManager.DeleteMatchingActionInitiators(action, JoyButtonJustClicked, JOYSTICK); } } if (typeOfControl == KEYBOARD) { ControlsManager.SetControllerKeyAssociatedWithAction(action, *pControlEdit, typeToSave); - } - else if (typeOfControl == MOUSE) { + } else if (typeOfControl == MOUSE) { ControlsManager.SetControllerKeyAssociatedWithAction(action, MouseButtonJustClicked, typeToSave); - } - else { + } else { if (typeOfControl == JOYSTICK) { ControlsManager.SetControllerKeyAssociatedWithAction(action, JoyButtonJustClicked, typeToSave); } @@ -552,8 +535,8 @@ CMenuManager::CheckCodesForControls(int typeOfControl) bool CMenuManager::CheckHover(int x1, int x2, int y1, int y2) { - return m_nMousePosX > x1 && m_nMousePosX < x2&& - m_nMousePosY > y1 && m_nMousePosY < y2; + return m_nMousePosX > x1 && m_nMousePosX < x2 && + m_nMousePosY > y1 && m_nMousePosY < y2; } void @@ -561,11 +544,11 @@ CMenuManager::CheckSliderMovement(int value) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_BRIGHTNESS: - m_PrefsBrightness += value * (512 / 16); + m_PrefsBrightness += value * (512/16); m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 511); break; case MENUACTION_DRAWDIST: - if (value > 0) + if(value > 0) m_PrefsLOD += ((1.8f - 0.8f) / 16.0f); else m_PrefsLOD -= ((1.8f - 0.8f) / 16.0f); @@ -573,18 +556,18 @@ CMenuManager::CheckSliderMovement(int value) CRenderer::ms_lodDistScale = m_PrefsLOD; break; case MENUACTION_MUSICVOLUME: - m_PrefsMusicVolume += value * (128 / 16); + m_PrefsMusicVolume += value * (128/16); m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 127); DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); break; case MENUACTION_SFXVOLUME: - m_PrefsSfxVolume += value * (128 / 16); + m_PrefsSfxVolume += value * (128/16); m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 127); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); break; case MENUACTION_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl += value * 1.0f / 200.0f / 15.0f; // ??? - TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200.0f, 1.0f / 200.0f); + TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // ??? + TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; break; default: @@ -628,39 +611,39 @@ CMenuManager::DisplayHelperText() // TODO: name this cases? switch (m_nHelperTextMsgId) { - case 0: - { - int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if (action != MENUACTION_CHANGEMENU && action != MENUACTION_REDEFCTRL && action != MENUACTION_RESTOREDEF) { - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); + case 0: + { + int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; + if (action != MENUACTION_CHANGEMENU && action != MENUACTION_REDEFCTRL && action != MENUACTION_RESTOREDEF) { + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); + } + break; } - break; - } - case 1: - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); - break; - case 2: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); - break; - case 3: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); - break; - case 4: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); - break; - default: - break; + case 1: + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); + break; + case 2: + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); + break; + case 3: + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); + break; + case 4: + CFont::SetColor(CRGBA(255, 255, 255, alpha)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); + break; + default: + break; } CFont::SetRightJustifyOff(); } int -CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress) +CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress) { CRGBA color; float maxBarHeight; @@ -669,13 +652,12 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR float curBarX = 0.0f; float spacing = SCREEN_SCALE_X(4.0f); // TODO: find actual numbers used in the game for (int i = 0; i < 16; i++) { - curBarX = i * rectSize / 32.0f + x; + curBarX = i * rectSize/32.0f + x; if (i / 16.0f + 1 / 32.0f < progress) { color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); lastActiveBarX = curBarX; - } - else + } else color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255)); maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); @@ -735,16 +717,16 @@ CMenuManager::Draw() CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); switch (m_nCurrScreen) { - case MENUPAGE_STATS: - PrintStats(); - break; - case MENUPAGE_BRIEFS: - PrintBriefs(); - break; + case MENUPAGE_STATS: + PrintStats(); + break; + case MENUPAGE_BRIEFS: + PrintBriefs(); + break; #ifdef MENU_MAP - case MENUPAGE_MAP: - PrintMap(); - break; + case MENUPAGE_MAP: + PrintMap(); + break; #endif } @@ -753,20 +735,20 @@ CMenuManager::Draw() // Page name #ifdef PS2_SAVE_DIALOG - if (!m_bRenderGameInMenu) + if(!m_bRenderGameInMenu) #endif - if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { + if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - PREPARE_MENU_HEADER - CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + PREPARE_MENU_HEADER + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - // Weird place to put that. - nextYToUse += 24.0f + 10.0f; - } + // Weird place to put that. + nextYToUse += 24.0f + 10.0f; + } CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y)); @@ -774,7 +756,7 @@ CMenuManager::Draw() CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); // Label - wchar* str; + wchar *str; if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) { switch (m_nCurrScreen) { case MENUPAGE_LOAD_SLOT_CONFIRM: @@ -819,87 +801,87 @@ CMenuManager::Draw() int headerHeight; int columnWidth; switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_BRIEFS: - columnWidth = 320; - headerHeight = 240; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_SOUND_SETTINGS: - case MENUPAGE_GRAPHICS_SETTINGS: - case MENUPAGE_MULTIPLAYER_CREATE: - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_CONTROLLER_PC_OLD1: - case MENUPAGE_CONTROLLER_PC_OLD2: - case MENUPAGE_CONTROLLER_PC_OLD3: - case MENUPAGE_CONTROLLER_PC_OLD4: - case MENUPAGE_CONTROLLER_DEBUG: - case MENUPAGE_MOUSE_CONTROLS: - columnWidth = 50; - headerHeight = 0; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = MEDIUMTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = MEDIUMTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_CHOOSE_SAVE_SLOT: - columnWidth = 120; - headerHeight = 38; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_SAVE_OVERWRITE_CONFIRM: - case MENUPAGE_EXIT: - columnWidth = 320; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_START_MENU: - columnWidth = 320; - headerHeight = 110; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_PAUSE_MENU: - columnWidth = 320; - headerHeight = 117; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; + case MENUPAGE_STATS: + case MENUPAGE_BRIEFS: + columnWidth = 320; + headerHeight = 240; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; + case MENUPAGE_SOUND_SETTINGS: + case MENUPAGE_GRAPHICS_SETTINGS: + case MENUPAGE_MULTIPLAYER_CREATE: + case MENUPAGE_SKIN_SELECT_OLD: + case MENUPAGE_CONTROLLER_PC_OLD1: + case MENUPAGE_CONTROLLER_PC_OLD2: + case MENUPAGE_CONTROLLER_PC_OLD3: + case MENUPAGE_CONTROLLER_PC_OLD4: + case MENUPAGE_CONTROLLER_DEBUG: + case MENUPAGE_MOUSE_CONTROLS: + columnWidth = 50; + headerHeight = 0; + lineHeight = 20; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = MEDIUMTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = MEDIUMTEXT_Y_SCALE)); + CFont::SetRightJustifyOff(); + break; + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + columnWidth = 120; + headerHeight = 38; + lineHeight = 20; + CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE)); + CFont::SetRightJustifyOff(); + break; + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + case MENUPAGE_SAVE_OVERWRITE_CONFIRM: + case MENUPAGE_EXIT: + columnWidth = 320; + headerHeight = 60; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; + case MENUPAGE_START_MENU: + columnWidth = 320; + headerHeight = 110; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; + case MENUPAGE_PAUSE_MENU: + columnWidth = 320; + headerHeight = 117; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; #ifdef PS2_SAVE_DIALOG - case MENUPAGE_SAVE: - columnWidth = 180; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - break; + case MENUPAGE_SAVE: + columnWidth = 180; + headerHeight = 60; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + break; #endif - default: - columnWidth = 320; - headerHeight = 40; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; + default: + columnWidth = 320; + headerHeight = 40; + lineHeight = 24; + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); + CFont::SetCentreOn(); + break; } #ifdef PS2_LIKE_MENU @@ -907,18 +889,18 @@ CMenuManager::Draw() #endif switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD1: - case MENUPAGE_CONTROLLER_PC_OLD2: - case MENUPAGE_CONTROLLER_PC_OLD3: - case MENUPAGE_CONTROLLER_PC_OLD4: - case MENUPAGE_CONTROLLER_DEBUG: - if (m_bWaitingForNewKeyBind) - itemsAreSelectable = false; + case MENUPAGE_CONTROLLER_PC_OLD1: + case MENUPAGE_CONTROLLER_PC_OLD2: + case MENUPAGE_CONTROLLER_PC_OLD3: + case MENUPAGE_CONTROLLER_PC_OLD4: + case MENUPAGE_CONTROLLER_DEBUG: + if (m_bWaitingForNewKeyBind) + itemsAreSelectable = false; - DrawControllerScreenExtraText(nextYToUse - 8.0f, MENU_X_LEFT_ALIGNED(350), lineHeight); - break; - default: - break; + DrawControllerScreenExtraText(nextYToUse - 8.0f, MENU_X_LEFT_ALIGNED(350), lineHeight); + break; + default: + break; } float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider @@ -930,7 +912,7 @@ CMenuManager::Draw() #ifdef MENU_MAP if (m_nCurrScreen == MENUPAGE_MAP) { // Back button - wchar* backTx = TheText.Get("FEDS_TB"); + wchar *backTx = TheText.Get("FEDS_TB"); CFont::SetDropShadowPosition(1); CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(MENU_X(60.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), backTx); @@ -938,8 +920,7 @@ CMenuManager::Draw() if (!CheckHover(MENU_X(30.0f), MENU_X(30.0f) + CFont::GetStringWidth(backTx), SCREEN_SCALE_FROM_BOTTOM(125.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f))) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; m_nCurrOption = m_nPrevOption = 0; - } - else { + } else { m_nHoverOption = HOVEROPTION_RANDOM_ITEM; m_nCurrOption = m_nPrevOption = 1; } @@ -949,8 +930,8 @@ CMenuManager::Draw() for (int i = 0; i < NUM_MENUROWS; ++i) { if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { - wchar* rightText = nil; - wchar* leftText; + wchar *rightText = nil; + wchar *leftText; if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { CFont::SetRightJustifyOff(); @@ -963,76 +944,75 @@ CMenuManager::Draw() sprintf(gString, "FEM_SL%d", i); leftText = TheText.Get(gString); } - } - else { + } else { leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { case MENUACTION_CHANGEMENU: { switch (aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu) { - case MENUPAGE_MULTIPLAYER_MAP: - switch (m_SelectedMap) { - case 0: - rightText = TheText.Get("FEM_MA0"); + case MENUPAGE_MULTIPLAYER_MAP: + switch (m_SelectedMap) { + case 0: + rightText = TheText.Get("FEM_MA0"); + break; + case 1: + rightText = TheText.Get("FEM_MA1"); + break; + case 2: + rightText = TheText.Get("FEM_MA2"); + break; + case 3: + rightText = TheText.Get("FEM_MA3"); + break; + case 4: + rightText = TheText.Get("FEM_MA4"); + break; + case 5: + rightText = TheText.Get("FEM_MA5"); + break; + case 6: + rightText = TheText.Get("FEM_MA6"); + break; + case 7: + rightText = TheText.Get("FEM_MA7"); + break; + default: + break; + } break; - case 1: - rightText = TheText.Get("FEM_MA1"); - break; - case 2: - rightText = TheText.Get("FEM_MA2"); - break; - case 3: - rightText = TheText.Get("FEM_MA3"); - break; - case 4: - rightText = TheText.Get("FEM_MA4"); - break; - case 5: - rightText = TheText.Get("FEM_MA5"); - break; - case 6: - rightText = TheText.Get("FEM_MA6"); - break; - case 7: - rightText = TheText.Get("FEM_MA7"); + case MENUPAGE_MULTIPLAYER_MODE: + switch (m_SelectedGameType) { + case 0: + rightText = TheText.Get("FEN_TY0"); + break; + case 1: + rightText = TheText.Get("FEN_TY1"); + break; + case 2: + rightText = TheText.Get("FEN_TY2"); + break; + case 3: + rightText = TheText.Get("FEN_TY3"); + break; + case 4: + rightText = TheText.Get("FEN_TY4"); + break; + case 5: + rightText = TheText.Get("FEN_TY5"); + break; + case 6: + rightText = TheText.Get("FEN_TY6"); + break; + case 7: + rightText = TheText.Get("FEN_TY7"); + break; + default: + break; + } break; default: break; - } - break; - case MENUPAGE_MULTIPLAYER_MODE: - switch (m_SelectedGameType) { - case 0: - rightText = TheText.Get("FEN_TY0"); - break; - case 1: - rightText = TheText.Get("FEN_TY1"); - break; - case 2: - rightText = TheText.Get("FEN_TY2"); - break; - case 3: - rightText = TheText.Get("FEN_TY3"); - break; - case 4: - rightText = TheText.Get("FEN_TY4"); - break; - case 5: - rightText = TheText.Get("FEN_TY5"); - break; - case 6: - rightText = TheText.Get("FEN_TY6"); - break; - case 7: - rightText = TheText.Get("FEN_TY7"); - break; - default: - break; - } - break; - default: - break; } break; } @@ -1146,12 +1126,11 @@ CMenuManager::Draw() if (m_nPrefsAudio3DProviderIndex == -1) rightText = TheText.Get("FEA_NAH"); else { - char* provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); + char *provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); if (!strcmp(strupr(provider), "DIRECTSOUND3D HARDWARE SUPPORT")) { strcpy(provider, "DSOUND3D HARDWARE SUPPORT"); - } - else if (!strcmp(strupr(provider), "DIRECTSOUND3D SOFTWARE EMULATION")) { + } else if (!strcmp(strupr(provider), "DIRECTSOUND3D SOFTWARE EMULATION")) { strcpy(provider, "DSOUND3D SOFTWARE EMULATION"); } AsciiToUnicode(provider, unicodeTemp); @@ -1198,10 +1177,10 @@ CMenuManager::Draw() float nextItemY = headerHeight + nextYToUse; float bitAboveNextItemY = nextItemY - 2.0f; int nextYToCheck = bitAboveNextItemY; - + if (!foundTheHoveringItem) { for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) { - if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) + if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) break; int extraOffset = 0; @@ -1219,13 +1198,13 @@ CMenuManager::Draw() m_nMousePosY < MENU_Y((nextYToCheck + 2) + usableLineHeight)) { static int oldOption = -99; - static int oldScreen = m_nCurrScreen; + static int oldScreen = m_nCurrScreen; - m_nPrevOption = rowToCheck; - if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { - m_nCurrOption = rowToCheck; - m_bShowMouse = true; - } + m_nPrevOption = rowToCheck; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrOption = rowToCheck; + m_bShowMouse = true; + } if (oldOption != m_nCurrOption) { if (oldScreen == m_nCurrScreen && m_bShowMouse) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); @@ -1249,17 +1228,17 @@ CMenuManager::Draw() #ifdef PS2_SAVE_DIALOG if (!m_bRenderGameInMenu) #endif - if (i == m_nCurrOption && itemsAreSelectable) { - // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background - CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), - SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); - } + if (i == m_nCurrOption && itemsAreSelectable) { + // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background + CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), + SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); + } CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); // Button and it's shadow - for (int textLayer = 0; textLayer < 2; textLayer++) { + for(int textLayer = 0; textLayer < 2; textLayer++) { if (!CFont::Details.centre) CFont::SetRightJustifyOff(); @@ -1269,23 +1248,22 @@ CMenuManager::Draw() if (rightText) { if (!CFont::Details.centre) CFont::SetRightJustifyOn(); - - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") + + if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") && !m_bGameNotLoaded && textLayer == 1) { CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); } - if (i == m_nCurrOption && itemsAreSelectable) { + if (i == m_nCurrOption && itemsAreSelectable){ CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); - } - else { + } else { CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); } } if (m_nPrefsAudio3DProviderIndex == DMAudio.GetCurrent3DProviderIndex()) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) + if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) ResetHelperText(); } if (m_nDisplayVideoMode == m_nPrefsVideoMode) { @@ -1327,21 +1305,21 @@ CMenuManager::Draw() // Sliders int lastActiveBarX; switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case MENUACTION_BRIGHTNESS: - ProcessSlider(m_PrefsBrightness / 512.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_DRAWDIST: - ProcessSlider((m_PrefsLOD - 0.8f) * 1.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_MUSICVOLUME: - ProcessSlider(m_PrefsMusicVolume / 128.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_SFXVOLUME: - ProcessSlider(m_PrefsSfxVolume / 128.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_MOUSESENS: - ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); - break; + case MENUACTION_BRIGHTNESS: + ProcessSlider(m_PrefsBrightness / 512.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_DRAWDIST: + ProcessSlider((m_PrefsLOD - 0.8f) * 1.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_MUSICVOLUME: + ProcessSlider(m_PrefsMusicVolume / 128.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_SFXVOLUME: + ProcessSlider(m_PrefsSfxVolume / 128.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_MOUSESENS: + ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); + break; } // 60.0 is silly @@ -1392,22 +1370,22 @@ CMenuManager::GetNumOptionsCntrlConfigScreens(void) { int number = 0; switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD3: - number = 2; - break; - case MENUPAGE_CONTROLLER_DEBUG: - number = 4; - break; - case MENUPAGE_KEYBOARD_CONTROLS: - switch (m_ControlMethod) { - case CONTROL_STANDARD: - number = 25; + case MENUPAGE_CONTROLLER_PC_OLD3: + number = 2; break; - case CONTROL_CLASSIC: - number = 30; + case MENUPAGE_CONTROLLER_DEBUG: + number = 4; + break; + case MENUPAGE_KEYBOARD_CONTROLS: + switch (m_ControlMethod) { + case CONTROL_STANDARD: + number = 25; + break; + case CONTROL_CLASSIC: + number = 30; + break; + } break; - } - break; } return number; } @@ -1421,14 +1399,14 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 int bindingMargin = MENU_X(3.0f); float rowHeight; switch (m_ControlMethod) { - case CONTROL_STANDARD: - rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; - break; - case CONTROL_CLASSIC: - rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; - break; - default: - break; + case CONTROL_STANDARD: + rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; + break; + case CONTROL_CLASSIC: + rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; + break; + default: + break; } // MENU_Y(rowHeight * 0.0f + yStart); @@ -1439,164 +1417,163 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (column == CONTSETUP_PED_COLUMN) { switch (optionIdx) { - case 0: - controllerAction = PED_FIREWEAPON; - break; - case 1: - controllerAction = PED_CYCLE_WEAPON_RIGHT; - break; - case 2: - controllerAction = PED_CYCLE_WEAPON_LEFT; - break; - case 3: - controllerAction = GO_FORWARD; - break; - case 4: - controllerAction = GO_BACK; - break; - case 5: - controllerAction = GO_LEFT; - break; - case 6: - controllerAction = GO_RIGHT; - break; - case 7: - controllerAction = PED_SNIPER_ZOOM_IN; - break; - case 8: - controllerAction = PED_SNIPER_ZOOM_OUT; - break; - case 9: - controllerAction = VEHICLE_ENTER_EXIT; - break; - case 10: - case 11: - case 12: - case 16: - case 18: - case 19: - case 20: - case 21: - controllerAction = -1; - break; - case 13: - controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; - break; - case 14: - controllerAction = PED_JUMPING; - break; - case 15: - controllerAction = PED_SPRINT; - break; - case 17: - controllerAction = PED_LOCK_TARGET; - break; - case 22: - controllerAction = PED_LOOKBEHIND; - break; - case 23: - if (m_ControlMethod == CONTROL_STANDARD) + case 0: + controllerAction = PED_FIREWEAPON; + break; + case 1: + controllerAction = PED_CYCLE_WEAPON_RIGHT; + break; + case 2: + controllerAction = PED_CYCLE_WEAPON_LEFT; + break; + case 3: + controllerAction = GO_FORWARD; + break; + case 4: + controllerAction = GO_BACK; + break; + case 5: + controllerAction = GO_LEFT; + break; + case 6: + controllerAction = GO_RIGHT; + break; + case 7: + controllerAction = PED_SNIPER_ZOOM_IN; + break; + case 8: + controllerAction = PED_SNIPER_ZOOM_OUT; + break; + case 9: + controllerAction = VEHICLE_ENTER_EXIT; + break; + case 10: + case 11: + case 12: + case 16: + case 18: + case 19: + case 20: + case 21: controllerAction = -1; - else - controllerAction = PED_1RST_PERSON_LOOK_LEFT; - break; - case 24: - if (m_ControlMethod == CONTROL_STANDARD) - controllerAction = -1; - else - controllerAction = PED_1RST_PERSON_LOOK_RIGHT; - break; - case 25: - controllerAction = PED_1RST_PERSON_LOOK_UP; - break; - case 26: - controllerAction = PED_1RST_PERSON_LOOK_DOWN; - break; - case 27: - controllerAction = PED_CYCLE_TARGET_LEFT; - break; - case 28: - controllerAction = PED_CYCLE_TARGET_RIGHT; - break; - case 29: - controllerAction = PED_CENTER_CAMERA_BEHIND_PLAYER; - break; - default: - break; + break; + case 13: + controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; + break; + case 14: + controllerAction = PED_JUMPING; + break; + case 15: + controllerAction = PED_SPRINT; + break; + case 17: + controllerAction = PED_LOCK_TARGET; + break; + case 22: + controllerAction = PED_LOOKBEHIND; + break; + case 23: + if (m_ControlMethod == CONTROL_STANDARD) + controllerAction = -1; + else + controllerAction = PED_1RST_PERSON_LOOK_LEFT; + break; + case 24: + if (m_ControlMethod == CONTROL_STANDARD) + controllerAction = -1; + else + controllerAction = PED_1RST_PERSON_LOOK_RIGHT; + break; + case 25: + controllerAction = PED_1RST_PERSON_LOOK_UP; + break; + case 26: + controllerAction = PED_1RST_PERSON_LOOK_DOWN; + break; + case 27: + controllerAction = PED_CYCLE_TARGET_LEFT; + break; + case 28: + controllerAction = PED_CYCLE_TARGET_RIGHT; + break; + case 29: + controllerAction = PED_CENTER_CAMERA_BEHIND_PLAYER; + break; + default: + break; } - } - else if (column == CONTSETUP_VEHICLE_COLUMN) { + } else if (column == CONTSETUP_VEHICLE_COLUMN) { switch (optionIdx) { - case 0: - controllerAction = PED_FIREWEAPON; - break; - case 1: - case 2: - case 7: - case 8: - case 14: - case 15: - case 17: - case 25: - case 26: - case 27: - case 28: - case 29: - controllerAction = -1; - break; - case 3: - controllerAction = VEHICLE_ACCELERATE; - break; - case 4: - controllerAction = VEHICLE_BRAKE; - break; - case 5: - controllerAction = GO_LEFT; - break; - case 6: - controllerAction = GO_RIGHT; - break; - case 9: - controllerAction = VEHICLE_ENTER_EXIT; - break; - case 10: - controllerAction = VEHICLE_CHANGE_RADIO_STATION; - break; - case 11: - controllerAction = VEHICLE_HORN; - break; - case 12: - controllerAction = TOGGLE_SUBMISSIONS; - break; - case 13: - controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; - break; - case 16: - controllerAction = VEHICLE_HANDBRAKE; - break; - case 18: - controllerAction = VEHICLE_TURRETLEFT; - break; - case 19: - controllerAction = VEHICLE_TURRETRIGHT; - break; - case 20: - controllerAction = VEHICLE_TURRETUP; - break; - case 21: - controllerAction = VEHICLE_TURRETDOWN; - break; - case 22: - controllerAction = -2; - break; - case 23: - controllerAction = VEHICLE_LOOKLEFT; - break; - case 24: - controllerAction = VEHICLE_LOOKRIGHT; - break; - default: - break; + case 0: + controllerAction = PED_FIREWEAPON; + break; + case 1: + case 2: + case 7: + case 8: + case 14: + case 15: + case 17: + case 25: + case 26: + case 27: + case 28: + case 29: + controllerAction = -1; + break; + case 3: + controllerAction = VEHICLE_ACCELERATE; + break; + case 4: + controllerAction = VEHICLE_BRAKE; + break; + case 5: + controllerAction = GO_LEFT; + break; + case 6: + controllerAction = GO_RIGHT; + break; + case 9: + controllerAction = VEHICLE_ENTER_EXIT; + break; + case 10: + controllerAction = VEHICLE_CHANGE_RADIO_STATION; + break; + case 11: + controllerAction = VEHICLE_HORN; + break; + case 12: + controllerAction = TOGGLE_SUBMISSIONS; + break; + case 13: + controllerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS; + break; + case 16: + controllerAction = VEHICLE_HANDBRAKE; + break; + case 18: + controllerAction = VEHICLE_TURRETLEFT; + break; + case 19: + controllerAction = VEHICLE_TURRETRIGHT; + break; + case 20: + controllerAction = VEHICLE_TURRETUP; + break; + case 21: + controllerAction = VEHICLE_TURRETDOWN; + break; + case 22: + controllerAction = -2; + break; + case 23: + controllerAction = VEHICLE_LOOKLEFT; + break; + case 24: + controllerAction = VEHICLE_LOOKRIGHT; + break; + default: + break; } } int bindingWhite = 155; @@ -1611,8 +1588,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (controllerAction == -1) { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); - } - else { + } else { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); } @@ -1620,8 +1596,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (controllerAction == -1) { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); - } - else { + } else { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); } @@ -1629,22 +1604,19 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); bindingWhite = 0; - } - else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { + } else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { #ifdef FIX_BUGS if (controllerAction == -1) { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(235, 170, 50, FadeIn(150))); - } - else { + } else { CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(255, 217, 106, FadeIn(210))); } #else if (controllerAction == -1) { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(235, 170, 50, FadeIn(150))); - } - else { + } else { CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(255, 217, 106, FadeIn(210))); } #endif @@ -1657,11 +1629,11 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 // Print bindings, including seperator (-) between them CFont::SetScale(MENU_X(0.25f), MENU_Y(0.6f)); for (int contSetOrder = SETORDER_1; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) { - wchar* settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); + wchar *settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder); if (settingText) { ++bindingsForThisOpt; if (bindingsForThisOpt > 1) { - wchar* seperator = TheText.Get("FEC_IBT"); + wchar *seperator = TheText.Get("FEC_IBT"); CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); CFont::PrintString(nextX, nextY, seperator); CFont::SetColor(CRGBA(bindingWhite, bindingWhite, bindingWhite, FadeIn(255))); @@ -1679,23 +1651,19 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (controllerAction == -1) { CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_NUS")); // not used - } - else if (controllerAction == -2) { + } else if (controllerAction == -2) { CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_CMP")); // combo: l+r - } - else if (bindingsForThisOpt == 0) { + } else if (bindingsForThisOpt == 0) { if (m_nSelectedListRow != optionIdx) { CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound - } - else if (m_bWaitingForNewKeyBind) { + } else if (m_bWaitingForNewKeyBind) { if (column != m_nSelectedContSetupColumn) { CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound } - } - else { + } else { if (column != m_nSelectedContSetupColumn) { CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); } @@ -1707,11 +1675,11 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { if (optionIdx == m_nSelectedListRow && controllerAction != -1 && controllerAction != -2) { - m_CurrCntrlAction = controllerAction; + m_CurrCntrlAction = controllerAction; if (m_bWaitingForNewKeyBind) { static bool showWaitingText = false; if (bindingsForThisOpt > 0) { - wchar* seperator = TheText.Get("FEC_IBT"); + wchar *seperator = TheText.Get("FEC_IBT"); CFont::PrintString(nextX, nextY, seperator); nextX += CFont::GetStringWidth(seperator, true) + bindingMargin; } @@ -1730,11 +1698,10 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); if (m_bKeyChangeNotProcessed) { CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_CIG")); // BACKSPACE TO CLEAR - LMB,RETURN TO CHANGE - } - else { + } else { CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_RIG")); // SELECT A NEW CONTROL FOR THIS ACTION OR ESC TO CANCEL } - + CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); @@ -1742,8 +1709,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); m_bKeyIsOK = true; - } - else { + } else { CFont::SetCentreOn(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -1755,8 +1721,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 m_bKeyIsOK = false; m_bKeyChangeNotProcessed = false; } - } - else if (optionIdx == m_nSelectedListRow) { + } else if (optionIdx == m_nSelectedListRow) { CFont::SetCentreOn(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -1780,7 +1745,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig int numTextsPrinted = 0; int nextX = xStart; for (int j = 1; j < 5; j++) { - wchar* text = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)i, (eContSetOrder)j); + wchar *text = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)i, (eContSetOrder)j); if (text) ++numTextsPrinted; @@ -1816,7 +1781,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig } yStart += lineHeight; } - wchar* error = nil; + wchar *error = nil; if (DisplayComboButtonErrMsg) error = ControlsManager.GetButtonComboText((e_ControllerAction)(m_nCurrOption + extraTextStart)); @@ -1831,14 +1796,14 @@ CMenuManager::DrawControllerSetupScreen() { float rowHeight; switch (m_ControlMethod) { - case CONTROL_STANDARD: - rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; - break; - case CONTROL_CLASSIC: - rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; - break; - default: - break; + case CONTROL_STANDARD: + rowHeight = CONTSETUP_STANDARD_ROW_HEIGHT; + break; + case CONTROL_CLASSIC: + rowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT; + break; + default: + break; } CFont::SetBackgroundOff(); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); @@ -1852,15 +1817,15 @@ CMenuManager::DrawControllerSetupScreen() PREPARE_MENU_HEADER - switch (m_ControlMethod) { + switch (m_ControlMethod) { case CONTROL_STANDARD: CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), - TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), + TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); break; case CONTROL_CLASSIC: CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); @@ -1868,13 +1833,13 @@ CMenuManager::DrawControllerSetupScreen() TheText.Get("FET_CTI")); PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), - TheText.Get("FET_CTI")); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), + TheText.Get("FET_CTI")); break; default: break; - } - wchar* actionTexts[31]; + } + wchar *actionTexts[31]; actionTexts[0] = TheText.Get("FEC_FIR"); actionTexts[1] = TheText.Get("FEC_NWE"); actionTexts[2] = TheText.Get("FEC_PWE"); @@ -1907,8 +1872,7 @@ CMenuManager::DrawControllerSetupScreen() actionTexts[28] = TheText.Get("FEC_PTT"); actionTexts[29] = TheText.Get("FEC_CEN"); actionTexts[30] = nil; - } - else { + } else { actionTexts[18] = TheText.Get("FEC_TFL"); actionTexts[19] = TheText.Get("FEC_TFR"); actionTexts[20] = TheText.Get("FEC_TFU"); @@ -1946,7 +1910,7 @@ CMenuManager::DrawControllerSetupScreen() yStart = CONTSETUP_LIST_HEADER_HEIGHT + 34; for (int i = 0; i < ARRAY_SIZE(actionTexts); ++i) { - wchar* actionText = actionTexts[i]; + wchar *actionText = actionTexts[i]; if (!actionText) break; @@ -1955,50 +1919,47 @@ CMenuManager::DrawControllerSetupScreen() float curOptY = i * rowHeight + yStart; if (m_nMousePosY > MENU_Y(curOptY) && m_nMousePosY < MENU_Y(rowHeight + curOptY)) { - if (m_nPrevOption != i && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + if (m_nPrevOption != i && m_nCurrExLayer == HOVEROPTION_LIST) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nPrevOption = i; - if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_nSelectedListRow = i; + m_nPrevOption = i; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_nSelectedListRow = i; - // why different number for 3rd column hovering X?? this function is a mess + // why different number for 3rd column hovering X?? this function is a mess #ifdef FIX_BUGS - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { #else - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { #endif - if (m_nSelectedContSetupColumn != CONTSETUP_PED_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + if (m_nSelectedContSetupColumn != CONTSETUP_PED_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; + m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; #ifdef FIX_BUGS - } - else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { #else - } - else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { #endif - if (m_nSelectedContSetupColumn != CONTSETUP_VEHICLE_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + if (m_nSelectedContSetupColumn != CONTSETUP_VEHICLE_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + } } - } - // what?? - if (m_nHoverOption == HOVEROPTION_SKIN) { - if (i == m_nSelectedListRow) { + // what?? + if (m_nHoverOption == HOVEROPTION_SKIN) { + if (i == m_nSelectedListRow) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + } else m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - } - } - else - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - } } + } if (m_nSelectedListRow != 35) CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); else if (m_nCurrExLayer == HOVEROPTION_LIST) @@ -2011,7 +1972,7 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetScale(MENU_X(0.32f), MENU_Y(SMALLESTTEXT_Y_SCALE)); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(i * rowHeight + yStart), actionText); - } + } DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), rowHeight, CONTSETUP_PED_COLUMN); DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), rowHeight, CONTSETUP_VEHICLE_COLUMN); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); @@ -2021,13 +1982,11 @@ CMenuManager::DrawControllerSetupScreen() && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - CONTSETUP_BACK_HEIGHT)) || m_nCurrExLayer == HOVEROPTION_BACK) { m_nHoverOption = HOVEROPTION_BACK; - } - else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosY > MENU_Y(CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM + 5.0f)) { m_nHoverOption = HOVEROPTION_LIST; - } - else { + } else { m_nHoverOption = HOVEROPTION_NOT_HOVERING; } @@ -2045,7 +2004,7 @@ CMenuManager::DrawControllerSetupScreen() else CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } - } +} void CMenuManager::DrawFrontEnd() @@ -2064,8 +2023,7 @@ CMenuManager::DrawFrontEnd() bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT }; bbTabCount = 6; } - } - else { + } else { if (bbTabCount != 8) { bbNames[0] = { "FEB_STA",MENUPAGE_STATS }; bbNames[1] = { "FEB_SAV",MENUPAGE_NEW_GAME }; @@ -2086,8 +2044,7 @@ CMenuManager::DrawFrontEnd() if (m_nCurrScreen == MENUPAGE_NONE) { if (m_bGameNotLoaded) { m_nCurrScreen = MENUPAGE_START_MENU; - } - else { + } else { m_nCurrScreen = MENUPAGE_PAUSE_MENU; } } @@ -2097,7 +2054,7 @@ CMenuManager::DrawFrontEnd() m_nCurrOption = 1; #ifdef PS2_SAVE_DIALOG - if (m_bRenderGameInMenu) + if(m_bRenderGameInMenu) DrawFrontEndSaveZone(); else #endif @@ -2137,12 +2094,11 @@ CMenuManager::DrawFrontEndSaveZone() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if (field_518 == 4) { + if(field_518 == 4){ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - } - else { + }else{ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); @@ -2160,10 +2116,9 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); if (!m_bGameNotLoaded) { - CSprite2d* bg = LoadSplash(nil); + CSprite2d *bg = LoadSplash(nil); bg->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - } - else { + } else { CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } @@ -2176,44 +2131,44 @@ CMenuManager::DrawFrontEndNormal() m_aFrontEndSprites[FE2_MAINPANEL_UR].Draw(CRect(SCREEN_WIDTH / 2, 0.0f, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE2_MAINPANEL_DL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), SCREEN_HEIGHT / 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE2_MAINPANEL_DR].Draw(CRect(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); eFrontendSprites currentSprite; switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - case MENUPAGE_EXIT: - currentSprite = FE_ICONSTATS; - break; - case MENUPAGE_LANGUAGE_SETTINGS: - currentSprite = FE_ICONLANGUAGE; - break; - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - currentSprite = FE_ICONSAVE; - break; - case MENUPAGE_GRAPHICS_SETTINGS: - currentSprite = FE_ICONDISPLAY; - break; - case MENUPAGE_SOUND_SETTINGS: - currentSprite = FE_ICONAUDIO; - break; - case MENUPAGE_CONTROLLER_PC: - case MENUPAGE_OPTIONS: - case MENUPAGE_CONTROLLER_SETTINGS: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - currentSprite = FE_ICONCONTROLS; - break; - default: - /*case MENUPAGE_NEW_GAME: */ - /*case MENUPAGE_BRIEFS: */ - currentSprite = FE_ICONBRIEF; - break; + case MENUPAGE_STATS: + case MENUPAGE_START_MENU: + case MENUPAGE_PAUSE_MENU: + case MENUPAGE_EXIT: + currentSprite = FE_ICONSTATS; + break; + case MENUPAGE_LANGUAGE_SETTINGS: + currentSprite = FE_ICONLANGUAGE; + break; + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + currentSprite = FE_ICONSAVE; + break; + case MENUPAGE_GRAPHICS_SETTINGS: + currentSprite = FE_ICONDISPLAY; + break; + case MENUPAGE_SOUND_SETTINGS: + currentSprite = FE_ICONAUDIO; + break; + case MENUPAGE_CONTROLLER_PC: + case MENUPAGE_OPTIONS: + case MENUPAGE_CONTROLLER_SETTINGS: + case MENUPAGE_KEYBOARD_CONTROLS: + case MENUPAGE_MOUSE_CONTROLS: + currentSprite = FE_ICONCONTROLS; + break; + default: + /*case MENUPAGE_NEW_GAME: */ + /*case MENUPAGE_BRIEFS: */ + currentSprite = FE_ICONBRIEF; + break; } m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); @@ -2229,8 +2184,7 @@ CMenuManager::DrawFrontEndNormal() if (m_nMenuFadeAlpha <= 0 && reverseAlpha) { reverseAlpha = false; ChangeScreen(pendingScreen, pendingOption, true, false); - } - else { + } else { // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) if (!reverseAlpha) fadeAlpha += (frameTime) * 20.f / 33.f; @@ -2238,10 +2192,9 @@ CMenuManager::DrawFrontEndNormal() fadeAlpha = max(0.0f, fadeAlpha - (frameTime) * 30.f / 33.f); m_nMenuFadeAlpha = fadeAlpha; - } + } lastState = 0; - } - else { + } else { if (lastState == 0) fadeAlpha = 255.f; if (reverseAlpha) { @@ -2252,8 +2205,8 @@ CMenuManager::DrawFrontEndNormal() lastState = 1; // TODO: what is this? waiting mouse? - if (field_518 == 4) { - if (m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || + if(field_518 == 4){ + if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) field_518 = 2; @@ -2266,28 +2219,28 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); switch (m_nCurrScreen) { - case MENUPAGE_SKIN_SELECT: - DrawPlayerSetupScreen(); - break; - case MENUPAGE_KEYBOARD_CONTROLS: - DrawControllerSetupScreen(); - break; - default: - Draw(); - break; + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + default: + Draw(); + break; } -#define optionWidth MENU_X(66.0f) -#define rawOptionHeight 22.0f -#define optionBottom SCREEN_SCALE_FROM_BOTTOM(20.0f) -#define optionTop SCREEN_SCALE_FROM_BOTTOM(20.0f + rawOptionHeight) -#define leftPadding MENU_X_LEFT_ALIGNED(90.0f) - wchar* str; + #define optionWidth MENU_X(66.0f) + #define rawOptionHeight 22.0f + #define optionBottom SCREEN_SCALE_FROM_BOTTOM(20.0f) + #define optionTop SCREEN_SCALE_FROM_BOTTOM(20.0f + rawOptionHeight) + #define leftPadding MENU_X_LEFT_ALIGNED(90.0f) + wchar *str; hoveredBottomBarOption = -1; if (curBottomBarOption != -1) { // This active tab sprite is needlessly big - m_aFrontEndSprites[FE2_TABACTIVE].Draw(CRect(leftPadding - MENU_X(2.0f) + (optionWidth)*curBottomBarOption, optionTop, + m_aFrontEndSprites[FE2_TABACTIVE].Draw(CRect(leftPadding - MENU_X(2.0f) + (optionWidth) * curBottomBarOption, optionTop, leftPadding - MENU_X(5.0f) + optionWidth * (curBottomBarOption + 2), optionBottom + MENU_Y(rawOptionHeight - 9.0f)), CRGBA(CRGBA(255, 255, 255, 255))); @@ -2302,23 +2255,23 @@ CMenuManager::DrawFrontEndNormal() if (hoveredBottomBarOption == i && hoveredBottomBarOption != curBottomBarOption) CFont::SetColor(CRGBA(235, 170, 50, 255)); else { - if (bottomBarActive || curBottomBarOption == i) + if(bottomBarActive || curBottomBarOption == i) CFont::SetColor(CRGBA(0, 0, 0, 255)); else CFont::SetColor(CRGBA(0, 0, 0, 110)); } str = TheText.Get(bbNames[i].name); - + CFont::PrintString(xStart + MENU_X(4.0f), SCREEN_SCALE_FROM_BOTTOM(39.0f), str); - + } } -#undef optionBottom -#undef optionTop -#undef leftPadding -#undef optionWidth -#undef rawOptionHeight + #undef optionBottom + #undef optionTop + #undef leftPadding + #undef optionWidth + #undef rawOptionHeight CFont::DrawFonts(); @@ -2335,12 +2288,11 @@ CMenuManager::DrawFrontEndNormal() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if (field_518 == 4) { + if(field_518 == 4){ m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); - } - else { + }else{ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); @@ -2356,7 +2308,7 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); LoadSplash(nil); - + eMenuSprites previousSprite = MENUSPRITE_BACKGROUND; if (m_nMenuFadeAlpha < 255) { @@ -2372,29 +2324,29 @@ CMenuManager::DrawFrontEndNormal() eMenuSprites currentSprite = MENUSPRITE_BACKGROUND; // actually uninitialized switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - case MENUPAGE_NEW_GAME: - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_EXIT: - case MENUPAGE_MULTIPLAYER_MAIN: - case MENUPAGE_MULTIPLAYER_MAP: - case MENUPAGE_MULTIPLAYER_FIND_GAME: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - case MENUPAGE_MULTIPLAYER_CONNECTION: - case MENUPAGE_MULTIPLAYER_MODE: - case MENUPAGE_MULTIPLAYER_CREATE: - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - currentSprite = MENUSPRITE_BACKGROUND; - break; + case MENUPAGE_STATS: + case MENUPAGE_START_MENU: + case MENUPAGE_PAUSE_MENU: + case MENUPAGE_NEW_GAME: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_NEW_GAME_RELOAD: + case MENUPAGE_LOAD_SLOT_CONFIRM: + case MENUPAGE_DELETE_SLOT_CONFIRM: + case MENUPAGE_EXIT: + case MENUPAGE_MULTIPLAYER_MAIN: + case MENUPAGE_MULTIPLAYER_MAP: + case MENUPAGE_MULTIPLAYER_FIND_GAME: + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_KEYBOARD_CONTROLS: + case MENUPAGE_MOUSE_CONTROLS: + case MENUPAGE_MULTIPLAYER_CONNECTION: + case MENUPAGE_MULTIPLAYER_MODE: + case MENUPAGE_MULTIPLAYER_CREATE: + case MENUPAGE_SKIN_SELECT_OLD: + case MENUPAGE_OPTIONS: + currentSprite = MENUSPRITE_BACKGROUND; + break; } if (m_nMenuFadeAlpha < 255) { @@ -2410,25 +2362,23 @@ CMenuManager::DrawFrontEndNormal() #else static uint32 LastFade = 0; - if (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10) { + if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ m_nMenuFadeAlpha += 20; LastFade = CTimer::GetTimeInMillisecondsPauseMode(); } #endif - - if (m_nMenuFadeAlpha > 255) { + + if (m_nMenuFadeAlpha > 255){ m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - } - else { + } else { RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); } - } - else { + } else { m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); // TODO: what is this? waiting mouse? - if (field_518 == 4) { - if (m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || + if(field_518 == 4){ + if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) field_518 = 2; @@ -2456,15 +2406,15 @@ CMenuManager::DrawFrontEndNormal() RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); switch (m_nCurrScreen) { - case MENUPAGE_SKIN_SELECT: - DrawPlayerSetupScreen(); - break; - case MENUPAGE_KEYBOARD_CONTROLS: - DrawControllerSetupScreen(); - break; - default: - Draw(); - break; + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + default: + Draw(); + break; } CFont::DrawFonts(); @@ -2482,12 +2432,11 @@ CMenuManager::DrawFrontEndNormal() mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if (field_518 == 4) { + if(field_518 == 4){ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - } - else { + }else{ m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); @@ -2511,7 +2460,7 @@ CMenuManager::DrawPlayerSetupScreen() PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // lstrcpy's changed with strcpy @@ -2592,18 +2541,17 @@ CMenuManager::DrawPlayerSetupScreen() } } } - } + } OutputDebugString("Finished enumerating skin files."); m_bSkinsEnumerated = true; - } + } CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(200, 200, 50, FadeIn(50))); // Header (Skin - Date) if (m_nCurrExLayer == HOVEROPTION_LIST) { CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } - else { + } else { CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); @@ -2611,13 +2559,13 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetRightJustifyOn(); CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_DAT")); switch (m_PrefsLanguage) { - case LANGUAGE_FRENCH: - case LANGUAGE_SPANISH: - CFont::SetScale(MENU_X(0.6f), MENU_Y(MENUACTION_SCALE_MULT)); - break; - default: - CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); - break; + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + CFont::SetScale(MENU_X(0.6f), MENU_Y(MENUACTION_SCALE_MULT)); + break; + default: + CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); + break; } CFont::SetRightJustifyOff(); CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_SKN")); @@ -2634,7 +2582,7 @@ CMenuManager::DrawPlayerSetupScreen() int orderInVisibles = 0; int rowEndY = PLAYERSETUP_LIST_BODY_TOP + PLAYERSETUP_ROW_HEIGHT + 1; int rowStartY = PLAYERSETUP_LIST_BODY_TOP; - for (int rowIdx = m_nFirstVisibleRowOnList; + for (int rowIdx = m_nFirstVisibleRowOnList; rowIdx < m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW && m_pSelectedSkin; ) { if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)) { @@ -2652,8 +2600,7 @@ CMenuManager::DrawPlayerSetupScreen() CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); } - } - else { + } else { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_nCurrExLayer = HOVEROPTION_LIST; m_nSelectedListRow = rowIdx; @@ -2672,11 +2619,9 @@ CMenuManager::DrawPlayerSetupScreen() CWorld::Players[0].SetPlayerSkin(m_aSkinName); } lastSelectedSkin = m_nSelectedListRow; - } - else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) { + } else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) { CFont::SetColor(CRGBA(255, 255, 155, FadeIn(255))); - } - else { + } else { CFont::SetColor(CRGBA(155, 155, 155, FadeIn(255))); } wchar unicodeTemp[80]; @@ -2702,9 +2647,9 @@ CMenuManager::DrawPlayerSetupScreen() // Scrollbar background CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205))); - + // Scrollbar - float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float)MAX_VISIBLE_LIST_ROW; + float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float) MAX_VISIBLE_LIST_ROW; float scrollbarBottom, scrollbarTop; if (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) { scrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f); @@ -2713,8 +2658,7 @@ CMenuManager::DrawPlayerSetupScreen() // Shadow CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255))); - } - else { + } else { #ifdef FIX_BUGS scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight); scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin); @@ -2745,8 +2689,7 @@ CMenuManager::DrawPlayerSetupScreen() MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), CRGBA(255, 255, 255, FadeIn(255))); #endif - } - else { + } else { #ifdef FIX_BUGS m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), @@ -2765,11 +2708,10 @@ CMenuManager::DrawPlayerSetupScreen() CRGBA(255, 255, 255, FadeIn(255))); #else m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), - MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), + MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), CRGBA(255, 255, 255, FadeIn(255))); #endif - } - else { + } else { #ifdef FIX_BUGS m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), @@ -2787,19 +2729,19 @@ CMenuManager::DrawPlayerSetupScreen() if (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); switch (m_PrefsLanguage) { - case LANGUAGE_FRENCH: - CFont::SetScale(MENU_X(1.1f), MENU_Y(1.9f)); - break; - case LANGUAGE_GERMAN: - CFont::SetScale(MENU_X(0.85f), MENU_Y(1.9f)); - break; - case LANGUAGE_ITALIAN: - case LANGUAGE_SPANISH: - CFont::SetScale(MENU_X(1.4f), MENU_Y(1.9f)); - break; - default: - CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); - break; + case LANGUAGE_FRENCH: + CFont::SetScale(MENU_X(1.1f), MENU_Y(1.9f)); + break; + case LANGUAGE_GERMAN: + CFont::SetScale(MENU_X(0.85f), MENU_Y(1.9f)); + break; + case LANGUAGE_ITALIAN: + case LANGUAGE_SPANISH: + CFont::SetScale(MENU_X(1.4f), MENU_Y(1.9f)); + break; + default: + CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); + break; } CFont::SetColor(CRGBA(255, 217, 106, FadeIn(120))); CFont::SetRightJustifyOff(); @@ -2819,8 +2761,7 @@ CMenuManager::DrawPlayerSetupScreen() m_nHoverOption = HOVEROPTION_BACK; - } - else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0 + } else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0 && m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) + CFont::GetStringWidth(TheText.Get("FES_SET"), true) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3) @@ -2831,35 +2772,31 @@ CMenuManager::DrawPlayerSetupScreen() m_nHoverOption = HOVEROPTION_USESKIN; - } - else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_TOP) && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3)) { if (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN) m_nHoverOption = HOVEROPTION_OVER_SCROLL_UP; - } - else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) { if (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN) m_nHoverOption = HOVEROPTION_OVER_SCROLL_DOWN; - } - else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) - && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3) + && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3) #ifdef FIX_BUGS - && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)) { + && m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)) { #else - && m_nMousePosY < MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)) { + && m_nMousePosY < MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)) { #endif m_nHoverOption = HOVEROPTION_PAGEUP; - } - else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) #ifdef FIX_BUGS && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight) @@ -2869,8 +2806,7 @@ CMenuManager::DrawPlayerSetupScreen() && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1)) { m_nHoverOption = HOVEROPTION_PAGEDOWN; - } - else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4) + } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH) #ifdef FIX_BUGS && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin) @@ -2881,16 +2817,14 @@ CMenuManager::DrawPlayerSetupScreen() #endif m_nHoverOption = HOVEROPTION_HOLDING_SCROLLBAR; - } - else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT) + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT) && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + 1) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) { m_nHoverOption = HOVEROPTION_LIST; - } - else { + } else { m_nHoverOption = HOVEROPTION_NOT_HOVERING; } - } + } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); CFont::SetRightJustifyOn(); @@ -2901,8 +2835,7 @@ CMenuManager::DrawPlayerSetupScreen() CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - i), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FEDS_TB")); if (m_nHoverOption == HOVEROPTION_BACK) { CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } - else { + } else { CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } } @@ -2914,16 +2847,14 @@ CMenuManager::DrawPlayerSetupScreen() CFont::PrintString(MENU_X_LEFT_ALIGNED(i + PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FES_SET")); if (!strcmp(m_aSkinName, m_PrefsSkinFile)) { CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); - } - else if (m_nHoverOption == HOVEROPTION_USESKIN) { + } else if (m_nHoverOption == HOVEROPTION_USESKIN) { CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } - else { + } else { CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); } } - } +} int CMenuManager::FadeIn(int alpha) @@ -2937,28 +2868,27 @@ CMenuManager::FadeIn(int alpha) } void -CMenuManager::FilterOutColorMarkersFromString(wchar * str, CRGBA & newColor) +CMenuManager::FilterOutColorMarkersFromString(wchar *str, CRGBA &newColor) { int newIdx = 0; - wchar copy[256], * c; + wchar copy[256], *c; UnicodeStrcpy(copy, str); for (c = copy; *c != '\0'; c++) { if (*c == '~') { c++; switch (*c) { - case 'b': newColor = CRGBA(40, 40, 255, 255); break; - case 'g': newColor = CRGBA(40, 235, 40, 255); break; + case 'b': newColor = CRGBA(40, 40, 255, 255); break; + case 'g': newColor = CRGBA(40, 235, 40, 255); break; // There is no case for "h", is that a mistake? - case 'l': newColor = CRGBA(0, 0, 0, 255); break; - case 'p': newColor = CRGBA(255, 0, 255, 255); break; - case 'r': newColor = CRGBA(255, 0, 0, 255); break; - case 'w': newColor = CRGBA(255, 255, 255, 255); break; - case 'y': newColor = CRGBA(255, 255, 0, 255); break; + case 'l': newColor = CRGBA(0, 0, 0, 255); break; + case 'p': newColor = CRGBA(255, 0, 255, 255); break; + case 'r': newColor = CRGBA(255, 0, 0, 255); break; + case 'w': newColor = CRGBA(255, 255, 255, 255); break; + case 'y': newColor = CRGBA(255, 255, 0, 255); break; } while (*c != '~') c++; - } - else { + } else { str[newIdx++] = *c; } } @@ -2970,17 +2900,17 @@ CMenuManager::GetStartOptionsCntrlConfigScreens() { int number = 0; switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD3: - number = 34; - break; - case MENUPAGE_CONTROLLER_DEBUG: - number = 35; - break; - case MENUPAGE_KEYBOARD_CONTROLS: - number = 0; - break; - default: - break; + case MENUPAGE_CONTROLLER_PC_OLD3: + number = 34; + break; + case MENUPAGE_CONTROLLER_DEBUG: + number = 35; + break; + case MENUPAGE_KEYBOARD_CONTROLS: + number = 0; + break; + default: + break; } return number; } @@ -3051,10 +2981,9 @@ CMenuManager::LoadAllTextures() if (DMAudio.IsMP3RadioChannelAvailable()) { if (m_PrefsRadioStation > USERTRACK) m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; - } - else if (m_PrefsRadioStation > CHATTERBOX) + } else if (m_PrefsRadioStation > CHATTERBOX) m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; - + CFileMgr::SetDir(""); //CFileMgr::SetDir(""); CTimer::Stop(); @@ -3064,7 +2993,7 @@ CMenuManager::LoadAllTextures() CTxdStore::PushCurrentTxd(); int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1"); - if (frontendTxdSlot1 == -1) + if(frontendTxdSlot1 == -1) frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1"); printf("LOAD frontend1\n"); @@ -3146,7 +3075,7 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, (char*)&m_nPrefsDepth, sizeof(m_nPrefsDepth)); CFileMgr::Read(fileHandle, (char*)&m_nPrefsWindowed, sizeof(m_nPrefsWindowed)); CFileMgr::Read(fileHandle, (char*)&m_nPrefsSubsystem, sizeof(m_nPrefsSubsystem)); - if (m_nPrefsWindowed != 0 && m_nPrefsWindowed != 1) { + if(m_nPrefsWindowed != 0 && m_nPrefsWindowed != 1){ // garbage data from vanilla settings file // let skeleton find something m_nPrefsWidth = 0; @@ -3215,7 +3144,7 @@ CMenuManager::LoadSettings() } WIN32_FIND_DATA FindFileData; - char skinfile[256 + 16]; // Stack analysis shows 16 bits gap, but I don't trust it. It may very well be MAX_PATH(260). + char skinfile[256+16]; // Stack analysis shows 16 bits gap, but I don't trust it. It may very well be MAX_PATH(260). bool SkinFound = false; HANDLE handle = FindFirstFile("skins\\*.bmp", &FindFileData); for (int i = 1; handle != INVALID_HANDLE_VALUE && i; i = FindNextFile(handle, &FindFileData)) { @@ -3293,9 +3222,9 @@ bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 Bo void DoRWStuffEndOfFrame(void); void -CMenuManager::MessageScreen(const char* text) +CMenuManager::MessageScreen(const char *text) { - CSprite2d* splash = LoadSplash(nil); + CSprite2d *splash = LoadSplash(nil); if (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)) return; @@ -3351,7 +3280,7 @@ CMenuManager::PrintBriefs() float nextY = BRIEFS_TOP_MARGIN; CRGBA newColor; for (int i = 4; i >= 0; i--) { - tPreviousBrief& brief = CMessages::PreviousBriefs[i]; + tPreviousBrief &brief = CMessages::PreviousBriefs[i]; if (brief.m_pText) { CMessages::InsertNumberInString(brief.m_pText, brief.m_nNumber[0], brief.m_nNumber[1], @@ -3432,8 +3361,7 @@ CMenuManager::PrintStats() if (CPad::GetPad(0)->GetLeftMouse()) { scrollY += (m_nMouseOldPosY - m_nMousePosY); lastChange = CTimer::GetTimeInMillisecondsPauseMode(); - } - else { + } else { scrollY += MENU_Y(STATS_SLIDE_Y_PER_SECOND) / 1000.0f * (CTimer::GetTimeInMillisecondsPauseMode() - lastChange); lastChange = CTimer::GetTimeInMillisecondsPauseMode(); } @@ -3459,15 +3387,13 @@ CMenuManager::PrintStats() else alphaMult = (y - MENU_Y(STATS_BOTTOM_MARGIN)) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); - // About to dim from bottom - } - else if (y > SCREEN_SCALE_FROM_BOTTOM(STATS_TOP_DIMMING_AREA_LENGTH) - MENU_Y(STATS_BOTTOM_DIMMING_AREA_LENGTH)) { + // About to dim from bottom + } else if (y > SCREEN_SCALE_FROM_BOTTOM(STATS_TOP_DIMMING_AREA_LENGTH) - MENU_Y(STATS_BOTTOM_DIMMING_AREA_LENGTH)) { if ((SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH) < 0.0f) alphaMult = 0.0f; else alphaMult = (SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); - } - else + } else alphaMult = 1.0f; CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255.0f * alphaMult))); @@ -3541,7 +3467,7 @@ CMenuManager::Process(void) SlotPopulated = true; } - if (SlotPopulated) + if (SlotPopulated) ChangeScreen(MENUPAGE_DELETE_SUCCESS, 0, true, false); else SaveLoadFileError_SetUpErrorScreen(); @@ -3567,8 +3493,7 @@ CMenuManager::Process(void) DMAudio.SetEffectsFadeVol(0); DMAudio.SetMusicFadeVol(0); DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); - } - else + } else SaveLoadFileError_SetUpErrorScreen(); } @@ -3618,14 +3543,12 @@ CMenuManager::Process(void) m_bWaitingForNewKeyBind = false; m_KeyPressedCode = -1; m_bStartWaitingForKeyBind = false; - } - else if (!m_bKeyChangeNotProcessed) { + } else if (!m_bKeyChangeNotProcessed) { if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) CheckCodesForControls(TypeOfControl); field_535 = true; - } - else { + } else { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); for (int i = 0; i < 4; i++) ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); @@ -3650,8 +3573,7 @@ CMenuManager::Process(void) TimeToStopPadShaking = 0; } - } - else { + } else { UnloadTextures(); m_bRenderGameInMenu = false; // byte_5F33E4 = 1; // unused @@ -3720,8 +3642,7 @@ CMenuManager::ProcessButtonPresses(void) m_bKeyChangeNotProcessed = true; pControlEdit = &m_KeyPressedCode; } - } - else { + } else { field_535 = false; } @@ -3740,15 +3661,15 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); m_bShowMouse = false; switch (m_nCurrExLayer) { - case HOVEROPTION_BACK: - default: - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case HOVEROPTION_LIST: - m_nCurrExLayer = HOVEROPTION_USESKIN; - break; - case HOVEROPTION_USESKIN: - m_nCurrExLayer = HOVEROPTION_BACK; + case HOVEROPTION_BACK: + default: + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case HOVEROPTION_LIST: + m_nCurrExLayer = HOVEROPTION_USESKIN; + break; + case HOVEROPTION_USESKIN: + m_nCurrExLayer = HOVEROPTION_BACK; } if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { m_nCurrExLayer = HOVEROPTION_BACK; @@ -3762,8 +3683,7 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; pressed = true; - } - else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { + } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { m_bShowMouse = true; pressed = true; } @@ -3777,8 +3697,7 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); ScrollUpListByOne(); } - } - else { + } else { m_bPressedUpOnList = false; } @@ -3786,8 +3705,7 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; pressed = true; - } - else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { m_bShowMouse = true; pressed = true; } @@ -3801,16 +3719,14 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); ScrollDownListByOne(); } - } - else { + } else { m_bPressedDownOnList = false; } if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { if (!CPad::GetPad(0)->GetPageUp()) { m_bPressedPgUpOnList = false; - } - else { + } else { m_nCurrExLayer = HOVEROPTION_LIST; if (!m_bPressedPgUpOnList) { m_bPressedPgUpOnList = true; @@ -3822,8 +3738,7 @@ CMenuManager::ProcessButtonPresses(void) } if (!CPad::GetPad(0)->GetPageDown()) { m_bPressedPgDnOnList = false; - } - else { + } else { m_nCurrExLayer = HOVEROPTION_LIST; if (!m_bPressedPgDnOnList) { m_bPressedPgDnOnList = true; @@ -3864,53 +3779,50 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetLeftMouseJustDown()) { switch (m_nHoverOption) { - case HOVEROPTION_BACK: - goBack = true; - break; - case HOVEROPTION_PAGEUP: - PageUpList(true); - break; - case HOVEROPTION_PAGEDOWN: - PageDownList(true); - break; - case HOVEROPTION_USESKIN: - if (m_nSkinsTotal > 0) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - m_pSelectedSkin = m_pSkinListHead.nextSkin; - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - SaveSettings(); - } + case HOVEROPTION_BACK: + goBack = true; + break; + case HOVEROPTION_PAGEUP: + PageUpList(true); + break; + case HOVEROPTION_PAGEDOWN: + PageDownList(true); + break; + case HOVEROPTION_USESKIN: + if (m_nSkinsTotal > 0) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + m_pSelectedSkin = m_pSkinListHead.nextSkin; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } } } if (CPad::GetPad(0)->GetLeftMouseJustDown()) { switch (m_nHoverOption) { - case HOVEROPTION_OVER_SCROLL_UP: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; - break; - case HOVEROPTION_OVER_SCROLL_DOWN: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; - break; - case HOVEROPTION_LIST: - m_nHoverOption = HOVEROPTION_SKIN; + case HOVEROPTION_OVER_SCROLL_UP: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; + break; + case HOVEROPTION_LIST: + m_nHoverOption = HOVEROPTION_SKIN; } - } - else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) + } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; } if (!CPad::GetPad(0)->GetLeftMouse()) { holdingScrollBar = false; - } - else { + } else { if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { holdingScrollBar = true; // TODO: This part is a bit hard to reverse. Not much code tho assert(0 && "Holding scrollbar isn't done yet"); - } - else { + } else { switch (m_nHoverOption) { case HOVEROPTION_OVER_SCROLL_UP: case HOVEROPTION_CLICKED_SCROLL_UP: @@ -3933,8 +3845,7 @@ CMenuManager::ProcessButtonPresses(void) } } } - } - else if (isPlainTextScreen(m_nCurrScreen)) { + } else if (isPlainTextScreen(m_nCurrScreen)) { #ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) { optionSelected = true; @@ -3945,14 +3856,12 @@ CMenuManager::ProcessButtonPresses(void) } } #endif - } - else { + } else { if (CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); goDown = true; - } - else if (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + } else if (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); goUp = true; @@ -3964,8 +3873,7 @@ CMenuManager::ProcessButtonPresses(void) m_bShowMouse = false; optionSelected = true; } - } - else { + } else { if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { m_bShowMouse = false; optionSelected = true; @@ -3981,10 +3889,9 @@ CMenuManager::ProcessButtonPresses(void) #endif (m_nHoverOption == HOVEROPTION_RANDOM_ITEM)) { m_nCurrOption = m_nPrevOption; - optionSelected = true; + optionSelected = true; } - } - else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + } else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { #ifdef TIDY_UP_PBP if (m_nHoverOption >= HOVEROPTION_RADIO_0 && m_nHoverOption <= HOVEROPTION_RADIO_9) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); @@ -3993,8 +3900,7 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); OutputDebugString("FRONTEND RADIO STATION CHANGED"); - } - else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM + } else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESUME) { m_nCurrOption = m_nPrevOption; optionSelected = true; @@ -4177,26 +4083,26 @@ CMenuManager::ProcessButtonPresses(void) TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; - } + } #else switch (m_nHoverOption) { - case HOVEROPTION_INCREASE_BRIGHTNESS: - case HOVEROPTION_INCREASE_DRAWDIST: - case HOVEROPTION_INCREASE_MUSICVOLUME: - case HOVEROPTION_INCREASE_SFXVOLUME: - case HOVEROPTION_INCREASE_MOUSESENS: - CheckSliderMovement(1); - break; - case HOVEROPTION_DECREASE_BRIGHTNESS: - case HOVEROPTION_DECREASE_DRAWDIST: - case HOVEROPTION_DECREASE_MUSICVOLUME: - case HOVEROPTION_DECREASE_SFXVOLUME: - case HOVEROPTION_DECREASE_MOUSESENS: - CheckSliderMovement(-1); - break; + case HOVEROPTION_INCREASE_BRIGHTNESS: + case HOVEROPTION_INCREASE_DRAWDIST: + case HOVEROPTION_INCREASE_MUSICVOLUME: + case HOVEROPTION_INCREASE_SFXVOLUME: + case HOVEROPTION_INCREASE_MOUSESENS: + CheckSliderMovement(1); + break; + case HOVEROPTION_DECREASE_BRIGHTNESS: + case HOVEROPTION_DECREASE_DRAWDIST: + case HOVEROPTION_DECREASE_MUSICVOLUME: + case HOVEROPTION_DECREASE_SFXVOLUME: + case HOVEROPTION_DECREASE_MOUSESENS: + CheckSliderMovement(-1); + break; } #endif - } + } if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp() || CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp() @@ -4230,7 +4136,7 @@ CMenuManager::ProcessButtonPresses(void) goBack = false; } #endif - } + } // Centralized enter/back (except some conditions) #ifdef TIDY_UP_PBP @@ -4243,8 +4149,7 @@ CMenuManager::ProcessButtonPresses(void) optionSelected = true; } - } - else { + } else { if (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) { m_bShowMouse = false; optionSelected = true; @@ -4257,8 +4162,7 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustUp()) { goBack = true; } - } - else { + } else { if (CPad::GetPad(0)->GetEscapeJustDown() || (m_nCurrScreen != MENUPAGE_PAUSE_MENU && CPad::GetPad(0)->GetBackJustDown())) { m_bShowMouse = false; goBack = true; @@ -4275,8 +4179,7 @@ CMenuManager::ProcessButtonPresses(void) curBottomBarOption = hoveredBottomBarOption; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, false); return; - } - else if (bottomBarActive) { + } else if (bottomBarActive) { if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); bottomBarActive = false; @@ -4285,8 +4188,7 @@ CMenuManager::ProcessButtonPresses(void) if (reverseAlpha) m_nMenuFadeAlpha = 0; return; - } - else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown() + } else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown() || CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); @@ -4294,12 +4196,11 @@ CMenuManager::ProcessButtonPresses(void) curBottomBarOption--; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); return; - } - else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown() + } else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown() || CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - if (curBottomBarOption < bbTabCount - 1) + if (curBottomBarOption < bbTabCount-1) curBottomBarOption++; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); return; @@ -4322,8 +4223,7 @@ CMenuManager::ProcessButtonPresses(void) && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption + 1].m_Action != MENUACTION_NOTHING) { m_nCurrOption++; } - } - else { + } else { m_nCurrOption--; } } @@ -4339,11 +4239,9 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); else DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - } - else + } else DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_COMPLETED, 0); - } - else { + } else { // This is duplicate, back button already processed below #ifndef TIDY_UP_PBP DMAudio.PlayFrontEndSound(SOUND_FRONTEND_EXIT, 0); @@ -4353,18 +4251,15 @@ CMenuManager::ProcessButtonPresses(void) } #endif } - } - else if (option == MENUACTION_CHECKSAVE) { + } else if (option == MENUACTION_CHECKSAVE) { if (Slots[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot - 1] == SLOT_EMPTY) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - } - else { + } else { if (m_nCurrScreen != MENUPAGE_NEW_GAME_RELOAD) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); } } - } - else if (option != MENUACTION_CHANGEMENU && option != MENUACTION_BRIGHTNESS && option != MENUACTION_DRAWDIST + } else if (option != MENUACTION_CHANGEMENU && option != MENUACTION_BRIGHTNESS && option != MENUACTION_DRAWDIST && option != MENUACTION_MUSICVOLUME && option != MENUACTION_SFXVOLUME && option != MENUACTION_CHECKSAVE && option != MENUACTION_UNK24 && option != MENUACTION_MOUSESENS && option != MENUACTION_SCREENRES) { @@ -4374,392 +4269,382 @@ CMenuManager::ProcessButtonPresses(void) if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) || (m_nCurrScreen == MENUPAGE_SKIN_SELECT)) { switch (m_nCurrExLayer) { - default: - goBack = true; - break; - case HOVEROPTION_LIST: - if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - } - if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + default: + goBack = true; + break; + case HOVEROPTION_LIST: + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + m_nCurrExLayer = HOVEROPTION_BACK; + SaveSettings(); + } + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + break; + case HOVEROPTION_USESKIN: + m_nHoverOption = HOVEROPTION_NOT_HOVERING; strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); m_nCurrExLayer = HOVEROPTION_BACK; SaveSettings(); - } - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - break; - case HOVEROPTION_USESKIN: - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - m_nCurrExLayer = HOVEROPTION_BACK; - SaveSettings(); - break; + break; } - } - else if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { + } else if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { DoSettingsBeforeStartingAGame(); - /* } else if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - // .. either empty or there was some outer if. :shrug: pointless anyway, keyboard_controls is handled in first if. - */ - } - else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { +/* } else if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + // .. either empty or there was some outer if. :shrug: pointless anyway, keyboard_controls is handled in first if. +*/ + } else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { if (m_nSkinsTotal > 0) { m_pSelectedSkin = m_pSkinListHead.nextSkin; strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); - } - else { + } else { if (!m_bGameNotLoaded) ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); else ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); } - } - else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { + } else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; switch (option) { - case MENUACTION_RADIO: + case MENUACTION_RADIO: #ifdef TIDY_UP_PBP - assumeIncrease = true; + assumeIncrease = true; #else - ++m_PrefsRadioStation; - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; - } - else if (m_PrefsRadioStation > CHATTERBOX) { - m_PrefsRadioStation = USERTRACK; - } - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); -#endif - break; - case MENUACTION_LANG_ENG: - m_PrefsLanguage = LANGUAGE_AMERICAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_FRE: - m_PrefsLanguage = LANGUAGE_FRENCH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_GER: - m_PrefsLanguage = LANGUAGE_GERMAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_ITA: - m_PrefsLanguage = LANGUAGE_ITALIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_SPA: - m_PrefsLanguage = LANGUAGE_SPANISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; -#ifdef MORE_LANGUAGES - case MENUACTION_LANG_PL: - m_PrefsLanguage = LANGUAGE_POLISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_RUS: - m_PrefsLanguage = LANGUAGE_RUSSIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - CMenuManager::InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_JAP: - m_PrefsLanguage = LANGUAGE_JAPANESE; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; -#endif - case MENUACTION_POPULATESLOTS_CHANGEMENU: - PcSaveHelper.PopulateSlotInfo(); - - // fall through - case MENUACTION_CHANGEMENU: - { - bool changeMenu = true; - int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; - - // This should be unused. - if (saveSlot >= 2 && saveSlot <= 9) { - m_nCurrSaveSlot = saveSlot - 2; - switch (m_nCurrScreen) { - case MENUPAGE_CHOOSE_LOAD_SLOT: - if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY) - changeMenu = false; - - break; - case MENUPAGE_CHOOSE_DELETE_SLOT: - if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY) - changeMenu = false; - - break; - } - } - if (changeMenu) { - if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) { -#ifndef TIDY_UP_PBP - ResetHelperText(); - if (!m_bGameNotLoaded) - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - else - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); -#else - goBack = true; - break; -#endif - } - else { -#ifdef MENU_MAP - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { - bMapLoaded = false; - } - -#endif - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } - break; - } - case MENUACTION_CHECKSAVE: - { - int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; - - if (saveSlot >= 2 && saveSlot <= 9) { - m_nCurrSaveSlot = saveSlot - 2; - if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY && Slots[m_nCurrSaveSlot + 1] != SLOT_CORRUPTED) { - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } - break; - } - case MENUACTION_NEWGAME: - DoSettingsBeforeStartingAGame(); - break; - case MENUACTION_RELOADIDE: - CFileLoader::ReloadObjectTypes("GTA3.IDE"); - break; - case MENUACTION_RELOADIPL: - CGame::ReloadIPLs(); - break; - case MENUACTION_SHOWCULL: - // REMOVED(MIAMI) - break; - case MENUACTION_MEMCARDSAVECONFIRM: - return; - case MENUACTION_RESUME_FROM_SAVEZONE: - RequestFrontEndShutDown(); - break; - case MENUACTION_MPMAP_LIBERTY: - case MENUACTION_MPMAP_REDLIGHT: - case MENUACTION_MPMAP_CHINATOWN: - case MENUACTION_MPMAP_TOWER: - case MENUACTION_MPMAP_SEWER: - case MENUACTION_MPMAP_INDUSTPARK: - case MENUACTION_MPMAP_DOCKS: - case MENUACTION_MPMAP_STAUNTON: - m_SelectedMap = option - MENUACTION_MPMAP_LIBERTY; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_MPMAP_DEATHMATCH1: - case MENUACTION_MPMAP_DEATHMATCH2: - case MENUACTION_MPMAP_TEAMDEATH1: - case MENUACTION_MPMAP_TEAMDEATH2: - case MENUACTION_MPMAP_STASH: - case MENUACTION_MPMAP_CAPTURE: - case MENUACTION_MPMAP_RATRACE: - case MENUACTION_MPMAP_DOMINATION: - m_SelectedGameType = option - MENUACTION_MPMAP_DEATHMATCH1; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_REDEFCTRL: - ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); - m_nSelectedListRow = 0; - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case MENUACTION_GETKEY: - m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; - m_bKeyIsOK = true; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - break; - case MENUACTION_CANCELGAME: - DMAudio.Service(); - RsEventHandler(rsQUITAPP, nil); - break; - case MENUACTION_RESUME: -#ifndef TIDY_UP_PBP - if (m_PrefsVsyncDisp != m_PrefsVsync) { - m_PrefsVsync = m_PrefsVsyncDisp; - } - RequestFrontEndShutDown(); -#else - goBack = true; -#endif - break; - case MENUACTION_DONTCANCEL: - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - break; - case MENUACTION_SCREENRES: - if (m_nDisplayVideoMode != m_nPrefsVideoMode) { - m_nPrefsVideoMode = m_nDisplayVideoMode; - _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); - SaveSettings(); - } - break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - if (m_nSelectedScreenMode != m_nPrefsWindowed) { - m_nPrefsWindowed = m_nSelectedScreenMode; - _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution - SetHelperText(0); - SaveSettings(); - } - break; -#endif - case MENUACTION_AUDIOHW: - { - int selectedProvider = m_nPrefsAudio3DProviderIndex; - if (selectedProvider != -1) { - m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); - if (selectedProvider == m_nPrefsAudio3DProviderIndex) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - SetHelperText(0); - } - else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - SetHelperText(4); + ++m_PrefsRadioStation; + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = HEAD_RADIO; + } else if (m_PrefsRadioStation > CHATTERBOX) { + m_PrefsRadioStation = USERTRACK; } SaveSettings(); - } - break; - } - case MENUACTION_SPEAKERCONF: -#ifndef TIDY_UP_PBP - if (m_nPrefsAudio3DProviderIndex != -1) { - if (--m_PrefsSpeakers < 0) - m_PrefsSpeakers = 2; - DMAudio.SetSpeakerConfig(m_PrefsSpeakers); - SaveSettings(); - } -#else - assumeIncrease = true; -#endif - break; - case MENUACTION_PLAYERSETUP: - CPlayerSkin::BeginFrontendSkinEdit(); - ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); - m_nCurrExLayer = HOVEROPTION_LIST; - m_bSkinsEnumerated = false; - break; - case MENUACTION_RESTOREDEF: - if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - m_PrefsSfxVolume = 102; - m_PrefsSpeakers = 0; - m_PrefsMusicVolume = 102; - m_PrefsStereoMono = 0; - m_PrefsRadioStation = HEAD_RADIO; - DMAudio.SetMusicMasterVolume(102); - DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - SaveSettings(); - } - else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_PrefsFrameLimiter = true; - m_PrefsBrightness = 256; - m_PrefsVsyncDisp = true; - m_PrefsLOD = 1.2f; - m_PrefsVsync = true; - CRenderer::ms_lodDistScale = 1.2f; - m_PrefsUseWideScreen = false; - m_PrefsShowSubtitles = true; - m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef GTA3_1_1_PATCH - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } - else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } -#else - CMBlur::BlurOn = true; + OutputDebugString("FRONTEND RADIO STATION CHANGED"); #endif + break; + case MENUACTION_LANG_ENG: + m_PrefsLanguage = LANGUAGE_AMERICAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); SaveSettings(); - } - else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { - ControlsManager.MakeControllerActionsBlank(); - ControlsManager.InitDefaultControlConfiguration(); - ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); -#if !defined RW_GL3 - if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { - DIDEVCAPS devCaps; - devCaps.dwSize = sizeof(DIDEVCAPS); - PSGLOBAL(joy1)->GetCapabilities(&devCaps); - ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); - } -#else - if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { - int count; - glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); - ControlsManager.InitDefaultControlConfigJoyPad(count); - } + break; + case MENUACTION_LANG_FRE: + m_PrefsLanguage = LANGUAGE_FRENCH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_GER: + m_PrefsLanguage = LANGUAGE_GERMAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_ITA: + m_PrefsLanguage = LANGUAGE_ITALIAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_SPA: + m_PrefsLanguage = LANGUAGE_SPANISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; +#ifdef MORE_LANGUAGES + case MENUACTION_LANG_PL: + m_PrefsLanguage = LANGUAGE_POLISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_RUS: + m_PrefsLanguage = LANGUAGE_RUSSIAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + CMenuManager::InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_JAP: + m_PrefsLanguage = LANGUAGE_JAPANESE; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; #endif - m_ControlMethod = CONTROL_STANDARD; - MousePointerStateHelper.bInvertVertically = false; - TheCamera.m_fMouseAccelHorzntl = 0.0025f; - CVehicle::m_bDisableMouseSteering = true; - TheCamera.m_bHeadBob = false; - SaveSettings(); - } - SetHelperText(2); - break; - case MENUACTION_CTRLMETHOD: + case MENUACTION_POPULATESLOTS_CHANGEMENU: + PcSaveHelper.PopulateSlotInfo(); + + // fall through + case MENUACTION_CHANGEMENU: + { + bool changeMenu = true; + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + // This should be unused. + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = saveSlot - 2; + switch (m_nCurrScreen) { + case MENUPAGE_CHOOSE_LOAD_SLOT: + if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY) + changeMenu = false; + + break; + case MENUPAGE_CHOOSE_DELETE_SLOT: + if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY) + changeMenu = false; + + break; + } + } + if (changeMenu) { + if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) { #ifndef TIDY_UP_PBP - if (m_ControlMethod == CONTROL_CLASSIC) { - CCamera::m_bUseMouse3rdPerson = true; - m_ControlMethod = CONTROL_STANDARD; - } - else { - CCamera::m_bUseMouse3rdPerson = false; - m_ControlMethod = CONTROL_CLASSIC; - } - SaveSettings(); + ResetHelperText(); + if (!m_bGameNotLoaded) + ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); + else + ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); #else - assumeIncrease = true; + goBack = true; + break; #endif - break; - case MENUACTION_LOADRADIO: - ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); - break; + } else { +#ifdef MENU_MAP + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { + bMapLoaded = false; + } + +#endif + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + } + } + break; + } + case MENUACTION_CHECKSAVE: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = saveSlot - 2; + if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY && Slots[m_nCurrSaveSlot + 1] != SLOT_CORRUPTED) { + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + } + } + break; + } + case MENUACTION_NEWGAME: + DoSettingsBeforeStartingAGame(); + break; + case MENUACTION_RELOADIDE: + CFileLoader::ReloadObjectTypes("GTA3.IDE"); + break; + case MENUACTION_RELOADIPL: + CGame::ReloadIPLs(); + break; + case MENUACTION_SHOWCULL: + // REMOVED(MIAMI) + break; + case MENUACTION_MEMCARDSAVECONFIRM: + return; + case MENUACTION_RESUME_FROM_SAVEZONE: + RequestFrontEndShutDown(); + break; + case MENUACTION_MPMAP_LIBERTY: + case MENUACTION_MPMAP_REDLIGHT: + case MENUACTION_MPMAP_CHINATOWN: + case MENUACTION_MPMAP_TOWER: + case MENUACTION_MPMAP_SEWER: + case MENUACTION_MPMAP_INDUSTPARK: + case MENUACTION_MPMAP_DOCKS: + case MENUACTION_MPMAP_STAUNTON: + m_SelectedMap = option - MENUACTION_MPMAP_LIBERTY; + SaveSettings(); + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + break; + case MENUACTION_MPMAP_DEATHMATCH1: + case MENUACTION_MPMAP_DEATHMATCH2: + case MENUACTION_MPMAP_TEAMDEATH1: + case MENUACTION_MPMAP_TEAMDEATH2: + case MENUACTION_MPMAP_STASH: + case MENUACTION_MPMAP_CAPTURE: + case MENUACTION_MPMAP_RATRACE: + case MENUACTION_MPMAP_DOMINATION: + m_SelectedGameType = option - MENUACTION_MPMAP_DEATHMATCH1; + SaveSettings(); + ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + break; + case MENUACTION_REDEFCTRL: + ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); + m_nSelectedListRow = 0; + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case MENUACTION_GETKEY: + m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; + m_bKeyIsOK = true; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + break; + case MENUACTION_CANCELGAME: + DMAudio.Service(); + RsEventHandler(rsQUITAPP, nil); + break; + case MENUACTION_RESUME: +#ifndef TIDY_UP_PBP + if (m_PrefsVsyncDisp != m_PrefsVsync) { + m_PrefsVsync = m_PrefsVsyncDisp; + } + RequestFrontEndShutDown(); +#else + goBack = true; +#endif + break; + case MENUACTION_DONTCANCEL: + ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); + break; + case MENUACTION_SCREENRES: + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + m_nPrefsVideoMode = m_nDisplayVideoMode; + _psSelectScreenVM(m_nPrefsVideoMode); + SetHelperText(0); + SaveSettings(); + } + break; +#ifdef IMPROVED_VIDEOMODE + case MENUACTION_SCREENMODE: + if (m_nSelectedScreenMode != m_nPrefsWindowed) { + m_nPrefsWindowed = m_nSelectedScreenMode; + _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution + SetHelperText(0); + SaveSettings(); + } + break; +#endif + case MENUACTION_AUDIOHW: + { + int selectedProvider = m_nPrefsAudio3DProviderIndex; + if (selectedProvider != -1) { + m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + if (selectedProvider == m_nPrefsAudio3DProviderIndex) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SetHelperText(0); + } else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + SetHelperText(4); + } + SaveSettings(); + } + break; + } + case MENUACTION_SPEAKERCONF: +#ifndef TIDY_UP_PBP + if (m_nPrefsAudio3DProviderIndex != -1) { + if (--m_PrefsSpeakers < 0) + m_PrefsSpeakers = 2; + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); + SaveSettings(); + } +#else + assumeIncrease = true; +#endif + break; + case MENUACTION_PLAYERSETUP: + CPlayerSkin::BeginFrontendSkinEdit(); + ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); + m_nCurrExLayer = HOVEROPTION_LIST; + m_bSkinsEnumerated = false; + break; + case MENUACTION_RESTOREDEF: + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + m_PrefsSfxVolume = 102; + m_PrefsSpeakers = 0; + m_PrefsMusicVolume = 102; + m_PrefsStereoMono = 0; + m_PrefsRadioStation = HEAD_RADIO; + DMAudio.SetMusicMasterVolume(102); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + SaveSettings(); + } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + m_PrefsFrameLimiter = true; + m_PrefsBrightness = 256; + m_PrefsVsyncDisp = true; + m_PrefsLOD = 1.2f; + m_PrefsVsync = true; + CRenderer::ms_lodDistScale = 1.2f; + m_PrefsUseWideScreen = false; + m_PrefsShowSubtitles = true; + m_nDisplayVideoMode = m_nPrefsVideoMode; +#ifdef GTA3_1_1_PATCH + if (_dwOperatingSystemVersion == OS_WIN98) { + CMBlur::BlurOn = false; + CMBlur::MotionBlurClose(); + } + else { + CMBlur::BlurOn = true; + CMBlur::MotionBlurOpen(Scene.camera); + } +#else + CMBlur::BlurOn = true; +#endif + SaveSettings(); + } else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { + ControlsManager.MakeControllerActionsBlank(); + ControlsManager.InitDefaultControlConfiguration(); + ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); +#if !defined RW_GL3 + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { + DIDEVCAPS devCaps; + devCaps.dwSize = sizeof(DIDEVCAPS); + PSGLOBAL(joy1)->GetCapabilities(&devCaps); + ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); + } +#else + if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + ControlsManager.InitDefaultControlConfigJoyPad(count); + } +#endif + m_ControlMethod = CONTROL_STANDARD; + MousePointerStateHelper.bInvertVertically = false; + TheCamera.m_fMouseAccelHorzntl = 0.0025f; + CVehicle::m_bDisableMouseSteering = true; + TheCamera.m_bHeadBob = false; + SaveSettings(); + } + SetHelperText(2); + break; + case MENUACTION_CTRLMETHOD: +#ifndef TIDY_UP_PBP + if (m_ControlMethod == CONTROL_CLASSIC) { + CCamera::m_bUseMouse3rdPerson = true; + m_ControlMethod = CONTROL_STANDARD; + } else { + CCamera::m_bUseMouse3rdPerson = false; + m_ControlMethod = CONTROL_CLASSIC; + } + SaveSettings(); +#else + assumeIncrease = true; +#endif + break; + case MENUACTION_LOADRADIO: + ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); + break; } } ProcessOnOffMenuOptions(); @@ -4810,8 +4695,7 @@ CMenuManager::ProcessButtonPresses(void) if (!bottomBarActive && (oldScreen == MENUPAGE_NONE || oldScreen == MENUPAGE_OPTIONS)) { bottomBarActive = true; - } - else + } else #endif { ChangeScreen(oldScreen, oldOption, true, true); @@ -4822,7 +4706,7 @@ CMenuManager::ProcessButtonPresses(void) return; #endif } - } + } #ifdef PS2_LIKE_MENU if (bottomBarActive) @@ -4842,8 +4726,7 @@ CMenuManager::ProcessButtonPresses(void) CheckSliderMovement(-1); lastSliderDecrease = CTimer::GetTimeInMillisecondsPauseMode(); } - } - else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { + } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { static uint32 lastSliderIncrease = 0; if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) { CheckSliderMovement(1); @@ -4854,8 +4737,7 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) { m_bShowMouse = false; increase = true; - } - else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + } else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { increase = true; CheckSliderMovement(1); m_bShowMouse = true; @@ -4869,8 +4751,7 @@ CMenuManager::ProcessButtonPresses(void) m_bShowMouse = true; } } - } - else { + } else { m_bShowMouse = false; decrease = true; } @@ -4882,105 +4763,101 @@ CMenuManager::ProcessButtonPresses(void) if (changeValueBy != 0) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { - case MENUACTION_RADIO: - m_PrefsRadioStation += changeValueBy; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = USERTRACK; - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; - } - else { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = CHATTERBOX; - if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = HEAD_RADIO; - } - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; -#ifdef ASPECT_RATIO_SCALE - case MENUACTION_WIDESCREEN: - if (changeValueBy > 0) { - m_PrefsUseWideScreen++; - if (m_PrefsUseWideScreen > 2) - m_PrefsUseWideScreen = 2; - } - else { - m_PrefsUseWideScreen--; - if (m_PrefsUseWideScreen < 0) - m_PrefsUseWideScreen = 0; - } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - SaveSettings(); - break; -#endif - case MENUACTION_SCREENRES: - if (m_bGameNotLoaded) { - RwChar** videoMods = _psGetVideoModeList(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - if (changeValueBy > 0) { - do { - ++m_nDisplayVideoMode; - - if (m_nDisplayVideoMode >= _psGetNumVideModes()) - m_nDisplayVideoMode = 0; - } while (!videoMods[m_nDisplayVideoMode]); - } - else { - do { - --m_nDisplayVideoMode; - - if (m_nDisplayVideoMode < 0) - m_nDisplayVideoMode = _psGetNumVideModes() - 1; - } while (!videoMods[m_nDisplayVideoMode]); - } - } - break; -#ifdef IMPROVED_VIDEOMODE - case MENUACTION_SCREENMODE: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nSelectedScreenMode = !m_nSelectedScreenMode; - break; -#endif - case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex != -1) { - m_nPrefsAudio3DProviderIndex += changeValueBy; - m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); - } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - break; - case MENUACTION_SPEAKERCONF: - if (m_nPrefsAudio3DProviderIndex != -1) { - m_PrefsSpeakers -= changeValueBy; - m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); - DMAudio.SetSpeakerConfig(m_PrefsSpeakers); - SaveSettings(); + case MENUACTION_RADIO: + m_PrefsRadioStation += changeValueBy; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - } - break; - case MENUACTION_CTRLMETHOD: - m_ControlMethod = !m_ControlMethod; - CCamera::m_bUseMouse3rdPerson = !m_ControlMethod; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - SaveSettings(); - break; + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < HEAD_RADIO) + m_PrefsRadioStation = USERTRACK; + if (m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = HEAD_RADIO; + } else { + if (m_PrefsRadioStation < HEAD_RADIO) + m_PrefsRadioStation = CHATTERBOX; + if (m_PrefsRadioStation > CHATTERBOX) + m_PrefsRadioStation = HEAD_RADIO; + } + SaveSettings(); + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); + OutputDebugString("FRONTEND RADIO STATION CHANGED"); + break; +#ifdef ASPECT_RATIO_SCALE + case MENUACTION_WIDESCREEN: + if (changeValueBy > 0) { + m_PrefsUseWideScreen++; + if (m_PrefsUseWideScreen > 2) + m_PrefsUseWideScreen = 2; + } else { + m_PrefsUseWideScreen--; + if (m_PrefsUseWideScreen < 0) + m_PrefsUseWideScreen = 0; + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SaveSettings(); + break; +#endif + case MENUACTION_SCREENRES: + if (m_bGameNotLoaded) { + RwChar** videoMods = _psGetVideoModeList(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + if (changeValueBy > 0) { + do { + ++m_nDisplayVideoMode; + + if (m_nDisplayVideoMode >= _psGetNumVideModes()) + m_nDisplayVideoMode = 0; + } while (!videoMods[m_nDisplayVideoMode]); + } else { + do { + --m_nDisplayVideoMode; + + if (m_nDisplayVideoMode < 0) + m_nDisplayVideoMode = _psGetNumVideModes() - 1; + } while (!videoMods[m_nDisplayVideoMode]); + } + } + break; +#ifdef IMPROVED_VIDEOMODE + case MENUACTION_SCREENMODE: + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + m_nSelectedScreenMode = !m_nSelectedScreenMode; + break; +#endif + case MENUACTION_AUDIOHW: + if (m_nPrefsAudio3DProviderIndex != -1) { + m_nPrefsAudio3DProviderIndex += changeValueBy; + m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); + break; + case MENUACTION_SPEAKERCONF: + if (m_nPrefsAudio3DProviderIndex != -1) { + m_PrefsSpeakers -= changeValueBy; + m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); + SaveSettings(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + } + break; + case MENUACTION_CTRLMETHOD: + m_ControlMethod = !m_ControlMethod; + CCamera::m_bUseMouse3rdPerson = !m_ControlMethod; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SaveSettings(); + break; } ProcessOnOffMenuOptions(); if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { if (changeValueBy < 1) { m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; - } - else { + } else { m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); } } - } +} void CMenuManager::ProcessOnOffMenuOptions() @@ -5106,7 +4983,7 @@ CMenuManager::RequestFrontEndStartUp() } void -CMenuManager::ResetHelperText() +CMenuManager::ResetHelperText() { m_nHelperTextMsgId = 0; m_nHelperTextAlpha = 300; @@ -5116,25 +4993,25 @@ void CMenuManager::SaveLoadFileError_SetUpErrorScreen() { switch (PcSaveHelper.nErrorCode) { - case SAVESTATUS_ERR_SAVE_CREATE: - case SAVESTATUS_ERR_SAVE_WRITE: - case SAVESTATUS_ERR_SAVE_CLOSE: - ChangeScreen(MENUPAGE_SAVE_FAILED, 0, true, false); - break; - case SAVESTATUS_ERR_LOAD_OPEN: - case SAVESTATUS_ERR_LOAD_READ: - case SAVESTATUS_ERR_LOAD_CLOSE: - ChangeScreen(MENUPAGE_LOAD_FAILED, 0, true, false); - break; - case SAVESTATUS_ERR_DATA_INVALID: - ChangeScreen(MENUPAGE_LOAD_FAILED_2, 0, true, false); - break; - case SAVESTATUS_DELETEFAILED8: - case SAVESTATUS_DELETEFAILED9: - case SAVESTATUS_DELETEFAILED10: - ChangeScreen(MENUPAGE_DELETE_FAILED, 0, true, false); - break; - default: break; + case SAVESTATUS_ERR_SAVE_CREATE: + case SAVESTATUS_ERR_SAVE_WRITE: + case SAVESTATUS_ERR_SAVE_CLOSE: + ChangeScreen(MENUPAGE_SAVE_FAILED, 0, true, false); + break; + case SAVESTATUS_ERR_LOAD_OPEN: + case SAVESTATUS_ERR_LOAD_READ: + case SAVESTATUS_ERR_LOAD_CLOSE: + ChangeScreen(MENUPAGE_LOAD_FAILED, 0, true, false); + break; + case SAVESTATUS_ERR_DATA_INVALID: + ChangeScreen(MENUPAGE_LOAD_FAILED_2, 0, true, false); + break; + case SAVESTATUS_DELETEFAILED8: + case SAVESTATUS_DELETEFAILED9: + case SAVESTATUS_DELETEFAILED10: + ChangeScreen(MENUPAGE_DELETE_FAILED, 0, true, false); + break; + default: break; } } @@ -5177,7 +5054,7 @@ CMenuManager::SwitchMenuOnAndOff() bool menuWasActive = GetIsMenuActive(); // Reminder: You need REGISTER_START_BUTTON defined to make it work. - if (CPad::GetPad(0)->GetStartJustDown() + if (CPad::GetPad(0)->GetStartJustDown() #ifdef FIX_BUGS && !m_bGameNotLoaded #endif @@ -5192,8 +5069,7 @@ CMenuManager::SwitchMenuOnAndOff() if (m_bMenuActive) { CTimer::StartUserPause(); - } - else { + } else { #ifdef PS2_LIKE_MENU bottomBarActive = false; #endif @@ -5237,14 +5113,14 @@ CMenuManager::SwitchMenuOnAndOff() PcSaveHelper.PopulateSlotInfo(); m_nCurrOption = 0; } - /* // PS2 leftover - if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) - { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); - gMusicPlaying = 0; - } - */ +/* // PS2 leftover + if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) + { + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); + gMusicPlaying = 0; + } +*/ if (m_bMenuActive != menuWasActive) m_bMenuStateChanged = true; @@ -5279,8 +5155,8 @@ CMenuManager::UnloadTextures() void CMenuManager::WaitForUserCD() { - CSprite2d* splash; - char* splashscreen = nil; + CSprite2d *splash; + char *splashscreen = nil; #if (!(defined RANDOMSPLASH) && !(defined GTA3_1_1_PATCH)) if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) @@ -5340,190 +5216,189 @@ CMenuManager::PrintController(void) if (m_DisplayControllerOnFoot) { switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - default: - return; + case 0: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + case 1: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + case 2: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + case 3: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + break; + default: + return; } - } - else { + } else { switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_RS3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_SMT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_ACC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_BRA")); - break; - default: - return; + case 0: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + break; + case 1: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HOR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + break; + case 2: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_RS3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HOR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + break; + case 3: + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); + CFont::SetRightJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); + CFont::SetJustifyOn(); // X + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_SMT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_ACC")); + // FIX: Coordinates of this line is undefined in PC... + CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_BRA")); + break; + default: + return; } } @@ -5638,8 +5513,7 @@ CMenuManager::PrintMap(void) if (m_bShowMouse) { bMapMouseShownOnce = true; - } - else if (!bMapMouseShownOnce) { + } else if (!bMapMouseShownOnce) { mapPoint.x = SCREEN_WIDTH / 2; mapPoint.y = SCREEN_HEIGHT / 2; } @@ -5667,24 +5541,19 @@ CMenuManager::PrintMap(void) if (CPad::GetPad(0)->GetLeftMouse()) { fMapCenterX += m_nMousePosX - m_nMouseOldPosX; fMapCenterY += m_nMousePosY - m_nMouseOldPosY; - } - else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { + } else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { fMapCenterX += 15.0f; - } - else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { + } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { fMapCenterX -= 15.0f; - } - else if (CPad::GetPad(0)->GetLeftStickX()) { + } else if (CPad::GetPad(0)->GetLeftStickX()) { fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; } if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetDPadUp()) { fMapCenterY += 15.0f; - } - else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { + } else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { fMapCenterY -= 15.0f; - } - else if (CPad::GetPad(0)->GetLeftStickY()) { + } else if (CPad::GetPad(0)->GetLeftStickY()) { fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; } @@ -5693,14 +5562,13 @@ CMenuManager::PrintMap(void) ZOOM(mapPoint.x, mapPoint.y, false); else ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false); - } - else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { + } else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { if (CPad::GetPad(0)->GetMouseWheelUp()) ZOOM(mapPoint.x, mapPoint.y, true); else ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); } - + if (fMapCenterX - fMapSize > SCREEN_WIDTH / 2) fMapCenterX = fMapSize + SCREEN_WIDTH / 2; @@ -5709,7 +5577,7 @@ CMenuManager::PrintMap(void) if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; - + if (fMapCenterY - fMapSize > SCREEN_HEIGHT / 2) fMapCenterY = SCREEN_HEIGHT / 2 + fMapSize; @@ -5727,7 +5595,7 @@ CMenuManager::PrintMap(void) CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); float nextX = MENU_X(30.0f), nextY = 95.0f; - wchar* text; + wchar *text; #ifdef MORE_LANGUAGES #define TEXT_PIECE(key,extraSpace) \ text = TheText.Get(key);\ @@ -5789,8 +5657,8 @@ CMenuManager::ConstructStatLine(int rowIdx) if (CGame::nastyGame) { STAT_LINE("FEST_RP", &CStats::NumberKillFrenziesPassed, false, &CStats::TotalNumberKillFrenzies); } - - CPlayerInfo& player = CWorld::Players[CWorld::PlayerInFocus]; + + CPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus]; float packagesPercent = 0.0f; if (player.m_nTotalPackages != 0) packagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; @@ -5807,16 +5675,16 @@ CMenuManager::ConstructStatLine(int rowIdx) STAT_LINE("TM_BUST", &CStats::TimesArrested, false, nil); STAT_LINE("TM_DED", &CStats::TimesDied, false, nil); STAT_LINE("GNG_WST", &(nTemp = CStats::PedsKilledOfThisType[PEDTYPE_GANG9] + CStats::PedsKilledOfThisType[PEDTYPE_GANG8] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]), false, nil); + + CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6] + + CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4] + + CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2] + + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]), false, nil); STAT_LINE("DED_CRI", &(nTemp = CStats::PedsKilledOfThisType[PEDTYPE_CRIMINAL]), false, nil); STAT_LINE("HEL_DST", &CStats::HelisDestroyed, false, nil); STAT_LINE("KGS_EXP", &CStats::KgsOfExplosivesUsed, false, nil); STAT_LINE("ACCURA", &(nTemp = (CStats::InstantHitsFiredByPlayer == 0 ? 0 : - CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)), false, nil); - + CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)), false, nil); + if (CStats::ElBurroTime > 0) { STAT_LINE("ELBURRO", &CStats::ElBurroTime, false, nil); } @@ -5861,33 +5729,33 @@ CMenuManager::ConstructStatLine(int rowIdx) } switch (m_PrefsLanguage) { - case LANGUAGE_AMERICAN: + case LANGUAGE_AMERICAN: #ifndef USE_MEASUREMENTS_IN_METERS - float fTemp; - STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); - STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); - STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); - STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); - break; + float fTemp; + STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); + STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); + STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); + STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); + STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); + break; #endif - case LANGUAGE_FRENCH: - case LANGUAGE_GERMAN: - case LANGUAGE_ITALIAN: - case LANGUAGE_SPANISH: + case LANGUAGE_FRENCH: + case LANGUAGE_GERMAN: + case LANGUAGE_ITALIAN: + case LANGUAGE_SPANISH: #ifdef MORE_LANGUAGES - case LANGUAGE_POLISH: - case LANGUAGE_RUSSIAN: - case LANGUAGE_JAPANESE: + case LANGUAGE_POLISH: + case LANGUAGE_RUSSIAN: + case LANGUAGE_JAPANESE: #endif - STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); - STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); - STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); - STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); - break; - default: - break; + STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); + STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); + STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); + STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); + STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); + break; + default: + break; } STAT_LINE("MXFLIP", &CStats::MaximumJumpFlips, false, nil); @@ -5897,33 +5765,33 @@ CMenuManager::ConstructStatLine(int rowIdx) if (counter == rowIdx) { gUString[0] = '\0'; switch (CStats::BestStuntJump) { - case 1: - UnicodeStrcpy(gUString2, TheText.Get("INSTUN")); - return 0; - case 2: - UnicodeStrcpy(gUString2, TheText.Get("PRINST")); - return 0; - case 3: - UnicodeStrcpy(gUString2, TheText.Get("DBINST")); - return 0; - case 4: - UnicodeStrcpy(gUString2, TheText.Get("DBPINS")); - return 0; - case 5: - UnicodeStrcpy(gUString2, TheText.Get("TRINST")); - return 0; - case 6: - UnicodeStrcpy(gUString2, TheText.Get("PRTRST")); - return 0; - case 7: - UnicodeStrcpy(gUString2, TheText.Get("QUINST")); - return 0; - case 8: - UnicodeStrcpy(gUString2, TheText.Get("PQUINS")); - return 0; - default: - UnicodeStrcpy(gUString2, TheText.Get("NOSTUC")); - return 0; + case 1: + UnicodeStrcpy(gUString2, TheText.Get("INSTUN")); + return 0; + case 2: + UnicodeStrcpy(gUString2, TheText.Get("PRINST")); + return 0; + case 3: + UnicodeStrcpy(gUString2, TheText.Get("DBINST")); + return 0; + case 4: + UnicodeStrcpy(gUString2, TheText.Get("DBPINS")); + return 0; + case 5: + UnicodeStrcpy(gUString2, TheText.Get("TRINST")); + return 0; + case 6: + UnicodeStrcpy(gUString2, TheText.Get("PRTRST")); + return 0; + case 7: + UnicodeStrcpy(gUString2, TheText.Get("QUINST")); + return 0; + case 8: + UnicodeStrcpy(gUString2, TheText.Get("PQUINS")); + return 0; + default: + UnicodeStrcpy(gUString2, TheText.Get("NOSTUC")); + return 0; } } counter++; diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 6804b938..bed943a1 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -143,7 +143,7 @@ void BlowUpCarsCheat() int i = CPools::GetVehiclePool()->GetSize(); while (i-- > 0) { - if (CVehicle* veh = CPools::GetVehiclePool()->GetSlot(i)) + if (CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i)) veh->BlowUpCar(nil); } } @@ -154,18 +154,18 @@ void ChangePlayerCheat() if (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo("player", nil)) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - CPlayerPed* ped = FindPlayerPed(); + CPlayerPed *ped = FindPlayerPed(); AssocGroupId AnimGrp = ped->m_animGroup; do { do - modelId = CGeneral::GetRandomNumberInRange(0, MI_WFYG2 + 1); + modelId = CGeneral::GetRandomNumberInRange(0, MI_WFYG2+1); while (!CModelInfo::GetModelInfo(modelId)); } while (modelId == MI_TAXI_D); uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags; ped->DeleteRwObject(); - CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE); CStreaming::LoadAllRequestedModels(false); ped->m_modelIndex = -1; ped->SetModelIndex(modelId); @@ -185,7 +185,7 @@ void MayhemCheat() PED_FLAG_CIVMALE | PED_FLAG_CIVFEMALE | PED_FLAG_COP | PED_FLAG_GANG1 | PED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 | PED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 | - PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL); + PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL ); } void EverybodyAttacksPlayerCheat() @@ -311,15 +311,14 @@ void PinkCarsCheat() #ifdef KANGAROO_CHEAT void KangarooCheat() { - wchar* string; - CPed* playerPed = FindPlayerPed(); + wchar *string; + CPed *playerPed = FindPlayerPed(); int m_fMass; if (playerPed->m_ped_flagI80) { string = TheText.Get("CHEATOF"); m_fMass = 70.0f; - } - else { + } else { string = TheText.Get("CHEAT1"); m_fMass = 15.0f; } @@ -368,8 +367,8 @@ bool CControllerState::IsAnyButtonPressed(void) { return !!LeftStickX || !!LeftStickY || !!RightStickX || !!RightStickY || !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2 || - !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight || !!Start || !!Select || !!Square || !!Triangle || !!Cross || !!Circle || !!LeftShock || - !!RightShock || !!NetworkTalk; + !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight || !!Start || !!Select || !!Square || !!Triangle || !!Cross || !!Circle || !!LeftShock || + !!RightShock || !!NetworkTalk; } #endif @@ -387,24 +386,24 @@ CControllerState::Clear(void) void CKeyboardState::Clear() { - for (int32 i = 0; i < 12; i++) + for ( int32 i = 0; i < 12; i++ ) F[i] = 0; - - for (int32 i = 0; i < 256; i++) + + for ( int32 i = 0; i < 256; i++ ) VK_KEYS[i] = 0; ESC = INS = DEL = HOME = END = PGUP = PGDN = 0; - + UP = DOWN = LEFT = RIGHT = 0; - + NUMLOCK = 0; - + DIV = MUL = SUB = ADD = 0; - + DECIMAL = NUM1 = NUM2 = NUM3 = NUM4 = 0; - + NUM5 = NUM6 = NUM7 = NUM8 = 0; - + NUM9 = NUM0 = SCROLLLOCK = PAUSE = 0; BACKSP = TAB = CAPSLOCK = EXTENTER = 0; @@ -422,10 +421,10 @@ void CPad::Initialise(void) CPad::GetPad(i)->Clear(true); CPad::GetPad(i)->Mode = 0; } - - bObsoleteControllerMessage = false; + + bObsoleteControllerMessage = false; bOldDisplayNoControllerMessage = false; - bDisplayNoControllerMessage = false; + bDisplayNoControllerMessage = false; } #endif @@ -433,37 +432,37 @@ void CPad::Clear(bool bResetPlayerControls) { NewState.Clear(); OldState.Clear(); - + PCTempKeyState.Clear(); PCTempJoyState.Clear(); PCTempMouseState.Clear(); - + NewKeyState.Clear(); OldKeyState.Clear(); TempKeyState.Clear(); - + NewMouseControllerState.Clear(); OldMouseControllerState.Clear(); PCTempMouseControllerState.Clear(); - + Phase = 0; ShakeFreq = 0; ShakeDur = 0; - - if (bResetPlayerControls) + + if ( bResetPlayerControls ) DisablePlayerControls = PLAYERCONTROL_ENABLED; - + bApplyBrakes = false; - - - for (int32 i = 0; i < HORNHISTORY_SIZE; i++) + + + for ( int32 i = 0; i < HORNHISTORY_SIZE; i++ ) bHornHistory[i] = false; - + iCurrHornHistory = 0; - - for (int32 i = 0; i < ARRAY_SIZE(CheatString); i++) + + for ( int32 i = 0; i < ARRAY_SIZE(CheatString); i++ ) CheatString[i] = ' '; - + LastTimeTouched = CTimer::GetTimeInMilliseconds(); AverageWeapon = 0; AverageEntries = 0; @@ -485,7 +484,7 @@ CMouseControllerState::CMouseControllerState() WHEELDN = 0; MXB1 = 0; MXB2 = 0; - + x = 0.0f; y = 0.0f; } @@ -504,35 +503,35 @@ void CMouseControllerState::Clear() CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() { CMouseControllerState state; - + #if defined RW_D3D9 || defined RWLIBS - if (PSGLOBAL(mouse) == nil) + if ( PSGLOBAL(mouse) == nil ) _InputInitialiseMouse(); - - if (PSGLOBAL(mouse) != nil) + + if ( PSGLOBAL(mouse) != nil ) { DIDEVCAPS devCaps; devCaps.dwSize = sizeof(DIDEVCAPS); - + PSGLOBAL(mouse)->GetCapabilities(&devCaps); - switch (devCaps.dwButtons) + switch ( devCaps.dwButtons ) { - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - state.MMB = true; - - case 2: - state.RMB = true; - - case 1: - state.LMB = true; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + state.MMB = true; + + case 2: + state.RMB = true; + + case 1: + state.LMB = true; } - - if (devCaps.dwAxes == 3) + + if ( devCaps.dwAxes == 3 ) { state.WHEELDN = true; state.WHEELUP = true; @@ -557,29 +556,29 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() void CPad::UpdateMouse() { - if (IsForegroundApp()) + if ( IsForegroundApp() ) { #if defined RW_D3D9 || defined RWLIBS - if (PSGLOBAL(mouse) == nil) + if ( PSGLOBAL(mouse) == nil ) _InputInitialiseMouse(); - + DIMOUSESTATE2 state; - - if (PSGLOBAL(mouse) != nil && SUCCEEDED(_InputGetMouseState(&state))) + + if ( PSGLOBAL(mouse) != nil && SUCCEEDED(_InputGetMouseState(&state)) ) { int32 signX = 1; int32 signy = 1; - if (!FrontEndMenuManager.m_bMenuActive) + if ( !FrontEndMenuManager.m_bMenuActive ) { - if (MousePointerStateHelper.bInvertVertically) + if ( MousePointerStateHelper.bInvertVertically ) signy = -1; - if (MousePointerStateHelper.bInvertHorizontally) + if ( MousePointerStateHelper.bInvertHorizontally ) signX = -1; } - + PCTempMouseControllerState.Clear(); - + PCTempMouseControllerState.x = (float)(signX * state.lX); PCTempMouseControllerState.y = (float)(signy * state.lY); PCTempMouseControllerState.LMB = state.rgbButtons[0] & 128; @@ -587,12 +586,12 @@ void CPad::UpdateMouse() PCTempMouseControllerState.MMB = state.rgbButtons[2] & 128; PCTempMouseControllerState.MXB1 = state.rgbButtons[3] & 128; PCTempMouseControllerState.MXB2 = state.rgbButtons[4] & 128; - - if (state.lZ > 0) + + if ( state.lZ > 0 ) PCTempMouseControllerState.WHEELUP = 1; - else if (state.lZ < 0) + else if ( state.lZ < 0 ) PCTempMouseControllerState.WHEELDN = 1; - + OldMouseControllerState = NewMouseControllerState; NewMouseControllerState = PCTempMouseControllerState; } @@ -638,15 +637,15 @@ void CPad::UpdateMouse() } } -CControllerState CPad::ReconcileTwoControllersInput(CControllerState const& State1, CControllerState const& State2) +CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2) { static CControllerState ReconState; - + ReconState.Clear(); #define _RECONCILE_BUTTON(button) \ { if ( State1.button || State2.button ) ReconState.button = 255; } - + #define _RECONCILE_AXIS_POSITIVE(axis) \ { if ( State1.axis >= 0 && State2.axis >= 0 ) ReconState.axis = Max(State1.axis, State2.axis); } @@ -655,10 +654,10 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const& Stat #define _RECONCILE_AXIS(axis) \ { _RECONCILE_AXIS_POSITIVE(axis); _RECONCILE_AXIS_NEGATIVE(axis); } - + #define _FIX_AXIS_DIR(axis) \ { if ( State1.axis > 0 && State2.axis < 0 || State1.axis < 0 && State2.axis > 0 ) ReconState.axis = 0; } - + #define _FIX_RECON_DIR(pos, neg, axis) \ { if ( (ReconState.pos || ReconState.axis < 0) && (ReconState.neg || ReconState.axis > 0) ) { ReconState.pos = 0; ReconState.neg = 0; ReconState.axis = 0; } } @@ -691,7 +690,7 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const& Stat _FIX_RECON_DIR(DPadLeft, DPadRight, LeftStickX); return ReconState; - + #undef _RECONCILE_BUTTON #undef _RECONCILE_AXIS_POSITIVE #undef _RECONCILE_AXIS_NEGATIVE @@ -702,20 +701,20 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const& Stat void CPad::StartShake(int16 nDur, uint8 nFreq) { - if (!CMenuManager::m_PrefsUseVibration) + if ( !CMenuManager::m_PrefsUseVibration ) return; - - if (CCutsceneMgr::IsRunning() || CGame::playingIntro) + + if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) return; - - if (nFreq == 0) + + if ( nFreq == 0 ) { ShakeDur = 0; ShakeFreq = 0; return; } - - if (nDur > ShakeDur) + + if ( nDur > ShakeDur ) { ShakeDur = nDur; ShakeFreq = nFreq; @@ -724,24 +723,24 @@ void CPad::StartShake(int16 nDur, uint8 nFreq) void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fZ) { - if (!CMenuManager::m_PrefsUseVibration) + if ( !CMenuManager::m_PrefsUseVibration ) return; - - if (CCutsceneMgr::IsRunning() || CGame::playingIntro) + + if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) return; - - float fDist = (TheCamera.GetPosition() - CVector(fX, fY, fZ)).Magnitude(); - - if (fDist < 70.0f) + + float fDist = ( TheCamera.GetPosition() - CVector(fX, fY, fZ) ).Magnitude(); + + if ( fDist < 70.0f ) { - if (nFreq == 0) + if ( nFreq == 0 ) { ShakeDur = 0; ShakeFreq = 0; return; } - - if (nDur > ShakeDur) + + if ( nDur > ShakeDur ) { ShakeDur = nDur; ShakeFreq = nFreq; @@ -751,22 +750,22 @@ void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, floa void CPad::StartShake_Train(float fX, float fY) { - if (!CMenuManager::m_PrefsUseVibration) + if ( !CMenuManager::m_PrefsUseVibration ) return; - - if (CCutsceneMgr::IsRunning() || CGame::playingIntro) + + if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) return; - - if (FindPlayerVehicle() != nil && FindPlayerVehicle()->IsTrain()) + + if (FindPlayerVehicle() != nil && FindPlayerVehicle()->IsTrain() ) return; - - float fDist = (TheCamera.GetPosition() - CVector(fX, fY, 0.0f)).Magnitude2D(); - - if (fDist < 70.0f) + + float fDist = ( TheCamera.GetPosition() - CVector(fX, fY, 0.0f) ).Magnitude2D(); + + if ( fDist < 70.0f ) { int32 freq = (int32)((70.0f - fDist) * 70.0f / 70.0f + 30.0f); - if (ShakeDur < 100) + if ( ShakeDur < 100 ) { ShakeDur = 100; ShakeFreq = freq; @@ -777,102 +776,102 @@ void CPad::StartShake_Train(float fX, float fY) #ifdef GTA_PS2_STUFF void CPad::AddToCheatString(char c) { - for (int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i--) + for ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- ) CheatString[i + 1] = CheatString[i]; - + CheatString[0] = c; #define _CHEATCMP(str) strncmp(str, CheatString, sizeof(str)-1) // "4414LDRULDRU" - R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - if (!_CHEATCMP("URDLURDL4144")) + if ( !_CHEATCMP("URDLURDL4144") ) WeaponCheat(); // "4411LDRULDRU" - R2 R2 L1 L1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - else if (!_CHEATCMP("URDLURDL1144")) + else if ( !_CHEATCMP("URDLURDL1144") ) MoneyCheat(); - + // "4412LDRULDRU" - R2 R2 L1 L2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - else if (!_CHEATCMP("URDLURDL2144")) + else if ( !_CHEATCMP("URDLURDL2144") ) ArmourCheat(); - + // "4413LDRULDRU" - R2 R2 L1 R1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP - else if (!_CHEATCMP("URDLURDL3144")) + else if ( !_CHEATCMP("URDLURDL3144") ) HealthCheat(); // "4414LRLRLR" - R2 R2 L1 R2 LEFT RIGHT LEFT RIGHT LEFT RIGHT - else if (!_CHEATCMP("RLRLRL4144")) + else if ( !_CHEATCMP("RLRLRL4144") ) WantedLevelUpCheat(); - + // "4414UDUDUD" - R2 R2 L1 R2 UP DOWN UP DOWN UP DOWN - else if (!_CHEATCMP("DUDUDU4144")) + else if ( !_CHEATCMP("DUDUDU4144") ) WantedLevelDownCheat(); - + // "1234432T" - L1 L2 R1 R2 R2 R1 L2 TRIANGLE - else if (!_CHEATCMP("T2344321")) + else if ( !_CHEATCMP("T2344321") ) SunnyWeatherCheat(); - + // "1234432S" - L1 L2 R1 R2 R2 R1 L2 SQUARE - else if (!_CHEATCMP("S2344321")) + else if ( !_CHEATCMP("S2344321") ) CloudyWeatherCheat(); - + // "1234432C" - L1 L2 R1 R2 R2 R1 L2 CIRCLE - else if (!_CHEATCMP("C2344321")) + else if ( !_CHEATCMP("C2344321") ) RainyWeatherCheat(); - + // "1234432X" - L1 L2 R1 R2 R2 R1 L2 CROSS - else if (!_CHEATCMP("X2344321")) + else if ( !_CHEATCMP("X2344321") ) FoggyWeatherCheat(); - + // "CCCCCC321TCT" - CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE - else if (!_CHEATCMP("TCT123CCCCCC")) + else if ( !_CHEATCMP("TCT123CCCCCC") ) VehicleCheat(true, MI_RHINO); - + // "CCCSSSSS1TCT" - CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE - else if (!_CHEATCMP("TCT1SSSSSCCC")) + else if ( !_CHEATCMP("TCT1SSSSSCCC") ) FastWeatherCheat(); - + // "241324TSCT21" - L2 R2 L1 R1 L2 R2 TRIANGLE SQUARE CIRCLE TRIANGLE L2 L1 - else if (!_CHEATCMP("12TCST423142")) + else if ( !_CHEATCMP("12TCST423142") ) BlowUpCarsCheat(); - + // "RDLU12ULDR" - RIGHT DOWN LEFT UP L1 L2 UP LEFT DOWN RIGHT - else if (!_CHEATCMP("RDLU21ULDR")) + else if ( !_CHEATCMP("RDLU21ULDR") ) ChangePlayerCheat(); - + // "DULUX3421" - DOWN UP LEFT UP CROSS R1 R2 L2 L1 - else if (!_CHEATCMP("1243XULUD")) + else if ( !_CHEATCMP("1243XULUD") ) MayhemCheat(); - + // "DULUX3412" - DOWN UP LEFT UP CROSS R1 R2 L1 L2 - else if (!_CHEATCMP("2143XULUD")) + else if ( !_CHEATCMP("2143XULUD") ) EverybodyAttacksPlayerCheat(); - + // "43TX21UD" - R2 R1 TRIANGLE CROSS L2 L1 UP DOWN - else if (!_CHEATCMP("DU12XT34")) + else if ( !_CHEATCMP("DU12XT34") ) WeaponsForAllCheat(); - + // "TURDS12" - TRIANGLE UP RIGHT DOWN SQUARE L1 L2 - else if (!_CHEATCMP("21SDRUT")) + else if ( !_CHEATCMP("21SDRUT") ) FastTimeCheat(); - + // "TURDS34" - TRIANGLE UP RIGHT DOWN SQUARE R1 R2 - else if (!_CHEATCMP("43SDRUT")) + else if ( !_CHEATCMP("43SDRUT") ) SlowTimeCheat(); // "11S4T1T" - L1 L1 SQUARE R2 TRIANGLE L1 TRIANGLE - else if (!_CHEATCMP("T1T4S11")) + else if ( !_CHEATCMP("T1T4S11") ) OnlyRenderWheelsCheat(); - + // "R4C32D13" - RIGHT R2 CIRCLE R1 L2 DOWN L1 R1 - else if (!_CHEATCMP("31D23C4R")) + else if ( !_CHEATCMP("31D23C4R") ) ChittyChittyBangBangCheat(); - + // "3141L33T" - R1 L1 R2 L1 LEFT R1 R1 TRIANGLE - else if (!_CHEATCMP("T33L1413")) + else if ( !_CHEATCMP("T33L1413") ) StrongGripCheat(); - + // "S1CD13TR1X" - SQUARE L1 CIRCLE DOWN L1 R1 TRIANGLE RIGHT L1 CROSS - else if (!_CHEATCMP("X1RT31DC1S")) + else if ( !_CHEATCMP("X1RT31DC1S") ) NastyLimbsCheat(); #undef _CHEATCMP } @@ -880,153 +879,153 @@ void CPad::AddToCheatString(char c) void CPad::AddToPCCheatString(char c) { - for (int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i--) + for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- ) KeyBoardCheatString[i + 1] = KeyBoardCheatString[i]; - + KeyBoardCheatString[0] = c; - -#define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) - + + #define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) + // "GUNSGUNSGUNS" - if (!_CHEATCMP("SNUGSNUGSNUG")) + if ( !_CHEATCMP("SNUGSNUGSNUG") ) WeaponCheat(); // "IFIWEREARICHMAN" - if (!_CHEATCMP("NAMHCIRAEREWIFI")) + if ( !_CHEATCMP("NAMHCIRAEREWIFI") ) MoneyCheat(); - + // "GESUNDHEIT" - if (!_CHEATCMP("TIEHDNUSEG")) + if ( !_CHEATCMP("TIEHDNUSEG") ) HealthCheat(); - + // "MOREPOLICEPLEASE" - if (!_CHEATCMP("ESAELPECILOPEROM")) + if ( !_CHEATCMP("ESAELPECILOPEROM") ) WantedLevelUpCheat(); - + // "NOPOLICEPLEASE" - if (!_CHEATCMP("ESAELPECILOPON")) + if ( !_CHEATCMP("ESAELPECILOPON") ) WantedLevelDownCheat(); // "PANZER" - if (!_CHEATCMP("REZNAP")) + if ( !_CHEATCMP("REZNAP") ) VehicleCheat(true, MI_RHINO); // "TRAVELINSTYLE" - if (!_CHEATCMP("ELYTSNILEVART")) + if ( !_CHEATCMP("ELYTSNILEVART") ) VehicleCheat(true, MI_BLOODRA); // "GETTHEREQUICKLY" - if (!_CHEATCMP("YLKCIUQEREHTTEG")) + if ( !_CHEATCMP("YLKCIUQEREHTTEG") ) VehicleCheat(true, MI_BLOODRB); // "GETTHEREFAST" - if (!_CHEATCMP("TSAFEREHTTEG")) + if ( !_CHEATCMP("TSAFEREHTTEG") ) VehicleCheat(true, MI_SABRETUR); // "GETTHEREVERYFASTINDEED" - if (!_CHEATCMP("DEEDNITSAFYREVEREHTTEG")) + if ( !_CHEATCMP("DEEDNITSAFYREVEREHTTEG") ) VehicleCheat(true, MI_HOTRINA); // "GETTHEREAMAZINGLYFAST" - if (!_CHEATCMP("TSAFYLGNIZAMAEREHTTEG")) + if ( !_CHEATCMP("TSAFYLGNIZAMAEREHTTEG") ) VehicleCheat(true, MI_HOTRINB); // "THELASTRIDE" - if (!_CHEATCMP("EDIRTSALEHT")) + if ( !_CHEATCMP("EDIRTSALEHT") ) VehicleCheat(true, MI_ROMERO); // "ROCKANDROLLCAR" - if (!_CHEATCMP("RACLLORDNAKCOR")) + if ( !_CHEATCMP("RACLLORDNAKCOR") ) VehicleCheat(true, MI_LOVEFIST); // "RUBBISHCAR" - if (!_CHEATCMP("RACHSIBBUR")) + if ( !_CHEATCMP("RACHSIBBUR") ) VehicleCheat(true, MI_TRASH); // "BETTERTHANWALKING" - if (!_CHEATCMP("GNIKLAWNAHTRETTEB")) + if ( !_CHEATCMP("GNIKLAWNAHTRETTEB") ) VehicleCheat(true, MI_CADDY); - + // "BANGBANGBANG" - if (!_CHEATCMP("GNABGNABGNAB")) + if ( !_CHEATCMP("GNABGNABGNAB") ) BlowUpCarsCheat(); - + // "ILIKEDRESSINGUP" - if (!_CHEATCMP("PUGNISSERDEKILI")) + if ( !_CHEATCMP("PUGNISSERDEKILI") ) ChangePlayerCheat(); - + // "ITSALLGOINGMAAAD" - if (!_CHEATCMP("DAAAMGNIOGLLASTI")) + if ( !_CHEATCMP("DAAAMGNIOGLLASTI") ) MayhemCheat(); - + // "NOBODYLIKESME" - if (!_CHEATCMP("EMSEKILYDOBON")) + if ( !_CHEATCMP("EMSEKILYDOBON") ) EverybodyAttacksPlayerCheat(); - + // "WEAPONSFORALL" - if (!_CHEATCMP("LLAROFSNOPAEW")) + if ( !_CHEATCMP("LLAROFSNOPAEW") ) WeaponsForAllCheat(); - + // "TIMEFLIESWHENYOU" - if (!_CHEATCMP("UOYNEHWSEILFEMIT")) + if ( !_CHEATCMP("UOYNEHWSEILFEMIT") ) FastTimeCheat(); - + // "BOOOOORING" - if (!_CHEATCMP("GNIROOOOOB")) + if ( !_CHEATCMP("GNIROOOOOB") ) SlowTimeCheat(); - + #ifndef GTA3_1_1_PATCH // "TURTOISE" - if (!_CHEATCMP("ESIOTRUT")) + if ( !_CHEATCMP("ESIOTRUT") ) ArmourCheat(); #else // "TORTOISE" - if (!_CHEATCMP("ESIOTROT")) + if ( !_CHEATCMP("ESIOTROT") ) ArmourCheat(); #endif - + // "SKINCANCERFORME" - if (!_CHEATCMP("EMROFRECNACNIKS")) + if ( !_CHEATCMP("EMROFRECNACNIKS") ) SunnyWeatherCheat(); - + // "ILIKESCOTLAND" - if (!_CHEATCMP("DNALTOCSEKILI")) + if ( !_CHEATCMP("DNALTOCSEKILI") ) CloudyWeatherCheat(); - + // "ILOVESCOTLAND" - if (!_CHEATCMP("DNALTOCSEVOLI")) + if ( !_CHEATCMP("DNALTOCSEVOLI") ) RainyWeatherCheat(); - + // "PEASOUP" - if (!_CHEATCMP("PUOSAEP")) + if ( !_CHEATCMP("PUOSAEP") ) FoggyWeatherCheat(); - + // "MADWEATHER" - if (!_CHEATCMP("REHTAEWDAM")) + if ( !_CHEATCMP("REHTAEWDAM") ) FastWeatherCheat(); - + // "ANICESETOFWHEELS" - if (!_CHEATCMP("SLEEHWFOTESECINA")) + if ( !_CHEATCMP("SLEEHWFOTESECINA") ) OnlyRenderWheelsCheat(); - + // "CHITTYCHITTYBB" - if (!_CHEATCMP("BBYTTIHCYTTIHC")) + if ( !_CHEATCMP("BBYTTIHCYTTIHC") ) ChittyChittyBangBangCheat(); - + // "CORNERSLIKEMAD" - if (!_CHEATCMP("DAMEKILSRENROC")) + if ( !_CHEATCMP("DAMEKILSRENROC") ) StrongGripCheat(); - + // "NASTYLIMBSCHEAT" - if (!_CHEATCMP("TAEHCSBMILYTSAN")) + if ( !_CHEATCMP("TAEHCSBMILYTSAN") ) NastyLimbsCheat(); // "IWANTITPAINTEDBLACK" - if (!_CHEATCMP("KCALBDETNIAPTITNAWI")) + if ( !_CHEATCMP("KCALBDETNIAPTITNAWI") ) BlackCarsCheat(); // "AHAIRDRESSERSCAR" - if (!_CHEATCMP("RACSRESSERDRIAHA")) + if ( !_CHEATCMP("RACSRESSERDRIAHA") ) PinkCarsCheat(); #ifdef KANGAROO_CHEAT @@ -1052,8 +1051,8 @@ void CPad::AddToPCCheatString(char c) if (!_CHEATCMP("ODODRETSAMOTTNAWI")) AltDodoCheat(); #endif - -#undef _CHEATCMP + + #undef _CHEATCMP } #ifdef XINPUT @@ -1103,7 +1102,7 @@ void CPad::AffectFromXinput(uint32 pad) uint16 iLeftMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff); uint16 iRightMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff); - + if (ShakeDur < CTimer::GetTimeStepInMilliseconds()) ShakeDur = 0; else @@ -1118,10 +1117,10 @@ void CPad::AffectFromXinput(uint32 pad) } #endif -void CPad::UpdatePads(void) +void CPad::UpdatePads(void) { bool bUpdate = true; - + GetPad(0)->UpdateMouse(); #ifdef XINPUT GetPad(0)->AffectFromXinput(0); @@ -1143,11 +1142,11 @@ void CPad::UpdatePads(void) if (IsAffectedByController && (GetPad(0)->PCTempKeyState.IsAnyButtonPressed() || GetPad(0)->PCTempMouseState.IsAnyButtonPressed())) IsAffectedByController = false; #endif - - if (CReplay::IsPlayingBackFromFile()) + + if ( CReplay::IsPlayingBackFromFile() ) bUpdate = false; - - if (bUpdate) + + if ( bUpdate ) { GetPad(0)->Update(0); GetPad(1)->Update(0); @@ -1157,7 +1156,7 @@ void CPad::UpdatePads(void) GetPad(1)->NewState.Clear(); GetPad(1)->OldState.Clear(); #endif - + OldKeyState = NewKeyState; NewKeyState = TempKeyState; } @@ -1170,7 +1169,7 @@ void CPad::ProcessPCSpecificStuff(void) void CPad::Update(int16 unk) { OldState = NewState; - + #if (defined GTA_PS2 || defined FIX_BUGS) if (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(unk)) #endif @@ -1182,16 +1181,16 @@ void CPad::Update(int16 unk) PCTempJoyState.Clear(); PCTempKeyState.Clear(); PCTempMouseState.Clear(); - + ProcessPCSpecificStuff(); - - if (++iCurrHornHistory >= HORNHISTORY_SIZE) + + if ( ++iCurrHornHistory >= HORNHISTORY_SIZE ) iCurrHornHistory = 0; bHornHistory[iCurrHornHistory] = GetHorn(); - if (!bDisplayNoControllerMessage) + if ( !bDisplayNoControllerMessage ) CGame::bDemoMode = false; } @@ -1206,40 +1205,40 @@ void CPad::DoCheats(void) void CPad::DoCheats(int16 unk) { #ifdef GTA_PS2_STUFF - if (GetTriangleJustDown()) + if ( GetTriangleJustDown() ) AddToCheatString('T'); - - if (GetCircleJustDown()) + + if ( GetCircleJustDown() ) AddToCheatString('C'); - - if (GetCrossJustDown()) + + if ( GetCrossJustDown() ) AddToCheatString('X'); - - if (GetSquareJustDown()) + + if ( GetSquareJustDown() ) AddToCheatString('S'); - - if (GetDPadUpJustDown()) + + if ( GetDPadUpJustDown() ) AddToCheatString('U'); - - if (GetDPadDownJustDown()) + + if ( GetDPadDownJustDown() ) AddToCheatString('D'); - - if (GetDPadLeftJustDown()) + + if ( GetDPadLeftJustDown() ) AddToCheatString('L'); - - if (GetDPadRightJustDown()) + + if ( GetDPadRightJustDown() ) AddToCheatString('R'); - - if (GetLeftShoulder1JustDown()) + + if ( GetLeftShoulder1JustDown() ) AddToCheatString('1'); - - if (GetLeftShoulder2JustDown()) + + if ( GetLeftShoulder2JustDown() ) AddToCheatString('2'); - - if (GetRightShoulder1JustDown()) + + if ( GetRightShoulder1JustDown() ) AddToCheatString('3'); - - if (GetRightShoulder2JustDown()) + + if ( GetRightShoulder2JustDown() ) AddToCheatString('4'); #endif } @@ -1254,7 +1253,7 @@ void CPad::StopShaking(int16 unk) ; } -CPad* CPad::GetPad(int32 pad) +CPad *CPad::GetPad(int32 pad) { return &Pads[pad]; } @@ -1267,188 +1266,188 @@ CPad* CPad::GetPad(int32 pad) int16 CPad::GetSteeringLeftRight(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickX; - int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; + case 0: + case 2: + { + int16 axis = NewState.LeftStickX; + int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; + + if ( Abs(axis) > Abs(dpad) ) + return axis; + else + return dpad; + + break; + } + + case 1: + case 3: + { + return NewState.LeftStickX; - if (Abs(axis) > Abs(dpad)) - return axis; - else - return dpad; - - break; + break; + } } - - case 1: - case 3: - { - return NewState.LeftStickX; - - break; - } - } - + return 0; } int16 CPad::GetSteeringUpDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; + case 0: + case 2: + { + int16 axis = NewState.LeftStickY; + int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; + + if ( Abs(axis) > Abs(dpad) ) + return axis; + else + return dpad; + + break; + } + + case 1: + case 3: + { + return NewState.LeftStickY; - if (Abs(axis) > Abs(dpad)) - return axis; - else - return dpad; - - break; + break; + } } - - case 1: - case 3: - { - return NewState.LeftStickY; - - break; - } - } - + return 0; } int16 CPad::GetCarGunUpDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return NewState.RightStickY; - - break; + case 0: + case 1: + case 2: + { + return NewState.RightStickY; + + break; + } + + case 3: + { + return (NewState.DPadUp - NewState.DPadDown) / 2; + + break; + } } - - case 3: - { - return (NewState.DPadUp - NewState.DPadDown) / 2; - - break; - } - } - + return 0; } int16 CPad::GetCarGunLeftRight(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return NewState.RightStickX; - - break; + case 0: + case 1: + case 2: + { + return NewState.RightStickX; + + break; + } + + case 3: + { + return (NewState.DPadRight - NewState.DPadLeft) / 2; + + break; + } } - - case 3: - { - return (NewState.DPadRight - NewState.DPadLeft) / 2; - - break; - } - } - + return 0; } int16 CPad::GetPedWalkLeftRight(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickX; - int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; + case 0: + case 2: + { + int16 axis = NewState.LeftStickX; + int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; + + if ( Abs(axis) > Abs(dpad) ) + return axis; + else + return dpad; + + break; + } + + case 1: + case 3: + { + return NewState.LeftStickX; - if (Abs(axis) > Abs(dpad)) - return axis; - else - return dpad; - - break; + break; + } } - - case 1: - case 3: - { - return NewState.LeftStickX; - - break; - } - } - + return 0; } int16 CPad::GetPedWalkUpDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; + case 0: + case 2: + { + int16 axis = NewState.LeftStickY; + int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; + + if ( Abs(axis) > Abs(dpad) ) + return axis; + else + return dpad; + + break; + } + + case 1: + case 3: + { + return NewState.LeftStickY; - if (Abs(axis) > Abs(dpad)) - return axis; - else - return dpad; - - break; + break; + } } - - case 1: - case 3: - { - return NewState.LeftStickY; - - break; - } - } - + return 0; } @@ -1456,43 +1455,43 @@ int16 CPad::GetAnalogueUpDown(void) { switch (CURMODE) { - case 0: - case 2: - { - int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; + case 0: + case 2: + { + int16 axis = NewState.LeftStickY; + int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; + + if ( Abs(axis) > Abs(dpad) ) + return axis; + else + return dpad; + + break; + } + + case 1: + case 3: + { + return NewState.LeftStickY; - if (Abs(axis) > Abs(dpad)) - return axis; - else - return dpad; - - break; + break; + } } - - case 1: - case 3: - { - return NewState.LeftStickY; - - break; - } - } - + return 0; } bool CPad::GetLookLeft(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.LeftShoulder2 && !NewState.RightShoulder2); } bool CPad::GetLookRight(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; return !!(NewState.RightShoulder2 && !NewState.LeftShoulder2); @@ -1501,7 +1500,7 @@ bool CPad::GetLookRight(void) bool CPad::GetLookBehindForCar(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; return !!(NewState.RightShoulder2 && NewState.LeftShoulder2); @@ -1509,7 +1508,7 @@ bool CPad::GetLookBehindForCar(void) bool CPad::GetLookBehindForPed(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; return !!NewState.RightShock; @@ -1517,363 +1516,363 @@ bool CPad::GetLookBehindForPed(void) bool CPad::GetHorn(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - { - return !!NewState.LeftShock; + case 0: + { + return !!NewState.LeftShock; - break; + break; + } + + case 1: + { + return !!NewState.LeftShoulder1; + + break; + } + + case 2: + { + return !!NewState.RightShoulder1; + + break; + } + + case 3: + { + return !!NewState.LeftShock; + + break; + } } - - case 1: - { - return !!NewState.LeftShoulder1; - - break; - } - - case 2: - { - return !!NewState.RightShoulder1; - - break; - } - - case 3: - { - return !!NewState.LeftShock; - - break; - } - } - + return false; } bool CPad::HornJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - { - return !!(NewState.LeftShock && !OldState.LeftShock); + case 0: + { + return !!(NewState.LeftShock && !OldState.LeftShock); - break; + break; + } + + case 1: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } + + case 2: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } + + case 3: + { + return !!(NewState.LeftShock && !OldState.LeftShock); + + break; + } } - - case 1: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } - - case 2: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } - - case 3: - { - return !!(NewState.LeftShock && !OldState.LeftShock); - - break; - } - } - + return false; } bool CPad::GetCarGunFired(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!NewState.Circle; + case 0: + case 1: + case 2: + { + return !!NewState.Circle; - break; + break; + } + + case 3: + { + return !!NewState.RightShoulder1; + + break; + } } - - case 3: - { - return !!NewState.RightShoulder1; - - break; - } - } - + return false; } bool CPad::CarGunJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!(NewState.Circle && !OldState.Circle); + case 0: + case 1: + case 2: + { + return !!(NewState.Circle && !OldState.Circle); - break; + break; + } + + case 3: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } } - - case 3: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } - } - + return false; } int16 CPad::GetHandBrake(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 1: - { - return NewState.RightShoulder1; - - break; + case 0: + case 1: + { + return NewState.RightShoulder1; + + break; + } + + case 2: + { + return NewState.Triangle; + + break; + } + + case 3: + { + return NewState.LeftShoulder1; + + break; + } } - - case 2: - { - return NewState.Triangle; - - break; - } - - case 3: - { - return NewState.LeftShoulder1; - - break; - } - } - + return 0; } int16 CPad::GetBrake(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 2: - { - return NewState.Square; + case 0: + case 2: + { + return NewState.Square; + + break; + } + + case 1: + { + return NewState.Square; - break; + break; + } + + case 3: + { + int16 axis = 2 * NewState.RightStickY; + + if ( axis < 0 ) + return 0; + else + return axis; + + break; + } } - - case 1: - { - return NewState.Square; - - break; - } - - case 3: - { - int16 axis = 2 * NewState.RightStickY; - - if (axis < 0) - return 0; - else - return axis; - - break; - } - } - + return 0; } bool CPad::GetExitVehicle(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Triangle; - - break; + case 0: + case 1: + case 3: + { + return !!NewState.Triangle; + + break; + } + + case 2: + { + return !!NewState.LeftShoulder1; + + break; + } } - - case 2: - { - return !!NewState.LeftShoulder1; - - break; - } - } - + return false; } bool CPad::ExitVehicleJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!(NewState.Triangle && !OldState.Triangle); - - break; + case 0: + case 1: + case 3: + { + return !!(NewState.Triangle && !OldState.Triangle); + + break; + } + + case 2: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } } - - case 2: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } - } - + return false; } int32 CPad::GetWeapon(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - { - return NewState.Circle; - - break; + case 0: + case 1: + { + return NewState.Circle; + + break; + } + + case 2: + { + return NewState.Cross; + + break; + } + + case 3: + { + return NewState.RightShoulder1; + + break; + } } - - case 2: - { - return NewState.Cross; - - break; - } - - case 3: - { - return NewState.RightShoulder1; - - break; - } - } - + return false; } bool CPad::WeaponJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - { - return !!(NewState.Circle && !OldState.Circle); - - break; + case 0: + case 1: + { + return !!(NewState.Circle && !OldState.Circle); + + break; + } + + case 2: + { + return !!(NewState.Cross && !OldState.Cross); + + break; + } + + case 3: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } } - - case 2: - { - return !!(NewState.Cross && !OldState.Cross); - - break; - } - - case 3: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; - } - } - + return false; } int16 CPad::GetAccelerate(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return 0; switch (CURMODE) { - case 0: - case 2: - { - return NewState.Cross; - - break; + case 0: + case 2: + { + return NewState.Cross; + + break; + } + + case 1: + { + return NewState.Cross; + + break; + } + + case 3: + { + int16 axis = -2 * NewState.RightStickY; + + if ( axis < 0 ) + return 0; + else + return axis; + + break; + } } - - case 1: - { - return NewState.Cross; - - break; - } - - case 3: - { - int16 axis = -2 * NewState.RightStickY; - - if (axis < 0) - return 0; - else - return axis; - - break; - } - } - + return 0; } @@ -1881,23 +1880,23 @@ bool CPad::CycleCameraModeUpJustDown(void) { switch (CURMODE) { - case 0: - case 2: - case 3: - { - return !!(NewState.Select && !OldState.Select); - - break; + case 0: + case 2: + case 3: + { + return !!(NewState.Select && !OldState.Select); + + break; + } + + case 1: + { + return !!(NewState.DPadUp && !OldState.DPadUp); + + break; + } } - - case 1: - { - return !!(NewState.DPadUp && !OldState.DPadUp); - - break; - } - } - + return false; } @@ -1905,77 +1904,77 @@ bool CPad::CycleCameraModeDownJustDown(void) { switch (CURMODE) { - case 0: - case 2: - case 3: - { - return false; - - break; + case 0: + case 2: + case 3: + { + return false; + + break; + } + + case 1: + { + return !!(NewState.DPadDown && !OldState.DPadDown); + + break; + } } - - case 1: - { - return !!(NewState.DPadDown && !OldState.DPadDown); - - break; - } - } - + return false; } bool CPad::ChangeStationJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; + case 0: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } + + case 1: + { + return !!(NewState.Select && !OldState.Select); + + break; + } + + case 2: + { + return !!(NewState.LeftShock && !OldState.LeftShock); + + break; + } + + case 3: + { + return !!(NewState.Circle && !OldState.Circle); + + break; + } } - - case 1: - { - return !!(NewState.Select && !OldState.Select); - - break; - } - - case 2: - { - return !!(NewState.LeftShock && !OldState.LeftShock); - - break; - } - - case 3: - { - return !!(NewState.Circle && !OldState.Circle); - - break; - } - } - + return false; } bool CPad::CycleWeaponLeftJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); } bool CPad::CycleWeaponRightJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); @@ -1983,96 +1982,96 @@ bool CPad::CycleWeaponRightJustDown(void) bool CPad::GetTarget(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!NewState.RightShoulder1; - - break; + case 0: + case 1: + case 2: + { + return !!NewState.RightShoulder1; + + break; + } + + case 3: + { + return !!NewState.LeftShoulder1; + + break; + } } - - case 3: - { - return !!NewState.LeftShoulder1; - - break; - } - } - + return false; } bool CPad::TargetJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 2: - { - return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); - - break; + case 0: + case 1: + case 2: + { + return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); + + break; + } + + case 3: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } } - - case 3: - { - return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); - - break; - } - } - + return false; } bool CPad::JumpJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.Square && !OldState.Square); } bool CPad::GetSprint(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Cross; - - break; + case 0: + case 1: + case 3: + { + return !!NewState.Cross; + + break; + } + + case 2: + { + return !!NewState.Circle; + + break; + } } - - case 2: - { - return !!NewState.Circle; - - break; - } - } - + return false; } bool CPad::ShiftTargetLeftJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); @@ -2080,7 +2079,7 @@ bool CPad::ShiftTargetLeftJustDown(void) bool CPad::ShiftTargetRightJustDown(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); @@ -2089,10 +2088,10 @@ bool CPad::ShiftTargetRightJustDown(void) bool CPad::GetAnaloguePadUp(void) { static int16 oldfStickY = 0; - + int16 Y = CPad::GetPad(0)->GetAnalogueUpDown(); - - if (Y < 0 && oldfStickY >= 0) + + if ( Y < 0 && oldfStickY >= 0 ) { oldfStickY = Y; return true; @@ -2107,10 +2106,10 @@ bool CPad::GetAnaloguePadUp(void) bool CPad::GetAnaloguePadDown(void) { static int16 oldfStickY = 0; - + int16 Y = CPad::GetPad(0)->GetAnalogueUpDown(); - - if (Y > 0 && oldfStickY <= 0) + + if ( Y > 0 && oldfStickY <= 0 ) { oldfStickY = Y; return true; @@ -2125,10 +2124,10 @@ bool CPad::GetAnaloguePadDown(void) bool CPad::GetAnaloguePadLeft(void) { static int16 oldfStickX = 0; - + int16 X = CPad::GetPad(0)->GetPedWalkLeftRight(); - - if (X < 0 && oldfStickX >= 0) + + if ( X < 0 && oldfStickX >= 0 ) { oldfStickX = X; return true; @@ -2143,10 +2142,10 @@ bool CPad::GetAnaloguePadLeft(void) bool CPad::GetAnaloguePadRight(void) { static int16 oldfStickX = 0; - + int16 X = CPad::GetPad(0)->GetPedWalkLeftRight(); - - if (X > 0 && oldfStickX <= 0) + + if ( X > 0 && oldfStickX <= 0 ) { oldfStickX = X; return true; @@ -2161,19 +2160,19 @@ bool CPad::GetAnaloguePadRight(void) bool CPad::GetAnaloguePadLeftJustUp(void) { static int16 oldfStickX = 0; - + int16 X = GetPad(0)->GetPedWalkLeftRight(); - - if (X == 0 && oldfStickX < 0) + + if ( X == 0 && oldfStickX < 0 ) { oldfStickX = X; - + return true; } else { oldfStickX = X; - + return false; } } @@ -2181,107 +2180,107 @@ bool CPad::GetAnaloguePadLeftJustUp(void) bool CPad::GetAnaloguePadRightJustUp(void) { static int16 oldfStickX = 0; - + int16 X = GetPad(0)->GetPedWalkLeftRight(); - - if (X == 0 && oldfStickX > 0) + + if ( X == 0 && oldfStickX > 0 ) { oldfStickX = X; - + return true; } else { oldfStickX = X; - + return false; } } bool CPad::ForceCameraBehindPlayer(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - { - return !!NewState.LeftShoulder1; - - break; + case 0: + case 1: + { + return !!NewState.LeftShoulder1; + + break; + } + + case 2: + { + return !!NewState.Triangle; + + break; + } + + case 3: + { + return !!NewState.Circle; + + break; + } } - - case 2: - { - return !!NewState.Triangle; - - break; - } - - case 3: - { - return !!NewState.Circle; - - break; - } - } - + return false; } bool CPad::SniperZoomIn(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Square; + case 0: + case 1: + case 3: + { + return !!NewState.Square; - break; + break; + } + + case 2: + { + return !!NewState.Triangle; + + break; + } } - - case 2: - { - return !!NewState.Triangle; - - break; - } - } - + return false; } bool CPad::SniperZoomOut(void) { - if (ArePlayerControlsDisabled()) + if ( ArePlayerControlsDisabled() ) return false; switch (CURMODE) { - case 0: - case 1: - case 3: - { - return !!NewState.Cross; + case 0: + case 1: + case 3: + { + return !!NewState.Cross; - break; + break; + } + + case 2: + { + return !!NewState.Square; + + break; + } } - - case 2: - { - return !!NewState.Square; - - break; - } - } - + return false; } @@ -2291,8 +2290,8 @@ int16 CPad::SniperModeLookLeftRight(void) { int16 axis = NewState.LeftStickX; int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - - if (Abs(axis) > Abs(dpad)) + + if ( Abs(axis) > Abs(dpad) ) return axis; else return dpad; @@ -2305,8 +2304,8 @@ int16 CPad::SniperModeLookUpDown(void) axis = -axis; #endif int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; - - if (Abs(axis) > Abs(dpad)) + + if ( Abs(axis) > Abs(dpad) ) return axis; else return dpad; @@ -2315,15 +2314,15 @@ int16 CPad::SniperModeLookUpDown(void) int16 CPad::LookAroundLeftRight(void) { float axis = GetPad(0)->NewState.RightStickX; + + if ( Abs(axis) > 85 && !GetLookBehindForPed() ) + return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) ) + * (127.0f / 32.0f) ); // 3.96875f - if (Abs(axis) > 85 && !GetLookBehindForPed()) - return (int16)((axis + ((axis > 0) ? -85 : 85)) - * (127.0f / 32.0f)); // 3.96875f - - else if (TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 10) - return (int16)((axis + ((axis > 0) ? -10 : 10)) - * (127.0f / 64.0f)); // 1.984375f - + else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 10 ) + return (int16) ( (axis + ( ( axis > 0 ) ? -10 : 10) ) + * (127.0f / 64.0f) ); // 1.984375f + return 0; } @@ -2335,13 +2334,13 @@ int16 CPad::LookAroundUpDown(void) axis = -axis; #endif - if (Abs(axis) > 85 && !GetLookBehindForPed()) - return (int16)((axis + ((axis > 0) ? -85 : 85)) - * (127.0f / 32.0f)); // 3.96875f + if ( Abs(axis) > 85 && !GetLookBehindForPed() ) + return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) ) + * (127.0f / 32.0f) ); // 3.96875f - else if (TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 40) - return (int16)((axis + ((axis > 0) ? -40 : 40)) - * (127.0f / 64.0f)); // 1.984375f + else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 40 ) + return (int16) ( (axis + ( ( axis > 0 ) ? -40 : 40) ) + * (127.0f / 64.0f) ); // 1.984375f return 0; } @@ -2355,7 +2354,7 @@ void CPad::ResetAverageWeapon(void) void CPad::PrintErrorMessage(void) { - if (bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive) + if ( bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive ) { CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); @@ -2367,12 +2366,12 @@ void CPad::PrintErrorMessage(void) CFont::SetFontStyle(FONT_BANK); CFont::PrintString ( - SCREEN_WIDTH / 2, + SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, TheText.Get("NOCONT") // Please reconnect an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). to controller port 1 to continue - ); + ); } - else if (bObsoleteControllerMessage) + else if ( bObsoleteControllerMessage ) { CFont::SetScale(0.85f, 1.0f); CFont::SetJustifyOff(); @@ -2384,31 +2383,31 @@ void CPad::PrintErrorMessage(void) CFont::SetFontStyle(FONT_BANK); CFont::PrintString ( - SCREEN_WIDTH / 2, + SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, TheText.Get("WRCONT") // The controller connected to controller port 1 is an unsupported controller. Grand Theft Auto III requires an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). - ); + ); } - + } void LittleTest(void) { static int32 Cunt = 0; - + Cunt++; // ??? } void CPad::ResetCheats(void) { CWeather::ReleaseWeather(); - + CPopulation::ms_bGivePedsWeapons = false; - + CPed::bNastyLimbsCheat = false; CPed::bPedCheat2 = false; CPed::bPedCheat3 = false; - + CVehicle::bWheelsOnlyCheat = false; CVehicle::bAllDodosCheat = false; CVehicle::bCheat3 = false; @@ -2416,210 +2415,210 @@ void CPad::ResetCheats(void) CVehicle::bCheat5 = false; gbBlackCars = false; gbPinkCars = false; - + gbFastTime = false; CTimer::SetTimeScale(1.0f); } -char* CPad::EditString(char* pStr, int32 nSize) +char *CPad::EditString(char *pStr, int32 nSize) { int32 pos = strlen(pStr); - + // letters - for (int32 i = 0; i < ('Z' - 'A' + 1); i++) + for ( int32 i = 0; i < ('Z' - 'A' + 1); i++ ) { - if (GetPad(0)->GetCharJustDown(i + 'A') && pos < nSize - 1) + if ( GetPad(0)->GetCharJustDown(i + 'A') && pos < nSize - 1 ) { pStr[pos++] = i + 'A'; pStr[pos] = '\0'; } - - if (GetPad(0)->GetCharJustDown(i + 'a') && pos < nSize - 1) + + if ( GetPad(0)->GetCharJustDown(i + 'a') && pos < nSize - 1 ) { pStr[pos++] = i + 'a'; pStr[pos] = '\0'; } } - + // numbers - for (int32 i = 0; i < ('9' - '0' + 1); i++) + for ( int32 i = 0; i < ('9' - '0' + 1); i++ ) { - if (GetPad(0)->GetCharJustDown(i + '0') && pos < nSize - 1) + if ( GetPad(0)->GetCharJustDown(i + '0') && pos < nSize - 1 ) { pStr[pos++] = i + '0'; pStr[pos] = '\0'; } } - + // space - if (GetPad(0)->GetCharJustDown(' ') && pos < nSize - 1) + if ( GetPad(0)->GetCharJustDown(' ') && pos < nSize - 1 ) { pStr[pos++] = ' '; pStr[pos] = '\0'; } - - + + // del - if (GetPad(0)->GetDeleteJustDown() || GetPad(0)->GetBackspaceJustDown()) + if ( GetPad(0)->GetDeleteJustDown() || GetPad(0)->GetBackspaceJustDown() ) { - if (pos > 0) + if ( pos > 0 ) pStr[pos - 1] = '\0'; } // extenter/up/down - if (GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown()) + if ( GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown() ) return nil; - + return pStr; } -int32* CPad::EditCodesForControls(int32* pRsKeys, int32 nSize) +int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize) { *pRsKeys = rsNULL; - for (int32 i = 0; i < 255; i++) + for ( int32 i = 0; i < 255; i++ ) { - if (GetPad(0)->GetCharJustDown(i)) + if ( GetPad(0)->GetCharJustDown(i) ) *pRsKeys = i; } - - for (int32 i = 0; i < 12; i++) + + for ( int32 i = 0; i < 12; i++ ) { - if (GetPad(0)->GetFJustDown(i)) + if ( GetPad(0)->GetFJustDown(i) ) *pRsKeys = i + rsF1; } - - if (GetPad(0)->GetEscapeJustDown()) + + if ( GetPad(0)->GetEscapeJustDown() ) *pRsKeys = rsESC; - - if (GetPad(0)->GetInsertJustDown()) + + if ( GetPad(0)->GetInsertJustDown() ) *pRsKeys = rsINS; - - if (GetPad(0)->GetDeleteJustDown()) + + if ( GetPad(0)->GetDeleteJustDown() ) *pRsKeys = rsDEL; - - if (GetPad(0)->GetHomeJustDown()) + + if ( GetPad(0)->GetHomeJustDown() ) *pRsKeys = rsHOME; - - if (GetPad(0)->GetEndJustDown()) + + if ( GetPad(0)->GetEndJustDown() ) *pRsKeys = rsEND; - - if (GetPad(0)->GetPageUpJustDown()) + + if ( GetPad(0)->GetPageUpJustDown() ) *pRsKeys = rsPGUP; - - if (GetPad(0)->GetPageDownJustDown()) + + if ( GetPad(0)->GetPageDownJustDown() ) *pRsKeys = rsPGDN; - - if (GetPad(0)->GetUpJustDown()) + + if ( GetPad(0)->GetUpJustDown() ) *pRsKeys = rsUP; - - if (GetPad(0)->GetDownJustDown()) + + if ( GetPad(0)->GetDownJustDown() ) *pRsKeys = rsDOWN; - - if (GetPad(0)->GetLeftJustDown()) + + if ( GetPad(0)->GetLeftJustDown() ) *pRsKeys = rsLEFT; - - if (GetPad(0)->GetRightJustDown()) + + if ( GetPad(0)->GetRightJustDown() ) *pRsKeys = rsRIGHT; - - if (GetPad(0)->GetScrollLockJustDown()) + + if ( GetPad(0)->GetScrollLockJustDown() ) *pRsKeys = rsSCROLL; - - if (GetPad(0)->GetPauseJustDown()) + + if ( GetPad(0)->GetPauseJustDown() ) *pRsKeys = rsPAUSE; - - if (GetPad(0)->GetNumLockJustDown()) + + if ( GetPad(0)->GetNumLockJustDown() ) *pRsKeys = rsNUMLOCK; - - if (GetPad(0)->GetDivideJustDown()) + + if ( GetPad(0)->GetDivideJustDown() ) *pRsKeys = rsDIVIDE; - - if (GetPad(0)->GetTimesJustDown()) + + if ( GetPad(0)->GetTimesJustDown() ) *pRsKeys = rsTIMES; - - if (GetPad(0)->GetMinusJustDown()) + + if ( GetPad(0)->GetMinusJustDown() ) *pRsKeys = rsMINUS; - - if (GetPad(0)->GetPlusJustDown()) + + if ( GetPad(0)->GetPlusJustDown() ) *pRsKeys = rsPLUS; - if (GetPad(0)->GetPadEnterJustDown()) + if ( GetPad(0)->GetPadEnterJustDown() ) *pRsKeys = rsPADENTER; - if (GetPad(0)->GetPadDelJustDown()) + if ( GetPad(0)->GetPadDelJustDown() ) *pRsKeys = rsPADDEL; - if (GetPad(0)->GetPad1JustDown()) + if ( GetPad(0)->GetPad1JustDown() ) *pRsKeys = rsPADEND; - - if (GetPad(0)->GetPad2JustDown()) + + if ( GetPad(0)->GetPad2JustDown() ) *pRsKeys = rsPADDOWN; - - if (GetPad(0)->GetPad3JustDown()) + + if ( GetPad(0)->GetPad3JustDown() ) *pRsKeys = rsPADPGDN; - - if (GetPad(0)->GetPad4JustDown()) + + if ( GetPad(0)->GetPad4JustDown() ) *pRsKeys = rsPADLEFT; - - if (GetPad(0)->GetPad5JustDown()) + + if ( GetPad(0)->GetPad5JustDown() ) *pRsKeys = rsPAD5; - - if (GetPad(0)->GetPad6JustDown()) + + if ( GetPad(0)->GetPad6JustDown() ) *pRsKeys = rsPADRIGHT; - - if (GetPad(0)->GetPad7JustDown()) + + if ( GetPad(0)->GetPad7JustDown() ) *pRsKeys = rsPADHOME; - - if (GetPad(0)->GetPad8JustDown()) + + if ( GetPad(0)->GetPad8JustDown() ) *pRsKeys = rsPADUP; - - if (GetPad(0)->GetPad9JustDown()) + + if ( GetPad(0)->GetPad9JustDown() ) *pRsKeys = rsPADPGUP; - - if (GetPad(0)->GetPad0JustDown()) + + if ( GetPad(0)->GetPad0JustDown() ) *pRsKeys = rsPADINS; - if (GetPad(0)->GetBackspaceJustDown()) + if ( GetPad(0)->GetBackspaceJustDown() ) *pRsKeys = rsBACKSP; - - if (GetPad(0)->GetTabJustDown()) + + if ( GetPad(0)->GetTabJustDown() ) *pRsKeys = rsTAB; - - if (GetPad(0)->GetCapsLockJustDown()) + + if ( GetPad(0)->GetCapsLockJustDown() ) *pRsKeys = rsCAPSLK; - - if (GetPad(0)->GetReturnJustDown()) + + if ( GetPad(0)->GetReturnJustDown() ) *pRsKeys = rsENTER; - - if (GetPad(0)->GetLeftShiftJustDown()) + + if ( GetPad(0)->GetLeftShiftJustDown() ) *pRsKeys = rsLSHIFT; - - if (GetPad(0)->GetShiftJustDown()) + + if ( GetPad(0)->GetShiftJustDown() ) *pRsKeys = rsSHIFT; - - if (GetPad(0)->GetRightShiftJustDown()) + + if ( GetPad(0)->GetRightShiftJustDown() ) *pRsKeys = rsRSHIFT; - - if (GetPad(0)->GetLeftCtrlJustDown()) + + if ( GetPad(0)->GetLeftCtrlJustDown() ) *pRsKeys = rsLCTRL; - - if (GetPad(0)->GetRightCtrlJustDown()) + + if ( GetPad(0)->GetRightCtrlJustDown() ) *pRsKeys = rsRCTRL; - - if (GetPad(0)->GetLeftAltJustDown()) + + if ( GetPad(0)->GetLeftAltJustDown() ) *pRsKeys = rsLALT; - - if (GetPad(0)->GetRightAltJustDown()) + + if ( GetPad(0)->GetRightAltJustDown() ) *pRsKeys = rsRALT; - - if (GetPad(0)->GetLeftWinJustDown()) + + if ( GetPad(0)->GetLeftWinJustDown() ) *pRsKeys = rsLWIN; - - if (GetPad(0)->GetRightWinJustDown()) + + if ( GetPad(0)->GetRightWinJustDown() ) *pRsKeys = rsRWIN; - - if (GetPad(0)->GetAppsJustDown()) + + if ( GetPad(0)->GetAppsJustDown() ) *pRsKeys = rsAPPS; - + return pRsKeys; } From e0345732c02ecaf329d13ac7dd005bcac7596bf7 Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 17:50:08 +0300 Subject: [PATCH 090/148] wasted/busted text color how did nobody change it yet --- src/render/Hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 4e12ceb5..ff2af2d7 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -38,7 +38,7 @@ CRGBA COUNTER_COLOR(97, 194, 247, 255); CRGBA PAGER_COLOR(32, 162, 66, 205); CRGBA RADARDISC_COLOR(255, 255, 255, 255); CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255); -CRGBA WASTEDBUSTED_COLOR(170, 123, 87, 255); +CRGBA WASTEDBUSTED_COLOR(255, 150, 225, 255); CRGBA ODDJOB_COLOR(89, 115, 150, 255); CRGBA ODDJOB2_COLOR(156, 91, 40, 255); CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); From 900d5a4ce0631c48ced4d7840a0fbd7c4688da18 Mon Sep 17 00:00:00 2001 From: Xinerki Date: Thu, 21 May 2020 21:48:39 +0300 Subject: [PATCH 091/148] focus loss improvement for u aap --- src/skel/win/win.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 8ae0ce6e..2e72f1a3 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1222,9 +1222,12 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) break; } - case 7: +#ifdef FIX_BUGS // game turns on menu when focus is re-gained rather than lost + case WM_KILLFOCUS: +#else + case WM_SETFOCUS: +#endif { - debug("ALT TABBED! CGame::InitAfterFocusLoss() \n"); CGame::InitAfterFocusLoss(); break; } From 864847a6fe5461581232a68b64d98dd15d035330 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 22 May 2020 02:42:04 +0300 Subject: [PATCH 092/148] new script commands - mostly stubs --- src/control/Script.cpp | 1193 ++++++++++++++++++++++++++++++++++--- src/control/Script.h | 2 + src/core/ColStore.cpp | 2 +- src/core/PlayerInfo.cpp | 5 +- src/core/PlayerInfo.h | 3 +- src/entities/Physical.cpp | 3 + src/entities/Physical.h | 3 + src/peds/Ped.cpp | 15 +- src/peds/Ped.h | 22 +- src/vehicles/CarGen.cpp | 3 +- src/vehicles/Vehicle.cpp | 3 + src/vehicles/Vehicle.h | 5 +- 12 files changed, 1156 insertions(+), 103 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index eb94918e..79917002 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -38,6 +38,7 @@ #include "Pad.h" #include "Particle.h" #include "ParticleObject.h" +#include "PedAttractor.h" #include "PedRoutes.h" #include "Phones.h" #include "Pickups.h" @@ -298,7 +299,7 @@ void CMissionCleanup::Process() //TODO(MIAMI): drunkenness, enable drive by //DMAudio::ShutUpPlayerTalking(0); CVehicle::bDisableRemoteDetonation = false; - //CVehicle::bDisableRemoteDetonationOnContact = false; // TODO(MIAMI) + CVehicle::bDisableRemoteDetonationOnContact = false; //CGameLogic::ClearShortCut(); // TODO(MIAMI) CTheScripts::RiotIntensity = 0; CTheScripts::StoreVehicleIndex = -1; @@ -1948,8 +1949,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) float radius = *(float*)&ScriptParams[4]; eMoveState state; switch (ScriptParams[5]) { - case 0: state = PEDMOVE_WALK; - case 1: state = PEDMOVE_SPRINT; + case 0: state = PEDMOVE_WALK; break; + case 1: state = PEDMOVE_SPRINT; break; default: assert(0); } ped->ClearAll(); @@ -8944,7 +8945,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CStats::SetTotalNumberKillFrenzies(ScriptParams[0]); return 0; case COMMAND_BLOW_UP_RC_BUGGY: - CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(); + CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(true); return 0; /* case COMMAND_REMOVE_CAR_FROM_CHASE: @@ -10463,8 +10464,23 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) return 0; } case COMMAND_GET_CHAR_WEAPON_IN_SLOT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + ScriptParams[0] = pPed->GetWeapon(ScriptParams[1]).m_eWeaponType; + ScriptParams[1] = pPed->GetWeapon(ScriptParams[1]).m_nAmmoTotal; + ScriptParams[2] = CPickups::ModelForWeapon((eWeaponType)ScriptParams[0]); + StoreParameters(&m_nIp, 3); + } case COMMAND_GET_CLOSEST_STRAIGHT_ROAD: - assert(0); + { + CollectParameters(&m_nIp, 5); + debug("GET_CLOSEST_STRAIGHT_ROAD not implemented!\n"); + for (int i = 0; i < 7; i++) + ScriptParams[i] = 0; + StoreParameters(&m_nIp, 7); // TODO(MIAMI) + } case COMMAND_SET_CAR_FORWARD_SPEED: { CollectParameters(&m_nIp, 2); @@ -10498,17 +10514,82 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) return 0; } case COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER: + { + CollectParameters(&m_nIp, 1); + CWorld::Players[ScriptParams[0]].m_nHavocLevel = 0; + return 0; + } case COMMAND_GET_HAVOC_CAUSED_BY_PLAYER: + { + CollectParameters(&m_nIp, 1); + ScriptParams[0] = CWorld::Players[ScriptParams[0]].m_nHavocLevel; + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_CREATE_SCRIPT_ROADBLOCK: + { + CollectParameters(&m_nIp, 6); + debug("CREATE_SCRIPT_ROADBLOCK not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS: + { + debug("CLEAR_ALL_SCRIPT_ROADBLOCKS not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR: - case COMMAND_IS_PICKUP_IN_ZONE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + assert(pTargetPed); + pPed->bScriptObjectiveCompleted = false; + pPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, pPed); + return 0; + } + //case COMMAND_IS_PICKUP_IN_ZONE: case COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS: + { + CollectParameters(&m_nIp, 4); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + CVector offset = pPed->GetMatrix() * *(CVector*)&ScriptParams[1]; + *(CVector*)&ScriptParams[0] = pPed->GetPosition() + offset; + StoreParameters(&m_nIp, 3); + return 0; + } case COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + bool result = false; + if (pPed->bHasBeenPhotographed) { + result = true; + pPed->bHasBeenPhotographed = false; + } + UpdateCompareFlag(result); + return 0; + } case COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + assert(pTargetPed); + pPed->bScriptObjectiveCompleted = false; + debug("SET_CHAR_OBJ_AIM_GUN_AT_CHAR is not implemented\n"); + //pPed->SetObjective(OBJECTIVE_AIM_GUN_AT_PED, pTargetPed); // TODO(MIAMI) -- when objective is implemented + return 0; + } case COMMAND_SWITCH_SECURITY_CAMERA: - case COMMAND_IS_CHAR_IN_FLYING_VEHICLE: - assert(0); + { + CollectParameters(&m_nIp, 1); + debug("SWITCH_SECURITY_CAMERA is not implemented\n"); // TODO(MIAMI) + } + //case COMMAND_IS_CHAR_IN_FLYING_VEHICLE: case COMMAND_IS_PLAYER_IN_FLYING_VEHICLE: { CollectParameters(&m_nIp, 1); @@ -10517,11 +10598,10 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) UpdateCompareFlag(pPed->bInVehicle && (pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)); return 0; } - case COMMAND_HAS_SONY_CD_BEEN_READ: - case COMMAND_GET_NUMBER_OF_SONY_CDS_READ: - case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD: - case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD: - assert(0); + //case COMMAND_HAS_SONY_CD_BEEN_READ: + //case COMMAND_GET_NUMBER_OF_SONY_CDS_READ: + //case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD: + //case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD: case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD: { CollectParameters(&m_nIp, 4); @@ -10541,26 +10621,132 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) return 0; case COMMAND_SET_HELI_ORIENTATION: + { + CollectParameters(&m_nIp, 2); + debug("SET_HELI_ORIENTATION is not implemented\n"); // TODO(MIAMI); + return 0; + } case COMMAND_CLEAR_HELI_ORIENTATION: + { + CollectParameters(&m_nIp, 1); + debug("SET_HELI_ORIENTATION is not implemented\n"); // TODO(MIAMI); + return 0; + } case COMMAND_PLANE_GOTO_COORDS: + { + CollectParameters(&m_nIp, 5); + debug("PLANE_GOTO_COORS is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_GET_NTH_CLOSEST_CAR_NODE: - case COMMAND_GET_NTH_CLOSEST_CHAR_NODE: + { + CollectParameters(&m_nIp, 4); + debug("GET_NTH_CLOSEST_CAR_NODE is not implemented\n"); // TODO(MIAMI) + ScriptParams[0] = 0; + StoreParameters(&m_nIp, 1); + return 0; + } + //case COMMAND_GET_NTH_CLOSEST_CHAR_NODE: case COMMAND_DRAW_WEAPONSHOP_CORONA: + { + CollectParameters(&m_nIp, 9); + CVector pos = *(CVector*)&ScriptParams[0]; + if (pos.z <= MAP_Z_LOW_LIMIT) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CCoronas::RegisterCorona((uint32)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], 255, pos, *(float*)&ScriptParams[3], + 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f, false, 0.2f); + return 0; + } case COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT: + { + CollectParameters(&m_nIp, 1); + CVehicle::bDisableRemoteDetonationOnContact = (ScriptParams[0] == 0); + return 0; + } case COMMAND_FREEZE_CHAR_POSITION: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bIsFrozen = ScriptParams[1]; + return 0; + } case COMMAND_SET_CHAR_DROWNS_IN_WATER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bDrownsInWater = ScriptParams[1]; + return 0; + } case COMMAND_SET_OBJECT_RECORDS_COLLISIONS: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + pObject->bUseCollisionRecords = ScriptParams[1]; + return 0; + } case COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + UpdateCompareFlag(pObject->m_nCollisionRecords != 0); + return 0; + } case COMMAND_REMOVE_RC_BUGGY: - case COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN: + { + CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(false); + return 0; + } + //case COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN: case COMMAND_GET_CHAR_ARMOUR: - case COMMAND_SET_CHAR_ARMOUR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + ScriptParams[0] = pPed->m_fArmour; + StoreParameters(&m_nIp, 1); + return 0; + } + //case COMMAND_SET_CHAR_ARMOUR: case COMMAND_SET_HELI_STABILISER: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + pVehicle->bHeliMinimumTilt = ScriptParams[1]; + return 0; + } case COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + pVehicle->AutoPilot.m_nSwitchDistance = ScriptParams[1]; + return 0; + } case COMMAND_POP_CAR_BOOT: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + debug("POP_CAR_BOOT is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SHUT_PLAYER_UP: + { + CollectParameters(&m_nIp, 2); + debug("SHUT_PLAYER_UP is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SET_PLAYER_MOOD: - assert(0); + { + CollectParameters(&m_nIp, 3); + debug("SET_PLAYER_MOOD is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_REQUEST_COLLISION: { CollectParameters(&m_nIp, 2); @@ -10572,12 +10758,36 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) } case COMMAND_LOCATE_OBJECT_2D: case COMMAND_LOCATE_OBJECT_3D: + LocateObjectCommand(command, &m_nIp); + return 0; case COMMAND_IS_OBJECT_IN_WATER: - case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + UpdateCompareFlag(pObject->bIsInWater); + return 0; + } + //case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR: case COMMAND_IS_OBJECT_IN_AREA_2D: case COMMAND_IS_OBJECT_IN_AREA_3D: + ObjectInAreaCheckCommand(command, &m_nIp); + return 0; case COMMAND_TASK_TOGGLE_DUCK: - assert(0); + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + if (ScriptParams[1]) { + pPed->bIsDucking = true; + pPed->SetDuck(ScriptParams[2], true); + } + else { + pPed->ClearDuck(true); + pPed->bIsDucking = false; + } + return 0; + } case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO: { char label[12]; @@ -10604,17 +10814,88 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) return 0; } case COMMAND_REQUEST_ANIMATION: + { + char key[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CStreaming::RequestAnim(CAnimManager::GetAnimationBlockIndex(key), STREAMFLAGS_SCRIPTOWNED); + return 0; + } case COMMAND_HAS_ANIMATION_LOADED: + { + char key[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + UpdateCompareFlag(CAnimManager::GetAnimationBlock(key)->isLoaded); + return 0; + } case COMMAND_REMOVE_ANIMATION: + { + char key[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CStreaming::RemoveAnim(CAnimManager::GetAnimationBlockIndex(key)); + return 0; + } case COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bIsStaticWaitingForCollision); + return 0; + } case COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + UpdateCompareFlag(pVehicle->bIsStaticWaitingForCollision); + return 0; + } case COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION: + { + CollectParameters(&m_nIp, 1); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + UpdateCompareFlag(pObject->bIsStaticWaitingForCollision); + return 0; + } case COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + debug("SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT is not implemented\n"); + return 0; + } case COMMAND_ATTACH_CHAR_TO_OBJECT: + { + CollectParameters(&m_nIp, 8); + debug("ATTACH_CHAR_TO_OBJECT is not implemented\n"); + return 0; + } case COMMAND_SET_CHAR_AS_PLAYER_FRIEND: - case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bIsPlayerFriend = ScriptParams[2]; + return 0; + } + //case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER: case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING: - assert(0); + { + char onscreen_str[12]; + assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR); + int16 var = CTheScripts::Read2BytesFromScript(&m_nIp); + CollectParameters(&m_nIp, 2); + wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ??? + strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT); + m_nIp += KEY_LENGTH_IN_SCRIPT; + CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str, ScriptParams[1] - 1); + return 0; + } case COMMAND_ADD_SET_PIECE: { CollectParameters(&m_nIp, 13); @@ -10633,8 +10914,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) debug("CLEAR_EXTRA_COLOURS not implemented, skipping\n"); return 0; } - case COMMAND_CLOSE_CAR_BOOT: - assert(0); + //case COMMAND_CLOSE_CAR_BOOT: case COMMAND_GET_WHEELIE_STATS: { CollectParameters(&m_nIp, 1); @@ -10648,29 +10928,146 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) StoreParameters(&m_nIp, 6); return 0; } - case COMMAND_DISARM_CHAR: + //case COMMAND_DISARM_CHAR: case COMMAND_BURST_CAR_TYRE: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + if (pVehicle->IsBike()) { + if (ScriptParams[1] == 2) + ScriptParams[1] = 0; + else if (ScriptParams[1] == 3) + ScriptParams[1] = 1; + pVehicle->BurstTyre(ScriptParams[1]); // TODO(MIAMI): second param is true + } + else { + pVehicle->BurstTyre(ScriptParams[1]); // TODO(MIAMI): second param is true + } + return 0; + } case COMMAND_IS_CHAR_OBJ_NO_OBJ: + { + CollectParameters(&m_nIp, 1); + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->m_prevObjective == OBJECTIVE_NONE && pPed->m_objective == OBJECTIVE_NONE); + return 0; + } case COMMAND_IS_PLAYER_WEARING: + { + CollectParameters(&m_nIp, 1); + char key[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++) + key[i] = tolower(key[i]); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + UpdateCompareFlag(strcmp(key, CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetName()) == 0); + return 0; + } case COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY: + { + CollectParameters(&m_nIp, 2); + CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; + pPlayerInfo->m_bDriveByAllowed = ScriptParams[1]; + return 0; + } case COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD: + { + CollectParameters(&m_nIp, 3); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + CVector pos; + pos.x = *(float*)&ScriptParams[1]; + pos.y = *(float*)&ScriptParams[2]; + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pPed->bScriptObjectiveCompleted = false; + debug("SET_CHAR_OBJ_SPRINT_TO_COORD is not implemented\n"); + //pPed->SetObjective(OBJECTIVE_SPRINT_TO_COORD, pos); // TODO(MIAMI) -- when objective is implemented + return 0; + } case COMMAND_CREATE_SWAT_ROPE: - case COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA: - case COMMAND_GET_NEAREST_TYRE_TO_POINT: + { + CollectParameters(&m_nIp, 3); + debug("SET_CHAR_OBJ_SPRINT_TO_COORD is not implemented\n"); + return 0; + } + //case COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA: + //case COMMAND_GET_NEAREST_TYRE_TO_POINT: case COMMAND_SET_CAR_MODEL_COMPONENTS: + { + CollectParameters(&m_nIp, 3); + CVehicleModelInfo::SetComponentsToUse(ScriptParams[1], ScriptParams[2]); + return 0; + } case COMMAND_SWITCH_LIFT_CAMERA: + { + CollectParameters(&m_nIp, 1); + debug("SWITCH_LIFT_CAMERA is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_CLOSE_ALL_CAR_DOORS: + { + CollectParameters(&m_nIp, 1); + debug("CLOSE_ALL_CAR_DOORS is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D: + { + CollectParameters(&m_nIp, 4); + *(float*)&ScriptParams[0] = (*(CVector2D*)&ScriptParams[0] - *(CVector2D*)&ScriptParams[2]).Magnitude(); + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D: + { + CollectParameters(&m_nIp, 6); + *(float*)&ScriptParams[0] = (*(CVector*)&ScriptParams[0] - *(CVector*)&ScriptParams[3]).Magnitude(); + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_POP_CAR_BOOT_USING_PHYSICS: - case COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA: + { + CollectParameters(&m_nIp, 1); + debug("POP_CAR_BOOT_USING_PHYSICS is not implemented\n"); // TODO(MIAMI) + return 0; + } + //case COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA: case COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE); + return 0; + } case COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR: - case COMMAND_GET_MAX_WANTED_LEVEL: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + pObject->m_pCollidingEntity = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + return 0; + } + //case COMMAND_GET_MAX_WANTED_LEVEL: case COMMAND_IS_CHAR_WANDER_PATH_CLEAR: - case COMMAND_PRINT_HELP_WITH_NUMBER: + { + CollectParameters(&m_nIp, 5); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(CWorld::IsWanderPathClear(pPed->GetPosition(), *(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3], 4)); + return 0; + } + //case COMMAND_PRINT_HELP_WITH_NUMBER: case COMMAND_PRINT_HELP_FOREVER: - case COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CHud::SetHelpMessage(text, false); // TODO(MIAMI): third param is true + return 0; + } + //case COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER: default: assert(0); } @@ -10683,7 +11080,8 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG: { CollectParameters(&m_nIp, 3); - CPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pTarget); uint8 flag = 1 << (uint8)ScriptParams[1]; if (ScriptParams[2]) pTarget->m_gangFlags |= flag; @@ -10693,8 +11091,8 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE: - case COMMAND_IS_MISSION_AUDIO_PLAYING: - assert(0); + return 0; + //case COMMAND_IS_MISSION_AUDIO_PLAYING: case COMMAND_CREATE_LOCKED_PROPERTY_PICKUP: { CollectParameters(&m_nIp, 3); @@ -10722,67 +11120,266 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_FREEZE_CAR_POSITION: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + pVehicle->bIsFrozen = ScriptParams[1]; + return 0; + } case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR: - case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR: - case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR: - case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR: - case COMMAND_GET_RADIO_CHANNEL: - case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS: - case COMMAND_IS_CAR_DROWNING_IN_WATER: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); + bool result = false; + if (pPed) { + if (pPed->m_lastDamEntity) { + if (pPed->m_lastDamEntity == pTestedPed) + result = true; + if (pTestedPed->bInVehicle && pPed->m_lastDamEntity == pTestedPed->m_pMyVehicle) + result = true; + } + }else + debug("HAS_CHAR_BEEN_DAMAGED_BY_CHAR - First character doesn't exist\n"); + UpdateCompareFlag(result); + return 0; + } + //case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR: + //case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR: + //case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR: + //case COMMAND_GET_RADIO_CHANNEL: + //case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS: + //case COMMAND_IS_CAR_DROWNING_IN_WATER: case COMMAND_IS_CHAR_DROWNING_IN_WATER: - assert(0); + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(pPed && pPed->bIsDrowning); + return 0; + } case COMMAND_DISABLE_CUTSCENE_SHADOWS: { - debug("DISABLE_CUTSCENE_SHADOWS not implemented, skipping\n"); + debug("DISABLE_CUTSCENE_SHADOWS not implemented, skipping\n"); // TODO(MIAMI) return 0; } case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY: + { + CollectParameters(&m_nIp, 3); + static bool bShowed = false; + if (!bShowed) { + debug("HAS_GLASS_BEEN_SHATTERED_NEARBY not implemented, default to TRUE\n"); // TODO(MIAMI) + bShowed = true; + } + UpdateCompareFlag(true); + return 0; + } case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE: + { + CollectParameters(&m_nIp, 3); + debug("ATTACH_CUTSCENE_OBJECT_TO_BONE not implemented, skipping\n"); // TODO(MIAMI) + return 0; + } case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT: + { + CollectParameters(&m_nIp, 2); + debug("ATTACH_CUTSCENE_OBJECT_TO_COMPONENT not implemented, skipping\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED: - case COMMAND_IS_MISSION_AUDIO_LOADING: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bStayInCarOnJack = ScriptParams[1]; + return 0; + } + //case COMMAND_IS_MISSION_AUDIO_LOADING: case COMMAND_ADD_MONEY_SPENT_ON_WEAPONS: + CollectParameters(&m_nIp, 1); + debug("ADD_MONEY_SPENT_ON_WEAPON not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_ADD_MONEY_SPENT_ON_PROPERTY: - case COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING: + CollectParameters(&m_nIp, 1); + debug("ADD_MONEY_SPENT_ON_PROPERTY not implemented\n"); // TODO(MIAMI) + return 0; + //case COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING: case COMMAND_SET_CHAR_ANSWERING_MOBILE: + { + CollectParameters(&m_nIp, 2); + debug("SET_CHAR_ANSWERING_MOBILE not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SET_PLAYER_DRUNKENNESS: - case COMMAND_GET_PLAYER_DRUNKENNESS: - case COMMAND_SET_PLAYER_DRUG_LEVEL: - case COMMAND_GET_PLAYER_DRUG_LEVEL: - case COMMAND_ADD_LOAN_SHARK_VISITS: + { + CollectParameters(&m_nIp, 2); + debug("SET_PLAYER_DRUNKENNESS not implemented\n"); // TODO(MIAMI) + return 0; + } + //case COMMAND_GET_PLAYER_DRUNKENNESS: + //case COMMAND_SET_PLAYER_DRUG_LEVEL: + //case COMMAND_GET_PLAYER_DRUG_LEVEL: + //case COMMAND_ADD_LOAN_SHARK_VISITS: case COMMAND_ADD_STORES_KNOCKED_OFF: - case COMMAND_ADD_MOVIE_STUNTS: + CollectParameters(&m_nIp, 1); + debug("ADD_STORES_KNOCKED_OFF not implemented\n"); // TODO(MIAMI) + return 0; + //case COMMAND_ADD_MOVIE_STUNTS: case COMMAND_ADD_NUMBER_OF_ASSASSINATIONS: + CollectParameters(&m_nIp, 1); + debug("ADD_NUMBER_OF_ASSASSINATIONS not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_ADD_PIZZAS_DELIVERED: - case COMMAND_ADD_GARBAGE_PICKUPS: + CollectParameters(&m_nIp, 1); + debug("ADD_PIZZAS_DELIVERED not implemented\n"); // TODO(MIAMI) + return 0; + //case COMMAND_ADD_GARBAGE_PICKUPS: case COMMAND_ADD_ICE_CREAMS_SOLD: - case COMMAND_SET_TOP_SHOOTING_RANGE_SCORE: - case COMMAND_ADD_SHOOTING_RANGE_RANK: - case COMMAND_ADD_MONEY_SPENT_ON_GAMBLING: - case COMMAND_ADD_MONEY_WON_ON_GAMBLING: - case COMMAND_SET_LARGEST_GAMBLING_WIN: + CollectParameters(&m_nIp, 1); + debug("ADD_ICE_CREAMS_SOLD not implemented\n"); // TODO(MIAMI) + return 0; + //case COMMAND_SET_TOP_SHOOTING_RANGE_SCORE: + //case COMMAND_ADD_SHOOTING_RANGE_RANK: + //case COMMAND_ADD_MONEY_SPENT_ON_GAMBLING: + //case COMMAND_ADD_MONEY_WON_ON_GAMBLING: + //case COMMAND_SET_LARGEST_GAMBLING_WIN: case COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bDontFight = !ScriptParams[1]; + return 0; + } case COMMAND_CLEAR_CHAR_WAIT_STATE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->ClearWaitState(); + } case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE: + { + CollectParameters(&m_nIp, 5); + int handle = -1; + uint32 i = CPools::GetVehiclePool()->GetSize(); + float infX = *(float*)&ScriptParams[0]; + float infY = *(float*)&ScriptParams[1]; + float supX = *(float*)&ScriptParams[2]; + float supY = *(float*)&ScriptParams[3]; + while (i--) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (!pVehicle) + continue; + if (pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR && pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE) + continue; + if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0) + continue; + if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) + continue; + if (!pVehicle->IsWithinArea(infX, infY, supX, supY)) + continue; + handle = CPools::GetVehiclePool()->GetIndex(pVehicle); + } + ScriptParams[0] = handle; + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_SET_CAN_BURST_CAR_TYRES: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + pVehicle->bTyresDontBurst = !ScriptParams[1]; + return 0; + } case COMMAND_SET_PLAYER_AUTO_AIM: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + pPed->bDoomAim = ScriptParams[1]; + } case COMMAND_FIRE_HUNTER_GUN: + { + CollectParameters(&m_nIp, 1); + debug("FIRE_HUNTER_GUN is not implemented, skipping\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SET_PROPERTY_AS_OWNED: + CollectParameters(&m_nIp, 1); + debug("SET_PROPERTY_AS_OWNED not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_ADD_BLOOD_RING_KILLS: + CollectParameters(&m_nIp, 1); + debug("ADD_BLOOD_RING_KILLS not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING: - assert(0); + CollectParameters(&m_nIp, 1); + debug("SET_LONGEST_TIME_IN_BLOOD_RING not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE: { debug("REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE not implemented, skipping\n"); return 0; } case COMMAND_IS_PLAYER_TOUCHING_VEHICLE: - case COMMAND_IS_CHAR_TOUCHING_VEHICLE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + CPhysical* pTestedEntity = pPed; + if (pPed->bInVehicle && pPed->m_pMyVehicle) + pTestedEntity = pPed->m_pMyVehicle; + UpdateCompareFlag(pTestedEntity->GetHasCollidedWith(pVehicle)); + return 0; + } + //case COMMAND_IS_CHAR_TOUCHING_VEHICLE: case COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER: + { + CollectParameters(&m_nIp, 6); + CVector d1 = CWorld::Players[ScriptParams[0]].GetPos() - *(CVector*)&ScriptParams[1]; + CVector d2 = CWorld::Players[ScriptParams[0]].GetPos() + *(CVector*)&ScriptParams[1]; + int i = CPools::GetPedPool()->GetSize(); + bool result = false; + while (i--) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (ScriptParams[4] != pPed->GetModelIndex() && ScriptParams[5] != pPed->GetModelIndex()) + continue; + if (pPed->IsWithinArea(d1.x, d1.y, d1.z, d2.x, d2.y, d2.z)) + result = true; + } + UpdateCompareFlag(result); + return 0; + } case COMMAND_CLEAR_CHAR_FOLLOW_PATH: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + if (pPed->GetPedState() == PED_FOLLOW_PATH) { + pPed->RestorePreviousState(); + pPed->ClearFollowPath(); + } + return 0; + } case COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + pPed->bCanBeShotInVehicle = ScriptParams[1]; + return 0; + } case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE: - assert(0); + { + CollectParameters(&m_nIp, 2); + debug("ATTACH_CUTSCENE_OBJECT_TO_VEHICLE not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_LOAD_MISSION_TEXT: { char key[8]; @@ -10794,23 +11391,57 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_SET_TONIGHTS_EVENT: { CollectParameters(&m_nIp, 1); - debug("skipping SET_TONIGHTS_EVENT\n"); + debug("skipping SET_TONIGHTS_EVENT\n"); // TODO(MIAMI) return 0; } case COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY: - case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + if (pPed) + pPed->m_lastDamEntity = nil; + else + debug("CLEAR_CHAR_LAST_DAMAGE_ENTITY - Character doesn't exist\n"); + return 0; + } + //case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY: case COMMAND_FREEZE_OBJECT_POSITION: + { + CollectParameters(&m_nIp, 2); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + pObject->bIsFrozen = ScriptParams[1]; + return 0; + } case COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY: + { + CollectParameters(&m_nIp, 1); + CTheScripts::bPlayerHasMetDebbieHarry = ScriptParams[0]; + return 0; + } case COMMAND_SET_RIOT_INTENSITY: - case COMMAND_IS_CAR_IN_ANGLED_AREA_2D: - case COMMAND_IS_CAR_IN_ANGLED_AREA_3D: - case COMMAND_REMOVE_WEAPON_FROM_CHAR: + { + CollectParameters(&m_nIp, 1); + CTheScripts::RiotIntensity = ScriptParams[0]; + return 0; + } + //case COMMAND_IS_CAR_IN_ANGLED_AREA_2D: + //case COMMAND_IS_CAR_IN_ANGLED_AREA_3D: + //case COMMAND_REMOVE_WEAPON_FROM_CHAR: case COMMAND_SET_UP_TAXI_SHORTCUT: + { + CollectParameters(&m_nIp, 8); + debug("SET_UP_TAXI_SHORTCUT is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_CLEAR_TAXI_SHORTCUT: - case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT: - case COMMAND_GET_CLOSEST_WATER_NODE: + debug("CLEAR_TAXI_SHORTCUT is not implemented\n"); // TODO(MIAMI) + return 0; + //case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT: + //case COMMAND_GET_CLOSEST_WATER_NODE: case COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH: - assert(0); + debug("ADD_PORN_LEAFLET_TO_RUBBISH is not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_CREATE_CLOTHES_PICKUP: { CollectParameters(&m_nIp, 4); @@ -10822,8 +11453,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) StoreParameters(&m_nIp, 1); return 0; } - case COMMAND_CHANGE_BLIP_THRESHOLD: - assert(0); + //case COMMAND_CHANGE_BLIP_THRESHOLD: case COMMAND_MAKE_PLAYER_FIRE_PROOF: { CollectParameters(&m_nIp, 2); @@ -10909,10 +11539,44 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + pPed->bIgnoreThreatsBehindObjects = ScriptParams[1]; + return 0; + } case COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + assert(pPed); + if (pPed->bInVehicle) { + if (pPed->GetWeapon(5).m_eWeaponType) { // TODO(MIAMI): enum + if (pPed->GetWeapon(5).m_nAmmoTotal < ScriptParams[1]) + pPed->SetAmmo(pPed->GetWeapon(5).m_eWeaponType, ScriptParams[1]); + } + else { + pPed->GiveWeapon(WEAPONTYPE_UZI, ScriptParams[1], true); + if (pPed->m_storedWeapon == WEAPONTYPE_UNIDENTIFIED) + pPed->m_storedWeapon = pPed->GetWeapon()->m_eWeaponType; + pPed->SetCurrentWeapon(WEAPONTYPE_UZI); + } + } + return 0; + } case COMMAND_MAKE_HELI_COME_CRASHING_DOWN: + { + CollectParameters(&m_nIp, 1); + debug("MAKE_HELI_COME_CRASHING_DOWN is not implemented\n"); + return 0; + } case COMMAND_ADD_EXPLOSION_NO_SOUND: - assert(0); + { + CollectParameters(&m_nIp, 4); + CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0); // TODO(MIAMI): last arg is 0 + return 0; + } case COMMAND_SET_OBJECT_AREA_VISIBLE: { CollectParameters(&m_nIp, 2); @@ -10921,10 +11585,23 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) pObject->m_area = ScriptParams[1]; return 0; } - case COMMAND_WAS_VEHICLE_EVER_POLICE: + //case COMMAND_WAS_VEHICLE_EVER_POLICE: case COMMAND_SET_CHAR_NEVER_TARGETTED: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bNeverEverTargetThisPed = ScriptParams[1]; + return 0; + } case COMMAND_LOAD_UNCOMPRESSED_ANIM: - assert(0); + { + char key[KEY_LENGTH_IN_SCRIPT]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, key); + m_nIp += KEY_LENGTH_IN_SCRIPT; + debug("LOAD_UNCOMPRESSED_ANIM not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_WAS_CUTSCENE_SKIPPED: { static bool bShowed = false; @@ -10954,9 +11631,11 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_DOES_CHAR_EXIST: - case COMMAND_DOES_VEHICLE_EXIST: - case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT: - assert(0); + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CPools::GetPedPool()->GetAt(ScriptParams[0]) != 0); + return 0; + //case COMMAND_DOES_VEHICLE_EXIST: + //case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT: case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT: { CollectParameters(&m_nIp, 4); @@ -10971,12 +11650,55 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) return 0; } case COMMAND_IS_CHAR_STUCK: + { + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->m_nWaitState == WAITSTATE_STUCK); + } case COMMAND_SET_ALL_TAXIS_HAVE_NITRO: + { + CollectParameters(&m_nIp, 1); + debug("SET_ALL_TAXIS_HAVE_NITRO is not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + if (ScriptParams[1]) { + pPed->bKindaStayInSamePlace = true; + pPed->bStopAndShoot = true; + } + else { + pPed->bKindaStayInSamePlace = false; + pPed->bStopAndShoot = false; + } + pPed->m_nLastPedState = PED_NONE; + } case COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION: - case COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION: - case COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION: - case COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + if (ScriptParams[1]) { + pVehicle->bIsFrozen = true; + pVehicle->bInfiniteMass = true; + if (m_bIsMissionScript) { + CWorld::Remove(pVehicle); + pVehicle->bIsStaticWaitingForCollision = true; + CWorld::Add(pVehicle); + } + } + else { + pVehicle->bIsFrozen = false; + pVehicle->bInfiniteMass = false; + } + return 0; + } + //case COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION: + //case COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION: + //case COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION: default: assert(0); } @@ -10987,8 +11709,31 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) { switch (command) { case COMMAND_REGISTER_VIGILANTE_LEVEL: + CollectParameters(&m_nIp, 1); + debug("REGISTER_VIGILANTE_LEVEL not implemented\n"); // TODO(MIAMI) case COMMAND_CLEAR_ALL_CHAR_ANIMS: - assert(0); + { + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + if (!pPed->bInVehicle) { + pPed->m_pVehicleAnim = nil; + pPed->RestartNonPartialAnims(); + RpAnimBlendClumpRemoveAllAssociations(pPed->GetClump()); + pPed->SetPedState(PED_IDLE); + pPed->SetMoveState(PEDMOVE_STILL); + pPed->m_nLastPedState = PED_NONE; + pPed->ClearAimFlag(); + pPed->ClearLookFlag(); + pPed->bIsPointingGunAt = false; + if (pPed->IsPlayer()) + ((CPlayerPed*)pPed)->m_fMoveSpeed = 0.0f; + else + pPed->m_nStoredMoveState = PEDMOVE_STILL; + CAnimManager::AddAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_IDLE_STANCE); + pPed->bIsPedDieAnimPlaying = false; + } + return 0; + } case COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE: CollectParameters(&m_nIp, 2); CGarages::SetMaxNumStoredCarsForGarage(ScriptParams[0], ScriptParams[1]); @@ -11014,11 +11759,46 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_SET_PLAYER_IS_IN_STADIUM: + { + CollectParameters(&m_nIp, 1); + CTheScripts::bPlayerIsInTheStatium = ScriptParams[0]; + return 0; + } case COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER: + { + CollectParameters(&m_nIp, 1); + debug("GET_BUS_FARES_COLLECTED_BY_PLAYER not implemented\n"); // TODO(MIAMI) + ScriptParams[0] = 0; + StoreParameters(&m_nIp, 1); + } case COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + assert(pVehicle); + ScriptParams[0] = 0; + if (pPed->m_objective == OBJECTIVE_NONE && !pPed->bHasAlreadyUsedAttractor) { + C2dEffect* pEffect = (C2dEffect*)GetPedAttractorManager()->GetEffectForIceCreamVan(pVehicle, pPed->GetPosition()); // has to be casted, because inner methods are const + if ((pPed->GetPosition() - pEffect->pos).MagnitudeSqr() < SQR(20.0f)) { + if (GetPedAttractorManager()->HasEmptySlot(pEffect) && GetPedAttractorManager()->IsApproachable(pEffect, pVehicle->GetMatrix(), 0, pPed)) { + if (GetPedAttractorManager()->RegisterPedWithAttractor(pPed, pEffect, pVehicle->GetMatrix())) + ScriptParams[0] = 1; + } + } + } + StoreParameters(&m_nIp, 1); + return 0; + } case COMMAND_DISPLAY_RADAR: + CollectParameters(&m_nIp, 1); + debug("DISPLAY_RADAR not implemented\n"); + return 0; case COMMAND_REGISTER_BEST_POSITION: - assert(0); + CollectParameters(&m_nIp, 2); + debug("REGISTER_BEST_POSITION not implemented\n"); + return 0; case COMMAND_IS_PLAYER_IN_INFO_ZONE: { CollectParameters(&m_nIp, 1); @@ -11034,14 +11814,86 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + if (pPed->m_attractor) + GetPedAttractorManager()->DeRegisterPed(pPed, pPed->m_attractor); + return 0; + } case COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED: + UpdateCompareFlag(CPad::GetPad(0)->GetCarGunFired()); + return 0; case COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bHasAlreadyUsedAttractor); + return 0; + } case COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + if (ScriptParams[1]) { + pVehicle->bDontLoadCollision = false; + if (m_bMissionFlag) { + CWorld::Remove(pVehicle); + pVehicle->bIsStaticWaitingForCollision = true; + CWorld::Add(pVehicle); + } + } + else { + pVehicle->bDontLoadCollision = true; + if (pVehicle->bIsStaticWaitingForCollision) { + pVehicle->bIsStaticWaitingForCollision = false; + if (!pVehicle->IsStatic()) + pVehicle->AddToMovingList(); + } + } + return 0; + } case COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG: - case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + if (ScriptParams[1]) { + pPed->bDontLoadCollision = false; + if (m_bMissionFlag) { + CWorld::Remove(pPed); + pPed->bIsStaticWaitingForCollision = true; + CWorld::Add(pPed); + } + } + else { + pPed->bDontLoadCollision = true; + if (pPed->bIsStaticWaitingForCollision) { + pPed->bIsStaticWaitingForCollision = false; + if (!pPed->IsStatic()) + pPed->AddToMovingList(); + } + } + return 0; + } + //case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG: case COMMAND_ADD_BIG_GUN_FLASH: + { + CollectParameters(&m_nIp, 6); + debug("ADD_BIG_GUN_FLASH not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM: - assert(0); + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bBoughtIceCream); + return 0; + } case COMMAND_GET_PROGRESS_PERCENTAGE: *(float*)&ScriptParams[0] = CStats::GetPercentageProgress(); StoreParameters(&m_nIp, 1); @@ -11059,9 +11911,16 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA: - case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE: + CollectParameters(&m_nIp, 7); + debug("GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA not implemented\n"); // TODO(MIAMI) + ScriptParams[0] = -1; + StoreParameters(&m_nIp, 1); + return 0; + //case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE: case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA: - assert(0); + CollectParameters(&m_nIp, 4); + debug("UNLOCK_ALL_CAR_DOORS_IN_AREA not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS: CollectParameters(&m_nIp, 2); CGangs::SetWillAttackPlayerWithCops((ePedType)((int)PEDTYPE_GANG1 + ScriptParams[0]), !!ScriptParams[1]); @@ -11077,7 +11936,10 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_REGISTER_ODDJOB_MISSION_PASSED: - assert(0); + ++CStats::MissionsPassed; + CStats::CheckPointReachedSuccessfully(); + CTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds(); + // CGameLogic::RemoveShortCutDropOffPointForMission(); // TODO(MIAMI) case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI: { CollectParameters(&m_nIp, 1); @@ -11090,10 +11952,35 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_IS_CHAR_DUCKING: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_DUCK_DOWN) != nil); + return 0; + } case COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI: + { + CollectParameters(&m_nIp, 3); + debug("CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI not implemented\n"); // TODO(MIAMI) + return 0; + } case COMMAND_REGISTER_FIRE_LEVEL: + CollectParameters(&m_nIp, 1); + debug("REGISTER_FIRE_LEVEL not implemented\n"); // TODO(MIAMI) + return 0; case COMMAND_IS_AUSTRALIAN_GAME: + UpdateCompareFlag(false); // should we make some check? case COMMAND_DISARM_CAR_BOMB: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + if (pVehicle->m_bombType != CARBOMB_NONE) { + pVehicle->m_bombType = CARBOMB_NONE; + pVehicle->m_pBombRigger = nil; + } + return 0; + } default: assert(0); } @@ -12022,6 +12909,64 @@ void CRunningScript::LocateCarCommand(int32 command, uint32* pIp) } } +void CRunningScript::LocateObjectCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float X, Y, Z, dX, dY, dZ; + switch (command) { + case COMMAND_LOCATE_OBJECT_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + CVector pos = pObject->GetPosition(); + X = *(float*)&ScriptParams[1]; + Y = *(float*)&ScriptParams[2]; + if (b3D) { + Z = *(float*)&ScriptParams[3]; + dX = *(float*)&ScriptParams[4]; + dY = *(float*)&ScriptParams[5]; + dZ = *(float*)&ScriptParams[6]; + debug = ScriptParams[7]; + } + else { + dX = *(float*)&ScriptParams[3]; + dY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + result = false; + bool in_area; + if (b3D) { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y && + Z - dZ <= pos.z && + Z + dZ >= pos.z; + } + else { + in_area = X - dX <= pos.x && + X + dX >= pos.x && + Y - dY <= pos.y && + Y + dY >= pos.y; + } + result = in_area; + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ); + else + CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY); + } +} + void CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp) { bool b3D, result, debug; @@ -12519,6 +13464,88 @@ void CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp) } } +void CRunningScript::ObjectInAreaCheckCommand(int32 command, uint32* pIp) +{ + bool b3D, result, debug; + float infX, infY, infZ, supX, supY, supZ; + switch (command) { + case COMMAND_IS_OBJECT_IN_AREA_3D: + b3D = true; + break; + default: + b3D = false; + break; + } + CollectParameters(pIp, b3D ? 8 : 6); + CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + assert(pObject); + CVector pos = pObject->GetPosition(); + infX = *(float*)&ScriptParams[1]; + infY = *(float*)&ScriptParams[2]; + if (b3D) { + infZ = *(float*)&ScriptParams[3]; + supX = *(float*)&ScriptParams[4]; + supY = *(float*)&ScriptParams[5]; + supZ = *(float*)&ScriptParams[6]; + if (infZ > supZ) { + infZ = *(float*)&ScriptParams[6]; + supZ = *(float*)&ScriptParams[3]; + } + debug = ScriptParams[7]; + } + else { + supX = *(float*)&ScriptParams[3]; + supY = *(float*)&ScriptParams[4]; + debug = ScriptParams[5]; + } + if (infX > supX) { + float tmp = infX; + infX = supX; + supX = tmp; + } + if (infY > supY) { + float tmp = infY; + infY = supY; + supY = tmp; + } + result = false; + bool in_area; + if (b3D) { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y && + infZ <= pos.z && + supZ >= pos.z; + } + else { + in_area = infX <= pos.x && + supX >= pos.x && + infY <= pos.y && + supY >= pos.y; + } + if (in_area) { + switch (command) { + case COMMAND_IS_OBJECT_IN_AREA_2D: + case COMMAND_IS_OBJECT_IN_AREA_3D: + result = true; + break; + default: + assert(false); + break; + } + } + UpdateCompareFlag(result); + if (debug) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT); + if (CTheScripts::DbgFlag) { + if (b3D) + CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ); + else + CTheScripts::DrawDebugSquare(infX, infY, supX, supY); + } +} + void CRunningScript::DoDeatharrestCheck() { if (!m_bDeatharrestEnabled) diff --git a/src/control/Script.h b/src/control/Script.h index 811fbef5..75a2c1e0 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -488,6 +488,8 @@ private: void PlayerInAngledAreaCheckCommand(int32, uint32*); void CharInAreaCheckCommand(int32, uint32*); void CarInAreaCheckCommand(int32, uint32*); + void LocateObjectCommand(int32, uint32*); + void ObjectInAreaCheckCommand(int32, uint32*); float LimitAngleOnCircle(float angle) { return angle < 0.0f ? angle + 360.0f : angle; } diff --git a/src/core/ColStore.cpp b/src/core/ColStore.cpp index 80bbdc77..070967e5 100644 --- a/src/core/ColStore.cpp +++ b/src/core/ColStore.cpp @@ -178,7 +178,7 @@ CColStore::LoadCollision(const CVector2D &pos) }else{ for (int j = 0; j < MAX_CLEANUP; j++) { CPhysical* pEntity = CTheScripts::MissionCleanup.DoesThisEntityWaitForCollision(j); - if (pEntity /* !pEntity->bDontLoadCollision && !pEntity->bIsFrozen */) { + if (pEntity && !pEntity->bDontLoadCollision && !pEntity->bIsFrozen) { if (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f)) wantThisOne = true; } diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 37a62adf..675fafb3 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -149,13 +149,14 @@ CPlayerInfo::Clear(void) } void -CPlayerInfo::BlowUpRCBuggy(void) +CPlayerInfo::BlowUpRCBuggy(bool actually) { if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld) return; CRemote::TakeRemoteControlledCarFromPlayer(); - m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); + if (actually) + m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); } void diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index ea9d563a..119f0b2c 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -50,6 +50,7 @@ public: int32 m_nExplosionsSinceLastReward; int32 field_268; int32 field_272; + uint32 m_nHavocLevel; bool m_bInfiniteSprint; bool m_bFastReload; bool m_bFireproof; @@ -73,7 +74,7 @@ public: bool IsPlayerInRemoteMode(void); void PlayerFailedCriticalMission(void); void Clear(void); - void BlowUpRCBuggy(void); + void BlowUpRCBuggy(bool); void CancelPlayerEnteringCars(CVehicle*); bool IsRestartingAfterDeath(void); bool IsRestartingAfterArrest(void); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 92542071..6275e2b3 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -64,6 +64,9 @@ CPhysical::CPhysical(void) m_phy_flagA20 = false; m_nZoneLevel = LEVEL_NONE; + + bIsFrozen = false; + bDontLoadCollision = false; } CPhysical::~CPhysical(void) diff --git a/src/entities/Physical.h b/src/entities/Physical.h index b6e28275..a1c60b6b 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -60,6 +60,9 @@ public: uint8 bHitByTrain : 1; uint8 bSkipLineCol : 1; + uint8 bIsFrozen : 1; + uint8 bDontLoadCollision : 1; + uint8 m_nSurfaceTouched; int8 m_nZoneLevel; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 539bbfaf..081ea91e 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -603,14 +603,25 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bCarPassenger = false; bMiamiViceCop = false; bMoneyHasBeenGivenByScript = false; + bHasBeenPhotographed = false; bIsDrowning = false; - bCanDrownInWater = true; + bDrownsInWater = true; #ifdef VC_PED_PORTS bHeadStuckInCollision = false; #endif bIsPlayerFriend = true; bDeadPedInFrontOfCar = false; + bStayInCarOnJack = false; + + bDontFight = false; + bDoomAim = true; + bCanBeShotInVehicle = true; + bIgnoreThreatsBehindObjects = false; + + bNeverEverTargetThisPed = false; + + bBoughtIceCream = false; if ((CGeneral::GetRandomNumber() & 3) == 0) bHasACamera = true; @@ -4116,7 +4127,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi if (DyingOrDead()) return false; - if (method == WEAPONTYPE_DROWNING && !bCanDrownInWater) + if (method == WEAPONTYPE_DROWNING && !bDrownsInWater) return false; if (!bUsesCollision && (!bInVehicle || m_nPedState != PED_DRIVING) && method != WEAPONTYPE_DROWNING) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 4452c13a..0cbf5701 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -225,10 +225,10 @@ enum eObjective : uint32 { OBJECTIVE_USE_STOP_ATTRACTOR, OBJECTIVE_USE_PIZZA_ATTRACTOR, OBJECTIVE_USE_SHELTER_ATTRACTOR, - OBJ_46, + OBJECTIVE_AIM_GUN_AT_PED, OBJ_47, OBJECTIVE_WAIT_FOR_RAIN_TO_END, - OBJ_49, + OBJECTIVE_SPRINT_TO_COORD, OBJ_50, OBJ_51, OBJECTIVE_WAIT_FOR_BUS, @@ -442,10 +442,10 @@ public: //uint32 b155_10 uint32 bMiamiViceCop : 1; uint32 bMoneyHasBeenGivenByScript : 1; // - //uint32 b155_80 + uint32 bHasBeenPhotographed : 1; // uint32 bIsDrowning : 1; - uint32 bCanDrownInWater : 1; // Originally bDrownsInWater + uint32 bDrownsInWater : 1; //uint32 b156_4 //uint32 b156_8 uint32 bIsPlayerFriend : 1; @@ -453,23 +453,23 @@ public: uint32 bHeadStuckInCollision : 1; #endif uint32 bDeadPedInFrontOfCar : 1; - //uint32 b156_80 + uint32 bStayInCarOnJack : 1; - //uint32 b157_1 - //uint32 b157_2 - //uint32 b157_4 + uint32 bDontFight : 1; + uint32 bDoomAim : 1; + uint32 bCanBeShotInVehicle : 1; //uint32 b157_8 //uint32 b157_10 //uint32 b157_20 //uint32 b157_40 - //uint32 b157_80 + uint32 bIgnoreThreatsBehindObjects : 1; - //uint32 b158_1 + uint32 bNeverEverTargetThisPed : 1; //uint32 b158_2 //uint32 b158_4 //uint32 b158_8 //uint32 b158_10 - //uint32 b158_20 + uint32 bBoughtIceCream : 1; //uint32 b158_40 //uint32 b158_80 diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 7c02f3ee..a1d58ab2 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -57,7 +57,8 @@ void CCarGenerator::DoInternalProcessing() mi = -m_nModelIndex; if (m_nModelIndex == -1 || !CStreaming::HasModelLoaded(mi)) { CZoneInfo pZone; - CTheZones::GetZoneInfoForTimeOfDay(&FindPlayerCoors(), &pZone); + CVector pos = FindPlayerCoors(); + CTheZones::GetZoneInfoForTimeOfDay(&pos, &pZone); mi = CCarCtrl::ChooseCarModel(CCarCtrl::ChooseCarRating(&pZone)); if (mi < 0) return; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 58c68a8d..cd85c3db 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -30,6 +30,7 @@ bool CVehicle::bAltDodoCheat; #endif bool CVehicle::m_bDisableMouseSteering = true; bool CVehicle::bDisableRemoteDetonation; +bool CVehicle::bDisableRemoteDetonationOnContact; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } @@ -104,7 +105,9 @@ CVehicle::CVehicle(uint8 CreatedBy) m_nCarHornPattern = 0; m_nCarHornDelay = 0; bPartOfConvoy = false; + bHeliMinimumTilt = false; bIsDrowning = false; + bTyresDontBurst = false; bCreatedAsPoliceVehicle = false; bParking = false; m_nAlarmState = 0; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 0b7d3cba..e07c2768 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -183,11 +183,11 @@ public: uint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command uint8 bHasAlreadyBeenRecorded : 1; // Used for replays uint8 bPartOfConvoy : 1; - //uint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really + uint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really //uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water) - //uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible + uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc) //uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed uint8 bParking : 1; @@ -318,6 +318,7 @@ public: #endif static bool m_bDisableMouseSteering; static bool bDisableRemoteDetonation; + static bool bDisableRemoteDetonationOnContact; }; void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle); From a5f23a03424cf312add998edce6ef4122c0a29d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 22 May 2020 02:44:01 +0300 Subject: [PATCH 093/148] VC CMenuManager struct, ctor etc. --- src/control/Script.cpp | 4 +- src/core/Cam.cpp | 2 +- src/core/Camera.cpp | 24 +- src/core/ControllerConfig.cpp | 8 +- src/core/Frontend.cpp | 1400 ++++++++++--------------------- src/core/Frontend.h | 304 ++++--- src/core/Game.cpp | 12 +- src/core/MenuScreens.h | 8 - src/core/Pad.cpp | 6 +- src/core/Radar.cpp | 28 +- src/core/config.h | 1 - src/core/main.cpp | 70 +- src/render/Credits.cpp | 56 +- src/render/Fluff.cpp | 4 +- src/render/Hud.cpp | 96 ++- src/render/Hud.h | 1 + src/rw/Lights.cpp | 6 +- src/save/GenericGameStorage.cpp | 4 +- src/skel/glfw/glfw.cpp | 26 +- src/skel/win/win.cpp | 28 +- src/text/Text.cpp | 4 +- 21 files changed, 788 insertions(+), 1304 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index eb94918e..5777cff2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8627,13 +8627,13 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) case COMMAND_ACTIVATE_SAVE_MENU: { CStats::SafeHouseVisits++; - FrontEndMenuManager.m_bSaveMenuActive = true; + FrontEndMenuManager.m_bActivateSaveMenu = true; FindPlayerPed()->SetMoveSpeed(0.0f, 0.0f, 0.0f); FindPlayerPed()->SetTurnSpeed(0.0f, 0.0f, 0.0f); return 0; } case COMMAND_HAS_SAVE_GAME_FINISHED: - UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive && !FrontEndMenuManager.m_bSaveMenuActive); + UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive && !FrontEndMenuManager.m_bActivateSaveMenu); return 0; case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE: CollectParameters(&m_nIp, 1); diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index afa153f9..871b6dba 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -3630,7 +3630,7 @@ CCam::Process_Fixed(const CVector &CameraTarget, float, float, float) if(TheCamera.m_bUseSpecialFovTrain) FOV = TheCamera.m_fFovForTrain; - if(CMenuManager::m_ControlMethod == 0 && Using3rdPersonMouseCam()){ + if(FrontEndMenuManager.m_ControlMethod == 0 && Using3rdPersonMouseCam()){ CPed *player = FindPlayerPed(); if(player && player->CanStrafeOrMouseControl()){ float Heading = Front.Heading(); diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index fa5e44bb..486c2c9e 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -3037,33 +3037,25 @@ CCamera::SetNearClipScript(float clip) void CCamera::ProcessFade(void) { - float fade = (CTimer::GetTimeInMilliseconds() - m_uiFadeTimeStarted)/1000.0f; - // Why even set CDraw::FadeValue if m_fFLOATingFade sets it anyway? if(m_bFading){ if(m_iFadingDirection == FADE_IN){ if(m_fTimeToFadeOut != 0.0f){ - m_fFLOATingFade = 255.0f - 255.0f*fade/m_fTimeToFadeOut; - if(m_fFLOATingFade <= 0.0f){ - m_bFading = false; - CDraw::FadeValue = 0; - m_fFLOATingFade = 0.0f; - } + m_fFLOATingFade -= CTimer::GetTimeStepInSeconds() * 255.0f / m_fTimeToFadeOut; }else{ + m_fFLOATingFade = 0.0f; + } + if (m_fFLOATingFade <= 0.0f) { m_bFading = false; - CDraw::FadeValue = 0; m_fFLOATingFade = 0.0f; } }else if(m_iFadingDirection == FADE_OUT){ if(m_fTimeToFadeOut != 0.0f){ - m_fFLOATingFade = 255.0f*fade/m_fTimeToFadeOut; - if(m_fFLOATingFade >= 255.0f){ - m_bFading = false; - CDraw::FadeValue = 255; - m_fFLOATingFade = 255.0f; - } + m_fFLOATingFade += CTimer::GetTimeStepInSeconds() * 255.0f / m_fTimeToFadeOut; }else{ + m_fFLOATingFade = 255.0f; + } + if (m_fFLOATingFade >= 255.0f) { m_bFading = false; - CDraw::FadeValue = 255; m_fFLOATingFade = 255.0f; } } diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 6a5080e5..453889a5 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -769,7 +769,7 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnl if (button == GetControllerKeyAssociatedWithAction(PED_SPRINT, type)) state.Cross = 255; - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type)) state.LeftShoulder2 = 255; @@ -835,7 +835,7 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstAndThirdP state.RightStickX = 128; } - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (button == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_UP, type)) { @@ -1617,7 +1617,7 @@ void CControllerConfigManager::DeleteMatching3rdPersonControls(e_ControllerActio if (key == GetControllerKeyAssociatedWithAction(PED_SPRINT, type)) ClearSettingsAssociatedWithAction(PED_SPRINT, type); - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (key == GetControllerKeyAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type)) ClearSettingsAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type); @@ -1640,7 +1640,7 @@ void CControllerConfigManager::DeleteMatching1rst3rdPersonControls(e_ControllerA if (key == GetControllerKeyAssociatedWithAction(GO_BACK, type)) ClearSettingsAssociatedWithAction(GO_BACK, type); - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (key == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_LEFT, type)) ClearSettingsAssociatedWithAction(PED_1RST_PERSON_LOOK_LEFT, type); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index dd840bdc..8149a201 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -78,14 +78,6 @@ CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); #define GetBackJustDown GetSquareJustDown #endif -#ifdef MENU_MAP -bool CMenuManager::bMenuMapActive = false; -bool CMenuManager::bMapMouseShownOnce = false; -bool CMenuManager::bMapLoaded = false; -float CMenuManager::fMapSize; -float CMenuManager::fMapCenterY; -float CMenuManager::fMapCenterX; -#endif #ifdef PS2_LIKE_MENU BottomBarOption bbNames[8]; @@ -98,35 +90,8 @@ int curBottomBarOption = -1; int hoveredBottomBarOption = -1; #endif -int32 CMenuManager::OS_Language = LANG_ENGLISH; -int8 CMenuManager::m_PrefsUseVibration; -int8 CMenuManager::m_DisplayControllerOnFoot; -int8 CMenuManager::m_PrefsVsync = 1; -int8 CMenuManager::m_PrefsVsyncDisp = 1; -int8 CMenuManager::m_PrefsFrameLimiter = 1; -int8 CMenuManager::m_PrefsShowSubtitles = 1; -int8 CMenuManager::m_PrefsSpeakers; -int32 CMenuManager::m_ControlMethod; -int8 CMenuManager::m_PrefsDMA = 1; -int32 CMenuManager::m_PrefsLanguage; uint8 CMenuManager::m_PrefsStereoMono; // unused except restore settings -bool CMenuManager::m_PrefsAllowNastyGame = true; -bool CMenuManager::m_bStartUpFrontEndRequested; -bool CMenuManager::m_bShutDownFrontEndRequested; - -int8 CMenuManager::m_PrefsUseWideScreen; -int8 CMenuManager::m_PrefsRadioStation; -int32 CMenuManager::m_PrefsBrightness = 256; -float CMenuManager::m_PrefsLOD = CRenderer::ms_lodDistScale; -int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; -int32 CMenuManager::m_PrefsMusicVolume = 102; -int32 CMenuManager::m_PrefsSfxVolume = 102; - -char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME; - -int32 CMenuManager::m_KeyPressedCode = -1; - // Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) #ifdef PS2_LIKE_MENU const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); @@ -137,56 +102,25 @@ const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; -bool holdingScrollBar; // *(bool*)0x628D59; // not original name -int32 CMenuManager::m_SelectedMap; -int32 CMenuManager::m_SelectedGameType; - -// Used in a hidden menu -uint8 CMenuManager::m_PrefsPlayerRed = 255; -uint8 CMenuManager::m_PrefsPlayerGreen = 128; -uint8 CMenuManager::m_PrefsPlayerBlue; // why?? +bool holdingScrollBar; // *(bool*)0x7039B9; // not original name CMenuManager FrontEndMenuManager; +MenuTrapezoid menuBg(CGeneral::GetRandomNumber() % 40 + 65, CGeneral::GetRandomNumber() % 40 + 21, + CGeneral::GetRandomNumber() % 40 + 568, CGeneral::GetRandomNumber() % 40 + 44, + CGeneral::GetRandomNumber() % 40 + 36, CGeneral::GetRandomNumber() % 40 + 352, + CGeneral::GetRandomNumber() % 40 + 593, CGeneral::GetRandomNumber() % 40 + 312); -uint32 TimeToStopPadShaking; -char *pEditString; -int32 *pControlEdit; -bool DisplayComboButtonErrMsg; -int32 MouseButtonJustClicked; -int32 JoyButtonJustClicked; -//int32 *pControlTemp = 0; +MenuTrapezoid menuOptionHighlight(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + +// TODO(Miami): TEMPORARY +bool bMapLoaded = false; +bool bMapMouseShownOnce = false; #ifndef MASTER bool CMenuManager::m_PrefsMarketing = false; bool CMenuManager::m_PrefsDisableTutorials = false; #endif // !MASTER -/* -// 0x5F3344 -const char* MenuFilenames[][2] = { - {"connection24", ""}, - {"findgame24", ""}, - {"hostgame24", ""}, - {"mainmenu24", ""}, - {"Playersetup24", ""}, - {"singleplayer24", ""}, - {"multiplayer24", ""}, - {"dmalogo128", "dmalogo128m"}, - {"gtaLogo128", "gtaLogo128"}, - {"rockstarLogo128", "rockstarlogo128m"}, - {"gamespy256", "gamespy256a"}, - {"mouse", "mousetimera"}, - {"mousetimer", "mousetimera"}, - {"mp3logo", "mp3logoA"}, - {"downOFF", "buttonA"}, - {"downON", "buttonA"}, - {"upOff", "buttonA"}, - {"upON", "buttonA"}, - {"gta3logo256", "gta3logo256m"}, - { nil, nil } -}; -*/ - // 0x68C144 const char* FrontendFilenames[][2] = { {"background", ""}, @@ -252,7 +186,7 @@ ScaleAndCenterX(float x) m_nCurrOption = pendingOption; \ reverseAlpha = false; \ if (updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); \ } \ if (withReverseAlpha) { \ pendingOption = option; \ @@ -263,7 +197,7 @@ ScaleAndCenterX(float x) m_nCurrScreen = screen; \ m_nCurrOption = option; \ if (updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); \ } \ m_nMenuFadeAlpha = 255; \ } while(0) @@ -274,7 +208,7 @@ ScaleAndCenterX(float x) m_nCurrScreen = screen; \ m_nCurrOption = option; \ if(updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); \ if(clearAlpha) \ m_nMenuFadeAlpha = 0; \ } while(0) @@ -409,6 +343,125 @@ CMenuManager::ThingsToDoBeforeLeavingPage() // ------ Functions not in the game/inlined ends +CMenuManager::CMenuManager() +{ + m_StatsScrollSpeed = 150.0f; + m_StatsScrollDirection = 1; + m_PrefsSfxVolume = 49; + m_PrefsMusicVolume = 49; + m_PrefsRadioStation = 0; + field_2C = 1; + m_PrefsBrightness = 256; + m_PrefsLOD = 1.2f; + m_KeyPressedCode = -1; + m_bFrontEnd_ReloadObrTxtGxt = false; + m_PrefsMP3BoostVolume = 0; + m_PrefsShowSubtitles = 0; + m_PrefsShowLegends = 1; + m_PrefsUseWideScreen = 0; + m_PrefsVsync = 0; + m_PrefsVsyncDisp = 1; + m_PrefsFrameLimiter = 1; + m_PrefsLanguage = 0; + field_54 = 0; + m_PrefsAllowNastyGame = 1; + m_PrefsSpeakers = 0; + field_8 = 0; + m_PrefsUseVibration = 0; + m_PrefsShowHud = 1; + m_PrefsRadarMode = 0; + field_10 = 0; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + pEditString = nil; + pControlEdit = nil; + DisplayComboButtonErrMsg = false; + m_PrefsDMA = 1; + OS_Language = LANG_ENGLISH; + m_ControlMethod = CONTROL_STANDARD; + CCamera::m_bUseMouse3rdPerson = true; + m_3DProviderOnLastSaveLoad = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0.0f; + m_nSelectedListRow = 0; + m_nSkinsTotal = 0; + m_nPrefsAudio3DProviderIndex = -99; + m_bGameNotLoaded = true; + m_nMousePosX = m_nMouseTempPosX; + m_nMousePosY = m_nMouseTempPosY; + m_nMouseOldPosX = m_nMousePosX; + m_nMouseOldPosY = m_nMousePosY; + m_bShowMouse = true; + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + + // TODO(Miami) + // DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + m_bMenuActive = false; + m_bActivateSaveMenu = false; + m_bWantToLoad = false; + m_nMenuFadeAlpha = 0; + m_OnlySaveMenu = false; + m_fMapSize = 162.0f; + m_fMapCenterX = 320.0f; + m_fMapCenterY = 225.0f; + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); +} + +void +CMenuManager::SetFrontEndRenderStates(void) +{ + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); +} + +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +void DoRWStuffEndOfFrame(void); + +void +CMenuManager::Initialise(void) +{ + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_AllowNavigation = false; + m_menuTransitionProgress = -50; + m_nMenuFadeAlpha = 0; + m_nCurrOption = 0; + bOptionHighlightTransitionBlend = 0; + CentreMousePointer(); + m_bShowMouse = true; + m_fMapSize = 162.0f; + m_fMapCenterX = 320.0f; + m_fMapCenterY = 225.0f; + CPad::StopPadsShaking(); + if (!m_OnlySaveMenu) + m_nCurrScreen = MENUPAGE_NONE; + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + DMAudio.Service(); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + m_PrefsRadioStation = DMAudio.GetRadioInCar(); + + // TODO(Miami) + // DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < HEAD_RADIO || m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; + } else if (m_PrefsRadioStation < HEAD_RADIO || m_PrefsRadioStation > CHATTERBOX) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; + + CFileMgr::SetDir(""); + //CFileMgr::SetDir(""); + PcSaveHelper.PopulateSlotInfo(); + CTimer::StartUserPause(); +} + void CMenuManager::BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2) { @@ -682,16 +735,15 @@ CMenuManager::DoSettingsBeforeStartingAGame() DMAudio.Service(); m_bWantToRestart = true; - - ShutdownJustMenu(); - UnloadTextures(); + m_bShutDownFrontEndRequested = true; DMAudio.SetEffectsFadeVol(0); DMAudio.SetMusicFadeVol(0); + SwitchMenuOnAndOff(); DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); } void -CMenuManager::Draw() +CMenuManager::DrawStandardMenus() { CFont::SetBackgroundOff(); CFont::SetPropOn(); @@ -699,19 +751,6 @@ CMenuManager::Draw() CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); - // no V1.1 text in vc obv -#if 0 //def GTA3_1_1_PATCH - CFont::SetColor(CRGBA(255, 150, 225, FadeIn(255))); - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); - CFont::SetWrapx(SCREEN_WIDTH); - CFont::SetRightJustifyWrap(0.0f); - strcpy(gString, "V1.1"); - AsciiToUnicode(gString, gUString); - CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); -#endif - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); @@ -733,9 +772,6 @@ CMenuManager::Draw() float nextYToUse = 40.0f; // Page name -#ifdef PS2_SAVE_DIALOG - if(!m_bRenderGameInMenu) -#endif if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { PREPARE_MENU_HEADER @@ -864,15 +900,6 @@ CMenuManager::Draw() CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); CFont::SetCentreOn(); break; -#ifdef PS2_SAVE_DIALOG - case MENUPAGE_SAVE: - columnWidth = 180; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - break; -#endif default: columnWidth = 320; headerHeight = 40; @@ -948,73 +975,8 @@ CMenuManager::Draw() } switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case MENUACTION_CHANGEMENU: { - switch (aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu) { - case MENUPAGE_MULTIPLAYER_MAP: - switch (m_SelectedMap) { - case 0: - rightText = TheText.Get("FEM_MA0"); - break; - case 1: - rightText = TheText.Get("FEM_MA1"); - break; - case 2: - rightText = TheText.Get("FEM_MA2"); - break; - case 3: - rightText = TheText.Get("FEM_MA3"); - break; - case 4: - rightText = TheText.Get("FEM_MA4"); - break; - case 5: - rightText = TheText.Get("FEM_MA5"); - break; - case 6: - rightText = TheText.Get("FEM_MA6"); - break; - case 7: - rightText = TheText.Get("FEM_MA7"); - break; - default: - break; - } - break; - case MENUPAGE_MULTIPLAYER_MODE: - switch (m_SelectedGameType) { - case 0: - rightText = TheText.Get("FEN_TY0"); - break; - case 1: - rightText = TheText.Get("FEN_TY1"); - break; - case 2: - rightText = TheText.Get("FEN_TY2"); - break; - case 3: - rightText = TheText.Get("FEN_TY3"); - break; - case 4: - rightText = TheText.Get("FEN_TY4"); - break; - case 5: - rightText = TheText.Get("FEN_TY5"); - break; - case 6: - rightText = TheText.Get("FEN_TY6"); - break; - case 7: - rightText = TheText.Get("FEN_TY7"); - break; - default: - break; - } - break; - default: - break; - } + case MENUACTION_CHANGEMENU: break; - } case MENUACTION_CTRLVIBRATION: if (m_PrefsUseVibration) rightText = TheText.Get("FEM_ON"); @@ -1037,12 +999,6 @@ CMenuManager::Draw() break; } break; - case MENUACTION_CTRLDISPLAY: - if (m_DisplayControllerOnFoot) - rightText = TheText.Get("FEC_ONF"); - else - rightText = TheText.Get("FEC_INC"); - break; case MENUACTION_FRAMESYNC: rightText = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); break; @@ -1224,9 +1180,6 @@ CMenuManager::Draw() } // Green bar behind selected option -#ifdef PS2_SAVE_DIALOG - if (!m_bRenderGameInMenu) -#endif if (i == m_nCurrOption && itemsAreSelectable) { // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), @@ -1354,14 +1307,6 @@ CMenuManager::Draw() DisplayHelperText(); break; } - - if (m_nCurrScreen == MENUPAGE_CONTROLLER_SETTINGS) - PrintController(); - else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT_OLD) { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(180), MENU_Y(98), MENU_X_LEFT_ALIGNED(230), MENU_Y(123)), CRGBA(255, 255, 255, FadeIn(255))); - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(181), MENU_Y(99), MENU_X_LEFT_ALIGNED(229), MENU_Y(122)), CRGBA(m_PrefsPlayerRed, m_PrefsPlayerGreen, m_PrefsPlayerBlue, FadeIn(255))); - } - } int @@ -2009,6 +1954,10 @@ void CMenuManager::DrawFrontEnd() { CFont::SetAlphaFade(255.0f); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + SetFrontEndRenderStates(); + m_NoEmptyBinding = true; #ifdef PS2_LIKE_MENU if (m_nCurrScreen == MENUPAGE_NONE) { @@ -2052,63 +2001,18 @@ CMenuManager::DrawFrontEnd() if (m_nCurrOption == 0 && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) m_nCurrOption = 1; -#ifdef PS2_SAVE_DIALOG - if(m_bRenderGameInMenu) - DrawFrontEndSaveZone(); - else -#endif - DrawFrontEndNormal(); + if (m_menuTransitionProgress == 255 && m_nMenuFadeAlpha == 255) + bMenuChangeOngoing = false; + DrawBackground(); + + // TODO(Miami): Delete dis PrintErrorMessage(); } -#ifdef PS2_SAVE_DIALOG -void -CMenuManager::DrawFrontEndSaveZone() -{ - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); - - // Not original dimensions, have been changed to fit PC screen & PC menu layout. - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(30.0f), SCREEN_SCALE_FROM_BOTTOM(50.0f)), CRGBA(0, 0, 0, 175)); - - m_nMenuFadeAlpha = 255; - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - Draw(); - - CFont::DrawFonts(); - - // Draw mouse - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - if (m_bShowMouse) { - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - - CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f)); - CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f)); - - mouse.Translate(m_nMousePosX, m_nMousePosY); - shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - } - } -} -#endif - #ifdef PS2_LIKE_MENU void -CMenuManager::DrawFrontEndNormal() +CMenuManager::DrawBackground() { CSprite2d::InitPerFrame(); CFont::InitPerFrame(); @@ -2225,7 +2129,7 @@ CMenuManager::DrawFrontEndNormal() DrawControllerSetupScreen(); break; default: - Draw(); + DrawStandardMenus(); break; } @@ -2300,53 +2204,17 @@ CMenuManager::DrawFrontEndNormal() } #else void -CMenuManager::DrawFrontEndNormal() +CMenuManager::DrawBackground() { - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + if (!m_bSpritesLoaded) + return; - LoadSplash(nil); - - eMenuSprites previousSprite = MENUSPRITE_BACKGROUND; + SetFrontEndRenderStates(); - if (m_nMenuFadeAlpha < 255) { - if (m_nPrevScreen == m_nCurrScreen) - CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255 - m_nMenuFadeAlpha)); - else - m_aFrontEndSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha)); + if (m_menuTransitionProgress < 255) { + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - - eMenuSprites currentSprite = MENUSPRITE_BACKGROUND; // actually uninitialized - - switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - case MENUPAGE_NEW_GAME: - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_EXIT: - case MENUPAGE_MULTIPLAYER_MAIN: - case MENUPAGE_MULTIPLAYER_MAP: - case MENUPAGE_MULTIPLAYER_FIND_GAME: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - case MENUPAGE_MULTIPLAYER_CONNECTION: - case MENUPAGE_MULTIPLAYER_MODE: - case MENUPAGE_MULTIPLAYER_CREATE: - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - currentSprite = MENUSPRITE_BACKGROUND; - break; - } if (m_nMenuFadeAlpha < 255) { @@ -2358,6 +2226,7 @@ CMenuManager::DrawFrontEndNormal() // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) fadeAlpha += (frameTime) * 20.f / 33.f; m_nMenuFadeAlpha = fadeAlpha; + m_menuTransitionProgress = clamp(fadeAlpha, 0, 255); #else static uint32 LastFade = 0; @@ -2366,44 +2235,15 @@ CMenuManager::DrawFrontEndNormal() LastFade = CTimer::GetTimeInMillisecondsPauseMode(); } #endif - - if (m_nMenuFadeAlpha > 255){ - m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - } else { - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); - } } else { - m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - // TODO: what is this? waiting mouse? - if(field_518 == 4){ - if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || - m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) - - field_518 = 2; - else - field_518 = 1; - } + m_nMenuFadeAlpha = 255; + m_menuTransitionProgress = 255; } - m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, Min(255, m_nMenuFadeAlpha))); - // GTA LOGO - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - /* - if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) { - if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); - else - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); - } - */ - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_SCALE_X(27.0f), MENU_Y(8.0f), SCREEN_SCALE_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); + SetFrontEndRenderStates(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); switch (m_nCurrScreen) { case MENUPAGE_SKIN_SELECT: DrawPlayerSetupScreen(); @@ -2412,34 +2252,28 @@ CMenuManager::DrawFrontEndNormal() DrawControllerSetupScreen(); break; default: - Draw(); + DrawStandardMenus(); break; } CFont::DrawFonts(); - // Draw mouse - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - if (m_bShowMouse) { - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + SetFrontEndRenderStates(); + if (m_menuTransitionProgress == 255) { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); + } else { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, Min(m_nMenuFadeAlpha, 255))); + } + + if (m_bShowMouse) { CRect mouse(0.0f, 0.0f, MENU_X(40.0f), MENU_Y(40.0f)); CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(55.0f), MENU_Y(43.0f)); mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - } + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); } } #endif @@ -2971,21 +2805,9 @@ CMenuManager::LoadAllTextures() if (m_bSpritesLoaded) return; - CentreMousePointer(); - DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); - m_nCurrOption = 0; - m_PrefsRadioStation = DMAudio.GetRadioInCar(); - - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; - } else if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; - - CFileMgr::SetDir(""); - //CFileMgr::SetDir(""); + field_F0 = SCREEN_STRETCH_X(178.0f); // TODO(Miami) CTimer::Stop(); + CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile CStreaming::ImGonnaUseStreamingMemory(); CGame::TidyUpMemory(false, true); @@ -3008,39 +2830,30 @@ CMenuManager::LoadAllTextures() CTxdStore::PopCurrentTxd(); CStreaming::IHaveUsedStreamingMemory(); + if (!m_OnlySaveMenu) { + CStreaming::MakeSpaceFor(692 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); - // if ( !*(_BYTE *)(v1 + 124) ) + int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2"); - CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile - CStreaming::ImGonnaUseStreamingMemory(); - CTxdStore::PushCurrentTxd(); + if (frontendTxdSlot2 == -1) + frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2"); - int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2"); + printf("LOAD frontend2\n"); + CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD"); + CTxdStore::AddRef(frontendTxdSlot2); + CTxdStore::SetCurrentTxd(frontendTxdSlot2); - if (frontendTxdSlot2 == -1) - frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2"); + for (int i = 3; i < NUM_MENU_SPRITES; i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + } - printf("LOAD frontend2\n"); - CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD"); - CTxdStore::AddRef(frontendTxdSlot2); - CTxdStore::SetCurrentTxd(frontendTxdSlot2); - - for (int i = 3; i < NUM_MENU_SPRITES; i++) { - m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); - m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + CTxdStore::PopCurrentTxd(); + CStreaming::IHaveUsedStreamingMemory(); } - CTxdStore::PopCurrentTxd(); - CStreaming::IHaveUsedStreamingMemory(); - - -#if 0 //MENU_MAP - for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) { - m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]); - m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); - } -#endif - m_bSpritesLoaded = true; CTimer::Update(); } @@ -3211,9 +3024,6 @@ CMenuManager::SaveSettings() CFileMgr::SetDir(""); } -bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); -void DoRWStuffEndOfFrame(void); - void CMenuManager::MessageScreen(const char *text) { @@ -3246,22 +3056,6 @@ CMenuManager::MessageScreen(const char *text) DoRWStuffEndOfFrame(); } -void -CMenuManager::PickNewPlayerColour() -{ - m_PrefsPlayerRed = 0; - m_PrefsPlayerGreen = 0; - m_PrefsPlayerBlue = 0; - while (true) { - int sum = m_PrefsPlayerRed + m_PrefsPlayerGreen + m_PrefsPlayerBlue; - if (sum >= 100 && sum <= 650) - break; - m_PrefsPlayerRed = CGeneral::GetRandomNumber(); - m_PrefsPlayerGreen = CGeneral::GetRandomNumber(); - m_PrefsPlayerBlue = CGeneral::GetRandomNumber(); - } -} - void CMenuManager::PrintBriefs() { @@ -3350,7 +3144,7 @@ CMenuManager::PrintStats() // Scroll stats with mouse #ifdef SCROLLABLE_STATS_PAGE static float scrollY = 0; - static uint32 lastChange = m_nScreenChangeDelayTimer; + static uint32 lastChange = m_LastScreenSwitch; if (CPad::GetPad(0)->GetLeftMouse()) { scrollY += (m_nMouseOldPosY - m_nMousePosY); lastChange = CTimer::GetTimeInMillisecondsPauseMode(); @@ -3360,7 +3154,7 @@ CMenuManager::PrintStats() } #else // MENU_Y(30.0f) per second - float scrollY = MENU_Y(STATS_SLIDE_Y_PER_SECOND) * (CTimer::GetTimeInMillisecondsPauseMode() - m_nScreenChangeDelayTimer) / 1000.0f; + float scrollY = MENU_Y(STATS_SLIDE_Y_PER_SECOND) * (CTimer::GetTimeInMillisecondsPauseMode() - m_LastScreenSwitch) / 1000.0f; #endif for (int row = 0; row < rowNum; ++row) { @@ -3423,7 +3217,7 @@ CMenuManager::PrintStats() // ::Draw already does that. /* PREPARE_MENU_HEADER - CFont::PrintString(MENU_X_RIGHT_ALIGNED(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); */ CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); } @@ -3431,159 +3225,86 @@ CMenuManager::PrintStats() void CMenuManager::Process(void) { - m_bMenuStateChanged = false; - - if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0) + if (TheCamera.GetScreenFadeStatus() != FADE_0) return; - m_bWantToRestart = false; InitialiseChangedLanguageSettings(); - // Just a hack by R* to not make game continuously resume/pause. But we it seems we can live with it. - if (CPad::GetPad(0)->GetEscapeJustDown()) - RequestFrontEndStartUp(); + if (m_bMenuActive) { + ProcessButtonPresses(); + ProcessFileActions(); + DMAudio.Service(); + + // TODO(Miami): What are the functions in here? + } SwitchMenuOnAndOff(); - - // Be able to re-open menu correctly. - if (m_bMenuActive) { - - // Load frontend textures. - LoadAllTextures(); - - // Set save/delete game pages. - if (m_nCurrScreen == MENUPAGE_DELETING) { - bool SlotPopulated = false; - - if (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) { - PcSaveHelper.PopulateSlotInfo(); - SlotPopulated = true; - } - - if (SlotPopulated) - ChangeScreen(MENUPAGE_DELETE_SUCCESS, 0, true, false); - else - SaveLoadFileError_SetUpErrorScreen(); - } - if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) { - int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); - PcSaveHelper.PopulateSlotInfo(); - if (SaveSlot) - ChangeScreen(MENUPAGE_SAVE_SUCCESSFUL, 0, true, false); - else - SaveLoadFileError_SetUpErrorScreen(); - } - if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS) { - if (CheckSlotDataValid(m_nCurrSaveSlot)) { - TheCamera.m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; - if (m_PrefsVsyncDisp != m_PrefsVsync) - m_PrefsVsync = m_PrefsVsyncDisp; - DMAudio.Service(); - m_bWantToRestart = true; - RequestFrontEndShutDown(); - m_bWantToLoad = true; - b_FoundRecentSavedGameWantToLoad = true; - DMAudio.SetEffectsFadeVol(0); - DMAudio.SetMusicFadeVol(0); - DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); - } else - SaveLoadFileError_SetUpErrorScreen(); - } - - ProcessButtonPresses(); - - // Set binding keys. - if (pEditString && CPad::EditString(pEditString, 0) == nil) { - if (*pEditString == 0) - strcpy(pEditString, "NoName"); - pEditString = nil; - SaveSettings(); - } - - if (m_bWaitingForNewKeyBind) { - if (m_bStartWaitingForKeyBind) - m_bStartWaitingForKeyBind = false; - else { - pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); - JoyButtonJustClicked = false; - MouseButtonJustClicked = false; - - if (CPad::GetPad(0)->GetLeftMouseJustDown()) - MouseButtonJustClicked = 1; - else if (CPad::GetPad(0)->GetRightMouseJustUp()) - MouseButtonJustClicked = 3; - else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) - MouseButtonJustClicked = 2; - else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) - MouseButtonJustClicked = 4; - else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) - MouseButtonJustClicked = 5; - // TODO two more buttons - - JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); - - int32 TypeOfControl = KEYBOARD; - if (JoyButtonJustClicked) - TypeOfControl = JOYSTICK; - if (MouseButtonJustClicked) - TypeOfControl = MOUSE; - if (*pControlEdit != rsNULL) - TypeOfControl = KEYBOARD; - - if (!m_bKeyIsOK) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - pControlEdit = nil; - m_bWaitingForNewKeyBind = false; - m_KeyPressedCode = -1; - m_bStartWaitingForKeyBind = false; - } else if (!m_bKeyChangeNotProcessed) { - if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) - CheckCodesForControls(TypeOfControl); - - field_535 = true; - } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - for (int i = 0; i < 4; i++) - ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); - m_bKeyIsOK = false; - m_bKeyChangeNotProcessed = false; - pControlEdit = nil; - m_bWaitingForNewKeyBind = false; - m_KeyPressedCode = -1; - m_bStartWaitingForKeyBind = false; - } - } - } - - if ((m_nCurrScreen == MENUPAGE_NO_MEMORY_CARD || m_nCurrScreen == MENUPAGE_PS2_LOAD_FAILED) && CTimer::GetTimeInMillisecondsPauseMode() > field_558) { - m_nCurrScreen = m_nPrevScreen; - m_nCurrOption = 0; - } - - // Reset pad shaking. - if (TimeToStopPadShaking && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode()) { - CPad::StopPadsShaking(); - TimeToStopPadShaking = 0; - } - - } else { - UnloadTextures(); - m_bRenderGameInMenu = false; - // byte_5F33E4 = 1; // unused - ChangeScreen(MENUPAGE_NONE, 0, false, false); - pEditString = nil; - m_bWaitingForNewKeyBind = false; - } - - if (!m_bWantToRestart) { - if (m_bGameNotLoaded) - DMAudio.Service(); - } } void CMenuManager::ProcessButtonPresses(void) { + // TODO(Miami) + // if (m_nCurrScreen == MENUPAGE_OUTRO) + // return; + + if (m_bWaitingForNewKeyBind) { + if (m_bStartWaitingForKeyBind) + m_bStartWaitingForKeyBind = false; + else { + pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); + JoyButtonJustClicked = false; + MouseButtonJustClicked = false; + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) + MouseButtonJustClicked = 1; + else if (CPad::GetPad(0)->GetRightMouseJustUp()) + MouseButtonJustClicked = 3; + else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) + MouseButtonJustClicked = 2; + else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) + MouseButtonJustClicked = 4; + else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) + MouseButtonJustClicked = 5; + // TODO two more buttons + + JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); + + int32 TypeOfControl = KEYBOARD; + if (JoyButtonJustClicked) + TypeOfControl = JOYSTICK; + if (MouseButtonJustClicked) + TypeOfControl = MOUSE; + if (*pControlEdit != rsNULL) + TypeOfControl = KEYBOARD; + + if (!m_bKeyIsOK) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + pControlEdit = nil; + m_bWaitingForNewKeyBind = false; + m_KeyPressedCode = -1; + m_bStartWaitingForKeyBind = false; + } + else if (!m_bKeyChangeNotProcessed) { + if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) + CheckCodesForControls(TypeOfControl); + + field_159 = true; + } + else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + for (int i = 0; i < 4; i++) + ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); + m_bKeyIsOK = false; + m_bKeyChangeNotProcessed = false; + pControlEdit = nil; + m_bWaitingForNewKeyBind = false; + m_KeyPressedCode = -1; + m_bStartWaitingForKeyBind = false; + } + } + } + if (pEditString || pControlEdit) return; @@ -3627,7 +3348,7 @@ CMenuManager::ProcessButtonPresses(void) optionSelected = true; } #endif - if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) { + if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_159) { if (m_nCurrExLayer == HOVEROPTION_LIST) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; m_bWaitingForNewKeyBind = true; @@ -3636,7 +3357,7 @@ CMenuManager::ProcessButtonPresses(void) pControlEdit = &m_KeyPressedCode; } } else { - field_535 = false; + field_159 = false; } static uint32 lastTimeClickedScrollButton = 0; @@ -4452,30 +4173,6 @@ CMenuManager::ProcessButtonPresses(void) case MENUACTION_RESUME_FROM_SAVEZONE: RequestFrontEndShutDown(); break; - case MENUACTION_MPMAP_LIBERTY: - case MENUACTION_MPMAP_REDLIGHT: - case MENUACTION_MPMAP_CHINATOWN: - case MENUACTION_MPMAP_TOWER: - case MENUACTION_MPMAP_SEWER: - case MENUACTION_MPMAP_INDUSTPARK: - case MENUACTION_MPMAP_DOCKS: - case MENUACTION_MPMAP_STAUNTON: - m_SelectedMap = option - MENUACTION_MPMAP_LIBERTY; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_MPMAP_DEATHMATCH1: - case MENUACTION_MPMAP_DEATHMATCH2: - case MENUACTION_MPMAP_TEAMDEATH1: - case MENUACTION_MPMAP_TEAMDEATH2: - case MENUACTION_MPMAP_STASH: - case MENUACTION_MPMAP_CAPTURE: - case MENUACTION_MPMAP_RATRACE: - case MENUACTION_MPMAP_DOMINATION: - m_SelectedGameType = option - MENUACTION_MPMAP_DEATHMATCH1; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; case MENUACTION_REDEFCTRL: ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); m_nSelectedListRow = 0; @@ -4509,7 +4206,13 @@ CMenuManager::ProcessButtonPresses(void) if (m_nDisplayVideoMode != m_nPrefsVideoMode) { m_nPrefsVideoMode = m_nDisplayVideoMode; _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); + SetHelperText(0); // TODO(Miami): Remove that + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.Service(); + CentreMousePointer(); + m_bShowMouse = true; + // m_nCurrOption = 5; // Why? + bOptionHighlightTransitionBlend = 0; SaveSettings(); } break; @@ -4651,7 +4354,7 @@ CMenuManager::ProcessButtonPresses(void) #else if (m_nCurrScreen == MENUPAGE_PAUSE_MENU) { #endif - if (!m_bGameNotLoaded && !m_bMenuStateChanged) { + if (!m_bGameNotLoaded) { if (m_PrefsVsyncDisp != m_PrefsVsync) { m_PrefsVsync = m_PrefsVsyncDisp; } @@ -4858,11 +4561,6 @@ CMenuManager::ProcessOnOffMenuOptions() switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_CTRLVIBRATION: m_PrefsUseVibration = !m_PrefsUseVibration; - - if (m_PrefsUseVibration) { - CPad::GetPad(0)->StartShake(350, 150); - TimeToStopPadShaking = CTimer::GetTimeInMillisecondsPauseMode() + 500; - } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); break; case MENUACTION_CTRLCONFIG: @@ -4871,10 +4569,6 @@ CMenuManager::ProcessOnOffMenuOptions() CPad::GetPad(0)->Mode = 0; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); break; - case MENUACTION_CTRLDISPLAY: - m_DisplayControllerOnFoot = !m_DisplayControllerOnFoot; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - break; case MENUACTION_FRAMESYNC: m_PrefsVsyncDisp = !m_PrefsVsyncDisp; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); @@ -4926,11 +4620,6 @@ CMenuManager::ProcessOnOffMenuOptions() gbShowCollisionPolys = !gbShowCollisionPolys; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); break; - case MENUACTION_MP_PLAYERCOLOR: - PickNewPlayerColour(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); - SaveSettings(); - break; case MENUACTION_SHOWHEADBOB: TheCamera.m_bHeadBob = !TheCamera.m_bHeadBob; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); @@ -4959,7 +4648,6 @@ void CMenuManager::RequestFrontEndShutDown() { m_bShutDownFrontEndRequested = true; - DMAudio.ChangeMusicMode(MUSICMODE_GAME); } void @@ -5008,13 +4696,6 @@ CMenuManager::SetHelperText(int text) m_nHelperTextAlpha = 300; } -void -CMenuManager::ShutdownJustMenu() -{ - m_bMenuActive = false; - CTimer::EndUserPause(); -} - float CMenuManager::StretchX(float x) { @@ -5034,81 +4715,131 @@ float CMenuManager::StretchY(float y) return SCREEN_STRETCH_Y(y); } +void +CMenuManager::ProcessFileActions() +{ + if (m_nCurrScreen == MENUPAGE_DELETING) { + bool SlotPopulated = false; + + if (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) { + PcSaveHelper.PopulateSlotInfo(); + SlotPopulated = true; + } + + if (SlotPopulated) + ChangeScreen(MENUPAGE_DELETE_SUCCESS, 0, true, false); + else + SaveLoadFileError_SetUpErrorScreen(); + } + if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) { + int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); + PcSaveHelper.PopulateSlotInfo(); + if (SaveSlot) + ChangeScreen(MENUPAGE_SAVE_SUCCESSFUL, 0, true, false); + else + SaveLoadFileError_SetUpErrorScreen(); + } + if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS) { + if (CheckSlotDataValid(m_nCurrSaveSlot)) { + DoSettingsBeforeStartingAGame(); + m_bWantToLoad = true; + } + else + SaveLoadFileError_SetUpErrorScreen(); + } +} + void CMenuManager::SwitchMenuOnAndOff() { - bool menuWasActive = GetIsMenuActive(); + if (!TheCamera.m_WideScreenOn) { - // Reminder: You need REGISTER_START_BUTTON defined to make it work. - if (CPad::GetPad(0)->GetStartJustDown() -#ifdef FIX_BUGS - && !m_bGameNotLoaded -#endif - || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { + // Reminder: You need REGISTER_START_BUTTON defined to make it work. + if ((CPad::GetPad(0)->GetStartJustDown() || CPad::GetPad(0)->GetEscapeJustDown()) + && (!m_bMenuActive || m_nCurrScreen == MENUPAGE_PAUSE_MENU || m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT/* || m_nCurrScreen == 20 */) // TODO(Miami): What is screen 20? + || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { - m_bMenuActive = !m_bMenuActive; + if (m_nCurrScreen != MENUPAGE_LOADING_IN_PROGRESS) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + } - if (m_bShutDownFrontEndRequested) - m_bMenuActive = false; - if (m_bStartUpFrontEndRequested) - m_bMenuActive = true; + if (m_bShutDownFrontEndRequested) + m_bMenuActive = false; + else if (m_bStartUpFrontEndRequested) + m_bMenuActive = true; + else + m_bMenuActive = !m_bMenuActive; + + if (m_bMenuActive) { + Initialise(); + LoadAllTextures(); + + // TODO(Miami): DxInput?? + } else { + if (CMBlur::BlurOn) + CMBlur::MotionBlurOpen(Scene.camera); + else + CMBlur::MotionBlurClose(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + + // TODO(Miami): DxInput?? - if (m_bMenuActive) { - CTimer::StartUserPause(); - } else { #ifdef PS2_LIKE_MENU - bottomBarActive = false; + bottomBarActive = false; #endif -#ifdef FIX_BUGS - ThingsToDoBeforeLeavingPage(); -#endif - ShutdownJustMenu(); - SaveSettings(); - m_bStartUpFrontEndRequested = false; - pControlEdit = nil; - m_bShutDownFrontEndRequested = false; - DisplayComboButtonErrMsg = false; + + m_StatsScrollSpeed = 150.0f; + SaveSettings(); + pControlEdit = nil; + pEditString = nil; + DisplayComboButtonErrMsg = false; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + m_bWaitingForNewKeyBind = false; #ifdef REGISTER_START_BUTTON - int16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start, - start3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start; + int16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start, + start3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start; #endif - CPad::GetPad(0)->Clear(false); - CPad::GetPad(1)->Clear(false); + CPad::GetPad(0)->Clear(false); + CPad::GetPad(1)->Clear(false); #ifdef REGISTER_START_BUTTON - CPad::GetPad(0)->PCTempJoyState.Start = start1; - CPad::GetPad(0)->PCTempKeyState.Start = start2; - CPad::GetPad(0)->OldState.Start = start3; - CPad::GetPad(0)->NewState.Start = start4; + CPad::GetPad(0)->PCTempJoyState.Start = start1; + CPad::GetPad(0)->PCTempKeyState.Start = start2; + CPad::GetPad(0)->OldState.Start = start3; + CPad::GetPad(0)->NewState.Start = start4; #endif - m_nCurrScreen = MENUPAGE_NONE; + UnloadTextures(); + CTimer::EndUserPause(); + CTimer::Update(); + m_OnlySaveMenu = false; + } } } // Just entered the save/safe zone - if (m_bSaveMenuActive && !m_bQuitGameNoCD) { - m_bSaveMenuActive = false; + if (m_bActivateSaveMenu) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_bActivateSaveMenu = false; m_bMenuActive = true; - CTimer::StartUserPause(); -#ifdef PS2_SAVE_DIALOG - m_nCurrScreen = MENUPAGE_SAVE; - m_bRenderGameInMenu = true; -#else + m_OnlySaveMenu = true; + + // TODO(Miami): DxInput?? + + Initialise(); + LoadAllTextures(); m_nCurrScreen = MENUPAGE_CHOOSE_SAVE_SLOT; -#endif - PcSaveHelper.PopulateSlotInfo(); m_nCurrOption = 0; } -/* // PS2 leftover - if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) - { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); - gMusicPlaying = 0; - } -*/ - if (m_bMenuActive != menuWasActive) - m_bMenuStateChanged = true; m_bStartUpFrontEndRequested = false; m_bShutDownFrontEndRequested = false; @@ -5117,25 +4848,31 @@ CMenuManager::SwitchMenuOnAndOff() void CMenuManager::UnloadTextures() { - if (!m_bSpritesLoaded) - return; + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) + DMAudio.StopFrontEndTrack(); - printf("REMOVE frontend\n"); - for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i) - m_aFrontEndSprites[i].Delete(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); + if (m_bSpritesLoaded) { + printf("REMOVE frontend\n"); + int frontend = CTxdStore::FindTxdSlot("frontend1"); + for (int i = 0; i < 3; ++i) + m_aFrontEndSprites[i].Delete(); - int frontend = CTxdStore::FindTxdSlot("frontend1"); - CTxdStore::RemoveTxd(frontend); + CTxdStore::RemoveTxd(frontend); - int frontend2 = CTxdStore::FindTxdSlot("frontend2"); - CTxdStore::RemoveTxd(frontend2); + if (!m_OnlySaveMenu) { + int frontend2 = CTxdStore::FindTxdSlot("frontend2"); + for (int i = 3; i < NUM_MENU_SPRITES; ++i) + m_aFrontEndSprites[i].Delete(); -#ifdef false //MENU_MAP - for (int i = 0; i < ARRAY_SIZE(MapFilenames); ++i) - m_aMapSprites[i].Delete(); -#endif + CTxdStore::RemoveTxd(frontend2); + } - m_bSpritesLoaded = false; + m_bSpritesLoaded = false; + } + m_OnlySaveMenu = false; + // TODO(Miami): Place name thing } void @@ -5166,278 +4903,53 @@ CMenuManager::WaitForUserCD() } } -void -CMenuManager::PrintController(void) -{ - // FIX: Originally this function doesn't have StretchX/Y, everything had constant pixel size (due to screen was abandoned early?) - // Also texts and their alignment were very bad, so I tried to make them readable (commented out the original code, and marked the ones I added with X) - - // sorry! - - /* - m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(240.0f), MENU_Y(180.0f), CRGBA(0, 0, 0, 255)); - m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - if (m_DisplayControllerOnFoot) { - if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400) - m_aFrontEndSprites[FE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - else - m_aFrontEndSprites[FE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - } else { - if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400) - m_aFrontEndSprites[FE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - else - m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - } - */ - - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // X - - // CFont::SetScale(0.4f, 0.4f); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); // X - - // CFont::SetColor(CRGBA(128, 128, 128, FadeIn(255))); - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // X - CFont::SetDropShadowPosition(1); // X - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); // X - - if (m_DisplayControllerOnFoot) { - switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); - break; - default: - return; - } - } else { - switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_RS3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); - break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_SMT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_ACC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_BRA")); - break; - default: - return; - } - } - - CFont::SetDropShadowPosition(0); // X -} - #ifdef MENU_MAP #define ZOOM(x, y, in) \ do { \ - if(fMapSize > SCREEN_HEIGHT * 3.0f && in) \ + if(m_fMapSize > SCREEN_HEIGHT * 3.0f && in) \ break; \ float z2 = in? 1.1f : 1.f/1.1f; \ - fMapCenterX += (x - fMapCenterX) * (1.0f - z2); \ - fMapCenterY += (y - fMapCenterY) * (1.0f - z2); \ + m_fMapCenterX += (x - m_fMapCenterX) * (1.0f - z2); \ + m_fMapCenterY += (y - m_fMapCenterY) * (1.0f - z2); \ \ - if (fMapSize < SCREEN_HEIGHT / 2 && !in) \ + if (m_fMapSize < SCREEN_HEIGHT / 2 && !in) \ break; \ \ - fMapSize *= z2; \ + m_fMapSize *= z2; \ } while(0) \ void CMenuManager::PrintMap(void) { CFont::SetJustifyOn(); - bMenuMapActive = true; + m_bMenuMapActive = true; CRadar::InitFrontEndMap(); // Just entered to map if (!bMapLoaded) { - fMapSize = SCREEN_HEIGHT * 2.0f; - fMapCenterX = 0.0f; - fMapCenterY = 0.0f; + m_fMapSize = SCREEN_HEIGHT * 2.0f; + m_fMapCenterX = 0.0f; + m_fMapCenterY = 0.0f; CVector2D radarSpacePlayer; CVector2D screenSpacePlayer; CRadar::TransformRealWorldPointToRadarSpace(radarSpacePlayer, CVector2D(FindPlayerCoors())); CRadar::TransformRadarPointToScreenSpace(screenSpacePlayer, radarSpacePlayer); - fMapCenterX = (-screenSpacePlayer.x) + SCREEN_WIDTH / 2; - fMapCenterY = (-screenSpacePlayer.y) + SCREEN_HEIGHT / 2; + m_fMapCenterX = (-screenSpacePlayer.x) + SCREEN_WIDTH / 2; + m_fMapCenterY = (-screenSpacePlayer.y) + SCREEN_HEIGHT / 2; bMapMouseShownOnce = false; bMapLoaded = true; // Let's wait for a frame to not toggle the waypoint if (CPad::GetPad(0)->NewState.Cross) { - bMenuMapActive = false; + m_bMenuMapActive = false; return; } } - // Because fMapSize is half of the map length, and map consists of 3x3 tiles. - float halfTile = fMapSize / 3.0f; + // Because m_fMapSize is half of the map length, and map consists of 3x3 tiles. + float halfTile = m_fMapSize / 3.0f; // Darken background a bit CSprite2d::DrawRect(CRect(0, 0, @@ -5446,49 +4958,49 @@ CMenuManager::PrintMap(void) RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize, - fMapCenterX - halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - m_fMapSize, + m_fMapCenterX - halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize, - fMapCenterX + halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - m_fMapSize, + m_fMapCenterX + halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize, - fMapCenterX + fMapSize, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - m_fMapSize, + m_fMapCenterX + m_fMapSize, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile, - fMapCenterX - halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - halfTile, + m_fMapCenterX - halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile, - fMapCenterX + halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - halfTile, + m_fMapCenterX + halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile, - fMapCenterX + fMapSize, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - halfTile, + m_fMapCenterX + m_fMapSize, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile, - fMapCenterX - halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY + halfTile, + m_fMapCenterX - halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile, - fMapCenterX + halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY + halfTile, + m_fMapCenterX + halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); } - if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile, - fMapCenterX + fMapSize, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY + halfTile, + m_fMapCenterX + m_fMapSize, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); } CRadar::DrawBlips(); @@ -5512,35 +5024,35 @@ CMenuManager::PrintMap(void) CRGBA(0, 0, 0, 150)); if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - if (mapPoint.y > fMapCenterY - fMapSize && mapPoint.y < fMapCenterY + fMapSize && - mapPoint.x > fMapCenterX - fMapSize && mapPoint.x < fMapCenterX + fMapSize) { + if (mapPoint.y > m_fMapCenterY - m_fMapSize && mapPoint.y < m_fMapCenterY + m_fMapSize && + mapPoint.x > m_fMapCenterX - m_fMapSize && mapPoint.x < m_fMapCenterX + m_fMapSize) { // Don't ask me the meanings, I don't know. Found them by trying - float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize; - float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT); - float y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapPoint.y - diffY) / (fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE); + float diffX = m_fMapCenterX - m_fMapSize, diffY = m_fMapCenterY - m_fMapSize; + float x = ((mapPoint.x - diffX) / (m_fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT); + float y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapPoint.y - diffY) / (m_fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE); CRadar::ToggleTargetMarker(x, y); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); } } if (CPad::GetPad(0)->GetLeftMouse()) { - fMapCenterX += m_nMousePosX - m_nMouseOldPosX; - fMapCenterY += m_nMousePosY - m_nMouseOldPosY; + m_fMapCenterX += m_nMousePosX - m_nMouseOldPosX; + m_fMapCenterY += m_nMousePosY - m_nMouseOldPosY; } else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { - fMapCenterX += 15.0f; + m_fMapCenterX += 15.0f; } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { - fMapCenterX -= 15.0f; + m_fMapCenterX -= 15.0f; } else if (CPad::GetPad(0)->GetLeftStickX()) { - fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; + m_fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; } if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetDPadUp()) { - fMapCenterY += 15.0f; + m_fMapCenterY += 15.0f; } else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { - fMapCenterY -= 15.0f; + m_fMapCenterY -= 15.0f; } else if (CPad::GetPad(0)->GetLeftStickY()) { - fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; + m_fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; } if (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { @@ -5555,19 +5067,19 @@ CMenuManager::PrintMap(void) ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); } - if (fMapCenterX - fMapSize > SCREEN_WIDTH / 2) - fMapCenterX = fMapSize + SCREEN_WIDTH / 2; + if (m_fMapCenterX - m_fMapSize > SCREEN_WIDTH / 2) + m_fMapCenterX = m_fMapSize + SCREEN_WIDTH / 2; - if (fMapCenterX + fMapSize < SCREEN_WIDTH / 2) - fMapCenterX = SCREEN_WIDTH / 2 - fMapSize; + if (m_fMapCenterX + m_fMapSize < SCREEN_WIDTH / 2) + m_fMapCenterX = SCREEN_WIDTH / 2 - m_fMapSize; - if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) - fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; + if (m_fMapCenterY + m_fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) + m_fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - m_fMapSize; - if (fMapCenterY - fMapSize > SCREEN_HEIGHT / 2) - fMapCenterY = SCREEN_HEIGHT / 2 + fMapSize; + if (m_fMapCenterY - m_fMapSize > SCREEN_HEIGHT / 2) + m_fMapCenterY = SCREEN_HEIGHT / 2 + m_fMapSize; - bMenuMapActive = false; + m_bMenuMapActive = false; // CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(5.0f)); // From VC // CFont::SetRightJustifyWrap(10.0f); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 114ea6ba..a867e4c8 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -95,42 +95,6 @@ enum eLanguages #endif }; -/* -enum eFrontendSprites -{ - FE2_MAINPANEL_UL, - FE2_MAINPANEL_UR, - FE2_MAINPANEL_DL, - FE2_MAINPANEL_DR, - FE2_MAINPANEL_DR2, - FE2_TABACTIVE, - FE_ICONBRIEF, - FE_ICONSTATS, - FE_ICONCONTROLS, - FE_ICONSAVE, - FE_ICONAUDIO, - FE_ICONDISPLAY, - FE_ICONLANGUAGE, - FE_CONTROLLER, - FE_CONTROLLERSH, - FE_ARROWS1, - FE_ARROWS2, - FE_ARROWS3, - FE_ARROWS4, - FE_RADIO1, - FE_RADIO2, - FE_RADIO3, - FE_RADIO4, - FE_RADIO5, - FE_RADIO6, - FE_RADIO7, - FE_RADIO8, - FE_RADIO9, - - NUM_FE_SPRITES -}; -*/ - enum eMenuSprites { MENUSPRITE_BACKGROUND, @@ -177,22 +141,6 @@ enum eSaveSlot SAVESLOT_LABEL = 36 }; -#ifdef MENU_MAP -enum MapSprites -{ - MAPMID1, - MAPMID2, - MAPMID3, - MAPBOT1, - MAPBOT2, - MAPBOT3, - MAPTOP1, - MAPTOP2, - MAPTOP3, - NUM_MAP_SPRITES -}; -#endif - enum eMenuScreen { MENUPAGE_DISABLED = -1, @@ -480,70 +428,162 @@ struct CMenuScreen } m_aEntries[NUM_MENUROWS]; }; +struct MenuTrapezoid +{ + float topRight_x; + float topRight_y; + float topLeft_x; + float topLeft_y; + float bottomLeft_x; + float bottomLeft_y; + float bottomRight_x; + float bottomRight_y; + float old_topRight_x; + float old_topRight_y; + float old_topLeft_x; + float old_topLeft_y; + float old_bottomLeft_x; + float old_bottomLeft_y; + float old_bottomRight_x; + float old_bottomRight_y; + float mult_topRight_x; + float mult_topRight_y; + float mult_topLeft_x; + float mult_topLeft_y; + float mult_bottomLeft_x; + float mult_bottomLeft_y; + float mult_bottomRight_x; + float mult_bottomRight_y; + + MenuTrapezoid(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { + topRight_x = x1; + topRight_y = y1; + topLeft_x = x2; + topLeft_y = y2; + bottomLeft_x = x3; + bottomLeft_y = y3; + bottomRight_x = x4; + bottomRight_y = y4; + }; +}; + class CMenuManager { public: - int32 m_nPrefsVideoMode; - int32 m_nDisplayVideoMode; + int8 m_StatsScrollDirection; + float m_StatsScrollSpeed; + uint8 field_8; + bool m_PrefsUseVibration; + bool m_PrefsShowHud; + int32 m_PrefsRadarMode; + uint8 field_10; + bool m_bShutDownFrontEndRequested; + bool m_bStartUpFrontEndRequested; + int32 m_KeyPressedCode; + int32 m_PrefsBrightness; + float m_PrefsLOD; + int8 m_PrefsShowSubtitles; + int8 m_PrefsShowLegends; + int8 m_PrefsUseWideScreen; + int8 m_PrefsVsync; // TODO(Miami): Are we sure? + int8 m_PrefsVsyncDisp; + int8 m_PrefsFrameLimiter; int8 m_nPrefsAudio3DProviderIndex; - bool m_bKeyChangeNotProcessed; - char m_aSkinName[256]; - int32 m_nHelperTextMsgId; - bool m_bLanguageLoaded; + int8 m_PrefsSpeakers; + int8 m_PrefsDMA; + uint8 m_PrefsSfxVolume; + uint8 m_PrefsMusicVolume; + uint8 m_PrefsRadioStation; + uint8 field_2C; + int32 m_nCurrOption; + bool m_bQuitGameNoCD; + bool m_bMenuMapActive; + bool m_AllowNavigation; + uint8 field_37; bool m_bMenuActive; - bool m_bMenuStateChanged; - bool m_bWaitingForNewKeyBind; bool m_bWantToRestart; bool m_bFirstTime; - bool m_bGameNotLoaded; - int32 m_nMousePosX; - int32 m_nMousePosY; + bool m_bActivateSaveMenu; + bool m_bWantToLoad; + float m_fMapSize; + float m_fMapCenterX; + float m_fMapCenterY; + uint32 OS_Language; + int32 m_PrefsLanguage; + int32 field_54; + int8 m_bLanguageLoaded; + uint8 m_PrefsAllowNastyGame; + uint8 m_PrefsMP3BoostVolume; + uint8 m_ControlMethod; + int32 m_nPrefsVideoMode; + int32 m_nDisplayVideoMode; int32 m_nMouseTempPosX; int32 m_nMouseTempPosY; + bool m_bGameNotLoaded; + int8 m_3DProviderOnLastSaveLoad; + bool m_bFrontEnd_ReloadObrTxtGxt; + int32 *pEditString; + uint8 field_74[4]; + int32 *pControlEdit; + bool m_OnlySaveMenu; + int32 m_menuTransitionProgress; + CSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES]; + bool m_bSpritesLoaded; + int32 field_F0; + int32 m_LastRadioScrollDir; + int32 m_nCurrScreen; + int32 m_nPrevScreen; + int32 m_nCurrSaveSlot; + int32 m_LastScreenSwitch; + uint32 m_nMenuFadeAlpha; + int32 bOptionHighlightTransitionBlend; + bool bMenuChangeOngoing; + int32 MouseButtonJustClicked; + int32 JoyButtonJustClicked; + bool DisplayComboButtonErrMsg; + bool m_NoEmptyBinding; + bool m_ShowEmptyBindingError; + int32 m_nHelperTextAlpha; + bool m_bPressedPgUpOnList; + bool m_bPressedPgDnOnList; + bool m_bPressedUpOnList; + bool m_bPressedDownOnList; + bool m_bPressedScrollButton; + uint8 field_129; + uint8 field_12A; + uint8 field_12B; + int32 m_nMousePosX; + int32 m_nMousePosY; + int32 m_nMouseOldPosX; + int32 m_nMouseOldPosY; + int32 m_nHoverOption; bool m_bShowMouse; + int32 m_nPrevOption; + bool m_bStartWaitingForKeyBind; + bool m_bWaitingForNewKeyBind; + bool m_bKeyChangeNotProcessed; + int32 m_CurrCntrlAction; + uint8 field_150; + uint8 field_151; + uint8 field_152; + uint8 field_153; + int32 m_nSelectedContSetupColumn; + bool m_bKeyIsOK; + bool field_159; + uint8 m_nCurrExLayer; + char m_PrefsSkinFile[256]; + char m_aSkinName[256]; + uint8 field_35B; + int32 m_nHelperTextMsgId; tSkinInfo m_pSkinListHead; tSkinInfo *m_pSelectedSkin; int32 m_nFirstVisibleRowOnList; float m_nScrollbarTopMargin; int32 m_nTotalListRow; int32 m_nSkinsTotal; - char _unk0[4]; + uint8 field_67C[4]; int32 m_nSelectedListRow; bool m_bSkinsEnumerated; - bool m_bQuitGameNoCD; - bool m_bRenderGameInMenu; - bool m_bSaveMenuActive; - bool m_bWantToLoad; - char field_455; - bool m_bStartWaitingForKeyBind; - bool m_bSpritesLoaded; - //CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES]; - //CSprite2d m_aMenuSprites[NUM_MENU_SPRITES]; - CSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES]; - int32 field_518; - int32 m_nMenuFadeAlpha; - bool m_bPressedPgUpOnList; - bool m_bPressedPgDnOnList; - bool m_bPressedUpOnList; - bool m_bPressedDownOnList; - bool m_bPressedScrollButton; - int32 m_CurrCntrlAction; - char _unk1[4]; - int32 m_nSelectedContSetupColumn; - bool m_bKeyIsOK; - bool field_535; - int8 m_nCurrExLayer; - int32 m_nHelperTextAlpha; - int32 m_nMouseOldPosX; - int32 m_nMouseOldPosY; - int32 m_nHoverOption; - int32 m_nCurrScreen; - int32 m_nCurrOption; - int32 m_nPrevOption; - int32 m_nPrevScreen; - uint32 field_558; - int32 m_nCurrSaveSlot; - int32 m_nScreenChangeDelayTimer; #ifdef IMPROVED_VIDEOMODE int32 m_nPrefsWidth; @@ -554,107 +594,63 @@ public: int32 m_nSelectedScreenMode; #endif -public: bool GetIsMenuActive() {return !!m_bMenuActive;} -public: - static int32 OS_Language; - static int8 m_PrefsUseVibration; - static int8 m_DisplayControllerOnFoot; - static int8 m_PrefsUseWideScreen; - static int8 m_PrefsRadioStation; - static int8 m_PrefsVsync; - static int8 m_PrefsVsyncDisp; - static int8 m_PrefsFrameLimiter; - static int8 m_PrefsShowSubtitles; - static int8 m_PrefsSpeakers; - static int32 m_ControlMethod; - static int8 m_PrefsDMA; - static int32 m_PrefsLanguage; - static int32 m_PrefsBrightness; - static float m_PrefsLOD; - static int8 m_bFrontEnd_ReloadObrTxtGxt; - static int32 m_PrefsMusicVolume; - static int32 m_PrefsSfxVolume; - static char m_PrefsSkinFile[256]; - static int32 m_KeyPressedCode; - - static bool m_bStartUpFrontEndRequested; - static bool m_bShutDownFrontEndRequested; - static bool m_PrefsAllowNastyGame; - static uint8 m_PrefsStereoMono; - static int32 m_SelectedMap; - static int32 m_SelectedGameType; - static uint8 m_PrefsPlayerRed; - static uint8 m_PrefsPlayerGreen; - static uint8 m_PrefsPlayerBlue; #ifndef MASTER static bool m_PrefsMarketing; static bool m_PrefsDisableTutorials; #endif // !MASTER -#ifdef MENU_MAP - static bool bMenuMapActive; - static bool bMapMouseShownOnce; - static bool bMapLoaded; - static float fMapSize; - static float fMapCenterY; - static float fMapCenterX; - static CSprite2d m_aMapSprites[NUM_MAP_SPRITES]; + CMenuManager(void); + ~CMenuManager(void) { UnloadTextures(); } + + void Initialise(); void PrintMap(); -#endif - -public: + void SetFrontEndRenderStates(); static void BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2); static void CentreMousePointer(); void CheckCodesForControls(int); bool CheckHover(int x1, int x2, int y1, int y2); void CheckSliderMovement(int); - int CostructStatLine(int); void DisplayHelperText(); int DisplaySlider(float, float, float, float, float, float); void DoSettingsBeforeStartingAGame(); - void Draw(); + void DrawStandardMenus(); void DrawControllerBound(int32, int32, int32, int8); void DrawControllerScreenExtraText(int, int, int); void DrawControllerSetupScreen(); void DrawFrontEnd(); - void DrawFrontEndNormal(); -#ifdef PS2_SAVE_DIALOG - void DrawFrontEndSaveZone(); -#endif + void DrawBackground(); void DrawPlayerSetupScreen(); int FadeIn(int alpha); void FilterOutColorMarkersFromString(wchar*, CRGBA &); int GetStartOptionsCntrlConfigScreens(); - static void InitialiseChangedLanguageSettings(); + void InitialiseChangedLanguageSettings(); void LoadAllTextures(); void LoadSettings(); void MessageScreen(const char *); // TODO(MIAMI): implement the second argument void MessageScreen(const char *str, bool) { MessageScreen(str); } - void PickNewPlayerColour(); void PrintBriefs(); static void PrintErrorMessage(); void PrintStats(); void Process(); void ProcessButtonPresses(); + void ProcessFileActions(); void ProcessOnOffMenuOptions(); - static void RequestFrontEndShutDown(); - static void RequestFrontEndStartUp(); + void RequestFrontEndShutDown(); + void RequestFrontEndStartUp(); void ResetHelperText(); void SaveLoadFileError_SetUpErrorScreen(); void SaveSettings(); void SetHelperText(int text); - void ShutdownJustMenu(); float StretchX(float); float StretchY(float); void SwitchMenuOnAndOff(); void UnloadTextures(); void WaitForUserCD(); - void PrintController(); int GetNumOptionsCntrlConfigScreens(); int ConstructStatLine(int); @@ -669,7 +665,7 @@ public: }; #ifndef IMPROVED_VIDEOMODE -VALIDATE_SIZE(CMenuManager, 0x564); +VALIDATE_SIZE(CMenuManager, 0x688); #endif extern CMenuManager FrontEndMenuManager; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 3f4a3217..385b3892 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -221,20 +221,20 @@ bool CGame::InitialiseOnceAfterRW(void) if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -99 || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) { - CMenuManager::m_PrefsSpeakers = 0; + FrontEndMenuManager.m_PrefsSpeakers = 0; int8 provider = DMAudio.AutoDetect3DProviders(); if ( provider != -1 ) FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = provider; } DMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); - DMAudio.SetSpeakerConfig(CMenuManager::m_PrefsSpeakers); - DMAudio.SetDynamicAcousticModelingStatus(CMenuManager::m_PrefsDMA); - DMAudio.SetMusicMasterVolume(CMenuManager::m_PrefsMusicVolume); - DMAudio.SetEffectsMasterVolume(CMenuManager::m_PrefsSfxVolume); + DMAudio.SetSpeakerConfig(FrontEndMenuManager.m_PrefsSpeakers); + DMAudio.SetDynamicAcousticModelingStatus(FrontEndMenuManager.m_PrefsDMA); + DMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume); DMAudio.SetEffectsFadeVol(127); DMAudio.SetMusicFadeVol(127); - CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); + CWorld::Players[0].SetPlayerSkin(FrontEndMenuManager.m_PrefsSkinFile); return true; } diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index 6c2ebdb8..e9e37a9b 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -206,20 +206,12 @@ const CMenuScreen aScreens[] = { MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, }, - // Unused in PC but anyway // MENUPAGE_SAVE = 24 -#ifdef PS2_SAVE_DIALOG - { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_CHANGEMENU, "FESZ_SA", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, - }, -#else { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, MENUACTION_LABEL, "FES_SCG", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, }, -#endif // MENUPAGE_NO_MEMORY_CARD_2 = 25 { "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index ae7fcdb4..c3fb69d6 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -701,7 +701,7 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &Stat void CPad::StartShake(int16 nDur, uint8 nFreq) { - if ( !CMenuManager::m_PrefsUseVibration ) + if ( !FrontEndMenuManager.m_PrefsUseVibration ) return; if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) @@ -723,7 +723,7 @@ void CPad::StartShake(int16 nDur, uint8 nFreq) void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fZ) { - if ( !CMenuManager::m_PrefsUseVibration ) + if ( !FrontEndMenuManager.m_PrefsUseVibration ) return; if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) @@ -750,7 +750,7 @@ void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, floa void CPad::StartShake_Train(float fX, float fY) { - if ( !CMenuManager::m_PrefsUseVibration ) + if ( !FrontEndMenuManager.m_PrefsUseVibration ) return; if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 1267896a..95ae62a0 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -264,7 +264,7 @@ int LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D & uint8 CRadar::CalculateBlipAlpha(float dist) { #ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) + if (FrontEndMenuManager.m_bMenuMapActive) return 255; #endif if (dist <= 1.0f) @@ -487,7 +487,7 @@ void CRadar::DrawBlips() TransformRadarPointToScreenSpace(out, in); #ifdef MENU_MAP - if (!CMenuManager::bMenuMapActive) { + if (!FrontEndMenuManager.m_bMenuMapActive) { #endif float angle; if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN) @@ -555,7 +555,7 @@ void CRadar::DrawBlips() TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition()); float dist = LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); - if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) { + if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) { if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) { DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); } @@ -597,7 +597,7 @@ void CRadar::DrawBlips() TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos); float dist = LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); - if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) { + if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) { if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) { DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); } @@ -666,7 +666,7 @@ void CRadar::DrawBlips() TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition()); float dist = LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); - if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) { + if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) { if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); else @@ -717,7 +717,7 @@ void CRadar::DrawBlips() TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos); float dist = LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); - if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || CMenuManager::bMenuMapActive) { + if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) { if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); else @@ -744,7 +744,7 @@ void CRadar::DrawBlips() } } #ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { + if (FrontEndMenuManager.m_bMenuMapActive) { CVector2D in, out; TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift()); TransformRadarPointToScreenSpace(out, in); @@ -899,7 +899,7 @@ void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha) { RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); #ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { + if (FrontEndMenuManager.m_bMenuMapActive) { bool alreadyThere = false; for (int i = 0; i < NUM_MAP_LEGENDS; i++) { if (MapLegendList[i] == sprite) @@ -1047,7 +1047,7 @@ float CRadar::LimitRadarPoint(CVector2D &point) dist = point.Magnitude(); #ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) + if (FrontEndMenuManager.m_bMenuMapActive) return dist; #endif if (dist > 1.0f) { @@ -1278,7 +1278,7 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, } #ifdef MENU_MAP // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips - if (CMenuManager::bMenuMapActive) { + if (FrontEndMenuManager.m_bMenuMapActive) { bool alreadyThere = false; for (int i = 0; i < NUM_MAP_LEGENDS; i++) { if (MapLegendList[i] == -1) @@ -1403,9 +1403,9 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) { #ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { - out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * CMenuManager::fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH; - out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * CMenuManager::fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH; + if (FrontEndMenuManager.m_bMenuMapActive) { + out.x = (FrontEndMenuManager.m_fMapCenterX - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * FrontEndMenuManager.m_fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH; + out.y = (FrontEndMenuManager.m_fMapCenterY - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * FrontEndMenuManager.m_fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH; } else #endif { @@ -1463,7 +1463,7 @@ CRadar::CalculateCachedSinCos() { if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED #ifdef MENU_MAP - || CMenuManager::bMenuMapActive + || FrontEndMenuManager.m_bMenuMapActive #endif ) { cachedSin = 0.0f; diff --git a/src/core/config.h b/src/core/config.h index 105454fa..c7ce5016 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -222,7 +222,6 @@ enum Config { // Hud, frontend and radar #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios #define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC -#define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box // #define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. #define MENU_MAP // VC-like menu map. Make sure you have new menu.txd #define SCROLLABLE_STATS_PAGE // only draggable by mouse atm diff --git a/src/core/main.cpp b/src/core/main.cpp index 9b40b81d..ecae127a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -199,13 +199,13 @@ DoFade(void) } } - if(CDraw::FadeValue != 0 || CMenuManager::m_PrefsBrightness < 256){ + if(CDraw::FadeValue != 0 || FrontEndMenuManager.m_PrefsBrightness < 256){ CSprite2d *splash = LoadSplash(nil); CRGBA fadeColor; CRect rect; int fadeValue = CDraw::FadeValue; - float brightness = Min(CMenuManager::m_PrefsBrightness, 256); + float brightness = Min(FrontEndMenuManager.m_PrefsBrightness, 256); if(brightness <= 50) brightness = 50; if(FrontEndMenuManager.m_bMenuActive) @@ -944,35 +944,6 @@ Idle(void *arg) CSprite2d::InitPerFrame(); CFont::InitPerFrame(); - // We're basically merging FrontendIdle and Idle (just like TheGame on PS2) -#ifdef PS2_SAVE_DIALOG - // Only exists on PC FrontendIdle, probably some PS2 bug fix - if (FrontEndMenuManager.m_bMenuActive) - CSprite2d::SetRecipNearClip(); - - if (FrontEndMenuManager.m_bGameNotLoaded) { - CPad::UpdatePads(); - FrontEndMenuManager.Process(); - } else { - CPointLights::InitPerFrame(); -#ifdef TIMEBARS - tbStartTimer(0, "CGame::Process"); -#endif - CGame::Process(); -#ifdef TIMEBARS - tbEndTimer("CGame::Process"); - tbStartTimer(0, "DMAudio.Service"); -#endif - DMAudio.Service(); - -#ifdef TIMEBARS - tbEndTimer("DMAudio.Service"); -#endif - } - - if (RsGlobal.quit) - return; -#else CPointLights::InitPerFrame(); #ifdef TIMEBARS tbStartTimer(0, "CGame::Process"); @@ -987,7 +958,6 @@ Idle(void *arg) #ifdef TIMEBARS tbEndTimer("DMAudio.Service"); -#endif #endif if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){ @@ -1004,17 +974,16 @@ Idle(void *arg) if(arg == nil) return; - if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) && + // m_bRenderGameInMenu is there in III PS2 but I don't know about VC PS2. + if((!FrontEndMenuManager.m_bMenuActive/* || FrontEndMenuManager.m_bRenderGameInMenu*/) && TheCamera.GetScreenFadeStatus() != FADE_2) { #ifdef GTA_PC - if (!FrontEndMenuManager.m_bRenderGameInMenu) { // This is from SA, but it's nice for windowed mode RwV2d pos; pos.x = SCREEN_WIDTH / 2.0f; pos.y = SCREEN_HEIGHT / 2.0f; RsMouseSetPos(&pos); - } #endif #ifdef TIMEBARS tbStartTimer(0, "CnstrRenderList"); @@ -1082,10 +1051,6 @@ Idle(void *arg) return; } -#ifdef PS2_SAVE_DIALOG - if (FrontEndMenuManager.m_bMenuActive) - DefinedState(); -#endif #ifdef TIMEBARS tbStartTimer(0, "RenderMenus"); #endif @@ -1217,11 +1182,7 @@ AppEventHandler(RsEvent event, void *param) case rsFRONTENDIDLE: { -#ifdef PS2_SAVE_DIALOG - Idle((void*)1); -#else FrontendIdle(); -#endif return rsEVENTPROCESSED; } @@ -1307,9 +1268,9 @@ void TheGame(void) strcpy(TheMemoryCard.LoadFileName, TheMemoryCard.field37); TheMemoryCard.b_FoundRecentSavedGameWantToLoad = true; - if (CMenuManager::m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad()) + if (FrontEndMenuManager.m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad()) { - CMenuManager::m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad(); + FrontEndMenuManager.m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad(); TheText.Unload(); TheText.Load(); } @@ -1383,7 +1344,8 @@ void TheGame(void) gMainHeap.PushMemId(_TODOCONST(15)); #endif - if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 ) + // m_bRenderGameInMenu is there in III PS2 but I don't know about VC PS2. + if (!FrontEndMenuManager.m_bMenuActive || /*FrontEndMenuManager.m_bRenderGameInMenu == true && */TheCamera.GetScreenFadeStatus() != FADE_2 ) { #ifdef GTA_PS2 gMainHeap.PushMemId(_TODOCONST(11)); @@ -1590,30 +1552,30 @@ void SystemInit() CGame::frenchGame = false; CGame::germanGame = false; CGame::nastyGame = true; - CMenuManager::m_PrefsAllowNastyGame = true; + FrontEndMenuManager.m_PrefsAllowNastyGame = true; #ifdef GTA_PS2 int32 lang = sceScfGetLanguage(); if ( lang == SCE_ITALIAN_LANGUAGE ) - CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_ITALIAN; else if ( lang == SCE_SPANISH_LANGUAGE ) - CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_SPANISH; else if ( lang == SCE_GERMAN_LANGUAGE ) { CGame::germanGame = true; CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; - CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_GERMAN; } else if ( lang == SCE_FRENCH_LANGUAGE ) { CGame::frenchGame = true; CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; - CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_FRENCH; } else - CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_AMERICAN; FrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame(); #else diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index dc0b0252..60e69583 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -128,12 +128,12 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRED040"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED041"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.5, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED042"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED043"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.5, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED044"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); @@ -176,7 +176,7 @@ CCredits::Render(void) PrintCreditSpace(2.0f, lineoffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED061"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.5, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED062"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); @@ -191,7 +191,7 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRED068"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED069"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.5, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED070"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); @@ -220,7 +220,7 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRED262"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED085"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.5, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED086"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); @@ -265,76 +265,76 @@ CCredits::Render(void) PrintCreditText(1.0, 1.0, TheText.Get("CRED108"), lineoffset, scrolloffset); PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED109"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED110"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED111"), lineoffset, scrolloffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED112"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED113"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED114"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED115"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED116"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED117"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED118"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED119"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED120"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED121"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED122"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED123"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED124"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED125"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED126"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED127"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED128"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED129"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED130"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED131"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED132"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED133"), lineoffset, scrolloffset); - if(CMenuManager::m_PrefsLanguage == LANGUAGE_ITALIAN) + if(FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_ITALIAN) PrintCreditSpace(1.0, lineoffset); PrintCreditText(1.0, 1.0, TheText.Get("CRED134"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 59ac1652..1056d6ff 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -382,7 +382,7 @@ void CScrollBar::Update() m_pMessage = FindTimeMessage(); break; case 6: - if (CMenuManager::m_PrefsLanguage == LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == LANGUAGE_GERMAN) + if (FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_GERMAN) m_pMessage = FindTimeMessage(); else m_pMessage = "WWW.GRANDTHEFTAUTO3.COM "; @@ -602,7 +602,7 @@ void CScrollBar::Update() m_pMessage = "FREE FLUFFY DICE WITH ALL PURCHASES. . ."; break; case 9: - if (CMenuManager::m_PrefsLanguage == LANGUAGE_FRENCH || CMenuManager::m_PrefsLanguage == LANGUAGE_GERMAN) + if (FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_GERMAN) m_pMessage = "QUICK, TAKE A LOOK AT OUR CURRENT STOCK )CAUSE THESE AUTOS ARE MOVIN) FAST . . . "; else m_pMessage = "HTTP:((ROCKSTARGAMES.COM(GRANDTHEFTAUTO3(CAPITALAUTOS "; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 7289d70c..96149573 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -102,6 +102,7 @@ uint32 CHud::m_WeaponState; uint32 CHud::m_WeaponTimer; uint32 CHud::m_LastDisplayScore; +uint32 CHud::m_LastWanted; CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; @@ -483,33 +484,46 @@ void CHud::Draw() /* DrawWantedLevel */ - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); - CFont::SetJustifyOff(); - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - CFont::SetPropOn(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetDropShadowPosition(2); // TODO(Miami): Remove that, VC keeps that open above - - AsciiToUnicode("]", sPrintIcon); - - for (int i = 0; i < 6; i++) { - if (playerPed->m_pWanted->m_nWantedLevel > i - && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange - + 2000 || CTimer::GetFrameCounter() & 4)) { - - CFont::SetColor(WANTED_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); - - // TODO(Miami): There is one more condition in here - }else if (playerPed->m_pWanted->m_nWantedLevel <= i) { - CFont::SetColor(NOTWANTED_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); - } + if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel) + alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 0); + else { + alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 1); + m_LastWanted = playerPed->m_pWanted->m_nWantedLevel; } - CFont::SetDropShadowPosition(0); // TODO(Miami): Remove that, VC keeps that open + if (m_WantedState != FADED_OUT) { + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetJustifyOff(); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetPropOn(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetDropShadowPosition(2); // TODO(Miami): Remove that, VC keeps that open above + CFont::SetDropColor(CRGBA(0,0,0,alpha)); // TODO(Miami): Remove that, VC keeps that open above + + AsciiToUnicode("]", sPrintIcon); + + for (int i = 0; i < 6; i++) { + if (playerPed->m_pWanted->m_nWantedLevel > i + && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange + + 2000 || CTimer::GetFrameCounter() & 4)) { + + WANTED_COLOR.a = alpha; + CFont::SetColor(WANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + + // TODO(Miami): There is one more condition in here + } + else if (playerPed->m_pWanted->m_nWantedLevel <= i) { + NOTWANTED_COLOR.a = alpha; + CFont::SetColor(NOTWANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + } + } + + CFont::SetDropShadowPosition(0); // TODO(Miami): Remove that, VC keeps that open + } /* DrawZoneName @@ -1503,20 +1517,28 @@ void CHud::Initialise() PagerSoundPlayed = 0; PagerXOffset = 150.0f; - m_WantedFadeTimer = 0; +#ifdef HUD_AUTO_FADE + m_EnergyLostState = START_FADE_OUT; + m_WantedState = START_FADE_OUT; + m_DisplayScoreState = START_FADE_OUT; + m_WeaponState = START_FADE_OUT; +#else + m_EnergyLostState = FADE_DISABLED; m_WantedState = FADE_DISABLED; + m_DisplayScoreState = FADE_DISABLED; + m_WeaponState = FADE_DISABLED; +#endif + m_WantedFadeTimer = 0; m_WantedTimer = 0; m_EnergyLostFadeTimer = 0; - m_EnergyLostState = FADE_DISABLED; m_EnergyLostTimer = 0; m_DisplayScoreFadeTimer = 0; - m_DisplayScoreState = FADE_DISABLED; m_DisplayScoreTimer = 0; m_WeaponFadeTimer = 0; - m_WeaponState = FADE_DISABLED; m_WeaponTimer = 0; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + m_LastWanted = 0; CTxdStore::PopCurrentTxd(); } @@ -1542,20 +1564,28 @@ void CHud::ReInitialise() { PagerSoundPlayed = 0; PagerXOffset = 150.0f; - m_WantedFadeTimer = 0; +#ifdef HUD_AUTO_FADE + m_EnergyLostState = START_FADE_OUT; + m_WantedState = START_FADE_OUT; + m_DisplayScoreState = START_FADE_OUT; + m_WeaponState = START_FADE_OUT; +#else + m_EnergyLostState = FADE_DISABLED; m_WantedState = FADE_DISABLED; + m_DisplayScoreState = FADE_DISABLED; + m_WeaponState = FADE_DISABLED; +#endif + m_WantedFadeTimer = 0; m_WantedTimer = 0; m_EnergyLostFadeTimer = 0; - m_EnergyLostState = FADE_DISABLED; m_EnergyLostTimer = 0; m_DisplayScoreFadeTimer = 0; - m_DisplayScoreState = FADE_DISABLED; m_DisplayScoreTimer = 0; m_WeaponFadeTimer = 0; - m_WeaponState = FADE_DISABLED; m_WeaponTimer = 0; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + m_LastWanted = 0; } wchar LastBigMessage[6][128]; diff --git a/src/render/Hud.h b/src/render/Hud.h index bae19ee4..4c02827b 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -119,6 +119,7 @@ public: static uint32 m_WeaponTimer; static uint32 m_LastDisplayScore; + static uint32 m_LastWanted; public: static void Draw(); diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index 8f7f92b6..cd45b81f 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -86,9 +86,9 @@ SetLightsWithTimeOfDayColour(RpWorld *) RwFrameTransform(RpLightGetFrame(pDirect), &mat, rwCOMBINEREPLACE); } - if(CMenuManager::m_PrefsBrightness > 256){ - float f1 = 2.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f; - float f2 = 3.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f; + if(FrontEndMenuManager.m_PrefsBrightness > 256){ + float f1 = 2.0f * (FrontEndMenuManager.m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f; + float f2 = 3.0f * (FrontEndMenuManager.m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f; AmbientLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f2); AmbientLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f2); diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 1afa8165..4eff4fb7 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -341,8 +341,8 @@ GenericLoad() LoadSaveDataBlock(); ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load); - DMAudio.SetMusicMasterVolume(CMenuManager::m_PrefsMusicVolume); - DMAudio.SetEffectsMasterVolume(CMenuManager::m_PrefsSfxVolume); + DMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume); if (!CloseFile(file)) { PcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE; return false; diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index c60c5cd9..2c46374d 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -176,7 +176,7 @@ psCameraBeginUpdate(RwCamera *camera) void psCameraShowRaster(RwCamera *camera) { - if (CMenuManager::m_PrefsVsync) + if (FrontEndMenuManager.m_PrefsVsync) RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC); else RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT); @@ -944,7 +944,7 @@ void InitialiseLanguage() || primLayout == LANG_GERMAN ) { CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; CGame::germanGame = true; } @@ -953,7 +953,7 @@ void InitialiseLanguage() || primLayout == LANG_FRENCH ) { CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; CGame::frenchGame = true; } @@ -964,7 +964,7 @@ void InitialiseLanguage() #ifdef NASTY_GAME CGame::nastyGame = true; - CMenuManager::m_PrefsAllowNastyGame = true; + FrontEndMenuManager.m_PrefsAllowNastyGame = true; CGame::noProstitutes = false; #endif @@ -999,33 +999,33 @@ void InitialiseLanguage() } } - CMenuManager::OS_Language = primUserLCID; + FrontEndMenuManager.OS_Language = primUserLCID; switch ( lang ) { case LANG_GERMAN: { - CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_GERMAN; break; } case LANG_SPANISH: { - CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_SPANISH; break; } case LANG_FRENCH: { - CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_FRENCH; break; } case LANG_ITALIAN: { - CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_ITALIAN; break; } default: { - CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_AMERICAN; break; } } @@ -1486,7 +1486,7 @@ main(int argc, char *argv[]) FrontEndMenuManager.m_bGameNotLoaded = true; - CMenuManager::m_bStartUpFrontEndRequested = true; + FrontEndMenuManager.m_bStartUpFrontEndRequested = true; if ( defaultFullscreenRes ) { @@ -1535,7 +1535,7 @@ main(int argc, char *argv[]) float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); if ( RwInitialised ) { - if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) + if (!FrontEndMenuManager.m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) RsEventHandler(rsIDLE, (void *)TRUE); } break; @@ -1546,7 +1546,7 @@ main(int argc, char *argv[]) float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); if (RwInitialised) { - if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) + if (!FrontEndMenuManager.m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) RsEventHandler(rsANIMVIEWER, (void*)TRUE); } break; diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index f41b9ef8..7fc77d45 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -221,7 +221,7 @@ psCameraBeginUpdate(RwCamera *camera) void psCameraShowRaster(RwCamera *camera) { - if (CMenuManager::m_PrefsVsync) + if (FrontEndMenuManager.m_PrefsVsync) RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC); else RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT); @@ -1654,7 +1654,7 @@ void InitialiseLanguage() || primLayout == LANG_GERMAN ) { CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; CGame::germanGame = true; } @@ -1663,7 +1663,7 @@ void InitialiseLanguage() || primLayout == LANG_FRENCH ) { CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; CGame::frenchGame = true; } @@ -1674,7 +1674,7 @@ void InitialiseLanguage() #ifdef NASTY_GAME CGame::nastyGame = true; - CMenuManager::m_PrefsAllowNastyGame = true; + FrontEndMenuManager.m_PrefsAllowNastyGame = true; CGame::noProstitutes = false; #endif @@ -1709,33 +1709,33 @@ void InitialiseLanguage() } } - CMenuManager::OS_Language = primUserLCID; + FrontEndMenuManager.OS_Language = primUserLCID; switch ( lang ) { case LANG_GERMAN: { - CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_GERMAN; break; } case LANG_SPANISH: { - CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_SPANISH; break; } case LANG_FRENCH: { - CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_FRENCH; break; } case LANG_ITALIAN: { - CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_ITALIAN; break; } default: { - CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_AMERICAN; break; } } @@ -2128,7 +2128,7 @@ WinMain(HINSTANCE instance, CoUninitialize(); - if ( CMenuManager::OS_Language == LANG_FRENCH || CMenuManager::OS_Language == LANG_GERMAN ) + if ( FrontEndMenuManager.OS_Language == LANG_FRENCH || FrontEndMenuManager.OS_Language == LANG_GERMAN ) PlayMovieInWindow(cmdShow, "movies\\GTAtitlesGER.mpg"); else PlayMovieInWindow(cmdShow, "movies\\GTAtitles.mpg"); @@ -2179,7 +2179,7 @@ WinMain(HINSTANCE instance, FrontEndMenuManager.m_bGameNotLoaded = true; - CMenuManager::m_bStartUpFrontEndRequested = true; + FrontEndMenuManager.m_bStartUpFrontEndRequested = true; if ( defaultFullscreenRes ) { @@ -2230,7 +2230,7 @@ WinMain(HINSTANCE instance, float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); if ( RwInitialised ) { - if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) + if (!FrontEndMenuManager.m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) RsEventHandler(rsIDLE, (void *)TRUE); } break; @@ -2241,7 +2241,7 @@ WinMain(HINSTANCE instance, float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); if (RwInitialised) { - if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) + if (!FrontEndMenuManager.m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms) RsEventHandler(rsANIMVIEWER, (void*)TRUE); } break; diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 74f53f80..e092627e 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -39,7 +39,7 @@ CText::Load(void) Unload(); CFileMgr::SetDir("TEXT"); - switch(CMenuManager::m_PrefsLanguage){ + switch(FrontEndMenuManager.m_PrefsLanguage){ case LANGUAGE_AMERICAN: sprintf(filename, "AMERICAN.GXT"); break; @@ -241,7 +241,7 @@ CText::LoadMissionText(char *MissionTableName) } CFileMgr::SetDir("TEXT"); - switch (CMenuManager::m_PrefsLanguage) { + switch (FrontEndMenuManager.m_PrefsLanguage) { case LANGUAGE_AMERICAN: sprintf(filename, "AMERICAN.GXT"); break; From a53ca58e566ffceb058451bc49bcc5810c26cb37 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 22 May 2020 14:27:16 +0200 Subject: [PATCH 094/148] CPhysical --- librw | 2 +- src/core/PlayerInfo.h | 1 + src/core/Stats.cpp | 1 + src/core/Stats.h | 19 +- src/core/SurfaceTable.cpp | 135 +++++---- src/core/SurfaceTable.h | 46 +-- src/entities/Entity.h | 1 + src/entities/Physical.cpp | 565 ++++++++++++++++++++++++++--------- src/entities/Physical.h | 20 +- src/modelinfo/ModelIndices.h | 15 +- src/objects/Object.cpp | 6 +- src/objects/Object.h | 29 +- src/peds/Ped.cpp | 1 + src/peds/Ped.h | 2 +- src/render/Timecycle.h | 2 +- src/vehicles/Boat.cpp | 2 +- src/vehicles/Vehicle.cpp | 3 + src/vehicles/Vehicle.h | 2 +- 18 files changed, 558 insertions(+), 294 deletions(-) diff --git a/librw b/librw index 3971dda0..661feeab 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 3971dda001cba9c7dc67e86bc0b54a2c7568578f +Subproject commit 661feeabf4a4f0a8b0bee23b53ba557a14352d00 diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index ea9d563a..63a7a413 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -50,6 +50,7 @@ public: int32 m_nExplosionsSinceLastReward; int32 field_268; int32 field_272; + int32 m_nHavocCaused; // TODO: check offset bool m_bInfiniteSprint; bool m_bFastReload; bool m_bFireproof; diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index f1770796..3f930d49 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -57,6 +57,7 @@ int32 CStats::mmRain; int32 CStats::CarsCrushed; int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES]; int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; +int32 CStats::PropertyDestroyed; int32 CStats::Sprayings; float CStats::AutoPaintingBudget; diff --git a/src/core/Stats.h b/src/core/Stats.h index be1f55ef..37987ae5 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -10,7 +10,7 @@ public: TOTAL_HIGHEST_SCORES = 16 }; static int32 DaysPassed; - static int32 HeadsPopped; + static int32 HeadsPopped; static int32 CommercialPassed; static int32 IndustrialPassed; static int32 SuburbanPassed; @@ -52,16 +52,17 @@ public: static int32 LongestFlightInDodo; static int32 TimeTakenDefuseMission; static int32 TotalNumberKillFrenzies; - static int32 TotalNumberMissions; - static int32 RoundsFiredByPlayer; - static int32 KgsOfExplosivesUsed; - static int32 InstantHitsFiredByPlayer; - static int32 InstantHitsHitByPlayer; - static int32 BestTimeBombDefusal; - static int32 mmRain; - static int32 CarsCrushed; + static int32 TotalNumberMissions; + static int32 RoundsFiredByPlayer; + static int32 KgsOfExplosivesUsed; + static int32 InstantHitsFiredByPlayer; + static int32 InstantHitsHitByPlayer; + static int32 BestTimeBombDefusal; + static int32 mmRain; + static int32 CarsCrushed; static int32 FastestTimes[TOTAL_FASTEST_TIMES]; static int32 HighestScores[TOTAL_HIGHEST_SCORES]; + static int32 PropertyDestroyed; static int32 Sprayings; static float AutoPaintingBudget; static int32 NoMoreHurricanes; diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index 08a84cfd..f002bf49 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -56,40 +56,42 @@ int CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) { switch(surfaceType){ - case SURFACE_0: return ADHESIVE_ROAD; - case SURFACE_1: return ADHESIVE_ROAD; - case SURFACE_2: return ADHESIVE_LOOSE; - case SURFACE_3: return ADHESIVE_LOOSE; - case SURFACE_4: return ADHESIVE_HARD; - case SURFACE_5: return ADHESIVE_ROAD; - case SURFACE_6: return ADHESIVE_HARD; - case SURFACE_7: return ADHESIVE_HARD; - case SURFACE_8: return ADHESIVE_HARD; - case SURFACE_9: return ADHESIVE_HARD; - case SURFACE_10: return ADHESIVE_HARD; - case SURFACE_11: return ADHESIVE_HARD; - case SURFACE_12: return ADHESIVE_HARD; - case SURFACE_13: return ADHESIVE_HARD; - case SURFACE_14: return ADHESIVE_HARD; - case SURFACE_15: return ADHESIVE_HARD; - case SURFACE_16: return ADHESIVE_HARD; - case SURFACE_17: return ADHESIVE_RUBBER; - case SURFACE_18: return ADHESIVE_LOOSE; - case SURFACE_19: return ADHESIVE_WET; - case SURFACE_20: return ADHESIVE_ROAD; - case SURFACE_21: return ADHESIVE_ROAD; - case SURFACE_22: return ADHESIVE_ROAD; - case SURFACE_23: return ADHESIVE_RUBBER; - case SURFACE_24: return ADHESIVE_HARD; - case SURFACE_25: return ADHESIVE_LOOSE; - case SURFACE_26: return ADHESIVE_LOOSE; - case SURFACE_27: return ADHESIVE_HARD; - case SURFACE_28: return ADHESIVE_HARD; - case SURFACE_29: return ADHESIVE_RUBBER; - case SURFACE_30: return ADHESIVE_LOOSE; - case SURFACE_31: return ADHESIVE_HARD; - case SURFACE_32: return ADHESIVE_HARD; - default: return ADHESIVE_ROAD; + case SURFACE_DEFAULT: return ADHESIVE_ROAD; + case SURFACE_TARMAC: return ADHESIVE_ROAD; + case SURFACE_GRASS: return ADHESIVE_LOOSE; + case SURFACE_DIRT: return ADHESIVE_LOOSE; + case SURFACE_DIRTTRACK: return ADHESIVE_HARD; + case SURFACE_PAVEMENT: return ADHESIVE_ROAD; + case SURFACE_METAL6: return ADHESIVE_HARD; + case SURFACE_GLASS: return ADHESIVE_HARD; + case SURFACE_SCAFFOLD: return ADHESIVE_HARD; + case SURFACE_METAL_DOOR: return ADHESIVE_HARD; + case SURFACE_BILLBOARD: return ADHESIVE_HARD; + case SURFACE_STEEL: return ADHESIVE_HARD; + case SURFACE_METAL_POLE: return ADHESIVE_HARD; + case SURFACE_STREET_LIGHT: return ADHESIVE_HARD; + case SURFACE_METAL14: return ADHESIVE_HARD; + case SURFACE_METAL15: return ADHESIVE_HARD; + case SURFACE_METAL_FENCE: return ADHESIVE_HARD; + case SURFACE_FLESH: return ADHESIVE_RUBBER; + case SURFACE_SAND: return ADHESIVE_SAND; + case SURFACE_PUDDLE: return ADHESIVE_WET; + case SURFACE_WOOD: return ADHESIVE_ROAD; + case SURFACE_WOOD_BOX: return ADHESIVE_ROAD; + case SURFACE_WOOD_PLANK: return ADHESIVE_ROAD; + case SURFACE_TIRE: return ADHESIVE_RUBBER; + case SURFACE_HARD24: return ADHESIVE_HARD; + case SURFACE_HEDGE: return ADHESIVE_LOOSE; + case SURFACE_STONE: return ADHESIVE_LOOSE; + case SURFACE_METAL27: return ADHESIVE_HARD; + case SURFACE_METAL28: return ADHESIVE_HARD; + case SURFACE_RUBBER29: return ADHESIVE_RUBBER; + case SURFACE_LOOSE30: return ADHESIVE_LOOSE; + case SURFACE_BOLLARD: return ADHESIVE_HARD; + case SURFACE_GATE: return ADHESIVE_HARD; + case SURFACE_SAND33: return ADHESIVE_SAND; + case SURFACE_ROAD34: return ADHESIVE_ROAD; + default: return ADHESIVE_ROAD; } } @@ -97,40 +99,45 @@ float CSurfaceTable::GetWetMultiplier(uint8 surfaceType) { switch(surfaceType){ - case SURFACE_0: - case SURFACE_1: - case SURFACE_4: - case SURFACE_5: - case SURFACE_8: - case SURFACE_20: - case SURFACE_21: - case SURFACE_22: - case SURFACE_25: - case SURFACE_30: - case SURFACE_31: + case SURFACE_DEFAULT: + case SURFACE_TARMAC: + case SURFACE_DIRTTRACK: + case SURFACE_PAVEMENT: + case SURFACE_SCAFFOLD: + case SURFACE_WOOD: + case SURFACE_WOOD_BOX: + case SURFACE_WOOD_PLANK: + case SURFACE_HEDGE: + case SURFACE_LOOSE30: + case SURFACE_BOLLARD: + case SURFACE_ROAD34: return 1.0f - CWeather::WetRoads*0.25f; - case SURFACE_2: - case SURFACE_6: - case SURFACE_7: - case SURFACE_9: - case SURFACE_10: - case SURFACE_11: - case SURFACE_12: - case SURFACE_13: - case SURFACE_14: - case SURFACE_15: - case SURFACE_16: - case SURFACE_17: - case SURFACE_23: - case SURFACE_24: - case SURFACE_26: - case SURFACE_27: - case SURFACE_28: - case SURFACE_29: - case SURFACE_32: + case SURFACE_GRASS: + case SURFACE_METAL6: + case SURFACE_GLASS: + case SURFACE_METAL_DOOR: + case SURFACE_BILLBOARD: + case SURFACE_STEEL: + case SURFACE_METAL_POLE: + case SURFACE_STREET_LIGHT: + case SURFACE_METAL14: + case SURFACE_METAL15: + case SURFACE_METAL_FENCE: + case SURFACE_FLESH: + case SURFACE_TIRE: + case SURFACE_HARD24: + case SURFACE_STONE: + case SURFACE_METAL27: + case SURFACE_METAL28: + case SURFACE_RUBBER29: + case SURFACE_GATE: return 1.0f - CWeather::WetRoads*0.4f; + case SURFACE_SAND: + case SURFACE_SAND33: + return 1.0f - CWeather::WetRoads*0.5f; + default: return 1.0f; } diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 12246dce..5d8d2c4f 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -1,47 +1,6 @@ #pragma once - -enum -{ - SURFACE_0, - SURFACE_1, - SURFACE_2, - SURFACE_3, - SURFACE_4, - SURFACE_5, - SURFACE_6, - SURFACE_7, - SURFACE_8, - SURFACE_9, - SURFACE_10, - SURFACE_11, - SURFACE_12, - SURFACE_13, - SURFACE_14, - SURFACE_15, - SURFACE_16, - SURFACE_17, - SURFACE_18, - SURFACE_19, - SURFACE_20, - SURFACE_21, - SURFACE_22, - SURFACE_23, - SURFACE_24, - SURFACE_25, - SURFACE_26, - SURFACE_27, - SURFACE_28, - SURFACE_29, - SURFACE_30, - SURFACE_31, - SURFACE_32, - - NUMSURFACETYPES -}; - -// From nick -// TODO: check and use this +// TODO: check this enum eSurfaceType { SURFACE_DEFAULT, @@ -77,8 +36,6 @@ enum eSurfaceType SURFACE_LOOSE30, SURFACE_BOLLARD, SURFACE_GATE, - - // These are illegal SURFACE_SAND33, SURFACE_ROAD34, }; @@ -89,6 +46,7 @@ enum ADHESIVE_HARD, ADHESIVE_ROAD, ADHESIVE_LOOSE, + ADHESIVE_SAND, ADHESIVE_WET, NUMADHESIVEGROUPS diff --git a/src/entities/Entity.h b/src/entities/Entity.h index ab7b6203..e7d402d0 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -30,6 +30,7 @@ enum eEntityStatus : uint8 STATUS_PLANE, STATUS_PLAYER_REMOTE, STATUS_PLAYER_DISABLED, + STATUS_12, // TODO: what is this? used in CPhysical::ApplyAirResistance }; class CEntity : public CPlaceable diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 92542071..3821c736 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1,7 +1,9 @@ #include "common.h" #include "World.h" +#include "General.h" #include "Timer.h" +#include "Stats.h" #include "ModelIndices.h" #include "Treadable.h" #include "Vehicle.h" @@ -15,8 +17,11 @@ #include "CarCtrl.h" #include "DMAudio.h" #include "Automobile.h" +#include "Pickups.h" #include "Physical.h" +//--MIAMI: file done except one bike thing + CPhysical::CPhysical(void) { int i; @@ -37,6 +42,7 @@ CPhysical::CPhysical(void) m_aCollisionRecords[i] = nil; m_bIsVehicleBeingShifted = false; + bJustCheckCollision = false; m_nDamagePieceType = 0; m_fDamageImpulse = 0.0f; @@ -45,25 +51,26 @@ CPhysical::CPhysical(void) bUsesCollision = true; m_audioEntityId = -5; - unk1 = 100.0f; + m_phys_unused1 = 100.0f; m_vecCentreOfMass = CVector(0.0f, 0.0f, 0.0f); - field_EC = 0; + m_phys_unused2 = 0; bIsHeavy = false; bAffectedByGravity = true; bInfiniteMass = false; + m_phy_flagA08 = false; bIsInWater = false; bHitByTrain = false; bSkipLineCol = false; m_fDistanceTravelled = 0.0f; - m_treadable[PATH_CAR] = nil; - m_treadable[PATH_PED] = nil; - m_phy_flagA10 = false; m_phy_flagA20 = false; m_nZoneLevel = LEVEL_NONE; + + bIsFrozen = false; + bDontLoadCollision = false; } CPhysical::~CPhysical(void) @@ -264,7 +271,6 @@ CPhysical::AddCollisionRecord(CEntity *ent) } } -//--MIAMI: done void CPhysical::AddCollisionRecord_Treadable(CEntity *ent) { @@ -401,18 +407,26 @@ CPhysical::GetSpeed(const CVector &r) void CPhysical::ApplyMoveSpeed(void) { - GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep()); + if(bIsFrozen) + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + else + GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep()); } + void CPhysical::ApplyTurnSpeed(void) { - // Move the coordinate axes by their speed - // Note that this denormalizes the matrix - CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep(); - GetRight() += CrossProduct(turnvec, GetRight()); - GetForward() += CrossProduct(turnvec, GetForward()); - GetUp() += CrossProduct(turnvec, GetUp()); + if(bIsFrozen){ + m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + }else{ + // Move the coordinate axes by their speed + // Note that this denormalizes the matrix + CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep(); + GetRight() += CrossProduct(turnvec, GetRight()); + GetForward() += CrossProduct(turnvec, GetForward()); + GetUp() += CrossProduct(turnvec, GetUp()); + } } void @@ -456,6 +470,21 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector & return true; } +bool +CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir) +{ + float compression = 1.0f - springRatio; + if(compression > 0.0f){ + if(DotProduct(springDir, forceDir) > 0.0f) + forceDir *= -1.0f; + float step = Min(CTimer::GetTimeStep(), 3.0f); + float impulse = -GRAVITY*m_fMass*step * springConst * compression * bias*2.0f; + ApplyMoveForce(forceDir*impulse); + ApplyTurnForce(forceDir*impulse, point); + } + return true; +} + // What exactly is speed? bool CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed) @@ -464,6 +493,8 @@ CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &poin float speedB = DotProduct(GetSpeed(point), springDir); float step = Min(CTimer::GetTimeStep(), 3.0f); float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f; + if(bIsHeavy) + impulse *= 2.0f; // what is this? float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass); @@ -497,9 +528,11 @@ void CPhysical::ApplyAirResistance(void) { if(m_fAirResistance > 0.1f){ - float f = Pow(m_fAirResistance, CTimer::GetTimeStep()); - m_vecMoveSpeed *= f; - m_vecTurnSpeed *= f; + if(GetStatus() != STATUS_12){ + float f = Pow(m_fAirResistance, CTimer::GetTimeStep()); + m_vecMoveSpeed *= f; + m_vecTurnSpeed *= f; + } }else{ float f = Pow(1.0f/(m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr() + 1.0f), CTimer::GetTimeStep()); m_vecMoveSpeed *= f; @@ -507,7 +540,6 @@ CPhysical::ApplyAirResistance(void) } } - bool CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB) { @@ -515,32 +547,38 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl CPhysical *A = this; CObject *Bobj = (CObject*)B; + bool foo = false; // TODO: what does this mean? bool ispedcontactA = false; bool ispedcontactB = false; - float timestepA; + float massFactorA; if(B->bPedPhysics){ - timestepA = 10.0f; + massFactorA = 10.0f; if(B->IsPed() && ((CPed*)B)->m_pCurrentPhysSurface == A) ispedcontactA = true; }else - timestepA = A->bIsHeavy ? 2.0f : 1.0f; + massFactorA = A->bIsHeavy ? 2.0f : 1.0f; - float timestepB; + float massFactorB; if(A->bPedPhysics){ if(A->IsPed() && ((CPed*)A)->IsPlayer() && B->IsVehicle() && (B->GetStatus() == STATUS_ABANDONED || B->GetStatus() == STATUS_WRECKED || A->bHasHitWall)) - timestepB = 2200.0f / B->m_fMass; + massFactorB = 1.0f/(Max(B->m_fMass - 2000.0f, 0.0f)/5000.0f + 1.0f); else - timestepB = 10.0f; + massFactorB = 10.0f; if(A->IsPed() && ((CPed*)A)->m_pCurrentPhysSurface == B) ispedcontactB = true; }else - timestepB = B->bIsHeavy ? 2.0f : 1.0f; + massFactorB = B->bIsHeavy ? 2.0f : 1.0f; + + if(B->bInfiniteMass && !B->m_phy_flagA08){ + ispedcontactB = false; + foo = true; + } float speedA, speedB; - if(B->IsStatic()){ + if(B->IsStatic() && !foo){ if(A->bPedPhysics){ speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); if(speedA < 0.0f){ @@ -550,8 +588,11 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(impulseA > Bobj->m_fUprootLimit){ if(IsGlass(B->GetModelIndex())) CGlass::WindowRespondsToCollision(B, impulseA, A->m_vecMoveSpeed, colpoint.point, false); - else if(!B->bInfiniteMass) + else if(!B->bInfiniteMass){ B->bIsStatic = false; + CWorld::Players[CWorld::PlayerInFocus].m_nHavocCaused += 2; + CStats::PropertyDestroyed += CGeneral::GetRandomNumberInRange(30, 60); + } }else{ if(IsGlass(B->GetModelIndex())) CGlass::WindowRespondsToSoftCollision(B, impulseA); @@ -603,6 +644,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){ CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true); Bobj->bHasBeenDamaged = true; + }else if(model == MI_PARKINGMETER || model == MI_PARKINGMETER2){ + CPickups::CreateSomeMoney(GetPosition(), CGeneral::GetRandomNumber()%100); + Bobj->bHasBeenDamaged = true; }else if(B->IsObject() && !IsExplosiveThingModel(model)) Bobj->bHasBeenDamaged = true; }else{ @@ -625,7 +669,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(B->IsStatic()) return false; - if(!B->bInfiniteMass) + if(!B->bInfiniteMass && !B->m_phy_flagA08) B->AddToMovingList(); } @@ -635,16 +679,36 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl // negative if A is moving towards B speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); // positive if B is moving towards A - // not interested in how much B moves into A apparently? - // only interested in cases where A collided into B - speedB = Max(0.0f, DotProduct(B->m_vecMoveSpeed, colpoint.normal)); - // A has moved into B - if(speedA < speedB){ - if(!A->bHasHitWall) - speedB -= (speedA - speedB) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (speedB-speedA) * A->m_fMass * timestepA; + float speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal); + + bool affectB = false; + float mA = A->m_fMass;; + float mB = B->m_fMass;; + float speedSum; + if(((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){ + affectB = true; + speedSum = (2.0f*mA*speedA + mB*speedB)/(2.0f*mA + mB); + }else{ + speedSum = Max(speedB, 0.0f); + } + + if(speedA < speedSum){ + if(A->bHasHitWall) + eA = speedSum; + else + eA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; + impulseA = (eA-speedA) * mA; if(!A->bInfiniteMass) - A->ApplyMoveForce(colpoint.normal*(impulseA/timestepA)); + A->ApplyMoveForce(colpoint.normal*impulseA); + if(affectB && speedB < speedSum){ + if(B->bHasHitWall) + eB = speedSum; + else + eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; + impulseB = -(eB-speedB) * mB; + if(!B->bInfiniteMass) + B->ApplyMoveForce(colpoint.normal*-impulseB); + } return true; } }else if(A->bPedPhysics){ @@ -652,9 +716,13 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); - float a = A->m_fMass*timestepA; - float b = B->GetMassTime(pointposB, colpoint.normal, timestepB); - float speedSum = (b*speedB + a*speedA)/(a + b); + float mA = A->m_fMass*massFactorA; + float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB); + float speedSum; + if(foo) + speedSum = speedB; + else + speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) eA = speedSum; @@ -664,10 +732,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eB = speedSum; else eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (eA - speedA) * a; - impulseB = -(eB - speedB) * b; - CVector fA = colpoint.normal*(impulseA/timestepA); - CVector fB = colpoint.normal*(-impulseB/timestepB); + impulseA = (eA - speedA) * mA; + impulseB = -(eB - speedB) * mB; + CVector fA = colpoint.normal*(impulseA/massFactorA); + CVector fB = colpoint.normal*(-impulseB/massFactorB); if(!A->bInfiniteMass){ if(fA.z < 0.0f) fA.z = 0.0f; if(ispedcontactB){ @@ -687,9 +755,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal); - float a = A->GetMassTime(pointposA, colpoint.normal, timestepA); - float b = B->m_fMass*timestepB; - float speedSum = (b*speedB + a*speedA)/(a + b); + float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA); + float mB = B->m_fMass*massFactorB; + float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) eA = speedSum; @@ -699,10 +767,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eB = speedSum; else eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (eA - speedA) * a; - impulseB = -(eB - speedB) * b; - CVector fA = colpoint.normal*(impulseA/timestepA); - CVector fB = colpoint.normal*(-impulseB/timestepB); + impulseA = (eA - speedA) * mA; + impulseB = -(eB - speedB) * mB; + CVector fA = colpoint.normal*(impulseA/massFactorA); + CVector fB = colpoint.normal*(-impulseB/massFactorB); if(!A->bInfiniteMass && !ispedcontactA){ if(fA.z < 0.0f) fA.z = 0.0f; A->ApplyMoveForce(fA); @@ -727,9 +795,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl CVector pointposB = colpoint.point - B->GetPosition(); speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); - float a = A->GetMassTime(pointposA, colpoint.normal, timestepA); - float b = B->GetMassTime(pointposB, colpoint.normal, timestepB); - float speedSum = (b*speedB + a*speedA)/(a + b); + float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA); + float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB); + float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) eA = speedSum; @@ -739,10 +807,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eB = speedSum; else eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (eA - speedA) * a; - impulseB = -(eB - speedB) * b; - CVector fA = colpoint.normal*(impulseA/timestepA); - CVector fB = colpoint.normal*(-impulseB/timestepB); + impulseA = (eA - speedA) * mA; + impulseB = -(eB - speedB) * mB; + CVector fA = colpoint.normal*(impulseA/massFactorA); + CVector fB = colpoint.normal*(-impulseB/massFactorB); if(A->IsVehicle() && !A->bHasHitWall){ fA.x *= 1.4f; fA.y *= 1.4f; @@ -758,7 +826,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(B->IsVehicle() && !B->bHasHitWall){ fB.x *= 1.4f; fB.y *= 1.4f; - if(colpoint.normal.z < 0.7f) + if(-colpoint.normal.z < 0.7f) fB.z *= 0.3f; if(B->GetStatus() == STATUS_PLAYER) pointposB *= 0.8f; @@ -784,14 +852,53 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl return false; } +bool +CPhysical::ApplyCollision(CColPoint &colpoint, float &impulse) +{ + float speed; + if(bPedPhysics){ + speed = DotProduct(m_vecMoveSpeed, colpoint.normal); + if(speed < 0.0f){ + impulse = -speed * m_fMass; + ApplyMoveForce(colpoint.normal*impulse); + return true; + } + }else{ + CVector pointpos = colpoint.point - GetPosition(); + speed = DotProduct(GetSpeed(pointpos), colpoint.normal); + + if(speed < 0.0f){ + float mass = GetMass(pointpos, colpoint.normal); + impulse = -(m_fElasticity + 1.0f) * speed * mass; + CVector f = colpoint.normal*impulse; + if(IsVehicle()){ + f.x *= 1.4f; + f.y *= 1.4f; + if(colpoint.normal.z < 0.7f) + f.z *= 0.3f; + } + if(!bInfiniteMass){ + ApplyMoveForce(f); + if(!IsVehicle() || !CWorld::bNoMoreCollisionTorque) + ApplyTurnForce(f, pointpos); + } + return true; + } + } + + return false; +} + bool CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed) { float normalSpeed; - float e; CVector speed; CVector vImpulse; + if(GetModelIndex() == MI_BEACHBALL && B != (CEntity*)FindPlayerPed()) + ((CObject*)this)->m_nBeachballBounces = 0; + if(bPedPhysics){ normalSpeed = DotProduct(m_vecMoveSpeed, colpoint.normal); if(normalSpeed < 0.0f){ @@ -804,28 +911,61 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV speed = GetSpeed(pointpos); normalSpeed = DotProduct(speed, colpoint.normal); if(normalSpeed < 0.0f){ - float minspeed = 0.0104f * CTimer::GetTimeStep(); -#ifdef GTA3_1_1_PATCH - if ((IsObject() || IsVehicle() && (GetUp().z < -0.3f || ((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED))) && -#else - if((IsObject() || IsVehicle() && GetUp().z < -0.3f) && -#endif - !bHasContacted && + int16 elasticityType = 0; + float mass = GetMass(pointpos, colpoint.normal); + float minspeed = GRAVITY * CTimer::GetTimeStep(); + + if(IsObject()) + elasticityType = 1; + else if(IsVehicle() && !bIsInWater){ + if(((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED)){ + minspeed *= 1.3f; + elasticityType = 3; + }else if(((CVehicle*)this)->IsBoat()){ + minspeed *= 1.2f; + elasticityType = 4; + }else if(GetUp().z < -0.3f){ + minspeed *= 1.1f; + elasticityType = 2; + } + } + + if(elasticityType == 1 && !bHasContacted && Abs(m_vecMoveSpeed.x) < minspeed && Abs(m_vecMoveSpeed.y) < minspeed && Abs(m_vecMoveSpeed.z) < minspeed*2.0f) - e = -1.0f; + impulse = -0.98f * normalSpeed * mass; + if(elasticityType == 3 && + Abs(m_vecMoveSpeed.x) < minspeed && + Abs(m_vecMoveSpeed.y) < minspeed && + Abs(m_vecMoveSpeed.z) < minspeed*2.0f) + impulse = -0.8f * normalSpeed * mass; + else if(elasticityType == 2 && + Abs(m_vecMoveSpeed.x) < minspeed && + Abs(m_vecMoveSpeed.y) < minspeed && + Abs(m_vecMoveSpeed.z) < minspeed*2.0f) + impulse = -0.92f * normalSpeed * mass; + else if(elasticityType == 4 && + Abs(m_vecMoveSpeed.x) < minspeed && + Abs(m_vecMoveSpeed.y) < minspeed && + Abs(m_vecMoveSpeed.z) < minspeed*2.0f) + impulse = -0.8f * normalSpeed * mass; + else if(IsVehicle() && ((CVehicle*)this)->IsBoat() && + colpoint.surfaceB == SURFACE_WOOD_PLANK && colpoint.normal.z < 0.5f) + impulse = -(2.0f * m_fElasticity + 1.0f) * normalSpeed * mass; else - e = -(m_fElasticity + 1.0f); - impulse = normalSpeed * e * GetMass(pointpos, colpoint.normal); + impulse = -(m_fElasticity + 1.0f) * normalSpeed * mass; // ApplyMoveForce vImpulse = colpoint.normal*impulse; - if(IsVehicle() && - (!bHasHitWall || - !(m_vecMoveSpeed.MagnitudeSqr() > 0.1 || !(B->IsBuilding() || ((CPhysical*)B)->bInfiniteMass)))) - moveSpeed += vImpulse * 1.2f * (1.0f/m_fMass); - else + if(IsVehicle()){ + if(!bHasHitWall || + !(m_vecMoveSpeed.MagnitudeSqr() > 0.1 || !(B->IsBuilding() || ((CPhysical*)B)->bInfiniteMass))) + moveSpeed += vImpulse * 1.2f * (1.0f/m_fMass); + else + moveSpeed += vImpulse * (1.0f/m_fMass); + vImpulse *= 0.8f; + }else moveSpeed += vImpulse * (1.0f/m_fMass); // ApplyTurnForce @@ -1006,7 +1146,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint) ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos); if(fOtherSpeed > 0.1f && - colpoint.surfaceB != SURFACE_2 && colpoint.surfaceB != SURFACE_4 && + colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_DIRTTRACK && CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){ CVector v = frictionDir * fOtherSpeed * 0.25f; for(int i = 0; i < 4; i++) @@ -1055,7 +1195,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) canshift = true; else canshift = A->IsPed() && - B->IsObject() && B->bInfiniteMass && !Bobj->bHasBeenDamaged; + B->IsObject() && B->IsStatic() && !Bobj->bHasBeenDamaged; if(B == A || B->m_scanCode == CWorld::GetCurrentScanCode() || !B->bUsesCollision || @@ -1075,7 +1215,6 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) B->GetUp().z < 0.66f && IsLightWithoutShift(B->GetModelIndex())) skipShift = true; -// TODO: maybe flip some ifs here else if(A->IsObject() && B->IsVehicle()){ CObject *Aobj = (CObject*)A; if(Aobj->ObjectCreatedBy != TEMP_OBJECT && @@ -1194,6 +1333,9 @@ CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists) A = (CPhysical*)this; + if(!A->bUsesCollision) + return false; + radius = A->GetBoundRadius(); A->GetBoundCentre(center); @@ -1212,6 +1354,7 @@ CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists) for(listnode = list->first; listnode; listnode = listnode->next){ B = (CPhysical*)listnode->item; if(B != A && + !(B->IsObject() && ((CObject*)B)->bIsStreetLight && B->GetUp().z < 0.66f) && B->m_scanCode != CWorld::GetCurrentScanCode() && B->bUsesCollision && B->GetIsTouching(center, radius)){ @@ -1355,6 +1498,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) int numResponses; int i, j; bool skipCollision, altcollision; + bool ret = false; float impulseA = -1.0f; float impulseB = -1.0f; @@ -1375,9 +1519,9 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) Bped = (CPed*)B; bool isTouching = true; - if(B == A || + if(!B->bUsesCollision || B->m_scanCode == CWorld::GetCurrentScanCode() || - !B->bUsesCollision || + B == A || !(isTouching = B->GetIsTouching(center, radius))){ if(!isTouching){ if(A->IsObject() && Aobj->m_pCollidingEntity == B) @@ -1398,27 +1542,27 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(B->IsBuilding()) skipCollision = false; - else if(IsLightWithoutShift(A->GetModelIndex()) && + else if(A->IsObject() && Aobj->bIsStreetLight && (B->IsVehicle() || B->IsPed()) && A->GetUp().z < 0.66f){ skipCollision = true; A->bSkipLineCol = true; Aobj->m_pCollidingEntity = B; - }else if((A->IsVehicle() || A->IsPed()) && - B->GetUp().z < 0.66f && - IsLightWithoutShift(B->GetModelIndex())){ + }else if(B->IsObject() && Bobj->bIsStreetLight && + (A->IsVehicle() || A->IsPed()) && + B->GetUp().z < 0.66f){ skipCollision = true; A->bSkipLineCol = true; Bobj->m_pCollidingEntity = A; }else if(A->IsObject() && B->IsVehicle()){ - if(A->GetModelIndex() == MI_CAR_BUMPER)// || A->GetModelIndex() == MI_FILES) + if(A->GetModelIndex() == MI_CAR_BUMPER) skipCollision = true; else if(Aobj->ObjectCreatedBy == TEMP_OBJECT || Aobj->bHasBeenDamaged || !Aobj->IsStatic()){ if(Aobj->m_pCollidingEntity == B) skipCollision = true; - else{ + else if(Aobj->m_nCollisionDamageEffect < DAMAGE_EFFECT_SMASH_COMPLETELY){ CMatrix inv; CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize(); size = A->GetMatrix() * size; @@ -1430,14 +1574,14 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) } } }else if(B->IsObject() && A->IsVehicle()){ - if(B->GetModelIndex() == MI_CAR_BUMPER)// || B->GetModelIndex() == MI_FILES) + if(B->GetModelIndex() == MI_CAR_BUMPER) skipCollision = true; else if(Bobj->ObjectCreatedBy == TEMP_OBJECT || Bobj->bHasBeenDamaged || !Bobj->IsStatic()){ if(Bobj->m_pCollidingEntity == A) skipCollision = true; - else{ + else if(Bobj->m_nCollisionDamageEffect < DAMAGE_EFFECT_SMASH_COMPLETELY){ CMatrix inv; CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize(); size = B->GetMatrix() * size; @@ -1447,14 +1591,16 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) } } } - }else if(IsBodyPart(A->GetModelIndex()) && B->IsPed()){ + }else if(A->GetModelIndex() == MI_GRENADE && B->IsPed() && + A->GetPosition().z < B->GetPosition().z){ skipCollision = true; - }else if(A->IsPed() && IsBodyPart(B->GetModelIndex())){ + }else if(B->GetModelIndex() == MI_GRENADE && A->IsPed() && + B->GetPosition().z < A->GetPosition().z){ skipCollision = true; A->bSkipLineCol = true; }else if(A->IsPed() && Aped->m_pCollidingEntity == B){ skipCollision = true; - if(!Aped->bKnockedUpIntoAir) + if(!Aped->bKnockedUpIntoAir || Aped->b158_4) A->bSkipLineCol = true; }else if(B->IsPed() && Bped->m_pCollidingEntity == A){ skipCollision = true; @@ -1469,7 +1615,11 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(!A->bUsesCollision || skipCollision){ B->m_scanCode = CWorld::GetCurrentScanCode(); - A->ProcessEntityCollision(B, aColPoints); + numCollisions = A->ProcessEntityCollision(B, aColPoints); + if(A->bJustCheckCollision && numCollisions > 0) + return true; + if(numCollisions == 0 && A == (CEntity*)FindPlayerPed() && Aped->m_pCollidingEntity == B) + Aped->m_pCollidingEntity = nil; }else if(B->IsBuilding() || B->bIsStuck || B->bInfiniteMass || altcollision){ // This is the case where B doesn't move @@ -1481,6 +1631,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) CVector moveSpeed = { 0.0f, 0.0f, 0.0f }; CVector turnSpeed = { 0.0f, 0.0f, 0.0f }; + float maxImpulseA = 0.0f; numResponses = 0; if(A->bHasContacted){ for(i = 0; i < numCollisions; i++){ @@ -1488,20 +1639,35 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) continue; numResponses++; + if(impulseA > maxImpulseA) maxImpulseA = impulseA; - if(impulseA > A->m_fDamageImpulse) - A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); + if(A->IsVehicle()){ + if(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_PLANK) && + impulseA > A->m_fDamageImpulse) + A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); - float imp = impulseA; - if(A->IsVehicle() && A->GetUp().z < -0.6f && - Abs(A->m_vecMoveSpeed.x) < 0.05f && - Abs(A->m_vecMoveSpeed.y) < 0.05f) - imp *= 0.1f; + if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND) + aColPoints[i].surfaceB = SURFACE_SAND; - float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); - float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); + float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); + float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, Max(turnSpeedDiff, moveSpeedDiff)); + if(A->GetUp().z < -0.6f && + Abs(A->m_vecMoveSpeed.x) < 0.05f && + Abs(A->m_vecMoveSpeed.y) < 0.05f) + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, 0.1f*impulseA, Max(turnSpeedDiff, moveSpeedDiff)); + else + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); + + }else{ + if(impulseA > A->m_fDamageImpulse) + A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); + + float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); + float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); + + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); + } } }else{ for(i = 0; i < numCollisions; i++){ @@ -1509,39 +1675,52 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) continue; numResponses++; - - if(impulseA > A->m_fDamageImpulse) - A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); - - float imp = impulseA; - if(A->IsVehicle() && A->GetUp().z < -0.6f && - Abs(A->m_vecMoveSpeed.x) < 0.05f && - Abs(A->m_vecMoveSpeed.y) < 0.05f) - imp *= 0.1f; - - float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); - float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); - - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, Max(turnSpeedDiff, moveSpeedDiff)); - + if(impulseA > maxImpulseA) maxImpulseA = impulseA; float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions; - if(A->GetModelIndex() == MI_RCBANDIT) - adhesion *= 0.2f; -// TODO(MIAMI): check this - else if(A->IsVehicle() && ((CVehicle*)A)->IsBoat()){ - if(aColPoints[i].normal.z > 0.6f){ - if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_LOOSE) - adhesion *= 3.0f; - }else + if(A->IsVehicle()){ + if(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_PLANK) adhesion = 0.0f; - }else if(A->IsVehicle()){ - if(A->GetStatus() == STATUS_WRECKED) + else if(impulseA > A->m_fDamageImpulse) + A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); + + if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND) + aColPoints[i].surfaceB = SURFACE_SAND; + + float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); + float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); + + if(A->GetUp().z < -0.6f && + Abs(A->m_vecMoveSpeed.x) < 0.05f && + Abs(A->m_vecMoveSpeed.y) < 0.05f) + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, 0.1f*impulseA, Max(turnSpeedDiff, moveSpeedDiff)); + else + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); + + + if(A->GetModelIndex() == MI_RCBANDIT) + adhesion *= 0.2f; + else if(((CVehicle*)A)->IsBoat()){ + if(aColPoints[i].normal.z > 0.6f){ + if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_LOOSE || + CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND) + adhesion *= 3.0f; + }else + adhesion = 0.0f; + }else if(A->GetStatus() == STATUS_WRECKED) adhesion *= 3.0f; else if(A->GetUp().z > 0.3f) adhesion = 0.0f; else adhesion *= Min(5.0f, 0.03f*impulseA + 1.0f); + }else{ + if(impulseA > A->m_fDamageImpulse) + A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); + + float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); + float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); + + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); } if(A->ApplyFriction(adhesion, aColPoints[i])) @@ -1560,7 +1739,13 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) A->m_vecMoveFriction.y += moveSpeed.y * -0.3f / numCollisions; A->m_vecTurnFriction += turnSpeed * -0.3f / numCollisions; } - return true; + + if(B->IsObject() && Bobj->m_nCollisionDamageEffect && maxImpulseA > 20.0f) + Bobj->ObjectDamage(maxImpulseA); + + if(!CWorld::bSecondShift) + return true; + ret = true; } }else{ @@ -1691,18 +1876,34 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) } if(B->IsPed() && A->IsVehicle() && - (!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > 0.0025f)) + (!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > SQR(0.05f))) Bped->KillPedWithCar((CVehicle*)A, maxImpulseB); else if(B->GetModelIndex() == MI_TRAIN && A->IsPed() && (!Aped->IsPlayer() || A->bHasHitWall)) Aped->KillPedWithCar((CVehicle*)B, maxImpulseA*2.0f); else if(B->IsObject() && B->bUsesCollision && A->IsVehicle()){ + // BUG? not impulseA? if(Bobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f) Bobj->ObjectDamage(maxImpulseB); + else if(Bobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){ + CMatrix inv; + CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize(); + size = B->GetMatrix() * size; + if(size.z < B->GetPosition().z || + (Invert(A->GetMatrix(), inv) * size).z < 0.0f) + Bobj->ObjectDamage(50.0f); + } }else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){ - // BUG? not impulseA? if(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f) Aobj->ObjectDamage(maxImpulseB); + else if(Aobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){ + CMatrix inv; + CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize(); + size = A->GetMatrix() * size; + if(size.z < A->GetPosition().z || + (Invert(B->GetMatrix(), inv) * size).z < 0.0f) + Aobj->ObjectDamage(50.0f); + } } if(B->GetStatus() == STATUS_SIMPLE){ @@ -1711,13 +1912,15 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) CCarCtrl::SwitchVehicleToRealPhysics((CVehicle*)B); } - return true; + if(!CWorld::bSecondShift) + return true; + ret = true; } } } - return false; + return ret; } bool @@ -1746,6 +1949,8 @@ CPhysical::CheckCollision_SimpleCar(void) return false; } +float PHYSICAL_SHIFT_SPEED_DAMP = 0.707f; + void CPhysical::ProcessShift(void) { @@ -1755,6 +1960,13 @@ CPhysical::ProcessShift(void) bIsInSafePosition = true; RemoveAndAdd(); }else{ + CPhysical *surf; + if(bHasHitWall && IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) || + CWorld::bSecondShift){ + m_vecMoveSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep()); + m_vecTurnSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep()); + } + CMatrix matrix(GetMatrix()); ApplyMoveSpeed(); ApplyTurnSpeed(); @@ -1766,17 +1978,25 @@ CPhysical::ProcessShift(void) m_bIsVehicleBeingShifted = true; CEntryInfoNode *node; - bool hasshifted = false; // whatever that means... + bool hasshifted = false; for(node = m_entryInfoList.first; node; node = node->next) hasshifted |= ProcessShiftSectorList(node->sector->m_lists); m_bIsVehicleBeingShifted = false; if(hasshifted){ CWorld::AdvanceCurrentScanCode(); + bool hadCollision = false; for(node = m_entryInfoList.first; node; node = node->next) if(ProcessCollisionSectorList(node->sector->m_lists)){ - GetMatrix() = matrix; - return; + if(!CWorld::bSecondShift){ + GetMatrix() = matrix; + return; + } + hadCollision = true; } + if(hadCollision){ + GetMatrix() = matrix; + return; + } } bIsStuck = false; bIsInSafePosition = true; @@ -1788,6 +2008,9 @@ CPhysical::ProcessShift(void) // x is the number of units (m) we would like to step #define NUMSTEPS(x) ceil(Sqrt(distSq) * (1.0f/(x))) +float HIGHSPEED_ELASTICITY_MULT_PED = 2.0f; +float HIGHSPEED_ELASTICITY_MULT_COPCAR = 2.0f; + void CPhysical::ProcessCollision(void) { @@ -1819,31 +2042,78 @@ CPhysical::ProcessCollision(void) // Save current state CMatrix savedMatrix(GetMatrix()); + float savedElasticity = m_fElasticity; + CVector savedMoveSpeed = m_vecMoveSpeed; float savedTimeStep = CTimer::GetTimeStep(); int8 n = 1; // The number of steps we divide the time step into float step = 0.0f; // divided time step - float distSq = GetDistanceSq(); + float distSq = m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep()); - if(IsPed() && (distSq >= sq(0.2f) || ped->IsPlayer())){ - if(ped->IsPlayer()) - n = Max(NUMSTEPS(0.2f), 2.0f); - else - n = NUMSTEPS(0.3f); + if(IsPed() && (distSq >= sq(0.3f) || ped->IsPlayer())){ + if(ped->IsPlayer()){ + if(ped->m_pCurrentPhysSurface) + n = Max(NUMSTEPS(0.15f), 4.0f); + else + n = Max(NUMSTEPS(0.3f), 2.0f); + }else + n = NUMSTEPS(0.45f); step = savedTimeStep / n; + if(!ped->IsPlayer()) + ped->m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_PED; }else if(IsVehicle() && distSq >= sq(0.4f)){ if(GetStatus() == STATUS_PLAYER) n = NUMSTEPS(0.2f); else n = distSq > 0.32f ? NUMSTEPS(0.3f) : NUMSTEPS(0.4f); step = savedTimeStep / n; - }else if(IsObject()){ + + CVector bbox = GetColModel()->boundingBox.GetSize(); + float relDistX = Abs(DotProduct(m_vecMoveSpeed, GetRight())) * CTimer::GetTimeStep() / bbox.x; + float relDistY = Abs(DotProduct(m_vecMoveSpeed, GetForward())) * CTimer::GetTimeStep() / bbox.y; + float relDistZ = Abs(DotProduct(m_vecMoveSpeed, GetUp())) * CTimer::GetTimeStep() / bbox.z; + if(Max(relDistX, Max(relDistY, relDistZ)) < 1.0f){ + // check if we can get away with simplified processing + + ApplyMoveSpeed(); + ApplyTurnSpeed(); + GetMatrix().Reorthogonalise(); + bSkipLineCol = false; + m_bIsVehicleBeingShifted = false; + + bJustCheckCollision = true; + bUsesCollision = false; + if(!CheckCollision()){ + bJustCheckCollision = false; + bUsesCollision = true; + if(IsVehicle()) + ((CVehicle*)this)->bVehicleColProcessed = true; + + bHitByTrain = false; + m_fDistanceTravelled = (GetPosition() - savedMatrix.GetPosition()).Magnitude(); + bSkipLineCol = false; + + bIsStuck = false; + bIsInSafePosition = true; + m_fElasticity = savedElasticity; + RemoveAndAdd(); + return; + } + bJustCheckCollision = false; + bUsesCollision = true; + GetMatrix() = savedMatrix; + m_vecMoveSpeed = savedMoveSpeed; + if(IsVehicle() && ((CVehicle*)this)->bIsLawEnforcer) + m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_COPCAR; + } + }else if(IsObject() && ((CObject*)this)->ObjectCreatedBy != TEMP_OBJECT){ int responsecase = ((CObject*)this)->m_nSpecialCollisionResponseCases; if(responsecase == COLLRESPONSE_LAMPOST){ CVector speedUp = { 0.0f, 0.0f, 0.0f }; CVector speedDown = { 0.0f, 0.0f, 0.0f }; - speedUp.z = GetBoundRadius(); - speedDown.z = -speedUp.z; + CColModel *colModel = GetColModel(); + speedUp.z = colModel->boundingBox.max.z; + speedDown.z = colModel->boundingBox.min.z; speedUp = Multiply3x3(GetMatrix(), speedUp); speedDown = Multiply3x3(GetMatrix(), speedDown); speedUp = GetSpeed(speedUp); @@ -1883,6 +2153,7 @@ CPhysical::ProcessCollision(void) savedMatrix.GetPosition().z = GetPosition().z; GetMatrix() = savedMatrix; CTimer::SetTimeStep(savedTimeStep); + m_fElasticity = savedElasticity; return; } if(IsPed() && m_vecMoveSpeed.z == 0.0f && @@ -1900,7 +2171,7 @@ CPhysical::ProcessCollision(void) car->m_aSuspensionSpringRatio[2] = 1.0f; car->m_aSuspensionSpringRatio[3] = 1.0f; }else if(veh->m_vehType == VEHICLE_TYPE_BIKE){ - assert(0 && "TODO - but unused"); + assert(0 && "TODO(MIAMI)"); } } } @@ -1913,11 +2184,14 @@ CPhysical::ProcessCollision(void) if(!m_vecMoveSpeed.IsZero() || !m_vecTurnSpeed.IsZero() || bHitByTrain || - GetStatus() == STATUS_PLAYER || IsPed() && ped->IsPlayer()){ + GetStatus() == STATUS_PLAYER || + IsVehicle() && ((CVehicle*)this)->bRestingOnPhysical || + IsPed() && ped->IsPlayer()){ if(IsVehicle()) ((CVehicle*)this)->bVehicleColProcessed = true; if(CheckCollision()){ GetMatrix() = savedMatrix; + m_fElasticity = savedElasticity; return; } } @@ -1927,5 +2201,6 @@ CPhysical::ProcessCollision(void) bIsStuck = false; bIsInSafePosition = true; + m_fElasticity = savedElasticity; RemoveAndAdd(); } diff --git a/src/entities/Physical.h b/src/entities/Physical.h index b6e28275..926b9762 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -18,8 +18,7 @@ public: // The not properly indented fields haven't been checked properly yet int32 m_audioEntityId; - float unk1; - CTreadable *m_treadable[2]; // car and ped + float m_phys_unused1; uint32 m_nLastTimeCollided; CVector m_vecMoveSpeed; // velocity CVector m_vecTurnSpeed; // angular velocity @@ -37,16 +36,15 @@ public: CEntryInfoList m_entryInfoList; CPtrNode *m_movingListNode; - char field_EC; + int8 m_phys_unused2; uint8 m_nStaticFrames; uint8 m_nCollisionRecords; - bool m_bIsVehicleBeingShifted; CEntity *m_aCollisionRecords[PHYSICAL_MAX_COLLISIONRECORDS]; float m_fDistanceTravelled; // damaged piece - float m_fDamageImpulse; // fCollisionPower + float m_fDamageImpulse; CEntity *m_pDamageEntity; CVector m_vecDamageNormal; int16 m_nDamagePieceType; @@ -54,12 +52,17 @@ public: uint8 bIsHeavy : 1; uint8 bAffectedByGravity : 1; uint8 bInfiniteMass : 1; + uint8 m_phy_flagA08 : 1; uint8 bIsInWater : 1; - uint8 m_phy_flagA10 : 1; // unused uint8 m_phy_flagA20 : 1; // unused uint8 bHitByTrain : 1; uint8 bSkipLineCol : 1; + uint8 bIsFrozen : 1; + uint8 bDontLoadCollision : 1; + uint8 m_bIsVehicleBeingShifted : 1; // wrong name - also used on but never set for peds + uint8 bJustCheckCollision : 1; // just see if there is a collision + uint8 m_nSurfaceTouched; int8 m_nZoneLevel; @@ -86,7 +89,6 @@ public: void RemoveRefsToEntity(CEntity *ent); static void PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos); - float GetDistanceSq(void) { return m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep()); } // get speed of point p relative to entity center CVector GetSpeed(const CVector &r); CVector GetSpeed(void) { return GetSpeed(CVector(0.0f, 0.0f, 0.0f)); } @@ -94,7 +96,7 @@ public: return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/m_fTurnMass + 1.0f/m_fMass); } - float GetMassTime(const CVector &pos, const CVector &dir, float t) { + float GetMassTweak(const CVector &pos, const CVector &dir, float t) { return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/(m_fTurnMass*t) + 1.0f/(m_fMass*t)); } @@ -156,11 +158,13 @@ public: void ApplyFrictionTurnForce(const CVector &j, const CVector &p) { ApplyFrictionTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); } // springRatio: 1.0 fully extended, 0.0 fully compressed bool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias); + bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir); bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed); void ApplyGravity(void); void ApplyFriction(void); void ApplyAirResistance(void); bool ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB); + bool ApplyCollision(CColPoint &colpoint, float &impulse); bool ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed); bool ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint); bool ApplyFriction(float adhesiveLimit, CColPoint &colpoint); diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index b8c6964a..dd37b57d 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -399,6 +399,18 @@ IsLightThatNeedsRepositioning(int16 id) id == MI_STREETLAMP2; } +inline bool +IsLightObject(int16 id) +{ + return id == MI_TRAFFICLIGHTS_MIAMI || + id == MI_MLAMPPOST || + id == MI_SINGLESTREETLIGHTS1 || + id == MI_SINGLESTREETLIGHTS2 || + id == MI_SINGLESTREETLIGHTS3 || + id == MI_DOUBLESTREETLIGHTS || + id == MI_TRAFFICLIGHTS_TWOVERTICAL; +} + inline bool IsBodyPart(int16 id) { @@ -455,7 +467,8 @@ inline bool IsExplosiveThingModel(int16 id) { return id == MI_EXPLODINGBARREL || - id == MI_PETROLPUMP; + id == MI_PETROLPUMP || + id == MI_PETROLPUMP2; } inline bool diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index fd5a2aa3..daa48d98 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -330,6 +330,8 @@ CObject::Init(void) m_colour1 = 0; m_colour2 = 0; m_nBonusValue = 0; + bIsWeapon = false; +// TODO(MIAMI): some new field here m_pCollidingEntity = nil; CColPoint point; CEntity* outEntity = nil; @@ -342,7 +344,9 @@ CObject::Init(void) if (GetModelIndex() == MI_BUOY) bTouchingWater = true; - // TODO(Miami): Second flag set initialization + if(CModelInfo::GetModelInfo(GetModelIndex())->GetModelType() == MITYPE_WEAPON) + bIsWeapon = true; + bIsStreetLight = IsLightObject(GetModelIndex()); m_area = AREA_EVERYWHERE; } diff --git a/src/objects/Object.h b/src/objects/Object.h index 9ceffb2f..5a9c0195 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -59,26 +59,23 @@ public: CMatrix m_objectMatrix; float m_fUprootLimit; int8 ObjectCreatedBy; - int8 bIsPickup : 1; - int8 bPickupObjWithMessage : 1; - int8 bOutOfStock : 1; - int8 bGlassCracked : 1; - int8 bGlassBroken : 1; - int8 bHasBeenDamaged : 1; - int8 bUseVehicleColours : 1; + uint8 bIsPickup : 1; + uint8 obj_flag_02 : 1; + uint8 bPickupObjWithMessage : 1; + uint8 bOutOfStock : 1; + uint8 bGlassCracked : 1; + uint8 bGlassBroken : 1; + uint8 bHasBeenDamaged : 1; + uint8 bUseVehicleColours : 1; + uint8 bIsWeapon : 1; + uint8 bIsStreetLight : 1; int8 m_nBonusValue; float m_fCollisionDamageMultiplier; uint8 m_nCollisionDamageEffect; uint8 m_nSpecialCollisionResponseCases; bool m_bCameraToAvoidThisObject; - - // this batch is unused - int8 field_17B; - int8 field_17C; - int8 field_17D; - int8 field_17E; - int8 field_17F; - + int8 m_nBeachballBounces; + uint32 m_obj_unused1; uint32 m_nEndOfLifeTime; int16 m_nRefModelIndex; CEntity *m_pCurSurface; @@ -86,8 +83,6 @@ public: int8 m_colour1, m_colour2; static int16 nNoTempObjects; -// static int16 nBodyCastHealth; - static float fDistToNearestTree; static void *operator new(size_t); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 539bbfaf..c84e37c7 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -59,6 +59,7 @@ #include "Floater.h" #include "Streaming.h" #include "PedAttractor.h" +#include "Debug.h" #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 4452c13a..87f3456a 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -466,7 +466,7 @@ public: //uint32 b158_1 //uint32 b158_2 - //uint32 b158_4 + uint32 b158_4 : 1; //uint32 b158_8 //uint32 b158_10 //uint32 b158_20 diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index dc52d493..2d873e6d 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -155,7 +155,7 @@ public: static float GetSpriteSize(void) { return m_fCurrentSpriteSize; } static int GetShadowStrength(void) { return m_nCurrentShadowStrength; } static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; } - static int GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; } + static float GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; } static float GetFarClip(void) { return m_fCurrentFarClip; } static float GetFogStart(void) { return m_fCurrentFogStart; } diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index c4ac94a2..483aa562 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -83,7 +83,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) bIsInWater = true; - unk1 = 0.0f; + m_phys_unused1 = 0.0f; m_bIsAnchored = true; m_fOrientation = INVALID_ORIENTATION; bTouchingWater = true; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 58c68a8d..47098d6d 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -127,6 +127,9 @@ CVehicle::CVehicle(uint8 CreatedBy) AutoPilot.m_bStayInCurrentLevel = false; AutoPilot.m_bIgnorePathfinding = false; AutoPilot.m_nSwitchDistance = 20; + +// TODO(MIAMI) + bRestingOnPhysical = false; } CVehicle::~CVehicle() diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 0b7d3cba..a401975c 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -189,7 +189,7 @@ public: uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water) //uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc) - //uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed + uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed uint8 bParking : 1; //uint8 bCanPark : 1; From 21071edbfe5794393d1e64322e4689f50ddc1bc3 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 22 May 2020 14:34:44 +0200 Subject: [PATCH 095/148] fixes for CPhysical and friends --- src/core/Stats.h | 18 +++--- src/core/SurfaceTable.cpp | 128 +++++++++++++++++++------------------- src/core/SurfaceTable.h | 43 +------------ src/core/Timer.h | 2 +- src/entities/Physical.cpp | 97 +++++++++++++++-------------- src/entities/Physical.h | 7 +-- src/objects/Object.h | 9 +-- src/render/Timecycle.h | 2 +- src/vehicles/Boat.cpp | 2 +- 9 files changed, 132 insertions(+), 176 deletions(-) diff --git a/src/core/Stats.h b/src/core/Stats.h index 4445ecf4..ae3c0cb4 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -10,7 +10,7 @@ public: TOTAL_HIGHEST_SCORES = 16 }; static int32 DaysPassed; - static int32 HeadsPopped; + static int32 HeadsPopped; static int32 CommercialPassed; static int32 IndustrialPassed; static int32 SuburbanPassed; @@ -52,14 +52,14 @@ public: static int32 LongestFlightInDodo; static int32 TimeTakenDefuseMission; static int32 TotalNumberKillFrenzies; - static int32 TotalNumberMissions; - static int32 RoundsFiredByPlayer; - static int32 KgsOfExplosivesUsed; - static int32 InstantHitsFiredByPlayer; - static int32 InstantHitsHitByPlayer; - static int32 BestTimeBombDefusal; - static int32 mmRain; - static int32 CarsCrushed; + static int32 TotalNumberMissions; + static int32 RoundsFiredByPlayer; + static int32 KgsOfExplosivesUsed; + static int32 InstantHitsFiredByPlayer; + static int32 InstantHitsHitByPlayer; + static int32 BestTimeBombDefusal; + static int32 mmRain; + static int32 CarsCrushed; static int32 FastestTimes[TOTAL_FASTEST_TIMES]; static int32 HighestScores[TOTAL_HIGHEST_SCORES]; diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index 08a84cfd..e4f9c0cd 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -56,40 +56,40 @@ int CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) { switch(surfaceType){ - case SURFACE_0: return ADHESIVE_ROAD; - case SURFACE_1: return ADHESIVE_ROAD; - case SURFACE_2: return ADHESIVE_LOOSE; - case SURFACE_3: return ADHESIVE_LOOSE; - case SURFACE_4: return ADHESIVE_HARD; - case SURFACE_5: return ADHESIVE_ROAD; - case SURFACE_6: return ADHESIVE_HARD; - case SURFACE_7: return ADHESIVE_HARD; - case SURFACE_8: return ADHESIVE_HARD; - case SURFACE_9: return ADHESIVE_HARD; - case SURFACE_10: return ADHESIVE_HARD; - case SURFACE_11: return ADHESIVE_HARD; - case SURFACE_12: return ADHESIVE_HARD; - case SURFACE_13: return ADHESIVE_HARD; - case SURFACE_14: return ADHESIVE_HARD; - case SURFACE_15: return ADHESIVE_HARD; - case SURFACE_16: return ADHESIVE_HARD; - case SURFACE_17: return ADHESIVE_RUBBER; - case SURFACE_18: return ADHESIVE_LOOSE; - case SURFACE_19: return ADHESIVE_WET; - case SURFACE_20: return ADHESIVE_ROAD; - case SURFACE_21: return ADHESIVE_ROAD; - case SURFACE_22: return ADHESIVE_ROAD; - case SURFACE_23: return ADHESIVE_RUBBER; - case SURFACE_24: return ADHESIVE_HARD; - case SURFACE_25: return ADHESIVE_LOOSE; - case SURFACE_26: return ADHESIVE_LOOSE; - case SURFACE_27: return ADHESIVE_HARD; - case SURFACE_28: return ADHESIVE_HARD; - case SURFACE_29: return ADHESIVE_RUBBER; - case SURFACE_30: return ADHESIVE_LOOSE; - case SURFACE_31: return ADHESIVE_HARD; - case SURFACE_32: return ADHESIVE_HARD; - default: return ADHESIVE_ROAD; + case SURFACE_DEFAULT: return ADHESIVE_ROAD; + case SURFACE_TARMAC: return ADHESIVE_ROAD; + case SURFACE_GRASS: return ADHESIVE_LOOSE; + case SURFACE_DIRT: return ADHESIVE_LOOSE; + case SURFACE_DIRTTRACK: return ADHESIVE_HARD; + case SURFACE_PAVEMENT: return ADHESIVE_ROAD; + case SURFACE_METAL6: return ADHESIVE_HARD; + case SURFACE_GLASS: return ADHESIVE_HARD; + case SURFACE_SCAFFOLD: return ADHESIVE_HARD; + case SURFACE_METAL_DOOR: return ADHESIVE_HARD; + case SURFACE_BILLBOARD: return ADHESIVE_HARD; + case SURFACE_STEEL: return ADHESIVE_HARD; + case SURFACE_METAL_POLE: return ADHESIVE_HARD; + case SURFACE_STREET_LIGHT: return ADHESIVE_HARD; + case SURFACE_METAL14: return ADHESIVE_HARD; + case SURFACE_METAL15: return ADHESIVE_HARD; + case SURFACE_METAL_FENCE: return ADHESIVE_HARD; + case SURFACE_FLESH: return ADHESIVE_RUBBER; + case SURFACE_SAND: return ADHESIVE_LOOSE; + case SURFACE_PUDDLE: return ADHESIVE_WET; + case SURFACE_WOOD: return ADHESIVE_ROAD; + case SURFACE_WOOD_BOX: return ADHESIVE_ROAD; + case SURFACE_WOOD_PLANK: return ADHESIVE_ROAD; + case SURFACE_TIRE: return ADHESIVE_RUBBER; + case SURFACE_HARD24: return ADHESIVE_HARD; + case SURFACE_HEDGE: return ADHESIVE_LOOSE; + case SURFACE_STONE: return ADHESIVE_LOOSE; + case SURFACE_METAL27: return ADHESIVE_HARD; + case SURFACE_METAL28: return ADHESIVE_HARD; + case SURFACE_RUBBER29: return ADHESIVE_RUBBER; + case SURFACE_LOOSE30: return ADHESIVE_LOOSE; + case SURFACE_BOLLARD: return ADHESIVE_HARD; + case SURFACE_GATE: return ADHESIVE_HARD; + default: return ADHESIVE_ROAD; } } @@ -97,38 +97,38 @@ float CSurfaceTable::GetWetMultiplier(uint8 surfaceType) { switch(surfaceType){ - case SURFACE_0: - case SURFACE_1: - case SURFACE_4: - case SURFACE_5: - case SURFACE_8: - case SURFACE_20: - case SURFACE_21: - case SURFACE_22: - case SURFACE_25: - case SURFACE_30: - case SURFACE_31: + case SURFACE_DEFAULT: + case SURFACE_TARMAC: + case SURFACE_DIRTTRACK: + case SURFACE_PAVEMENT: + case SURFACE_SCAFFOLD: + case SURFACE_WOOD: + case SURFACE_WOOD_BOX: + case SURFACE_WOOD_PLANK: + case SURFACE_HEDGE: + case SURFACE_LOOSE30: + case SURFACE_BOLLARD: return 1.0f - CWeather::WetRoads*0.25f; - case SURFACE_2: - case SURFACE_6: - case SURFACE_7: - case SURFACE_9: - case SURFACE_10: - case SURFACE_11: - case SURFACE_12: - case SURFACE_13: - case SURFACE_14: - case SURFACE_15: - case SURFACE_16: - case SURFACE_17: - case SURFACE_23: - case SURFACE_24: - case SURFACE_26: - case SURFACE_27: - case SURFACE_28: - case SURFACE_29: - case SURFACE_32: + case SURFACE_GRASS: + case SURFACE_METAL6: + case SURFACE_GLASS: + case SURFACE_METAL_DOOR: + case SURFACE_BILLBOARD: + case SURFACE_STEEL: + case SURFACE_METAL_POLE: + case SURFACE_STREET_LIGHT: + case SURFACE_METAL14: + case SURFACE_METAL15: + case SURFACE_METAL_FENCE: + case SURFACE_FLESH: + case SURFACE_TIRE: + case SURFACE_HARD24: + case SURFACE_STONE: + case SURFACE_METAL27: + case SURFACE_METAL28: + case SURFACE_RUBBER29: + case SURFACE_GATE: return 1.0f - CWeather::WetRoads*0.4f; default: diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 12246dce..768521bf 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -1,47 +1,6 @@ #pragma once - -enum -{ - SURFACE_0, - SURFACE_1, - SURFACE_2, - SURFACE_3, - SURFACE_4, - SURFACE_5, - SURFACE_6, - SURFACE_7, - SURFACE_8, - SURFACE_9, - SURFACE_10, - SURFACE_11, - SURFACE_12, - SURFACE_13, - SURFACE_14, - SURFACE_15, - SURFACE_16, - SURFACE_17, - SURFACE_18, - SURFACE_19, - SURFACE_20, - SURFACE_21, - SURFACE_22, - SURFACE_23, - SURFACE_24, - SURFACE_25, - SURFACE_26, - SURFACE_27, - SURFACE_28, - SURFACE_29, - SURFACE_30, - SURFACE_31, - SURFACE_32, - - NUMSURFACETYPES -}; - -// From nick -// TODO: check and use this +// TODO: check this enum eSurfaceType { SURFACE_DEFAULT, diff --git a/src/core/Timer.h b/src/core/Timer.h index 004cda4d..e7b6fec8 100644 --- a/src/core/Timer.h +++ b/src/core/Timer.h @@ -58,7 +58,7 @@ public: friend bool GenericSave(int file); #ifdef FIX_BUGS - static float GetDefaultTimeStep(void) { return 5.0f / 3.0f; } + static float GetDefaultTimeStep(void) { return 50.0f / 30.0f; } static float GetTimeStepFix(void) { return GetTimeStep() / GetDefaultTimeStep(); } #endif }; diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 31f8fcbc..f9f8ae7e 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -45,9 +45,9 @@ CPhysical::CPhysical(void) bUsesCollision = true; m_audioEntityId = -5; - unk1 = 100.0f; + m_phys_unused1 = 100.0f; m_vecCentreOfMass = CVector(0.0f, 0.0f, 0.0f); - field_EC = 0; + m_phys_unused2 = 0; bIsHeavy = false; bAffectedByGravity = true; @@ -527,26 +527,26 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl bool ispedcontactA = false; bool ispedcontactB = false; - float timestepA; + float massFactorA; if(B->bPedPhysics){ - timestepA = 10.0f; + massFactorA = 10.0f; if(B->IsPed() && ((CPed*)B)->m_pCurrentPhysSurface == A) ispedcontactA = true; }else - timestepA = A->bIsHeavy ? 2.0f : 1.0f; + massFactorA = A->bIsHeavy ? 2.0f : 1.0f; - float timestepB; + float massFactorB; if(A->bPedPhysics){ if(A->IsPed() && ((CPed*)A)->IsPlayer() && B->IsVehicle() && (B->GetStatus() == STATUS_ABANDONED || B->GetStatus() == STATUS_WRECKED || A->bHasHitWall)) - timestepB = 2200.0f / B->m_fMass; + massFactorB = 2200.0f / B->m_fMass; else - timestepB = 10.0f; + massFactorB = 10.0f; if(A->IsPed() && ((CPed*)A)->m_pCurrentPhysSurface == B) ispedcontactB = true; }else - timestepB = B->bIsHeavy ? 2.0f : 1.0f; + massFactorB = B->bIsHeavy ? 2.0f : 1.0f; float speedA, speedB; if(B->IsStatic()){ @@ -646,14 +646,17 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl // positive if B is moving towards A // not interested in how much B moves into A apparently? // only interested in cases where A collided into B - speedB = Max(0.0f, DotProduct(B->m_vecMoveSpeed, colpoint.normal)); + speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal); + float speedSum = Max(0.0f, DotProduct(B->m_vecMoveSpeed, colpoint.normal)); // A has moved into B - if(speedA < speedB){ - if(!A->bHasHitWall) - speedB -= (speedA - speedB) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (speedB-speedA) * A->m_fMass * timestepA; + if(speedA < speedSum){ + if(A->bHasHitWall) + eA = speedSum; + else + eA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; + impulseA = (eA-speedA) * A->m_fMass * massFactorA; if(!A->bInfiniteMass) - A->ApplyMoveForce(colpoint.normal*(impulseA/timestepA)); + A->ApplyMoveForce(colpoint.normal*(impulseA/massFactorA)); return true; } }else if(A->bPedPhysics){ @@ -661,9 +664,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); - float a = A->m_fMass*timestepA; - float b = B->GetMassTime(pointposB, colpoint.normal, timestepB); - float speedSum = (b*speedB + a*speedA)/(a + b); + float mA = A->m_fMass*massFactorA; + float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB); + float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) eA = speedSum; @@ -673,10 +676,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eB = speedSum; else eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (eA - speedA) * a; - impulseB = -(eB - speedB) * b; - CVector fA = colpoint.normal*(impulseA/timestepA); - CVector fB = colpoint.normal*(-impulseB/timestepB); + impulseA = (eA - speedA) * mA; + impulseB = -(eB - speedB) * mB; + CVector fA = colpoint.normal*(impulseA/massFactorA); + CVector fB = colpoint.normal*(-impulseB/massFactorB); if(!A->bInfiniteMass){ if(fA.z < 0.0f) fA.z = 0.0f; if(ispedcontactB){ @@ -696,9 +699,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal); - float a = A->GetMassTime(pointposA, colpoint.normal, timestepA); - float b = B->m_fMass*timestepB; - float speedSum = (b*speedB + a*speedA)/(a + b); + float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA); + float mB = B->m_fMass*massFactorB; + float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) eA = speedSum; @@ -708,10 +711,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eB = speedSum; else eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (eA - speedA) * a; - impulseB = -(eB - speedB) * b; - CVector fA = colpoint.normal*(impulseA/timestepA); - CVector fB = colpoint.normal*(-impulseB/timestepB); + impulseA = (eA - speedA) * mA; + impulseB = -(eB - speedB) * mB; + CVector fA = colpoint.normal*(impulseA/massFactorA); + CVector fB = colpoint.normal*(-impulseB/massFactorB); if(!A->bInfiniteMass && !ispedcontactA){ if(fA.z < 0.0f) fA.z = 0.0f; A->ApplyMoveForce(fA); @@ -736,9 +739,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl CVector pointposB = colpoint.point - B->GetPosition(); speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); - float a = A->GetMassTime(pointposA, colpoint.normal, timestepA); - float b = B->GetMassTime(pointposB, colpoint.normal, timestepB); - float speedSum = (b*speedB + a*speedA)/(a + b); + float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA); + float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB); + float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) eA = speedSum; @@ -748,10 +751,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eB = speedSum; else eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; - impulseA = (eA - speedA) * a; - impulseB = -(eB - speedB) * b; - CVector fA = colpoint.normal*(impulseA/timestepA); - CVector fB = colpoint.normal*(-impulseB/timestepB); + impulseA = (eA - speedA) * mA; + impulseB = -(eB - speedB) * mB; + CVector fA = colpoint.normal*(impulseA/massFactorA); + CVector fB = colpoint.normal*(-impulseB/massFactorB); if(A->IsVehicle() && !A->bHasHitWall){ fA.x *= 1.4f; fA.y *= 1.4f; @@ -767,7 +770,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(B->IsVehicle() && !B->bHasHitWall){ fB.x *= 1.4f; fB.y *= 1.4f; - if(colpoint.normal.z < 0.7f) + if(-colpoint.normal.z < 0.7f) fB.z *= 0.3f; if(B->GetStatus() == STATUS_PLAYER) pointposB *= 0.8f; @@ -813,7 +816,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV speed = GetSpeed(pointpos); normalSpeed = DotProduct(speed, colpoint.normal); if(normalSpeed < 0.0f){ - float minspeed = 0.0104f * CTimer::GetTimeStep(); + float minspeed = 1.3f*GRAVITY * CTimer::GetTimeStep(); #ifdef GTA3_1_1_PATCH if ((IsObject() || IsVehicle() && (GetUp().z < -0.3f || ((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED))) && #else @@ -1015,7 +1018,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint) ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos); if(fOtherSpeed > 0.1f && - colpoint.surfaceB != SURFACE_2 && colpoint.surfaceB != SURFACE_4 && + colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_DIRTTRACK && CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){ CVector v = frictionDir * fOtherSpeed * 0.25f; for(int i = 0; i < 4; i++) @@ -1064,7 +1067,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) canshift = true; else canshift = A->IsPed() && - B->IsObject() && B->bInfiniteMass && !Bobj->bHasBeenDamaged; + B->IsObject() && B->bIsStatic && !Bobj->bHasBeenDamaged; if(B == A || B->m_scanCode == CWorld::GetCurrentScanCode() || !B->bUsesCollision || @@ -1084,7 +1087,6 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) B->GetUp().z < 0.66f && IsStreetLight(B->GetModelIndex())) skipShift = true; -// TODO: maybe flip some ifs here else if(A->IsObject() && B->IsVehicle()){ CObject *Aobj = (CObject*)A; if(Aobj->ObjectCreatedBy != TEMP_OBJECT && @@ -1699,16 +1701,16 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) } if(B->IsPed() && A->IsVehicle() && - (!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > 0.0025f)) + (!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > SQR(0.05f))) Bped->KillPedWithCar((CVehicle*)A, maxImpulseB); else if(B->GetModelIndex() == MI_TRAIN && A->IsPed() && (!Aped->IsPlayer() || A->bHasHitWall)) Aped->KillPedWithCar((CVehicle*)B, maxImpulseA*2.0f); else if(B->IsObject() && B->bUsesCollision && A->IsVehicle()){ + // BUG? not impulseA? if(Bobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f) Bobj->ObjectDamage(maxImpulseB); }else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){ - // BUG? not impulseA? if(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f) Aobj->ObjectDamage(maxImpulseB); } @@ -1774,7 +1776,7 @@ CPhysical::ProcessShift(void) m_bIsVehicleBeingShifted = true; CEntryInfoNode *node; - bool hasshifted = false; // whatever that means... + bool hasshifted = false; for(node = m_entryInfoList.first; node; node = node->next) hasshifted |= ProcessShiftSectorList(node->sector->m_lists); m_bIsVehicleBeingShifted = false; @@ -1831,7 +1833,7 @@ CPhysical::ProcessCollision(void) int8 n = 1; // The number of steps we divide the time step into float step = 0.0f; // divided time step - float distSq = GetDistanceSq(); + float distSq = m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep()); if(IsPed() && (distSq >= sq(0.2f) || ped->IsPlayer())){ if(ped->IsPlayer()) @@ -1920,8 +1922,11 @@ CPhysical::ProcessCollision(void) bSkipLineCol = false; if(!m_vecMoveSpeed.IsZero() || !m_vecTurnSpeed.IsZero() || +#ifdef GTA_TRAIN bHitByTrain || - GetStatus() == STATUS_PLAYER || IsPed() && ped->IsPlayer()){ +#endif + GetStatus() == STATUS_PLAYER || + IsPed() && ped->IsPlayer()){ if(IsVehicle()) ((CVehicle*)this)->bVehicleColProcessed = true; if(CheckCollision()){ diff --git a/src/entities/Physical.h b/src/entities/Physical.h index c84686ed..f8921a5c 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -18,7 +18,7 @@ public: // The not properly indented fields haven't been checked properly yet int32 m_audioEntityId; - float unk1; + float m_phys_unused1; CTreadable *m_treadable[2]; // car and ped uint32 m_nLastTimeCollided; CVector m_vecMoveSpeed; // velocity @@ -37,7 +37,7 @@ public: CEntryInfoList m_entryInfoList; CPtrNode *m_movingListNode; - char field_EC; + int8 m_phys_unused2; uint8 m_nStaticFrames; uint8 m_nCollisionRecords; bool m_bIsVehicleBeingShifted; @@ -86,7 +86,6 @@ public: void RemoveRefsToEntity(CEntity *ent); static void PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos); - float GetDistanceSq(void) { return m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep()); } // get speed of point p relative to entity center CVector GetSpeed(const CVector &r); CVector GetSpeed(void) { return GetSpeed(CVector(0.0f, 0.0f, 0.0f)); } @@ -94,7 +93,7 @@ public: return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/m_fTurnMass + 1.0f/m_fMass); } - float GetMassTime(const CVector &pos, const CVector &dir, float t) { + float GetMassTweak(const CVector &pos, const CVector &dir, float t) { return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/(m_fTurnMass*t) + 1.0f/(m_fMass*t)); } diff --git a/src/objects/Object.h b/src/objects/Object.h index 79589dc9..c9a1bba8 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -55,14 +55,7 @@ public: uint8 m_nCollisionDamageEffect; uint8 m_nSpecialCollisionResponseCases; bool m_bCameraToAvoidThisObject; - - // this batch is unused - int8 field_17B; - int8 field_17C; - int8 field_17D; - int8 field_17E; - int8 field_17F; - + uint32 m_obj_unused1; uint32 m_nEndOfLifeTime; int16 m_nRefModelIndex; CEntity *m_pCurSurface; diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index 28a0b7dd..9af4df49 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -122,7 +122,7 @@ public: static float GetSpriteSize(void) { return m_fCurrentSpriteSize; } static int GetShadowStrength(void) { return m_nCurrentShadowStrength; } static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; } - static int GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; } + static float GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; } static float GetFarClip(void) { return m_fCurrentFarClip; } static float GetFogStart(void) { return m_fCurrentFogStart; } diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 72fca542..0ed7876a 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -79,7 +79,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) bIsInWater = true; - unk1 = 0.0f; + m_phys_unused1 = 0.0f; m_bIsAnchored = true; m_fOrientation = INVALID_ORIENTATION; bTouchingWater = true; From a878e09f0f2a3c79d0deddc4455879523c8f9198 Mon Sep 17 00:00:00 2001 From: Xin Date: Fri, 22 May 2020 16:04:52 +0300 Subject: [PATCH 096/148] InitAfterFocusLoss compile fix --- src/core/Game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Game.cpp b/src/core/Game.cpp index d2f23b17..8c0b26e1 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -677,7 +677,7 @@ CGame::InitAfterFocusLoss() //cDMAudio::SetCurrent3DProvider( ? ? ? ); if (!FrontEndMenuManager.m_bGameNotLoaded && !FrontEndMenuManager.m_bMenuActive) - CMenuManager::m_bStartUpFrontEndRequested = true; + FrontEndMenuManager.m_bStartUpFrontEndRequested = true; } bool From e858314a9f1c0adb0a8c2ec2dd1536e111932650 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 22 May 2020 18:00:18 +0300 Subject: [PATCH 097/148] OpenAL configs --- .appveyor.yml | 2 ++ premake5.lua | 24 +++++++++++++++++++----- src/audio/oal/channel.cpp | 4 ++-- src/audio/oal/channel.h | 1 - src/audio/oal/oal_utils.cpp | 1 + src/audio/oal/oal_utils.h | 1 - src/audio/oal/stream.cpp | 8 ++++---- src/audio/oal/stream.h | 1 - src/core/config.h | 5 ----- 9 files changed, 28 insertions(+), 19 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 20adee80..05604e2c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -6,6 +6,8 @@ configuration: platform: - win-x86-librw_d3d9-mss - win-x86-librw_gl3_glfw-mss +- win-x86-librw_d3d9-oal +- win-x86-librw_gl3_glfw-oal environment: APPVEYOR_SAVE_CACHE_ON_ERROR: true GLEW_VER: "2.1.0" diff --git a/premake5.lua b/premake5.lua index c8494884..79b8db64 100644 --- a/premake5.lua +++ b/premake5.lua @@ -51,6 +51,9 @@ workspace "re3" "win-x86-RW33_d3d8-mss", "win-x86-librw_d3d9-mss", "win-x86-librw_gl3_glfw-mss", + "win-x86-RW33_d3d8-oal", + "win-x86-librw_d3d9-oal", + "win-x86-librw_gl3_glfw-oal", } filter { "system:linux" } @@ -183,11 +186,23 @@ project "re3" includedirs { "src/extras" } includedirs { "eax" } - includedirs { "milessdk/include" } includedirs { "eax" } - - libdirs { "milessdk/lib" } + filter "platforms:*mss" + defines { "AUIOD_MSS" } + includedirs { "milessdk/include" } + libdirs { "milessdk/lib" } + + filter "platforms:*oal" + defines { "AUIOD_OAL" } + includedirs { "openal-soft/include" } + includedirs { "libsndfile/include" } + includedirs { "mpg123/include" } + libdirs { "openal-soft/libs/Win32" } + libdirs { "libsndfile/lib" } + libdirs { "mpg123/lib" } + + filter {} if(os.getenv("GTA_III_RE_DIR")) then setpaths("$(GTA_III_RE_DIR)/", "%(cfg.buildtarget.name)", "") end @@ -199,8 +214,7 @@ project "re3" characterset ("MBCS") targetextension ".exe" - filter "platforms:linux*" - defines { "OPENAL" } + filter "platforms:linux*oal" links { "openal", "mpg123", "sndfile", "pthread" } filter "platforms:*RW33*" diff --git a/src/audio/oal/channel.cpp b/src/audio/oal/channel.cpp index 6fe1d856..731e3581 100644 --- a/src/audio/oal/channel.cpp +++ b/src/audio/oal/channel.cpp @@ -1,7 +1,7 @@ -#include "channel.h" +#include "common.h" #ifdef AUDIO_OAL -#include "common.h" +#include "channel.h" #include "sampman.h" #ifndef _WIN32 diff --git a/src/audio/oal/channel.h b/src/audio/oal/channel.h index 4dd09ca1..0c86bdc6 100644 --- a/src/audio/oal/channel.h +++ b/src/audio/oal/channel.h @@ -1,5 +1,4 @@ #pragma once -#include "common.h" #ifdef AUDIO_OAL #include "oal/oal_utils.h" diff --git a/src/audio/oal/oal_utils.cpp b/src/audio/oal/oal_utils.cpp index 4119672f..e16de572 100644 --- a/src/audio/oal/oal_utils.cpp +++ b/src/audio/oal/oal_utils.cpp @@ -1,3 +1,4 @@ +#include "common.h" #include "oal_utils.h" #ifdef AUDIO_OAL diff --git a/src/audio/oal/oal_utils.h b/src/audio/oal/oal_utils.h index af45a944..b89ccf36 100644 --- a/src/audio/oal/oal_utils.h +++ b/src/audio/oal/oal_utils.h @@ -1,5 +1,4 @@ #pragma once -#include "common.h" #ifdef AUDIO_OAL #include "eax.h" diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 5a9c7d7d..34518f54 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -1,11 +1,9 @@ -#include "stream.h" +#include "common.h" #ifdef AUDIO_OAL -#include "common.h" +#include "stream.h" #include "sampman.h" -#include -#include #ifdef _WIN32 typedef long ssize_t; #pragma comment( lib, "libsndfile-1.lib" ) @@ -13,6 +11,8 @@ typedef long ssize_t; #else #include "crossplatform.h" #endif +#include +#include class CSndFile : public IDecoder { diff --git a/src/audio/oal/stream.h b/src/audio/oal/stream.h index f1e5f458..456c080a 100644 --- a/src/audio/oal/stream.h +++ b/src/audio/oal/stream.h @@ -1,5 +1,4 @@ #pragma once -#include "common.h" #ifdef AUDIO_OAL #include diff --git a/src/core/config.h b/src/core/config.h index 40882128..f43067d7 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -196,11 +196,6 @@ enum Config { #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number //#define USE_TEXTURE_POOL -#ifdef _WIN32 -#define AUDIO_MSS -#else -#define AUDIO_OAL -#endif // Particle //#define PC_PARTICLE From 38a09c6e9b4a631aae699a8f3de6c0df33c021e5 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 22 May 2020 21:00:59 +0300 Subject: [PATCH 098/148] Fix linux build --- .appveyor.yml | 2 -- eax/eax.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 05604e2c..20adee80 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -6,8 +6,6 @@ configuration: platform: - win-x86-librw_d3d9-mss - win-x86-librw_gl3_glfw-mss -- win-x86-librw_d3d9-oal -- win-x86-librw_gl3_glfw-oal environment: APPVEYOR_SAVE_CACHE_ON_ERROR: true GLEW_VER: "2.1.0" diff --git a/eax/eax.h b/eax/eax.h index 0e2201db..503090d2 100644 --- a/eax/eax.h +++ b/eax/eax.h @@ -12,7 +12,7 @@ extern "C" { #endif // __cplusplus -#ifndef OPENAL +#ifndef AUDIO_OAL #include /* @@ -49,7 +49,7 @@ extern "C" { typedef void (CDECL *LPGETCURRENTVERSION)(LPDWORD major, LPDWORD minor); -#else // OPENAL +#else // AUDIO_OAL #ifndef _WIN32 #include #include From efe52dbbbc504acdf87573f23653d4a8ec295c46 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 22 May 2020 21:14:38 +0300 Subject: [PATCH 099/148] I am an idiot --- eax/eax.h | 4 ---- premake5.lua | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/eax/eax.h b/eax/eax.h index 503090d2..b2210936 100644 --- a/eax/eax.h +++ b/eax/eax.h @@ -50,12 +50,8 @@ extern "C" { #else // AUDIO_OAL -#ifndef _WIN32 #include #include -#else - #include -#endif #ifndef GUID_DEFINED #define GUID_DEFINED diff --git a/premake5.lua b/premake5.lua index 79b8db64..75b1b979 100644 --- a/premake5.lua +++ b/premake5.lua @@ -189,12 +189,12 @@ project "re3" includedirs { "eax" } filter "platforms:*mss" - defines { "AUIOD_MSS" } + defines { "AUDIO_MSS" } includedirs { "milessdk/include" } libdirs { "milessdk/lib" } filter "platforms:*oal" - defines { "AUIOD_OAL" } + defines { "AUDIO_OAL" } includedirs { "openal-soft/include" } includedirs { "libsndfile/include" } includedirs { "mpg123/include" } From a9f332f2d96b6a8b6f83b5da5c1c320d2ff4eab2 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 22 May 2020 21:26:31 +0300 Subject: [PATCH 100/148] Possibly fix travis --- src/audio/oal/stream.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 34518f54..c70cd2c1 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -8,11 +8,12 @@ typedef long ssize_t; #pragma comment( lib, "libsndfile-1.lib" ) #pragma comment( lib, "libmpg123.lib" ) -#else -#include "crossplatform.h" #endif #include #include +#ifndef _WIN32 +#include "crossplatform.h" +#endif class CSndFile : public IDecoder { From c993e99e0086aae50357c8ffa180de54396ede92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 22 May 2020 22:49:54 +0300 Subject: [PATCH 101/148] Fix linux build --- premake5.lua | 14 ++++++++------ src/audio/oal/stream.cpp | 5 ++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/premake5.lua b/premake5.lua index 75b1b979..fd6da6ac 100644 --- a/premake5.lua +++ b/premake5.lua @@ -195,12 +195,6 @@ project "re3" filter "platforms:*oal" defines { "AUDIO_OAL" } - includedirs { "openal-soft/include" } - includedirs { "libsndfile/include" } - includedirs { "mpg123/include" } - libdirs { "openal-soft/libs/Win32" } - libdirs { "libsndfile/lib" } - libdirs { "mpg123/lib" } filter {} if(os.getenv("GTA_III_RE_DIR")) then @@ -214,6 +208,14 @@ project "re3" characterset ("MBCS") targetextension ".exe" + filter "platforms:win*oal" + includedirs { "openal-soft/include" } + includedirs { "libsndfile/include" } + includedirs { "mpg123/include" } + libdirs { "openal-soft/libs/Win32" } + libdirs { "libsndfile/lib" } + libdirs { "mpg123/lib" } + filter "platforms:linux*oal" links { "openal", "mpg123", "sndfile", "pthread" } diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index c70cd2c1..34518f54 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -8,12 +8,11 @@ typedef long ssize_t; #pragma comment( lib, "libsndfile-1.lib" ) #pragma comment( lib, "libmpg123.lib" ) +#else +#include "crossplatform.h" #endif #include #include -#ifndef _WIN32 -#include "crossplatform.h" -#endif class CSndFile : public IDecoder { From e18eb0ce012282362203fc93e644914af1eaf51d Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 00:50:15 +0300 Subject: [PATCH 102/148] script fix --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 68b396f3..082beda9 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -4333,7 +4333,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) } case COMMAND_SET_CAR_HEAVY: { - CollectParameters(&m_nIp, 1); + CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); pVehicle->bIsHeavy = (ScriptParams[1] != 0); From 7bf561d440f0179f222e1e2811ac92384c1560a2 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 01:43:12 +0300 Subject: [PATCH 103/148] some fixes --- src/control/Garages.h | 1 - src/control/Script.cpp | 10 ++++++---- src/core/ControllerConfig.cpp | 26 +++++++++++++++++++++++--- src/core/ControllerConfig.h | 2 ++ src/peds/Ped.cpp | 7 ++++--- 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/control/Garages.h b/src/control/Garages.h index c5bede2b..79905ede 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -294,7 +294,6 @@ private: case GARAGE_HIDEOUT_TEN: return 9; case GARAGE_HIDEOUT_ELEVEN: return 10; case GARAGE_HIDEOUT_TWELVE: return 11; - default: assert(0); } return -1; } diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 36b7f34e..1f30f6a4 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -4414,7 +4414,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) } case COMMAND_SET_CAR_HEAVY: { - CollectParameters(&m_nIp, 1); + CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); if (ScriptParams[1] != 0) { @@ -10144,7 +10144,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) UpdateCompareFlag(CModelInfo::GetModelInfo(ScriptParams[0]) != nil); return 0; case COMMAND_SHUT_CHAR_UP: - CollectParameters(&m_nIp, 1); + CollectParameters(&m_nIp, 2); debug("SHUT_CHAR_UP not implemented"); // TODO(MIAMI) return 0; case COMMAND_SET_ENABLE_RC_DETONATE: @@ -10588,6 +10588,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) { CollectParameters(&m_nIp, 1); debug("SWITCH_SECURITY_CAMERA is not implemented\n"); // TODO(MIAMI) + return 0; } //case COMMAND_IS_CHAR_IN_FLYING_VEHICLE: case COMMAND_IS_PLAYER_IN_FLYING_VEHICLE: @@ -11153,7 +11154,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) //case COMMAND_IS_CAR_DROWNING_IN_WATER: case COMMAND_IS_CHAR_DROWNING_IN_WATER: { - CollectParameters(&m_nIp, 2); + CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); UpdateCompareFlag(pPed && pPed->bIsDrowning); return 0; @@ -11253,10 +11254,11 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) } case COMMAND_CLEAR_CHAR_WAIT_STATE: { - CollectParameters(&m_nIp, 2); + CollectParameters(&m_nIp, 1); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); pPed->ClearWaitState(); + return 0; } case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE: { diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 453889a5..e48f2c3f 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -205,6 +205,8 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (PED_LOOKBEHIND, rsPADEND, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_LOOKBEHIND, rsCAPSLK, OPTIONAL_EXTRA); + + SetControllerKeyAssociatedWithAction (PED_DUCK, 'C', KEYBOARD); SetControllerKeyAssociatedWithAction (PED_FIREWEAPON, rsPADINS, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_FIREWEAPON, rsLCTRL, OPTIONAL_EXTRA); @@ -217,6 +219,8 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (PED_JUMPING, rsRCTRL, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_JUMPING, ' ', OPTIONAL_EXTRA); + + SetControllerKeyAssociatedWithAction (PED_ANSWER_PHONE, rsTAB, KEYBOARD); if ( _dwOperatingSystemVersion == OS_WIN98 ) SetControllerKeyAssociatedWithAction(PED_SPRINT, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? @@ -259,7 +263,7 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (VEHICLE_TURRETDOWN, rsPADRIGHT, KEYBOARD); SetControllerKeyAssociatedWithAction (CAMERA_CHANGE_VIEW_ALL_SITUATIONS, rsHOME, KEYBOARD); - SetControllerKeyAssociatedWithAction (CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 'C', OPTIONAL_EXTRA); + SetControllerKeyAssociatedWithAction (CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 'V', OPTIONAL_EXTRA); for (int32 i = 0; i < MAX_SIMS; i++) { @@ -336,13 +340,14 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) SetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, 11, JOYSTICK); case 10: SetControllerKeyAssociatedWithAction(VEHICLE_HORN, 10, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_DUCK, 10, JOYSTICK); case 9: SetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 9, JOYSTICK); case 8: SetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, 8, JOYSTICK); SetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, 8, JOYSTICK); case 7: - SetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, 7, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, 7, JOYSTICK); SetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 7, JOYSTICK); case 6: SetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 6, JOYSTICK); @@ -384,13 +389,14 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) SetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, 11, JOYSTICK); case 10: SetControllerKeyAssociatedWithAction(VEHICLE_HORN, 10, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_DUCK, 10, JOYSTICK); case 9: SetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 9, JOYSTICK); case 8: SetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, 8, JOYSTICK); SetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, 8, JOYSTICK); case 7: - SetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, 7, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, 7, JOYSTICK); SetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 7, JOYSTICK); case 6: SetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 6, JOYSTICK); @@ -431,6 +437,8 @@ void CControllerConfigManager::InitialiseControllerActionNameArray() SETACTIONNAME(PED_CYCLE_TARGET_LEFT); SETACTIONNAME(PED_CYCLE_TARGET_RIGHT); SETACTIONNAME(PED_CENTER_CAMERA_BEHIND_PLAYER); + SETACTIONNAME(PED_DUCK); + SETACTIONNAME(PED_ANSWER_PHONE); SETACTIONNAME(VEHICLE_LOOKBEHIND); SETACTIONNAME(VEHICLE_LOOKLEFT); SETACTIONNAME(VEHICLE_LOOKRIGHT); @@ -754,6 +762,8 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstPersonOnl state.Square = 255; if (button == GetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_OUT, type)) state.Cross = 255; + if (button == GetControllerKeyAssociatedWithAction(PED_DUCK, type)) + state.RightShock = 255; } void CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnly(int32 button, eControllerType type, CControllerState &state) @@ -762,12 +772,16 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnl state.RightShock = 255; if (button == GetControllerKeyAssociatedWithAction(PED_JUMPING, type)) state.Square = 255; + if (button == GetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, type)) + state.LeftShoulder1 = 255; if (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_LEFT, type)) state.LeftShoulder2 = 255; if (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, type)) state.RightShoulder2 = 255; if (button == GetControllerKeyAssociatedWithAction(PED_SPRINT, type)) state.Cross = 255; + if (button == GetControllerKeyAssociatedWithAction(PED_DUCK, type)) + state.RightShock = 255; if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { @@ -1616,6 +1630,10 @@ void CControllerConfigManager::DeleteMatching3rdPersonControls(e_ControllerActio ClearSettingsAssociatedWithAction(PED_JUMPING, type); if (key == GetControllerKeyAssociatedWithAction(PED_SPRINT, type)) ClearSettingsAssociatedWithAction(PED_SPRINT, type); + if (key == GetControllerKeyAssociatedWithAction(PED_DUCK, type)) + ClearSettingsAssociatedWithAction(PED_DUCK, type); + if (key == GetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, type)) + ClearSettingsAssociatedWithAction(PED_ANSWER_PHONE, type); if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { @@ -1803,6 +1821,8 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio case PED_CYCLE_WEAPON_RIGHT: case PED_JUMPING: case PED_SPRINT: + case PED_DUCK: + case PED_ANSWER_PHONE: case PED_CYCLE_TARGET_LEFT: case PED_CYCLE_TARGET_RIGHT: case PED_CENTER_CAMERA_BEHIND_PLAYER: diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 7d0e1073..5f0b6862 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -32,6 +32,8 @@ enum e_ControllerAction PED_JUMPING, PED_SPRINT, PED_LOOKBEHIND, + PED_DUCK, + PED_ANSWER_PHONE, VEHICLE_ACCELERATE, VEHICLE_BRAKE, VEHICLE_CHANGE_RADIO_STATION, diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 081ea91e..28fcf74a 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -6025,7 +6025,6 @@ CPed::SetWaitState(eWaitState state, void *time) case WAITSTATE_GROUND_ATTACK: case WAITSTATE_LANCESITTING: case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE: - assert(0); default: ClearWaitState(); RestoreHeadingRate(); @@ -18533,7 +18532,7 @@ CPed::Save(uint8*& buf) CopyToBuf(buf, m_fHealth); CopyToBuf(buf, m_fArmour); SkipSaveBuf(buf, 148); - for (int i = 0; i < 10; i++) // has to be hardcoded + for (int i = 0; i < 13; i++) // has to be hardcoded m_weapons[i].Save(buf); SkipSaveBuf(buf, 5); CopyToBuf(buf, m_maxWeaponTypeAllowed); @@ -18555,8 +18554,10 @@ CPed::Load(uint8*& buf) SkipSaveBuf(buf, 148); CWeapon bufWeapon; - for (int i = 0; i < 10; i++) { // has to be hardcoded + for (int i = 0; i < 13; i++) { // has to be hardcoded bufWeapon.Load(buf); + if (i >= 10) + continue; // tmp hack before we fix save/load if (bufWeapon.m_eWeaponType != WEAPONTYPE_UNARMED) { int modelId = CWeaponInfo::GetWeaponInfo(bufWeapon.m_eWeaponType)->m_nModelId; From f8a509ffb3ffe6a66dfd8b81f1a4405513cb7622 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 02:17:27 +0300 Subject: [PATCH 104/148] fixes --- src/control/Script.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 1f30f6a4..dbbfd59e 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8712,6 +8712,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) return 0; case COMMAND_PRINT_HELP: { + debug("PRINT_HELP %s\n", (char*)&CTheScripts::ScriptSpace[m_nIp]); if (CCamera::m_bUseMouse3rdPerson && ( strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 || strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 || @@ -10149,7 +10150,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) return 0; case COMMAND_SET_ENABLE_RC_DETONATE: CollectParameters(&m_nIp, 1); - CVehicle::bDisableRemoteDetonation = ScriptParams[0]; + CVehicle::bDisableRemoteDetonation = !ScriptParams[0]; return 0; case COMMAND_SET_CAR_RANDOM_ROUTE_SEED: { @@ -10690,7 +10691,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) } case COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING: { - CollectParameters(&m_nIp, 2); + CollectParameters(&m_nIp, 1); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); assert(pObject); UpdateCompareFlag(pObject->m_nCollisionRecords != 0); From 7b7b0fb5f2174d4e8989ab32806297441131f5d5 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 02:18:16 +0300 Subject: [PATCH 105/148] removed debug --- src/control/Script.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index dbbfd59e..52247f05 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8712,7 +8712,6 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) return 0; case COMMAND_PRINT_HELP: { - debug("PRINT_HELP %s\n", (char*)&CTheScripts::ScriptSpace[m_nIp]); if (CCamera::m_bUseMouse3rdPerson && ( strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15", 7) == 0 || strncmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A", 7) == 0 || From 9c6046455ead2d8777f79e585254151b28551864 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 12:17:05 +0300 Subject: [PATCH 106/148] fixed script --- src/control/Script.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 52247f05..85098cca 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8902,7 +8902,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 4); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]); assert(pObject); - CVector result = pObject->GetPosition() + pObject->GetMatrix() * *(CVector*)&ScriptParams[1]; + CVector result = Multiply3x3(pObject->GetMatrix(), *(CVector*)&ScriptParams[1]) + pObject->GetPosition(); *(CVector*)&ScriptParams[0] = result; StoreParameters(&m_nIp, 3); return 0; @@ -8935,7 +8935,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 4); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - CVector result = pVehicle->GetMatrix() * *(CVector*)&ScriptParams[1] + pVehicle->GetPosition(); + CVector result = Multiply3x3(pVehicle->GetMatrix(), *(CVector*)&ScriptParams[1]) + pVehicle->GetPosition(); *(CVector*)&ScriptParams[0] = result; StoreParameters(&m_nIp, 3); return 0; @@ -10554,8 +10554,8 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) CollectParameters(&m_nIp, 4); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); - CVector offset = pPed->GetMatrix() * *(CVector*)&ScriptParams[1]; - *(CVector*)&ScriptParams[0] = pPed->GetPosition() + offset; + CVector result = Multiply3x3(pPed->GetMatrix(), *(CVector*)&ScriptParams[1]) + pPed->GetPosition(); + *(CVector*)&ScriptParams[0] = result; StoreParameters(&m_nIp, 3); return 0; } From e2d3ef449c0385acf36ba77ce2c9da62b88ea3a3 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 23 May 2020 11:34:40 +0200 Subject: [PATCH 107/148] skeleton typos --- src/core/main.cpp | 8 ++++---- src/skel/glfw/glfw.cpp | 8 ++++---- src/skel/platform.h | 2 +- src/skel/skeleton.cpp | 14 +++++++------- src/skel/skeleton.h | 18 +++++++++--------- src/skel/win/win.cpp | 8 ++++---- src/vehicles/Vehicle.h | 3 --- 7 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index 1ea8dc7f..acdf6f4e 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -328,7 +328,7 @@ PluginAttach(void) static RwBool Initialise3D(void *param) { - if (RsRwInitialise(param)) + if (RsRwInitialize(param)) { #ifdef DEBUGMENU DebugMenuInit(); @@ -1146,10 +1146,10 @@ AppEventHandler(RsEvent event, void *param) { switch( event ) { - case rsINITIALISE: + case rsINITIALIZE: { CGame::InitialiseOnceBeforeRW(); - return RsInitialise() ? rsEVENTPROCESSED : rsEVENTERROR; + return RsInitialize() ? rsEVENTPROCESSED : rsEVENTERROR; } case rsCAMERASIZE: @@ -1161,7 +1161,7 @@ AppEventHandler(RsEvent event, void *param) return rsEVENTPROCESSED; } - case rsRWINITIALISE: + case rsRWINITIALIZE: { return Initialise3D(param) ? rsEVENTPROCESSED : rsEVENTERROR; } diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index fc23e900..21115585 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -274,7 +274,7 @@ psNativeTextureSupport(void) ***************************************************************************** */ RwBool -psInitialise(void) +psInitialize(void) { PsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f; @@ -789,7 +789,7 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode) useDefault = TRUE; - if ( RsEventHandler(rsRWINITIALISE, &openParams) == rsEVENTERROR ) + if ( RsEventHandler(rsRWINITIALIZE, &openParams) == rsEVENTERROR ) return FALSE; RwInitialised = TRUE; @@ -1312,7 +1312,7 @@ main(int argc, char *argv[]) * Initialize the platform independent data. * This will in turn initialize the platform specific data... */ - if( RsEventHandler(rsINITIALISE, nil) == rsEVENTERROR ) + if( RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR ) { return FALSE; } @@ -1355,7 +1355,7 @@ main(int argc, char *argv[]) /* * Initialize the 3D (RenderWare) components of the app... */ - if( rsEVENTERROR == RsEventHandler(rsRWINITIALISE, &openParams) ) + if( rsEVENTERROR == RsEventHandler(rsRWINITIALIZE, &openParams) ) { RsEventHandler(rsTERMINATE, nil); diff --git a/src/skel/platform.h b/src/skel/platform.h index 65e20673..cbb1be28 100644 --- a/src/skel/platform.h +++ b/src/skel/platform.h @@ -15,7 +15,7 @@ extern RwUInt32 psTimer(void); extern double psTimer(void); #endif -extern RwBool psInitialise(void); +extern RwBool psInitialize(void); extern void psTerminate(void); extern void psCameraShowRaster(RwCamera *camera); diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index 5191eda7..8191107e 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -246,8 +246,8 @@ RsEventHandler(RsEvent event, void *param) result = (rsEVENTPROCESSED); break; - case rsRWINITIALISE: - result = (RsRwInitialise(param) ? + case rsRWINITIALIZE: + result = (RsRwInitialize(param) ? rsEVENTPROCESSED : rsEVENTERROR); break; @@ -256,9 +256,9 @@ RsEventHandler(RsEvent event, void *param) result = (rsEVENTPROCESSED); break; - case rsINITIALISE: + case rsINITIALIZE: result = - (RsInitialise()? rsEVENTPROCESSED : rsEVENTERROR); + (RsInitialize()? rsEVENTPROCESSED : rsEVENTERROR); break; default: @@ -294,7 +294,7 @@ RsRwTerminate(void) ***************************************************************************** */ RwBool -RsRwInitialise(void *displayID) +RsRwInitialize(void *displayID) { RwEngineOpenParams openParams; @@ -383,7 +383,7 @@ RsTerminate(void) ***************************************************************************** */ RwBool -RsInitialise(void) +RsInitialize(void) { /* * Initialize Platform independent data... @@ -415,7 +415,7 @@ RsInitialise(void) RsGlobal.pad.inputEventHandler = nil; RsGlobal.pad.used = FALSE; - result = psInitialise(); + result = psInitialize(); return result; } diff --git a/src/skel/skeleton.h b/src/skel/skeleton.h index 8303bd9a..b5ea5abf 100644 --- a/src/skel/skeleton.h +++ b/src/skel/skeleton.h @@ -61,10 +61,10 @@ enum RsEvent _rs_18, _rs_19, _rs_20, - rsRWINITIALISE, + rsRWINITIALIZE, rsRWTERMINATE, rsSELECTDEVICE, - rsINITIALISE, + rsINITIALIZE, rsTERMINATE, rsIDLE, rsFRONTENDIDLE, @@ -241,19 +241,19 @@ extern RsEventStatus RsEventHandler(RsEvent event, void *param); extern RsEventStatus RsKeyboardEventHandler(RsEvent event, void *param); extern RsEventStatus RsPadEventHandler(RsEvent event, void *param); -extern RwBool -RsInitialise(void); +extern RwBool +RsInitialize(void); -extern RwBool +extern RwBool RsRegisterImageLoader(void); -extern RwBool -RsRwInitialise(void *param); +extern RwBool +RsRwInitialize(void *param); -extern RwBool +extern RwBool RsSelectDevice(void); -extern RwBool +extern RwBool RsInputDeviceAttach(RsInputDeviceType inputDevice, RsInputEventHandler inputEventHandler); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 9a885818..83860f04 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -584,7 +584,7 @@ void _psPrintCpuInfo() ***************************************************************************** */ RwBool -psInitialise(void) +psInitialize(void) { PsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f; @@ -1525,7 +1525,7 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode) useDefault = TRUE; - if ( RsEventHandler(rsRWINITIALISE, PSGLOBAL(window)) == rsEVENTERROR ) + if ( RsEventHandler(rsRWINITIALIZE, PSGLOBAL(window)) == rsEVENTERROR ) return FALSE; RwInitialised = TRUE; @@ -1896,7 +1896,7 @@ WinMain(HINSTANCE instance, * Initialize the platform independent data. * This will in turn initialize the platform specific data... */ - if( RsEventHandler(rsINITIALISE, nil) == rsEVENTERROR ) + if( RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR ) { return FALSE; } @@ -1962,7 +1962,7 @@ WinMain(HINSTANCE instance, /* * Initialize the 3D (RenderWare) components of the app... */ - if( rsEVENTERROR == RsEventHandler(rsRWINITIALISE, PSGLOBAL(window)) ) + if( rsEVENTERROR == RsEventHandler(rsRWINITIALIZE, PSGLOBAL(window)) ) { DestroyWindow(PSGLOBAL(window)); diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index f7205c7d..06bdf714 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -109,9 +109,6 @@ enum eFlightModel FLIGHT_MODEL_SEAPLANE }; -// Or Weapon.h? -void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage); - class CVehicle : public CPhysical { public: From 9313bfa15531cb0254e7b8276e4d26a943bbfeec Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 23 May 2020 11:34:22 +0200 Subject: [PATCH 108/148] skeleton typos --- src/core/main.cpp | 8 ++++---- src/skel/glfw/glfw.cpp | 8 ++++---- src/skel/platform.h | 2 +- src/skel/skeleton.cpp | 16 ++++++++-------- src/skel/skeleton.h | 8 ++++---- src/skel/win/win.cpp | 8 ++++---- src/vehicles/Vehicle.h | 4 ---- 7 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index f06733f2..28ce73b8 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -328,7 +328,7 @@ PluginAttach(void) static RwBool Initialise3D(void *param) { - if (RsRwInitialise(param)) + if (RsRwInitialize(param)) { #ifdef DEBUGMENU DebugMenuInit(); @@ -1149,10 +1149,10 @@ AppEventHandler(RsEvent event, void *param) { switch( event ) { - case rsINITIALISE: + case rsINITIALIZE: { CGame::InitialiseOnceBeforeRW(); - return RsInitialise() ? rsEVENTPROCESSED : rsEVENTERROR; + return RsInitialize() ? rsEVENTPROCESSED : rsEVENTERROR; } case rsCAMERASIZE: @@ -1164,7 +1164,7 @@ AppEventHandler(RsEvent event, void *param) return rsEVENTPROCESSED; } - case rsRWINITIALISE: + case rsRWINITIALIZE: { return Initialise3D(param) ? rsEVENTPROCESSED : rsEVENTERROR; } diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 2c46374d..407418c7 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -274,7 +274,7 @@ psNativeTextureSupport(void) ***************************************************************************** */ RwBool -psInitialise(void) +psInitialize(void) { PsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f; @@ -789,7 +789,7 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode) useDefault = TRUE; - if ( RsEventHandler(rsRWINITIALISE, &openParams) == rsEVENTERROR ) + if ( RsEventHandler(rsRWINITIALIZE, &openParams) == rsEVENTERROR ) return FALSE; RwInitialised = TRUE; @@ -1312,7 +1312,7 @@ main(int argc, char *argv[]) * Initialize the platform independent data. * This will in turn initialize the platform specific data... */ - if( RsEventHandler(rsINITIALISE, nil) == rsEVENTERROR ) + if( RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR ) { return FALSE; } @@ -1355,7 +1355,7 @@ main(int argc, char *argv[]) /* * Initialize the 3D (RenderWare) components of the app... */ - if( rsEVENTERROR == RsEventHandler(rsRWINITIALISE, &openParams) ) + if( rsEVENTERROR == RsEventHandler(rsRWINITIALIZE, &openParams) ) { RsEventHandler(rsTERMINATE, nil); diff --git a/src/skel/platform.h b/src/skel/platform.h index 65e20673..cbb1be28 100644 --- a/src/skel/platform.h +++ b/src/skel/platform.h @@ -15,7 +15,7 @@ extern RwUInt32 psTimer(void); extern double psTimer(void); #endif -extern RwBool psInitialise(void); +extern RwBool psInitialize(void); extern void psTerminate(void); extern void psCameraShowRaster(RwCamera *camera); diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index 5191eda7..073155d6 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -246,8 +246,8 @@ RsEventHandler(RsEvent event, void *param) result = (rsEVENTPROCESSED); break; - case rsRWINITIALISE: - result = (RsRwInitialise(param) ? + case rsRWINITIALIZE: + result = (RsRwInitialize(param) ? rsEVENTPROCESSED : rsEVENTERROR); break; @@ -256,9 +256,9 @@ RsEventHandler(RsEvent event, void *param) result = (rsEVENTPROCESSED); break; - case rsINITIALISE: + case rsINITIALIZE: result = - (RsInitialise()? rsEVENTPROCESSED : rsEVENTERROR); + (RsInitialize()? rsEVENTPROCESSED : rsEVENTERROR); break; default: @@ -294,7 +294,7 @@ RsRwTerminate(void) ***************************************************************************** */ RwBool -RsRwInitialise(void *displayID) +RsRwInitialize(void *displayID) { RwEngineOpenParams openParams; @@ -383,14 +383,14 @@ RsTerminate(void) ***************************************************************************** */ RwBool -RsInitialise(void) +RsInitialize(void) { /* * Initialize Platform independent data... */ RwBool result; - RsGlobal.appName = RWSTRING("GTA3"); + RsGlobal.appName = RWSTRING("GTA: Vice City"); RsGlobal.maximumWidth = DEFAULT_SCREEN_WIDTH; RsGlobal.maximumHeight = DEFAULT_SCREEN_HEIGHT; RsGlobal.width = DEFAULT_SCREEN_WIDTH; @@ -415,7 +415,7 @@ RsInitialise(void) RsGlobal.pad.inputEventHandler = nil; RsGlobal.pad.used = FALSE; - result = psInitialise(); + result = psInitialize(); return result; } diff --git a/src/skel/skeleton.h b/src/skel/skeleton.h index 8303bd9a..9826f919 100644 --- a/src/skel/skeleton.h +++ b/src/skel/skeleton.h @@ -61,10 +61,10 @@ enum RsEvent _rs_18, _rs_19, _rs_20, - rsRWINITIALISE, + rsRWINITIALIZE, rsRWTERMINATE, rsSELECTDEVICE, - rsINITIALISE, + rsINITIALIZE, rsTERMINATE, rsIDLE, rsFRONTENDIDLE, @@ -242,13 +242,13 @@ extern RsEventStatus RsKeyboardEventHandler(RsEvent event, void *param); extern RsEventStatus RsPadEventHandler(RsEvent event, void *param); extern RwBool -RsInitialise(void); +RsInitialize(void); extern RwBool RsRegisterImageLoader(void); extern RwBool -RsRwInitialise(void *param); +RsRwInitialize(void *param); extern RwBool RsSelectDevice(void); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 415f665a..7de58d87 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -584,7 +584,7 @@ void _psPrintCpuInfo() ***************************************************************************** */ RwBool -psInitialise(void) +psInitialize(void) { PsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f; @@ -1535,7 +1535,7 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode) useDefault = TRUE; - if ( RsEventHandler(rsRWINITIALISE, PSGLOBAL(window)) == rsEVENTERROR ) + if ( RsEventHandler(rsRWINITIALIZE, PSGLOBAL(window)) == rsEVENTERROR ) return FALSE; RwInitialised = TRUE; @@ -1904,7 +1904,7 @@ WinMain(HINSTANCE instance, * Initialize the platform independent data. * This will in turn initialize the platform specific data... */ - if( RsEventHandler(rsINITIALISE, nil) == rsEVENTERROR ) + if( RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR ) { return FALSE; } @@ -1970,7 +1970,7 @@ WinMain(HINSTANCE instance, /* * Initialize the 3D (RenderWare) components of the app... */ - if( rsEVENTERROR == RsEventHandler(rsRWINITIALISE, PSGLOBAL(window)) ) + if( rsEVENTERROR == RsEventHandler(rsRWINITIALIZE, PSGLOBAL(window)) ) { DestroyWindow(PSGLOBAL(window)); diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 8673de8f..9ec48850 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -120,13 +120,9 @@ enum eVehicleAppearance VEHICLE_APPEARANCE_PLANE, }; -// Or Weapon.h? -void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage); - class CVehicle : public CPhysical { public: - // 0x128 tHandlingData *pHandling; CAutoPilot AutoPilot; uint8 m_currentColour1; From 100e59886d18db04efe5455cc35c056b69c5d1d3 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 16:14:39 +0300 Subject: [PATCH 109/148] cranes fix --- src/vehicles/Cranes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 9c8f9fda..936a4510 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -184,7 +184,7 @@ bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle) result = true; } } - return true; + return result; } void CCranes::UpdateCranes(void) From 5357957fe124afb8e9a5f737510fe4c96a7dc327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 23 May 2020 16:53:20 +0300 Subject: [PATCH 110/148] Compatibility with VC weapon.dat + new shotguns --- src/audio/AudioLogic.cpp | 8 +- src/control/Pickups.cpp | 51 ++----- src/control/Script.cpp | 61 +++++++-- src/control/Script.h | 2 +- src/core/Cam.cpp | 8 +- src/core/Frontend.cpp | 11 +- src/core/Frontend.h | 2 +- src/core/Pad.cpp | 20 +-- src/modelinfo/ModelIndices.h | 42 +++--- src/peds/CopPed.cpp | 2 +- src/peds/EmergencyPed.cpp | 16 +-- src/peds/Ped.cpp | 58 ++++---- src/peds/PedIK.cpp | 23 ++-- src/peds/PedIK.h | 2 +- src/peds/PlayerPed.cpp | 14 +- src/render/Hud.cpp | 37 +++-- src/vehicles/Vehicle.cpp | 6 +- src/weapons/Weapon.cpp | 258 ++++++++++++++++++++++++++++------- src/weapons/Weapon.h | 2 + src/weapons/WeaponInfo.cpp | 18 ++- src/weapons/WeaponType.h | 25 ++-- 21 files changed, 433 insertions(+), 233 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index cc157389..03cf391c 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -3478,7 +3478,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) else noReflection = true; break; - case WEAPONTYPE_AK47: + case WEAPONTYPE_RUGER: m_sQueueSample.m_nSampleIndex = SFX_AK47_LEFT; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nCounter = iSound++; @@ -3497,7 +3497,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_bReleasingSoundFlag = true; break; - case WEAPONTYPE_M16: + case WEAPONTYPE_M4: m_sQueueSample.m_nSampleIndex = SFX_M16_LEFT; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nCounter = iSound++; @@ -3604,11 +3604,11 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD; m_sQueueSample.m_nFrequency = 30290; break; - case WEAPONTYPE_AK47: + case WEAPONTYPE_RUGER: m_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AK47_RELOAD); break; - case WEAPONTYPE_M16: + case WEAPONTYPE_M4: m_sQueueSample.m_nSampleIndex = SFX_M16_RELOAD; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M16_RELOAD); break; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 4e4c02ab..1d2d06f7 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -46,55 +46,32 @@ tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES]; // TODO(Miami) uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 }; + +// --MIAMI: Done uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS] = { - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 4, - 4, - 4, - 4, - 34, - 16, - 100, - 60, - 60, - 60, - 60, - 60, - 20, - 4, - 14, - 1, - 400, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 34, + 12, 16, 14, 10, 100, 60, 60, 60, 60, 60, 20, 14, + 4, 150, 100, 500, 1, 400, 36, 0, }; uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 }; // TODO(Miami): Those are all placeholders!! uint8 aWeaponReds[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, -255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 255, 0 }; uint8 aWeaponGreens[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 255, 0 }; uint8 aWeaponBlues[] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, -255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 128, 255, 0, 0 }; + float aWeaponScale[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, +1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; void @@ -722,13 +699,13 @@ CPickups::DoPickUpEffects(CEntity *entity) int16 colorId; if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) - colorId = WEAPONTYPE_LAST_WEAPONTYPE; + colorId = WEAPONTYPE_TOTALWEAPONS; else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE) - colorId = WEAPONTYPE_LAST_WEAPONTYPE + 1; + colorId = WEAPONTYPE_TOTALWEAPONS + 1; else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) - colorId = WEAPONTYPE_LAST_WEAPONTYPE + 2; + colorId = WEAPONTYPE_TOTALWEAPONS + 2; else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) - colorId = WEAPONTYPE_LAST_WEAPONTYPE + 3; + colorId = WEAPONTYPE_TOTALWEAPONS + 3; else colorId = WeaponForModel(entity->GetModelIndex()); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 85098cca..4350d08b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -6545,7 +6545,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n"); else { if (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON) - result = CheckDamagedWeaponType(ScriptParams[1], pPed->m_lastWepDam); + result = CheckDamagedWeaponType(pPed->m_lastWepDam, ScriptParams[1]); else result = ScriptParams[1] == pPed->m_lastWepDam; } @@ -6561,7 +6561,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n"); else { if (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON) - result = CheckDamagedWeaponType(ScriptParams[1], pVehicle->m_nLastWeaponDamage); + result = CheckDamagedWeaponType(pVehicle->m_nLastWeaponDamage, ScriptParams[1]); else result = ScriptParams[1] == pVehicle->m_nLastWeaponDamage; } @@ -11989,12 +11989,23 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return -1; } -bool CRunningScript::CheckDamagedWeaponType(int32 type, int32 actual) +bool CRunningScript::CheckDamagedWeaponType(int32 actual, int32 type) { if (actual == -1) return false; + if (type == WEAPONTYPE_ANYMELEE) { - switch (actual) { + if (actual <= WEAPONTYPE_CHAINSAW) + return true; + if (actual - WEAPONTYPE_GRENADE <= WEAPONTYPE_MINIGUN) + return false; + return false; + } + + if (type != WEAPONTYPE_ANYWEAPON) + return false; + + switch (actual) { case WEAPONTYPE_UNARMED: case WEAPONTYPE_BRASSKNUCKLE: case WEAPONTYPE_SCREWDRIVER: @@ -12007,16 +12018,44 @@ bool CRunningScript::CheckDamagedWeaponType(int32 type, int32 actual) case WEAPONTYPE_MACHETE: case WEAPONTYPE_KATANA: case WEAPONTYPE_CHAINSAW: + case WEAPONTYPE_GRENADE: + case WEAPONTYPE_DETONATOR_GRENADE: + case WEAPONTYPE_TEARGAS: + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_ROCKET: + case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_ROCKETLAUNCHER: + case WEAPONTYPE_FLAMETHROWER: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_DETONATOR: + case WEAPONTYPE_HELICANNON: + case WEAPONTYPE_CAMERA: + case WEAPONTYPE_EXPLOSION: + case WEAPONTYPE_UZI_DRIVEBY: return true; - default: + case WEAPONTYPE_HEALTH: + case WEAPONTYPE_ARMOUR: + case WEAPONTYPE_RAMMEDBYCAR: + case WEAPONTYPE_RUNOVERBYCAR: + case WEAPONTYPE_DROWNING: + case WEAPONTYPE_FALL: + case WEAPONTYPE_UNIDENTIFIED: return false; - } - } - if (type == WEAPONTYPE_ANYWEAPON) { - // TODO(MIAMI)! - return actual != WEAPONTYPE_UNIDENTIFIED && actual != WEAPONTYPE_RAMMEDBYCAR && - actual != WEAPONTYPE_RUNOVERBYCAR && actual != WEAPONTYPE_FALL && actual != WEAPONTYPE_DROWNING; } + return false; } diff --git a/src/control/Script.h b/src/control/Script.h index 75a2c1e0..57b997b1 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -516,7 +516,7 @@ private: } } - bool CheckDamagedWeaponType(int32 type, int32 actual); + bool CheckDamagedWeaponType(int32 actual, int32 type); static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami); }; diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 0daecad1..24d32511 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -2429,7 +2429,7 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); @@ -2568,7 +2568,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) HeadPos.x = 0.0f; HeadPos.y = 0.0f; HeadPos.z = 0.0f; - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f * Cos(m_fInitialPlayerOrientation); @@ -2657,7 +2657,7 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); @@ -2925,7 +2925,7 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index c5e0d6ad..a9229c1c 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -2241,7 +2241,7 @@ CMenuManager::DrawBackground() m_menuTransitionProgress = 255; } - m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, Min(255, m_nMenuFadeAlpha))); + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); SetFrontEndRenderStates(); @@ -2264,7 +2264,7 @@ CMenuManager::DrawBackground() if (m_menuTransitionProgress == 255) { m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); } else { - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, Min(m_nMenuFadeAlpha, 255))); + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); } if (m_bShowMouse) { @@ -2693,11 +2693,6 @@ CMenuManager::DrawPlayerSetupScreen() int CMenuManager::FadeIn(int alpha) { - if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS || - m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS || - m_nCurrScreen == MENUPAGE_DELETING) - return alpha; - return Min(m_nMenuFadeAlpha, alpha); } @@ -3242,7 +3237,7 @@ CMenuManager::Process(void) ProcessFileActions(); DMAudio.Service(); - // TODO(Miami): What are the functions in here? + // Game calls some texture pool cleanup functions in here } SwitchMenuOnAndOff(); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 4e1d0edf..ca77d448 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -538,7 +538,7 @@ public: int32 m_nPrevScreen; int32 m_nCurrSaveSlot; int32 m_LastScreenSwitch; - uint32 m_nMenuFadeAlpha; + int32 m_nMenuFadeAlpha; int32 bOptionHighlightTransitionBlend; bool bMenuChangeOngoing; int32 MouseButtonJustClicked; diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index dc849a46..69f340dd 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -68,32 +68,32 @@ void WeaponCheat() CStreaming::RequestModel(MI_GRENADE, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestModel(MI_AK47, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_RUGER, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(MI_BASEBALL_BAT, STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestModel(MI_COLT, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_COLT45, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(MI_ROCKETLAUNCHER, STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestModel(MI_SNIPER, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_SPAS12_SHOTGUN, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_SNIPERRIFLE, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(MI_MP5, STREAMFLAGS_DONT_REMOVE); CStreaming::LoadAllRequestedModels(false); FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0); FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100); FindPlayerPed()->GiveWeapon(WEAPONTYPE_MP5, 100); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_SPAS12_SHOTGUN, 20); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_RUGER, 200); FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5); FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5); FindPlayerPed()->GiveWeapon(WEAPONTYPE_DETONATOR_GRENADE, 5); CStreaming::SetModelIsDeletable(MI_GRENADE); CStreaming::SetModelIsDeletable(MI_BOMB); - CStreaming::SetModelIsDeletable(MI_AK47); + CStreaming::SetModelIsDeletable(MI_RUGER); CStreaming::SetModelIsDeletable(MI_BASEBALL_BAT); - CStreaming::SetModelIsDeletable(MI_COLT); + CStreaming::SetModelIsDeletable(MI_COLT45); CStreaming::SetModelIsDeletable(MI_ROCKETLAUNCHER); - CStreaming::SetModelIsDeletable(MI_SHOTGUN); - CStreaming::SetModelIsDeletable(MI_SNIPER); + CStreaming::SetModelIsDeletable(MI_SPAS12_SHOTGUN); + CStreaming::SetModelIsDeletable(MI_SNIPERRIFLE); CStreaming::SetModelIsDeletable(MI_MP5); } diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index dd37b57d..91ba650e 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -303,23 +303,33 @@ enum MI_DODO = -2, MI_NIGHTSTICK = 262, - MI_BASEBALL_BAT = 264, + MI_KNIFE, + MI_BASEBALL_BAT, MI_GRENADE = 270, - MI_MOLOTOV = 272, - MI_MISSILE = 273, - MI_COLT = 274, - MI_AK47 = 276, - MI_SHOTGUN = 279, - MI_M16 = 280, - MI_TEC9 = 281, - MI_UZI = 282, - MI_SILENCEDINGRAM = 283, - MI_MP5 = 284, - MI_SNIPER = 285, - MI_ROCKETLAUNCHER = 287, - MI_FLAMETHROWER = 288, - MI_BOMB = 291, - MI_FINGERS = 293, + MI_TEARGAS, + MI_MOLOTOV, + MI_MISSILE, + MI_COLT45, + MI_PYTHON, + MI_RUGER, + MI_SHOTGUN, + MI_SPAS12_SHOTGUN, + MI_STUBBY_SHOTGUN, + MI_M4, + MI_TEC9, + MI_UZI, + MI_SILENCEDINGRAM, + MI_MP5, + MI_SNIPERRIFLE, + MI_LASERSCOPE, + MI_ROCKETLAUNCHER, + MI_FLAMETHROWER, + MI_M60, + MI_MINIGUN, + MI_BOMB, + MI_CAMERA, + MI_FINGERS, + MI_MINIGUN2, MI_CUTOBJ01 = 295, MI_CUTOBJ02, diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index b84dcf14..c24be62f 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -257,7 +257,7 @@ CCopPed::ArrestPlayer(void) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ARREST_GUN, 4.0f); CVector suspMidPos; - suspect->m_pedIK.GetComponentPosition((RwV3d*)suspMidPos, PED_MID); + suspect->m_pedIK.GetComponentPosition((RwV3d)suspMidPos, PED_MID); m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(suspMidPos.x, suspMidPos.y, GetPosition().x, GetPosition().y); diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index a62ac76d..95811dab 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -231,8 +231,8 @@ CEmergencyPed::MedicAI(void) if (nearestAccident) { m_pRevivedPed = nearestAccident->m_pVictim; m_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); SetSeek((headPos + midPos) * 0.5f, 1.0f); SetObjective(OBJECTIVE_NONE); bIsRunning = true; @@ -271,8 +271,8 @@ CEmergencyPed::MedicAI(void) m_nEmergencyPedState = EMERGENCY_PED_STOP; break; } - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); SetSeek((headPos + midPos) * 0.5f, nearestAccident->m_nMedicsPerformingCPR * 0.5f + 1.0f); SetObjective(OBJECTIVE_NONE); bIsRunning = true; @@ -326,8 +326,8 @@ CEmergencyPed::MedicAI(void) if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f) m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; else { - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); midPos = (headPos + midPos) * 0.5f; m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( midPos.x, midPos.y, @@ -348,8 +348,8 @@ CEmergencyPed::MedicAI(void) m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; break; } - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); midPos = (headPos + midPos) * 0.5f; m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( midPos.x, midPos.y, diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 278e5bef..7ab60faa 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -685,7 +685,7 @@ CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo, bool unused) if (m_weapons[slot].m_eWeaponType == weaponType) { GetWeapon(slot).m_nAmmoTotal += ammo; - if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { + if (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1. GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal); @@ -884,9 +884,8 @@ CPed::AddWeaponModel(int id) CModelInfo::GetModelInfo(id)->AddRef(); m_wepModelID = id; - // TODO(Miami) - // if (IsPlayer() && id == MI_MINIGUN) - // ((CPlayerPed*)this)->m_pMinigunTopAtomic = (RpAtomic*)CModelInfo::GetModelInfo(MI_MINIGUN2)->CreateInstance(); + if (IsPlayer() && id == MI_MINIGUN) + ((CPlayerPed*)this)->m_pMinigunTopAtomic = (RpAtomic*)CModelInfo::GetModelInfo(MI_MINIGUN2)->CreateInstance(); } } @@ -898,7 +897,7 @@ CPed::AimGun(void) if (m_pSeekTarget) { if (m_pSeekTarget->IsPed()) { - ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_MID); + ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(pos, PED_MID); vector = pos; } else { vector = m_pSeekTarget->GetPosition(); @@ -1507,9 +1506,8 @@ CPed::Attack(void) GetWeapon()->Fire(this, &firePos); - // TODO(Miami): Teargas - if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE - /* ourWeaponType == WEAPONTYPE_TEARGAS*/) { + if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE || ourWeaponType == WEAPONTYPE_DETONATOR_GRENADE || + ourWeaponType == WEAPONTYPE_TEARGAS) { RemoveWeaponModel(ourWeapon->m_nModelId); } if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) { @@ -1649,10 +1647,10 @@ CPed::Attack(void) case WEAPONTYPE_MP5: DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); break; - case WEAPONTYPE_AK47: + case WEAPONTYPE_RUGER: DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); break; - case WEAPONTYPE_M16: + case WEAPONTYPE_M4: DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); break; default: @@ -1667,7 +1665,7 @@ CPed::Attack(void) if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) && (GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING - /* || GetWeapon()->m_nWeaponType == WEAPONTYPE_MINIGUN */)) { // TODO(Miami): Minigun + || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)) { PedOnGroundState pedOnGroundState; if (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE && @@ -1715,10 +1713,10 @@ CPed::Attack(void) case WEAPONTYPE_MP5: DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f); break; - case WEAPONTYPE_AK47: + case WEAPONTYPE_RUGER: DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f); break; - case WEAPONTYPE_M16: + case WEAPONTYPE_M4: DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f); break; default: @@ -1764,8 +1762,7 @@ CPed::RemoveWeaponModel(int modelId) #endif RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil); - // TODO(Miami): Minigun - if (IsPlayer() && (modelId == -1 /* || modelId == MI_MINIGUN)*/)) { + if (IsPlayer() && (modelId == -1 || modelId == MI_MINIGUN)) { RpAtomic* &atm = ((CPlayerPed*)this)->m_pMinigunTopAtomic; if (atm) { RwFrame *frm = RpAtomicGetFrame(atm); @@ -1818,7 +1815,7 @@ CPed::SelectGunIfArmed(void) // First condition checks for Pistol, Python and Shotguns if ((weaponType >= WEAPONTYPE_COLT45 && weaponType < WEAPONTYPE_TEC9) || - weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M16 || weaponType == WEAPONTYPE_MP5 || + weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_M4 || weaponType == WEAPONTYPE_MP5 || weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_FLAMETHROWER || weaponType == WEAPONTYPE_SNIPERRIFLE) { SetCurrentWeapon(i); return true; @@ -4278,16 +4275,19 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi break; case WEAPONTYPE_COLT45: case WEAPONTYPE_SHOTGUN: - // TODO(Miami): Shotguns + case WEAPONTYPE_STUBBY_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: case WEAPONTYPE_TEC9: case WEAPONTYPE_UZI: case WEAPONTYPE_SILENCED_INGRAM: case WEAPONTYPE_MP5: - case WEAPONTYPE_M16: - case WEAPONTYPE_AK47: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: case WEAPONTYPE_UZI_DRIVEBY: - // TODO(Miami): Laserscope, M60, Minigun if (bBulletProof) return false; @@ -4295,8 +4295,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi bool dontRemoveLimb; if (IsPlayer() || bNoCriticalHits) dontRemoveLimb = true; - else if (method != WEAPONTYPE_M16 && method != WEAPONTYPE_AK47 && method != WEAPONTYPE_SNIPERRIFLE - /* method != WEAPONTYPE_LASERSCOPE */) { // TODO(Miami): Laserscope + else if (method != WEAPONTYPE_M4 && method != WEAPONTYPE_RUGER && method != WEAPONTYPE_SNIPERRIFLE && + method != WEAPONTYPE_LASERSCOPE) { if (method == WEAPONTYPE_SHOTGUN) dontRemoveLimb = CGeneral::GetRandomNumber() & 7; else @@ -5012,7 +5012,7 @@ CPed::SetAmmo(eWeaponType weaponType, uint32 ammo) return; GetWeapon(slot).m_nAmmoTotal = ammo; - if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { + if (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1. GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal); @@ -5037,7 +5037,7 @@ CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo) return; GetWeapon(slot).m_nAmmoTotal += ammo; - if (weaponType < WEAPONTYPE_LAST_WEAPONTYPE && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { + if (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) { // Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1. GetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal); @@ -6711,11 +6711,7 @@ CPed::SetSeek(CVector pos, float distanceToCountDone) || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y)) return; - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 - || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47 - || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE - || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER - || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) { + if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm) { ClearPointGunAt(); } @@ -9734,7 +9730,7 @@ CPed::MoveHeadToLook(void) } if (m_pLookTarget->IsPed()) { - ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID); + ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d)lookPos, PED_MID); } else { lookPos = m_pLookTarget->GetPosition(); } @@ -13696,7 +13692,7 @@ CPed::ProcessObjective(void) CVector target; CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); if (m_pedInObjective->IsPed()) - m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID); + m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d)target, PED_MID); else target = m_pedInObjective->GetPosition(); diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index 6543e9a3..2925667a 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -7,7 +7,7 @@ #include "General.h" #include "RwHelper.h" -//--MIAMI: file almost done (only some special weapon cases left) +//--MIAMI: file done LimbMovementInfo CPedIK::ms_torsoInfo = { DEGTORAD(50.0f), DEGTORAD(-50.0f), DEGTORAD(8.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(5.0f) }; LimbMovementInfo CPedIK::ms_headInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(15.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(8.0f) }; @@ -57,9 +57,9 @@ CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool change } void -CPedIK::GetComponentPosition(RwV3d *pos, uint32 node) +CPedIK::GetComponentPosition(RwV3d &pos, uint32 node) { - *pos = GetComponentMatrix(m_ped, node)->pos; + pos = GetComponentMatrix(m_ped, node)->pos; } LimbMoveStatus @@ -292,13 +292,20 @@ CPedIK::PointGunInDirectionUsingArm(float targetYaw, float targetPitch) bool CPedIK::PointGunAtPosition(CVector const& position) { - // TODO(MIAMI): special cases for some weapons + CVector startPoint; + if (m_ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_SPAS12_SHOTGUN || m_ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_STUBBY_SHOTGUN) + startPoint = m_ped->GetPosition(); + else { + RwV3d armPos; + GetComponentPosition(armPos, PED_UPPERARMR); + startPoint.x = m_ped->GetPosition().x; + startPoint.y = m_ped->GetPosition().y; + startPoint.z = armPos.z; + } - RwV3d armPos; - GetComponentPosition(&armPos, PED_UPPERARMR); return PointGunInDirection( - CGeneral::GetRadianAngleBetweenPoints(position.x, position.y, m_ped->GetPosition().x, m_ped->GetPosition().y), - CGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y), armPos.z, 0.0f)); + CGeneral::GetRadianAngleBetweenPoints(position.x, position.y, startPoint.x, startPoint.y), + CGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y), startPoint.z, 0.0f)); } bool diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index b5f895cd..ee719fea 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -51,7 +51,7 @@ public: bool PointGunInDirection(float targetYaw, float targetPitch); bool PointGunInDirectionUsingArm(float targetYaw, float targetPitch); bool PointGunAtPosition(CVector const& position); - void GetComponentPosition(RwV3d *pos, uint32 node); + void GetComponentPosition(RwV3d &pos, uint32 node); void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll); void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch); void ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index f6f1cf05..69369ea4 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -546,6 +546,8 @@ CPlayerPed::RestoreSprintEnergy(float restoreSpeed) m_fCurrentStamina += restoreSpeed * CTimer::GetTimeStep() * 0.5f; } + +// TODO(Miami) bool CPlayerPed::DoWeaponSmoothSpray(void) { @@ -553,7 +555,7 @@ CPlayerPed::DoWeaponSmoothSpray(void) eWeaponType weapon = GetWeapon()->m_eWeaponType; if (weapon == WEAPONTYPE_FLAMETHROWER || weapon == WEAPONTYPE_COLT45 || weapon == WEAPONTYPE_UZI || weapon == WEAPONTYPE_TEC9 || weapon == WEAPONTYPE_SILENCED_INGRAM || weapon == WEAPONTYPE_MP5 || - weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_AK47 || weapon == WEAPONTYPE_M16 || weapon == WEAPONTYPE_HELICANNON) + weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_RUGER || weapon == WEAPONTYPE_M4 || weapon == WEAPONTYPE_HELICANNON) return true; } return false; @@ -574,7 +576,7 @@ CPlayerPed::DoesTargetHaveToBeBroken(CVector target, CWeapon *weaponUsed) if (distVec.Magnitude() > CWeaponInfo::GetWeaponInfo(weaponUsed->m_eWeaponType)->m_fRange) return true; - if (weaponUsed->m_eWeaponType != WEAPONTYPE_SHOTGUN && weaponUsed->m_eWeaponType != WEAPONTYPE_AK47) + if (weaponUsed->m_eWeaponType != WEAPONTYPE_SHOTGUN && weaponUsed->m_eWeaponType != WEAPONTYPE_RUGER) return false; distVec.Normalise(); @@ -1099,8 +1101,8 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) } if (!m_pFire) { if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || - GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 || - GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47) { + GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M4 || + GetWeapon()->m_eWeaponType == WEAPONTYPE_RUGER) { if (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) { SetStoredState(); m_nPedState = PED_SNIPER_MODE; @@ -1261,7 +1263,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) #else CVector markPos; if (m_pPointGunAt->IsPed()) { - ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d*)markPos, PED_MID); + ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d)markPos, PED_MID); } else { markPos = m_pPointGunAt->GetPosition(); } @@ -1514,7 +1516,7 @@ CPlayerPed::ProcessControl(void) } break; case PED_SNIPER_MODE: - if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_M4) { if (padUsed) PlayerControlM16(padUsed); } else if (padUsed) { diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 00d5b5c7..5d1542ef 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -172,9 +172,8 @@ void CHud::Draw() if (playerPed) { if (playerPed->m_nPedState != PED_ENTER_CAR && playerPed->m_nPedState != PED_CARJACK) { - // TODO(Miami): Uncomment - if (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_AK47 - /*|| WeaponType == WEAPONTYPE_M60 || || WeaponType == WEAPONTYPE_MINIGUN */ + if (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_RUGER + || WeaponType == WEAPONTYPE_M60 || WeaponType == WEAPONTYPE_MINIGUN || WeaponType == WEAPONTYPE_FLAMETHROWER) { DrawCrossHairPC = 1; } @@ -198,8 +197,7 @@ void CHud::Draw() #ifdef ASPECT_RATIO_SCALE f3rdY -= SCREEN_SCALE_Y(2.0f); #endif - // TODO(Miami): M60 - if (playerPed && (WeaponType == WEAPONTYPE_M16 || WeaponType == WEAPONTYPE_AK47/* || WeaponType == WEAPONTYPE_M60*/)) { + if (playerPed && (WeaponType == WEAPONTYPE_M4 || WeaponType == WEAPONTYPE_RUGER || WeaponType == WEAPONTYPE_M60)) { rect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.6f); rect.top = f3rdY - SCREEN_SCALE_Y(32.0f * 0.6f); rect.right = f3rdX + SCREEN_SCALE_X(32.0f * 0.6f); @@ -314,9 +312,7 @@ void CHud::Draw() MONEY_COLOR.a = alpha; CFont::SetColor(MONEY_COLOR); - // TODO(Miami): m_nHudMode - //if (CMenuManager.m_nHudMode) - { + if (FrontEndMenuManager.m_PrefsShowHud) { CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint); } } @@ -505,20 +501,21 @@ void CHud::Draw() AsciiToUnicode("]", sPrintIcon); for (int i = 0; i < 6; i++) { - if (playerPed->m_pWanted->m_nWantedLevel > i - && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange - + 2000 || CTimer::GetFrameCounter() & 4)) { + if (FrontEndMenuManager.m_PrefsShowHud) { + if (playerPed->m_pWanted->m_nWantedLevel > i + && (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange + + 2000 || CTimer::GetFrameCounter() & 4)) { - WANTED_COLOR.a = alpha; - CFont::SetColor(WANTED_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + WANTED_COLOR.a = alpha; + CFont::SetColor(WANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); - // TODO(Miami): There is one more condition in here - } - else if (playerPed->m_pWanted->m_nWantedLevel <= i) { - NOTWANTED_COLOR.a = alpha; - CFont::SetColor(NOTWANTED_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + // TODO(Miami): There is one more condition in here + } else if (playerPed->m_pWanted->m_nWantedLevel <= i) { + NOTWANTED_COLOR.a = alpha; + CFont::SetColor(NOTWANTED_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon); + } } } diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 8d763300..5ac69905 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -623,8 +623,10 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage case WEAPONTYPE_SILENCED_INGRAM: case WEAPONTYPE_MP5: case WEAPONTYPE_SHOTGUN: - case WEAPONTYPE_AK47: - case WEAPONTYPE_M16: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_M4: case WEAPONTYPE_SNIPERRIFLE: case WEAPONTYPE_HELICANNON: case WEAPONTYPE_UZI_DRIVEBY: diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 4c1f1c52..17cee83a 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -29,11 +29,13 @@ #include "WaterLevel.h" #include "WeaponInfo.h" #include "World.h" +#include "SurfaceTable.h" // TODO(Miami) #define AUDIO_NOT_READY -uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = +// TODO(Miami): Those are mostly placeholders!!! +uint16 gReloadSampleTime[] = { 0, // UNARMED 0, @@ -49,10 +51,14 @@ uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = 0, 0, // GRENADE 0, // DETONATEGRENADE + 0, // TEARGAS 0, // MOLOTOV 0, // ROCKET 250, // COLT45 + 250, // PYTHON 650, // SHOTGUN + 650, // SPAS12 SHOTGUN + 650, // STUBBY SHOTGUN 400, // TEC9 400, // UZIhec 400, // SILENCED_INGRAM @@ -60,10 +66,14 @@ uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = 300, // M16 300, // AK47 423, // SNIPERRIFLE + 423, // LASERSCOPE 400, // ROCKETLAUNCHER 0, // FLAMETHROWER + 0, // M60 + 0, // MINIGUN 0, // DETONATOR - 0 // HELICANNON + 0, // HELICANNON + 0 // CAMERA }; CWeaponInfo * @@ -176,6 +186,8 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) switch ( m_eWeaponType ) { case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: { addFireRateAsDelay = true; fired = FireShotgun(shooter, source); @@ -184,12 +196,15 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: case WEAPONTYPE_UZI: case WEAPONTYPE_TEC9: case WEAPONTYPE_SILENCED_INGRAM: case WEAPONTYPE_MP5: - case WEAPONTYPE_AK47: - case WEAPONTYPE_M16: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: case WEAPONTYPE_HELICANNON: { if ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON) @@ -204,6 +219,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: { fired = FireSniper(shooter); @@ -230,6 +246,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) case WEAPONTYPE_MOLOTOV: case WEAPONTYPE_GRENADE: case WEAPONTYPE_DETONATOR_GRENADE: + case WEAPONTYPE_TEARGAS: { if ( shooter == FindPlayerPed() ) { @@ -800,7 +817,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; if ( threatAttack->IsPed() ) { - threatAttack->m_pedIK.GetComponentPosition(target, PED_MID); + threatAttack->m_pedIK.GetComponentPosition((RwV3d)target, PED_MID); threatAttack->ReactToPointGun(shooter); } else @@ -842,7 +859,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) CWorld::bIncludeDeadPeds = false; int32 rotSpeed = 1; - if ( m_eWeaponType == WEAPONTYPE_M16 ) + if ( m_eWeaponType == WEAPONTYPE_M4 ) rotSpeed = 4; CVector bulletPos; @@ -870,7 +887,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); int32 rotSpeed = 1; - if ( m_eWeaponType == WEAPONTYPE_M16 ) + if ( m_eWeaponType == WEAPONTYPE_M4 ) rotSpeed = 4; CVector bulletPos; @@ -895,10 +912,10 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) switch ( m_eWeaponType ) { - case WEAPONTYPE_M16: - case WEAPONTYPE_AK47: - // case WEAPONTYPE_M60: - // case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: case WEAPONTYPE_HELICANNON: { static uint8 counter = 0; @@ -1011,6 +1028,9 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, @@ -1124,7 +1144,8 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } else { - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + if ( IsShotgun(m_eWeaponType) || m_eWeaponType == WEAPONTYPE_HELICANNON + || m_eWeaponType == WEAPONTYPE_M60 || m_eWeaponType == WEAPONTYPE_PYTHON) { posOffset.Normalise(); victimPed->bIsStanding = false; @@ -1149,7 +1170,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - if ( m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_M16 ) + if ( m_eWeaponType == WEAPONTYPE_M4 ) victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; else victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 1000; @@ -1178,7 +1199,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( CGame::nastyGame ) { uint8 bloodAmount = 8; - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + if ( IsShotgun(m_eWeaponType) || m_eWeaponType == WEAPONTYPE_HELICANNON ) bloodAmount = 32; CVector dir = (point->point - victim->GetPosition()) * 0.01f; @@ -1394,10 +1415,35 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) else shooterAngle = RADTODEG(shooter->GetForward().Heading()); + int shootsAtOnce; + int checkObstacleOnShootNo; + float angleRange; + switch (m_eWeaponType) { + case WEAPONTYPE_SHOTGUN: + angleRange = DEGTORAD(9.0f); + checkObstacleOnShootNo = 1; + shootsAtOnce = 3; + break; + case WEAPONTYPE_SPAS12_SHOTGUN: + angleRange = DEGTORAD(6.0f); + checkObstacleOnShootNo = 1; + shootsAtOnce = 3; + break; + case WEAPONTYPE_STUBBY_SHOTGUN: + angleRange = DEGTORAD(18.0f); + checkObstacleOnShootNo = 2; + shootsAtOnce = 5; + break; + default: + break; + } + bool statUpdated = false; + float halfAngleRange = angleRange / 2.f; + float angleBetweenTwoShot = angleRange / (shootsAtOnce - 1.f); - for ( int32 i = 0; i < 5; i++ ) // five shoots at once + for ( int32 i = 0; i < shootsAtOnce; i++ ) { - float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); + float shootAngle = DEGTORAD(RADTODEG(halfAngleRange - angleBetweenTwoShot * i) + shooterAngle); CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); CVector source, target; @@ -1409,12 +1455,17 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) TheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target); CVector Left = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Front, TheCamera.Cams[TheCamera.ActiveCam].Up); - float f = float(i - 2) * (DEGTORAD(7.5f) / 2); + float f = (i - (shootsAtOnce / 2)) * angleBetweenTwoShot; target = f * Left + target - source; target *= info->m_fRange; target += source; + CWorld::bIncludeDeadPeds = true; + //bProcessVehicleWheels = true; // TODO(Miami): bProcessVehicleWheels + //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes - ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); // TODO(Miami): New parameter: ,true); + CWorld::bIncludeDeadPeds = false; + //bProcessVehicleWheels = false; // TODO(Miami): bProcessVehicleWheels } else { @@ -1430,24 +1481,84 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) DoDoomAiming(shooter, fireSource, &target); else { - float distToTarget = (shooterPed->m_pPointGunAt->GetPosition() - (*fireSource)).Magnitude2D(); - target.z += info->m_fRange / distToTarget * (shooterPed->m_pPointGunAt->GetPosition().z - target.z); + CVector pos; + if (shooterPed->m_pPointGunAt->IsPed()) { + ((CPed*)shooterPed->m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d)pos, PED_MID); + } else { + pos = ((CPed*)shooterPed->m_pPointGunAt)->GetPosition(); + } + + float distToTarget = (pos - (*fireSource)).Magnitude2D(); + target.z += info->m_fRange / distToTarget * (pos.z - target.z); } } + if (shooter == FindPlayerPed()) + CWorld::bIncludeDeadPeds = true; - ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); // TODO(Miami): New parameter: ,true); + CWorld::bIncludeDeadPeds = false; } + //bProcessPedsOnBoatsAndBikes = false; // TODO(Miami): bProcessPedsOnBoatsAndBikes if ( victim ) { CGlass::WasGlassHitByBullet(victim, point.point); + CWeapon::BlowUpExplosiveThings(victim); + if (i == checkObstacleOnShootNo) + { + if (shooter) + { + if (shooter->IsPed() && !((CPed*)shooter)->IsPlayer()) + { + CPed *shooterPed = (CPed*)shooter; + CEntity *guyWePointGun = shooterPed->m_pPointGunAt; + if (guyWePointGun) + { + if (victim != guyWePointGun) + { + float distWithAim = (guyWePointGun->GetPosition() - shooter->GetPosition()).Magnitude(); + float distWithBullet = (point.point - shooter->GetPosition()).Magnitude(); + if (distWithAim > 0.1f && distWithBullet > 0.1f) + { + // Normalize + CVector aimDir = (guyWePointGun->GetPosition() - shooter->GetPosition()) * (1.0f / distWithAim); + CVector bulletDir = (point.point - shooter->GetPosition()) * (1.0f / distWithBullet); + float dotProd = DotProduct(aimDir, bulletDir); + float aimAndBulletAngle; + if (dotProd <= 0.35f) + aimAndBulletAngle = PI; + else + aimAndBulletAngle = Acos(dotProd); + + if (aimAndBulletAngle <= DEGTORAD(45.0f) && (aimAndBulletAngle <= DEGTORAD(15.0f) || distWithBullet / distWithAim >= 0.75f) && distWithBullet / distWithAim >= 0.99f) + { + shooterPed->bObstacleShowedUpDuringKillObjective = false; + shooterPed->m_shotTime = 0; + } + else + { + shooterPed->bObstacleShowedUpDuringKillObjective = true; + shooterPed->m_shootTimer = 0; + shooterPed->m_shotTime = CTimer::GetTimeInMilliseconds(); + if (distWithAim >= 10.0f) + shooterPed->SetAttackTimer(3000); + else + shooterPed->SetAttackTimer(1500); + } + } + } + } + } + } + } CBulletTraces::AddTrace(fireSource, &point.point); if ( victim->IsPed() ) { CPed *victimPed = (CPed *)victim; - if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) ) + if ( !victimPed->DyingOrDead() && victim != shooter ) { bool cantStandup = true; @@ -1460,7 +1571,8 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) posOffset.Normalise(); - if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) ) + if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) || + !victimPed->bCanBeShotInVehicle) cantStandup = false; if ( victimPed->bIsStanding && cantStandup ) @@ -1485,7 +1597,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if ( CGame::nastyGame ) { uint8 bloodAmount = 8; - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN ) + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_SPAS12_SHOTGUN || m_eWeaponType == WEAPONTYPE_STUBBY_SHOTGUN) bloodAmount = 32; CVector dir = (point.point - victim->GetPosition()) * 0.01f; @@ -1497,6 +1609,36 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point, dir); } } + } else { + if (CGame::nastyGame) + { + CVector dir = (point.point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if (victimPed->GetIsOnScreen()) + { + for (uint8 i = 0; i < 8; i++) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point + CVector(0.0f, 0.0f, 0.15f), dir); + } + if (victimPed->Dead()) + { + CAnimBlendAssociation *hitAssoc; + if (RpAnimBlendClumpGetFirstAssociation(victimPed->GetClump(), ASSOC_FRONTAL)) + { + hitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); + } + else + { + hitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); + } + if (hitAssoc) + { + hitAssoc->SetCurrentTime(0.0f); + hitAssoc->SetRun(); + hitAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + } + } + } } } else @@ -1505,21 +1647,29 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { case ENTITY_TYPE_VEHICLE: { - ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + if (point.pieceB >= SURFACE_STREET_LIGHT && point.pieceB <= SURFACE_METAL_FENCE) { + ((CVehicle*)victim)->BurstTyre(point.pieceB); // TODO(Miami): New parameter: ,true); - for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); + for (int32 i = 0; i < 4; i++) + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point.point, point.normal * 0.05f); + } + else + { + ((CVehicle*)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for (int32 i = 0; i < 16; i++) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal * 0.05f); #ifndef FIX_BUGS - CVector dist = point.point - (*fireSource); - CVector offset = dist - Max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); - CVector smokePos = *fireSource + offset; + CVector dist = point.point - (*fireSource); + CVector offset = dist - Max(0.2f * dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector smokePos = *fireSource + offset; #else - CVector smokePos = point.point; + CVector smokePos = point.point; #endif - CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + } break; } @@ -1549,13 +1699,15 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if ( !victimObject->bInfiniteMass ) { - if ( victimObject->IsStatic() && victimObject->m_fUprootLimit <= 0.0f ) + bool notStatic = !victimObject->IsStatic(); + if ( notStatic && victimObject->m_fUprootLimit <= 0.0f ) { victimObject->bIsStatic = false; victimObject->AddToMovingList(); } - if ( !victimObject->IsStatic()) + notStatic = !victimObject->IsStatic(); + if ( !notStatic ) { CVector moveForce = point.normal*-5.0f; victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); @@ -1578,17 +1730,29 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } case ENTITY_TYPE_VEHICLE: { + if (!statUpdated) { + //CStats::NumBulletsHit++; // TODO(Miami): Stats + statUpdated = true; + } DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); break; } case ENTITY_TYPE_PED: { + if (!statUpdated) { + //CStats::NumBulletsHit++; // TODO(Miami): Stats + statUpdated = true; + } DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); break; } case ENTITY_TYPE_OBJECT: { + if (!statUpdated) { + //CStats::NumBulletsHit++; // TODO(Miami): Stats + statUpdated = true; + } PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); break; } @@ -1837,8 +2001,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) CVector bulletPos; - // TODO(Miami): M60 - if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, (/*m_eWeaponType == WEAPONTYPE_M60 || */ m_eWeaponType == WEAPONTYPE_HELICANNON ? 20 : 4)) ) + if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, (m_eWeaponType == WEAPONTYPE_M60 || m_eWeaponType == WEAPONTYPE_HELICANNON ? 20 : 4)) ) { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f)); @@ -1848,15 +2011,14 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) { CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - // TODO(Miami) float mult; switch (m_eWeaponType) { - case WEAPONTYPE_M16: // case WEAPONTYPE_M4: + case WEAPONTYPE_M4: case WEAPONTYPE_HELICANNON: - // case WEAPONTYPE_M60: + case WEAPONTYPE_M60: mult = 0.0003f; break; - case WEAPONTYPE_AK47: // case WEAPONTYPE_RUGER: + case WEAPONTYPE_RUGER: mult = 0.00015f; break; default: @@ -2260,9 +2422,9 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) case WEAPONSTATE_FIRING: { - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN && AEHANDLE_IS_OK(audioEntity) ) + if ( IsShotgun(m_eWeaponType) && AEHANDLE_IS_OK(audioEntity) ) { - uint32 timePassed = m_nTimer - gReloadSampleTime[WEAPONTYPE_SHOTGUN]; + uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } @@ -2280,7 +2442,7 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) case WEAPONSTATE_RELOADING: { - if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) + if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_TOTALWEAPONS) { CAnimBlendAssociation *reloadAssoc = nil; if (pedToAdjustSound) { @@ -2461,11 +2623,9 @@ CWeapon::IsTypeMelee(void) bool CWeapon::IsType2Handed(void) { - // TODO(Miami): Uncomment - return m_eWeaponType == WEAPONTYPE_FLAMETHROWER || m_eWeaponType == WEAPONTYPE_HELICANNON || /* m_eWeaponType == WEAPONTYPE_M60 */ - m_eWeaponType == WEAPONTYPE_M16 || - (m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType < WEAPONTYPE_TEC9) || // Shotguns - m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_SNIPERRIFLE /*|| m_eWeaponType == WEAPONTYPE_LASERSCOPE*/; + return m_eWeaponType == WEAPONTYPE_FLAMETHROWER || m_eWeaponType == WEAPONTYPE_HELICANNON || m_eWeaponType == WEAPONTYPE_M60 || + m_eWeaponType == WEAPONTYPE_M4 || IsShotgun(m_eWeaponType) || + m_eWeaponType == WEAPONTYPE_RUGER || m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || m_eWeaponType == WEAPONTYPE_LASERSCOPE; } void diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index f6228b32..b4ed93c3 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -68,6 +68,8 @@ public: static void BlowUpExplosiveThings(CEntity *thing); bool HasWeaponAmmoToBeUsed(void); + static bool IsShotgun(int weapon) { return weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_SPAS12_SHOTGUN || weapon == WEAPONTYPE_STUBBY_SHOTGUN; } + static bool ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects); #ifdef COMPATIBLE_SAVES diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index d5e759b9..104fa2ec 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -12,6 +12,7 @@ // Yeah... int32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }; CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; @@ -32,21 +33,29 @@ static char ms_aWeaponNames[][32] = { "Chainsaw", "Grenade", "DetonateGrenade", + "TearGas", "Molotov", "Rocket", "Colt45", + "Python", "Shotgun", + "Spas12Shotgun", + "StubbyShotgun", "Tec9", "Uzi", "SilencedIngram", "Mp5", - "M16", - "AK47", + "m4", + "Ruger", "SniperRifle", + "LaserScope", "RocketLauncher", "FlameThrower", + "M60", + "Minigun", "Detonator", "HeliCannon", + "Camera", }; CWeaponInfo* @@ -223,9 +232,7 @@ CWeaponInfo::LoadWeaponData(void) ms_apWeaponInfos[weaponType].m_nWeaponSlot = weaponSlot; - // TODO(Miami): Enable once weapons are done - if (animLoopEnd < 98.0f && weaponType != WEAPONTYPE_FLAMETHROWER && weaponType != WEAPONTYPE_SHOTGUN - /*&& weaponType != 20 && weaponType != 21*/) + if (animLoopEnd < 98.0f && weaponType != WEAPONTYPE_FLAMETHROWER && !CWeapon::IsShotgun(weaponType)) ms_apWeaponInfos[weaponType].m_nFiringRate = ((ms_apWeaponInfos[weaponType].m_fAnimLoopEnd - ms_apWeaponInfos[weaponType].m_fAnimLoopStart) * 900.0f); if (weaponType == WEAPONTYPE_DETONATOR || weaponType == WEAPONTYPE_HELICANNON) @@ -263,6 +270,7 @@ CWeaponInfo::FindWeaponFireType(char *name) if (strcmp(name, "INSTANT_HIT") == 0) return WEAPON_FIRE_INSTANT_HIT; if (strcmp(name, "PROJECTILE") == 0) return WEAPON_FIRE_PROJECTILE; if (strcmp(name, "AREA_EFFECT") == 0) return WEAPON_FIRE_AREA_EFFECT; + if (strcmp(name, "CAMERA") == 0) return WEAPON_FIRE_CAMERA; Error("Unknown weapon fire type, WeaponInfo.cpp"); return WEAPON_FIRE_INSTANT_HIT; } diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h index 4b8be40f..65d715ec 100644 --- a/src/weapons/WeaponType.h +++ b/src/weapons/WeaponType.h @@ -1,6 +1,5 @@ #pragma once -// --MIAMI: TODO enum eWeaponType { WEAPONTYPE_UNARMED, @@ -17,23 +16,31 @@ enum eWeaponType WEAPONTYPE_CHAINSAW, WEAPONTYPE_GRENADE, WEAPONTYPE_DETONATOR_GRENADE, + WEAPONTYPE_TEARGAS, WEAPONTYPE_MOLOTOV, WEAPONTYPE_ROCKET, WEAPONTYPE_COLT45, + WEAPONTYPE_PYTHON, WEAPONTYPE_SHOTGUN, + WEAPONTYPE_SPAS12_SHOTGUN, + WEAPONTYPE_STUBBY_SHOTGUN, WEAPONTYPE_TEC9, WEAPONTYPE_UZI, WEAPONTYPE_SILENCED_INGRAM, WEAPONTYPE_MP5, - WEAPONTYPE_M16, - WEAPONTYPE_AK47, + WEAPONTYPE_M4, + WEAPONTYPE_RUGER, WEAPONTYPE_SNIPERRIFLE, + WEAPONTYPE_LASERSCOPE, WEAPONTYPE_ROCKETLAUNCHER, WEAPONTYPE_FLAMETHROWER, + WEAPONTYPE_M60, + WEAPONTYPE_MINIGUN, WEAPONTYPE_DETONATOR, WEAPONTYPE_HELICANNON, - WEAPONTYPE_LAST_WEAPONTYPE, - WEAPONTYPE_HEALTH, + WEAPONTYPE_CAMERA, + WEAPONTYPE_TOTALWEAPONS = 37, + WEAPONTYPE_HEALTH = 37, WEAPONTYPE_ARMOUR, WEAPONTYPE_RAMMEDBYCAR, WEAPONTYPE_RUNOVERBYCAR, @@ -42,10 +49,8 @@ enum eWeaponType WEAPONTYPE_DROWNING, WEAPONTYPE_FALL, WEAPONTYPE_UNIDENTIFIED, - - WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE, - WEAPONTYPE_ANYMELEE = 46, - WEAPONTYPE_ANYWEAPON = 47 + WEAPONTYPE_ANYMELEE, + WEAPONTYPE_ANYWEAPON }; enum { @@ -57,7 +62,7 @@ enum eWeaponFire { WEAPON_FIRE_INSTANT_HIT, WEAPON_FIRE_PROJECTILE, WEAPON_FIRE_AREA_EFFECT, - WEAPON_FIRE_USE + WEAPON_FIRE_CAMERA }; // Taken from MTA SA, seems it's unchanged From c3b41d79a2d7490f3745bfc63484433ef88a34f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 23 May 2020 18:04:33 +0300 Subject: [PATCH 111/148] Cleanup and one needed function --- src/peds/Ped.cpp | 42 ++++++++++++------------------------------ src/peds/PlayerPed.cpp | 31 ++++++++++++++++++------------- src/peds/PlayerPed.h | 1 + src/weapons/Weapon.cpp | 2 +- 4 files changed, 32 insertions(+), 44 deletions(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7ab60faa..d5659a4a 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -386,6 +386,8 @@ CPed::~CPed(void) } if (m_pFire) m_pFire->Extinguish(); + + ClearWeapons(); if (bCarPassenger) CPopulation::ms_nTotalCarPassengerPeds--; if (bMiamiViceCop) @@ -409,10 +411,11 @@ CPed::FlagToDestroyWhenNextProcessed(void) } bInVehicle = false; m_pMyVehicle = nil; + if (CharCreatedBy == MISSION_CHAR) - m_nPedState = PED_DEAD; + SetPedState(PED_DEAD); else - m_nPedState = PED_NONE; + SetPedState(PED_NONE); m_pVehicleAnim = nil; } @@ -1884,10 +1887,7 @@ CPed::ClearPointGunAt(void) ClearAimFlag(); bIsPointingGunAt = false; if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) { - - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); RestorePreviousState(); } weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); @@ -4650,10 +4650,7 @@ CPed::SetGetUp(void) } if (m_nPedState != PED_GETUP) { SetStoredState(); - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_GETUP; + SetPedState(PED_GETUP); } CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity; @@ -4970,10 +4967,7 @@ CPed::SetPointGunAt(CEntity *to) if (m_nPedState != PED_ATTACK) SetStoredState(); - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_AIM_GUN; + SetPedState(PED_AIM_GUN); bIsPointingGunAt = true; SetMoveState(PEDMOVE_NONE); @@ -5267,10 +5261,7 @@ CPed::SetAttack(CEntity *victim) && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS) && curWeapon->m_bPartialAttack)) { if (m_nPedState != PED_ATTACK) { - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_ATTACK; + SetPedState(PED_ATTACK); bIsAttacking = false; CAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f); @@ -5291,10 +5282,7 @@ CPed::SetAttack(CEntity *victim) m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN)) { if (m_nPedState != PED_ATTACK) { - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_ATTACK; + SetPedState(PED_ATTACK); bIsAttacking = false; CAnimBlendAssociation* animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f); animAssoc->SetRun(); @@ -5371,10 +5359,7 @@ CPed::SetAttack(CEntity *victim) if (m_nPedState != PED_AIM_GUN) SetStoredState(); - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_ATTACK; + SetPedState(PED_ATTACK); SetMoveState(PEDMOVE_NONE); if (bCrouchWhenShooting && bIsDucking && !!curWeapon->m_bCrouchFire) { CAnimBlendAssociation* curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon)); @@ -6657,10 +6642,7 @@ CPed::SetDead(void) if (m_nPedState == PED_DRIVING) bIsVisible = false; - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_DEAD; + SetPedState(PED_DEAD); m_pVehicleAnim = nil; m_pCollidingEntity = nil; diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 69369ea4..bbdf57ed 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -47,19 +47,12 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_nSpeedTimer = 0; m_bSpeedTimerFlag = false; - // This should be something inlined // TODO(Miami) - // if (pPointGunAt) // m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); + m_pPointGunAt = nil; - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - // TODO(Miami) - // This should be something inlined - - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); m_fMaxStamina = 150.0f; m_fCurrentStamina = m_fMaxStamina; m_fStaminaProgress = 0.0f; @@ -290,10 +283,7 @@ CPlayerPed::SetInitialState(void) m_pFire->Extinguish(); RpAnimBlendClumpRemoveAllAssociations(GetClump()); - if (m_nPedState == PED_FOLLOW_PATH) - ClearFollowPath(); - - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); SetMoveState(PEDMOVE_STILL); m_nLastPedState = PED_NONE; m_animGroup = ASSOCGRP_PLAYER; @@ -1626,6 +1616,21 @@ CPlayerPed::ProcessControl(void) #endif } +bool +CPlayerPed::DoesPlayerWantNewWeapon(eWeaponType weapon, bool onlyIfSlotIsEmpty) +{ + uint32 slot = CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot; + + if (!HasWeaponSlot(slot) || GetWeapon(slot).m_eWeaponType == weapon) + return true; + + if (onlyIfSlotIsEmpty) + return false; + + // Check if he's using that slot right now. + return m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN || slot != m_currentWeapon; +} + #ifdef COMPATIBLE_SAVES #define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); #define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index 354140df..1042fe16 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -82,6 +82,7 @@ public: void ProcessAnimGroups(void); void ProcessPlayerWeapon(CPad*); void PlayerControlZelda(CPad*); + bool DoesPlayerWantNewWeapon(eWeaponType, bool); static void SetupPlayerPed(int32); static void DeactivatePlayerPed(int32); diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 17cee83a..ebdeb38b 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1597,7 +1597,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if ( CGame::nastyGame ) { uint8 bloodAmount = 8; - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_SPAS12_SHOTGUN || m_eWeaponType == WEAPONTYPE_STUBBY_SHOTGUN) + if ( IsShotgun(m_eWeaponType) ) bloodAmount = 32; CVector dir = (point.point - victim->GetPosition()) * 0.01f; From 607175f02a3f89665c953d09c603183f909cc15b Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 23 May 2020 20:06:52 +0300 Subject: [PATCH 112/148] set pieces --- src/control/CarAI.cpp | 1 + src/control/CarCtrl.cpp | 44 +++++- src/control/Script.cpp | 6 +- src/control/SetPieces.cpp | 319 ++++++++++++++++++++++++++++++++++++++ src/control/SetPieces.h | 48 ++++++ src/core/Game.cpp | 4 + src/core/config.h | 2 + src/peds/Ped.cpp | 1 + src/peds/Ped.h | 1 + src/vehicles/Vehicle.cpp | 1 + src/vehicles/Vehicle.h | 1 + 11 files changed, 425 insertions(+), 3 deletions(-) create mode 100644 src/control/SetPieces.cpp create mode 100644 src/control/SetPieces.h diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index a4406da9..589cc53b 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -350,6 +350,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (!FindPlayerVehicle() || DotProduct2D(CVector2D(diff.x / distance, diff.y / distance), FindPlayerSpeed()) > 0.05f) pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE; BackToCruisingIfNoWantedLevel(pVehicle); + break; } default: if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && !CCullZones::NoPolice()){ diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index b250cb97..5e8324ed 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -971,7 +971,8 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) pVehicle->GetModelIndex() == MI_AMBULAN || pVehicle->GetModelIndex() == MI_FIRETRUCK || pVehicle->bIsLawEnforcer || - pVehicle->bIsCarParkVehicle + pVehicle->bIsCarParkVehicle || + CTimer::GetTimeInMilliseconds() < pVehicle->m_nSetPieceExtendedRangeTime ){ threshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier; } @@ -2515,7 +2516,7 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe pSwerve, pAccel, pBrake, pHandbrake); return; case MISSION_BLOCKPLAYER_FORWARDANDBACK: - //SteerAICarBlockingPlayerForwardAndBack(pVehicle, pSwerve, pAccel, pBrake, pHandbrake); + SteerAICarBlockingPlayerForwardAndBack(pVehicle, pSwerve, pAccel, pBrake, pHandbrake); return; default: assert(0); @@ -2523,6 +2524,45 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe } } +void CCarCtrl::SteerAICarBlockingPlayerForwardAndBack(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake) +{ + *pSwerve = 0.0f; + *pHandbrake = false; + CVector player = FindPlayerSpeed() + 0.1f * FindPlayerEntity()->GetForward(); + player.z = 0.0f; + CVector right(pVehicle->GetRight().x, pVehicle->GetRight().y, 0.0f); + right.Normalise(); + CVector forward(pVehicle->GetForward().x, pVehicle->GetForward().y, 0.0f); + forward.Normalise(); + float dpPlayerAndRight = DotProduct(player, right); + if (dpPlayerAndRight == 0.0f) + dpPlayerAndRight = 0.01f; + float dpDiffAndRight = -DotProduct((FindPlayerCoors() - pVehicle->GetPosition()), right) / dpPlayerAndRight; + if (dpDiffAndRight < 0.0f) { + *pAccel = 0.0f; + *pBrake = 0.0f; + return; + } + float dpSpeedAndForward = DotProduct(pVehicle->GetMoveSpeed(), forward); + float dpPlayerAndForward = DotProduct(player, forward); + float dpDiffAndForward = DotProduct((FindPlayerCoors() - pVehicle->GetPosition()), forward); + float multiplier = dpPlayerAndForward * dpDiffAndRight + dpDiffAndForward - dpSpeedAndForward * dpDiffAndRight; + if (multiplier > 0) { + *pAccel = Min(1.0f, 0.1f * multiplier); + *pBrake = 0.0f; + } + else if (dpSpeedAndForward > 0) { + *pAccel = 0.0f; + *pBrake = Min(1.0f, -0.1f * multiplier); + if (*pBrake > 0.95f) + *pHandbrake = true; + } + else { + *pAccel = Max(-1.0f, 0.1f * multiplier); + *pBrake = 0.0f; + } +} + void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake) { CVector2D forward = pVehicle->GetForward(); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 85098cca..bcb6a388 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -59,6 +59,7 @@ #include "RpAnimBlend.h" #include "Rubbish.h" #include "SimpleModelInfo.h" +#include "SetPieces.h" #include "Shadows.h" #include "SpecialFX.h" #include "Sprite.h" @@ -10900,7 +10901,10 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_ADD_SET_PIECE: { CollectParameters(&m_nIp, 13); - debug("ADD_SET_PIECE not implemented, skipping\n"); + CSetPieces::AddOne(ScriptParams[0], + *(CVector2D*)&ScriptParams[1], *(CVector2D*)&ScriptParams[3], + *(CVector2D*)&ScriptParams[5], *(CVector2D*)&ScriptParams[7], + *(CVector2D*)&ScriptParams[9], *(CVector2D*)&ScriptParams[11]); return 0; } case COMMAND_SET_EXTRA_COLOURS: diff --git a/src/control/SetPieces.cpp b/src/control/SetPieces.cpp new file mode 100644 index 00000000..fb2a1f14 --- /dev/null +++ b/src/control/SetPieces.cpp @@ -0,0 +1,319 @@ +#include "common.h" + +#include "SetPieces.h" +#include "Automobile.h" +#include "CarAI.h" +#include "CopPed.h" +#include "GenericGameStorage.h" +#include "PlayerPed.h" +#include "Timer.h" +#include "Vehicle.h" +#include "Wanted.h" +#include "World.h" + +#define TIME_BETWEEN_SETPIECE_SPAWNS 20000 + +// MIAMI: file done + +bool CSetPieces::bDebug; +uint32 CSetPieces::NumSetPieces; +CSetPiece CSetPieces::aSetPieces[NUM_SETPIECES]; + +void CSetPieces::Init(void) +{ + bDebug = false; + NumSetPieces = 0; +} + +void CSetPieces::AddOne(uint8 type, CVector2D vTriggerInf, CVector2D vTriggerSup, CVector2D vSpawn1, CVector2D vTarget1, CVector2D vSpawn2, CVector2D vTarget2) +{ + if (NumSetPieces >= NUM_SETPIECES) + return; + aSetPieces[NumSetPieces].m_nType = (eSetPieceType)type; + aSetPieces[NumSetPieces].m_vTriggerInf.x = Min(vTriggerInf.x, vTriggerSup.x); + aSetPieces[NumSetPieces].m_vTriggerInf.y = Min(vTriggerInf.y, vTriggerSup.y); + aSetPieces[NumSetPieces].m_vTriggerSup.x = Max(vTriggerInf.x, vTriggerSup.x); + aSetPieces[NumSetPieces].m_vTriggerSup.y = Max(vTriggerInf.y, vTriggerSup.y); + aSetPieces[NumSetPieces].m_vSpawn1 = vSpawn1; + aSetPieces[NumSetPieces].m_vSpawn2 = vSpawn2; + aSetPieces[NumSetPieces].m_vTarget1 = vTarget1; + aSetPieces[NumSetPieces].m_vTarget2 = vTarget2; + ++NumSetPieces; +} + +void CSetPieces::Update(void) +{ + int nFirst = NumSetPieces * (CTimer::GetFrameCounter() % 8) / 8; + int nLast = NumSetPieces * (CTimer::GetFrameCounter() % 8 + 1) / 8; + for (int i = nFirst; i < nLast; i++) + aSetPieces[i].Update(); +} + +void CSetPieces::Save(uint8* buf, uint32* size) +{ +INITSAVEBUF + WriteSaveBuf(buf, NumSetPieces); + for (int i = 0; i < NUM_SETPIECES; i++) + WriteSaveBuf(buf, aSetPieces[i]); + *size = sizeof(NumSetPieces) + NUM_SETPIECES * sizeof(CSetPiece); +VALIDATESAVEBUF(*size) +} + +void CSetPieces::Load(uint8* buf, uint32 size) +{ +INITSAVEBUF + NumSetPieces = ReadSaveBuf(buf); + for (int i = 0; i < NUM_SETPIECES; i++) + aSetPieces[i] = ReadSaveBuf(buf); +VALIDATESAVEBUF(size) +} + +void CSetPiece::Update(void) +{ + if (m_nLastTimeCreated != 0 && CTimer::GetTimeInMilliseconds() <= m_nLastTimeCreated + TIME_BETWEEN_SETPIECE_SPAWNS) + return; + CVector pos = FindPlayerCoors(); + if (pos.x < m_vTriggerInf.x || pos.x > m_vTriggerSup.x || + pos.y < m_vTriggerInf.y || pos.y > m_vTriggerSup.y) + return; + switch (m_nType) { + case SETPIECE_TWOCOPCARSINALLEY: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 1 || FindPlayerVehicle()) + return; + CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1); + if (!pVehicle1) + return; + CVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2); + if (!pVehicle2) { + CWorld::Remove(pVehicle1); + delete pVehicle1; + return; + } + pVehicle1->SetStatus(STATUS_PHYSICS); + pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 4; + pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS; + pVehicle1->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1; + pVehicle1->AutoPilot.m_vecDestinationCoors.x = m_vTarget1.x; + pVehicle1->AutoPilot.m_vecDestinationCoors.y = m_vTarget1.y; + pVehicle1->AutoPilot.m_vecDestinationCoors.z = 0.0f; + pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 25000; + CCarAI::AddPoliceCarOccupants(pVehicle1); + pVehicle2->SetStatus(STATUS_PHYSICS); + pVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle2->AutoPilot.m_nCruiseSpeed = 4; + pVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS; + pVehicle2->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1; + pVehicle2->AutoPilot.m_vecDestinationCoors.x = m_vTarget2.x; + pVehicle2->AutoPilot.m_vecDestinationCoors.y = m_vTarget2.y; + pVehicle2->AutoPilot.m_vecDestinationCoors.z = 0.0f; + pVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 25000; + CCarAI::AddPoliceCarOccupants(pVehicle2); + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + break; + } + case SETPIECE_CARBLOCKINGPLAYERFROMSIDE: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 2) + return; + if (!FindPlayerVehicle()) + return; + if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f) + return; + CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1); + if (!pVehicle1) + return; + pVehicle1->SetStatus(STATUS_PHYSICS); + pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16; + pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH; + pVehicle1->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK; + pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100; + pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000; + pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f); + CCarAI::AddPoliceCarOccupants(pVehicle1); + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + return; + } + case SETPIECE_CARRAMMINGPLAYERFROMSIDE: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 2) + return; + if (!FindPlayerVehicle()) + return; + if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f) + return; + CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1); + if (!pVehicle1) + return; + pVehicle1->SetStatus(STATUS_PHYSICS); + pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16; + pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + pVehicle1->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE; + pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100; + pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000; + pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f); + CCarAI::AddPoliceCarOccupants(pVehicle1); + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + return; + } + case SETPIECE_CREATECOPPERONFOOT: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 1 || FindPlayerVehicle()) + return; + CCopPed* pCop = TryToGenerateCopPed(m_vSpawn1); + if (!pCop) + return; + float z = CWorld::FindGroundZForCoord(m_vTarget1.x, m_vTarget1.y); + pCop->bScriptObjectiveCompleted = false; + pCop->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget1.x, m_vTarget1.y, z)); + pCop->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000; + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + return; + } + case SETPIECE_CREATETWOCOPPERSONFOOT: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 1 || FindPlayerVehicle()) + return; + CCopPed* pCop = TryToGenerateCopPed(m_vSpawn1); + if (!pCop) + return; + float z = CWorld::FindGroundZForCoord(m_vTarget1.x, m_vTarget1.y); + pCop->bScriptObjectiveCompleted = false; + pCop->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget1.x, m_vTarget1.y, z)); + pCop->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000; + CCopPed* pCop2 = TryToGenerateCopPed(m_vSpawn2); + if (!pCop2) { + CWorld::Remove(pCop); + delete pCop; + return; + } + z = CWorld::FindGroundZForCoord(m_vTarget2.x, m_vTarget2.y); + pCop2->bScriptObjectiveCompleted = false; + pCop2->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget2.x, m_vTarget2.y, z)); + pCop2->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000; + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + return; + } + case SETPIECE_TWOCARSBLOCKINGPLAYERFROMSIDE: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 2) + return; + if (!FindPlayerVehicle()) + return; + if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f) + return; + CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1); + if (!pVehicle1) + return; + pVehicle1->SetStatus(STATUS_PHYSICS); + pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16; + pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH; + pVehicle1->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK; + pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100; + pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000; + pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f); + CCarAI::AddPoliceCarOccupants(pVehicle1); + CVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2); + if (!pVehicle2) { + CWorld::Remove(pVehicle1); + delete pVehicle1; + return; + } + pVehicle2->SetStatus(STATUS_PHYSICS); + pVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16; + pVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH; + pVehicle2->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK; + pVehicle2->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + pVehicle2->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100; + pVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000; + pVehicle2->SetMoveSpeed(2.0f * pVehicle2->GetForward() / 3.0f); + CCarAI::AddPoliceCarOccupants(pVehicle2); + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + return; + } + case SETPIECE_TWOCARSRAMMINGPLAYERFROMSIDE: + { + if (FindPlayerPed()->m_pWanted->m_nWantedLevel < 2) + return; + if (!FindPlayerVehicle()) + return; + if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f) + return; + CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1); + if (!pVehicle1) + return; + pVehicle1->SetStatus(STATUS_PHYSICS); + pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16; + pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + pVehicle1->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE; + pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100; + pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000; + pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f); + CCarAI::AddPoliceCarOccupants(pVehicle1); + CVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2); + if (!pVehicle2) { + CWorld::Remove(pVehicle2); + delete pVehicle2; + return; + } + pVehicle2->SetStatus(STATUS_PHYSICS); + pVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle2->AutoPilot.m_nCruiseSpeed = 16; + pVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + pVehicle2->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE; + pVehicle2->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + pVehicle2->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100; + pVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000; + pVehicle2->SetMoveSpeed(2.0f * pVehicle2->GetForward() / 3.0f); + CCarAI::AddPoliceCarOccupants(pVehicle2); + m_nLastTimeCreated = CTimer::GetTimeInMilliseconds(); + return; + } + } +} + +CVehicle* CSetPiece::TryToGenerateCopCar(CVector2D vSpawn, CVector2D vTarget) +{ + CVehicle* pVehicle = new CAutomobile(MI_POLICE, RANDOM_VEHICLE); + CVector pos(vSpawn.x, vSpawn.y, 1000.0f); + CColPoint point; + CEntity* pEntity; + if (CWorld::ProcessVerticalLine(pos, -1000.0f, point, pEntity, true, false, false, false, true, false, nil)) + pos.z = point.point.z + pVehicle->GetHeightAboveRoad(); + CVector vDirection(vTarget.x - vSpawn.x, vTarget.y - vSpawn.y, 0.0f); + vDirection.Normalise(); + pVehicle->GetForward() = CVector(vDirection.x, vDirection.y, 0.0f); + pVehicle->GetRight() = CVector(vDirection.y, -vDirection.x, 0.0f); + pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); + pVehicle->SetPosition(pos); + int16 total; + CWorld::FindObjectsKindaColliding(pos, pVehicle->GetColModel()->spheres->radius, false, &total, 16, nil, false, true, true, false, false); + if (total != 0) { + delete pVehicle; + return nil; + } + pVehicle->ChangeLawEnforcerState(true); + CWorld::Add(pVehicle); + return pVehicle; +} + +CCopPed* CSetPiece::TryToGenerateCopPed(CVector2D vSpawn) +{ + CCopPed* pCop = new CCopPed(COP_STREET); + CVector pos(vSpawn.x, vSpawn.y, 1000.0f); + CColPoint point; + CEntity* pEntity; + if (CWorld::ProcessVerticalLine(pos, -1000.0f, point, pEntity, true, false, false, false, true, false, nil)) + pos.z = point.point.z + 0.9f; + pCop->SetPosition(pos); + int16 total; + CWorld::FindObjectsKindaColliding(pos, pCop->GetColModel()->spheres->radius, false, &total, 16, nil, false, true, true, false, false); + if (total != 0) { + delete pCop; + return nil; + } + CWorld::Add(pCop); + return pCop; +} \ No newline at end of file diff --git a/src/control/SetPieces.h b/src/control/SetPieces.h new file mode 100644 index 00000000..5776d35a --- /dev/null +++ b/src/control/SetPieces.h @@ -0,0 +1,48 @@ +#pragma once + +#include "config.h" + +class CVehicle; +class CCopPed; + +enum eSetPieceType : uint8 +{ + SETPIECE_NONE = 0, + SETPIECE_TWOCOPCARSINALLEY, + SETPIECE_CARBLOCKINGPLAYERFROMSIDE, + SETPIECE_CARRAMMINGPLAYERFROMSIDE, + SETPIECE_CREATECOPPERONFOOT, + SETPIECE_CREATETWOCOPPERSONFOOT, + SETPIECE_TWOCARSBLOCKINGPLAYERFROMSIDE, + SETPIECE_TWOCARSRAMMINGPLAYERFROMSIDE +}; + +class CSetPiece +{ +public: + eSetPieceType m_nType; + uint32 m_nLastTimeCreated; + CVector2D m_vTriggerInf; + CVector2D m_vTriggerSup; + CVector2D m_vSpawn1; + CVector2D m_vSpawn2; + CVector2D m_vTarget1; + CVector2D m_vTarget2; + + CVehicle* TryToGenerateCopCar(CVector2D, CVector2D); + CCopPed* TryToGenerateCopPed(CVector2D); + void Update(void); +}; + +class CSetPieces +{ + static bool bDebug; + static uint32 NumSetPieces; + static CSetPiece aSetPieces[NUM_SETPIECES]; +public: + static void Init(void); + static void AddOne(uint8 type, CVector2D, CVector2D, CVector2D, CVector2D, CVector2D, CVector2D); + static void Save(uint8*, uint32*); + static void Load(uint8*, uint32); + static void Update(void); +}; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 437bd5ec..02648b27 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -64,6 +64,7 @@ #include "Script.h" #include "Shadows.h" #include "Skidmarks.h" +#include "SetPieces.h" #include "SpecialFX.h" #include "Sprite2d.h" #include "Stats.h" @@ -275,6 +276,7 @@ bool CGame::Initialise(const char* datFile) CCullZones::Init(); COcclusion::Init(); CCollision::Init(); + CSetPieces::Init(); CTheZones::Init(); CUserDisplay::Init(); CMessages::Init(); @@ -529,6 +531,7 @@ void CGame::ShutDownForRestart(void) CRadar::RemoveRadarSections(); FrontEndMenuManager.UnloadTextures(); CParticleObject::RemoveAllParticleObjects(); + CSetPieces::Init(); CPedType::Shutdown(); CSpecialFX::Shutdown(); TidyUpMemory(true, false); @@ -622,6 +625,7 @@ void CGame::Process(void) CAntennas::Update(); CGlass::Update(); CSceneEdit::Update(); + CSetPieces::Update(); CEventList::Update(); CParticle::Update(); gFireManager.Update(); diff --git a/src/core/config.h b/src/core/config.h index f0025dfa..4d1a5996 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -135,6 +135,8 @@ enum Config { NUM_CRANES = 8, NUM_EXPLOSIONS = 48, + + NUM_SETPIECES = 96 }; // We'll use this once we're ready to become independent of the game diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 278e5bef..512edf9a 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -670,6 +670,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_nPedMoney = random % 25; if (m_nPedMoney == 23) m_nPedMoney = 400; + m_nExtendedRangeTimer = 0; m_bleedCounter = 0; #ifdef PED_SKIN m_pWeaponModel = nil; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 2a774f9a..776aa1dd 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -523,6 +523,7 @@ public: CPathNode *m_pNextPathNode; float m_fHealth; float m_fArmour; + uint32 m_nExtendedRangeTimer; int16 m_routeLastPoint; uint16 m_routeStartPoint; int16 m_routePointsPassed; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 8d763300..21cf8ce0 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -110,6 +110,7 @@ CVehicle::CVehicle(uint8 CreatedBy) bTyresDontBurst = false; bCreatedAsPoliceVehicle = false; bParking = false; + m_nSetPieceExtendedRangeTime = 0; m_nAlarmState = 0; m_nDoorLock = CARLOCK_UNLOCKED; m_nLastWeaponDamage = -1; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 8673de8f..b036c46b 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -205,6 +205,7 @@ public: float m_fChangeGearTime; CEntity* m_pBombRigger; uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats) + uint32 m_nSetPieceExtendedRangeTime; uint32 m_nTimeOfDeath; uint16 m_nTimeBlocked; int16 m_nBombTimer; // goes down with each frame From f2790f610b370a3c693e6d957e7f8907d12204e6 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 23 May 2020 22:48:50 +0300 Subject: [PATCH 113/148] More audio cleanup --- src/audio/AudioLogic.cpp | 638 ++++++++++++++++++++------------------- src/audio/AudioManager.h | 2 +- 2 files changed, 322 insertions(+), 318 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 6f1a3432..07f80d72 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -52,8 +52,8 @@ uint32 gHomeNextTime; uint32 gCellNextTime; uint32 gNextCryTime; -enum PLAY_STATUS : uint8 { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING = 1, PLAY_STATUS_FINISHED = 2 }; -enum LOADING_STATUS : uint8 { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED = 1 }; +enum PLAY_STATUS : uint8 { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING, PLAY_STATUS_FINISHED }; +enum LOADING_STATUS : uint8 { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED, LOADING_STATUS_FAILED }; void cAudioManager::PreInitialiseGameSpecificSetup() const @@ -98,7 +98,7 @@ cAudioManager::PostInitialiseGameSpecificSetup() m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; m_sMissionAudio.field_22 = 0; m_sMissionAudio.m_bIsPlayed = false; - m_sMissionAudio.m_bPredefinedProperties = 1; + m_sMissionAudio.m_bPredefinedProperties = true; m_sMissionAudio.m_nMissionAudioCounter = 0; ResetAudioLogicTimers(CTimer::GetTimeInMilliseconds()); } @@ -396,6 +396,14 @@ enum eVehicleModel { MAX_CARS }; +enum +{ + DOOR_TYPE_OLD = 0, + DOOR_TYPE_NEW, + DOOR_TYPE_TRUCK, + DOOR_TYPE_AIRBREAK, +}; + struct tVehicleSampleData { eSfxSample m_nAccelerationSampleIndex; @@ -407,76 +415,76 @@ struct tVehicleSampleData { uint8 m_bDoorType; }; -const tVehicleSampleData aVehicleSettings[MAX_CARS] = {{SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 10928, 1}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_ALARM_1, 8941, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_ALARM_1, 11922, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 7948, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_ALARM_1, 8941, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_ALARM_1, 12220, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_ALARM_1, 12200, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 13600, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, 2}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_ALARM_1, 8000, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_ALARM_1, 8543, 1}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, 0}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 10000, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, 1}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, 2}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_ALARM_1, 10123, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_ALARM_1, 10554, 3}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 8000, 2}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, 3}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_ALARM_1, 7500, 3}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_ALARM_1, 8935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 8935, 0}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_ALARM_1, 17000, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_ALARM_1, 9935, 1}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9000, 0}, - {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, 2}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, 1}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}, - {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, 0}}; +const tVehicleSampleData aVehicleSettings[MAX_CARS] = {{SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 10928, DOOR_TYPE_NEW}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_ALARM_1, 8941, DOOR_TYPE_OLD}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_ALARM_1, 11922, DOOR_TYPE_NEW}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 7948, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 11556, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_ALARM_1, 8941, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_ALARM_1, 12220, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_3, 3, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_JEEP, 22295, SFX_CAR_ALARM_1, 12200, DOOR_TYPE_NEW}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, DOOR_TYPE_NEW}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_3, 3, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_ALARM_1, 13600, DOOR_TYPE_NEW}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 8795, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 16168, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_ALARM_1, 8000, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_BUS2, 12345, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_ALARM_1, 8543, DOOR_TYPE_NEW}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_PORSCHE, 9271, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, DOOR_TYPE_OLD}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 10000, DOOR_TYPE_OLD}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 13596, DOOR_TYPE_NEW}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 13000, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_8, 8, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_ALARM_1, 10123, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 13596, DOOR_TYPE_OLD}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_ALARM_1, 10554, DOOR_TYPE_AIRBREAK}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 8000, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_AIRBREAK}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CESNA_IDLE, 0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_BUS, 16291, SFX_CAR_ALARM_1, 7500, DOOR_TYPE_AIRBREAK}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_ALARM_1, 8935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_ALARM_1, 8935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_PICKUP, 2000, SFX_CAR_ALARM_1, 17000, DOOR_TYPE_OLD}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_2, 2, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_5, 5, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_NEW}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_7, 7, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 20143, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9000, DOOR_TYPE_OLD}, + {SFX_CAR_REV_6, 6, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS, 18286, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_TRUCK}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_4, 4, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_ALARM_1, 13400, DOOR_TYPE_NEW}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}, + {SFX_CAR_REV_1, 1, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_ALARM_1, 9935, DOOR_TYPE_OLD}}; bool bPlayerJustEnteredCar; @@ -898,15 +906,15 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) } break; case 'F': - if (automobile->m_aWheelState[0] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[VEHWHEEL_FRONT_LEFT] == WHEEL_STATE_SPINNING) traction += 0.1f; - if (automobile->m_aWheelState[2] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[VEHWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING) traction += 0.1f; break; case 'R': - if (automobile->m_aWheelState[1] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] == WHEEL_STATE_SPINNING) traction += 0.1f; - if (automobile->m_aWheelState[3] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING) traction += 0.1f; break; } @@ -1072,7 +1080,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params) } } else if (params->m_nIndex == DODO) { AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, 0, 52, 1); - } else if (params->m_fDistance < 40000.f) { + } else if (params->m_fDistance < SQR(200)) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { @@ -1094,7 +1102,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params) m_sQueueSample.m_bRequireReflection = false; AddSampleToRequestedQueue(); } - if (params->m_fDistance < 8100.f) { + if (params->m_fDistance < SQR(90)) { m_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { m_sQueueSample.m_nCounter = 2; @@ -1140,7 +1148,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * uint8 engineSoundType; int32 accelerateState; bool channelUsed; - char lostTraction; + bool lostTraction; bool processedAccelSampleStopped; uint8 currentGear; float gasPedalAudio; @@ -1154,8 +1162,8 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * static int32 nCruising = 0; static bool bAccelSampleStopped = true; - lostTraction = 0; - processedAccelSampleStopped = 0; + lostTraction = false; + processedAccelSampleStopped = false; if (bPlayerJustEnteredCar) { bAccelSampleStopped = true; bPlayerJustEnteredCar = false; @@ -1187,13 +1195,13 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * ++wheelInUseCounter; } if (wheelInUseCounter > 2) - lostTraction = 1; + lostTraction = true; } else if (transmission->nDriveType == 'F') { if ((automobile->m_aWheelState[0] || automobile->m_aWheelState[2]) && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { - lostTraction = 1; + lostTraction = true; } } else if (transmission->nDriveType == 'R' && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { - lostTraction = 1; + lostTraction = true; } if (0.0f != velocityChange) { time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; @@ -1290,7 +1298,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * gearNr = 1; CurrentPretendGear = gearNr; } - processedAccelSampleStopped = 1; + processedAccelSampleStopped = true; bAccelSampleStopped = false; } if (channelUsed) { @@ -1671,7 +1679,7 @@ cAudioManager::ProcessVehicleReverseWarning(cVehicleParams *params) if (veh->bEngineOn && veh->m_fGasPedal < 0.0f) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 12; m_sQueueSample.m_nSampleIndex = SFX_REVERSE_WARNING; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -1748,7 +1756,7 @@ cAudioManager::ProcessAirBrakes(cVehicleParams *params) CAutomobile *automobile; uint8 rand; - if (params->m_fDistance > 900.0f) + if (params->m_fDistance > SQR(30)) return false; automobile = (CAutomobile *)params->m_pVehicle; if (!automobile->bEngineOn) @@ -1761,7 +1769,7 @@ cAudioManager::ProcessAirBrakes(cVehicleParams *params) CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); rand = m_anRandomTable[0] % 10 + 70; m_sQueueSample.m_nVolume = ComputeVolume(rand, 30.0f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 13; m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AIR_BRAKES); @@ -1819,7 +1827,7 @@ cAudioManager::ProcessEngineDamage(cVehicleParams *params) } CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, engineDamageIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 28; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_bIs2D = false; @@ -1904,18 +1912,19 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) maxDist = SQR(SOUND_INTENSITY); emittingVol = m_anRandomTable[2] % 5 + 122; switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { - case 0: + case DOOR_TYPE_OLD: m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE; break; - case 2: - m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_CLOSE; - break; - case 3: - m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; - break; + case DOOR_TYPE_NEW: default: m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE; break; + case DOOR_TYPE_TRUCK: + m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_CLOSE; + break; + case DOOR_TYPE_AIRBREAK: + m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; + break; } m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22; @@ -1937,18 +1946,19 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) maxDist = SQR(SOUND_INTENSITY); emittingVol = m_anRandomTable[1] % 10 + 117; switch (aVehicleSettings[params->m_nIndex].m_bDoorType) { - case 0: + case DOOR_TYPE_OLD: m_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_OPEN; break; - case 2: - m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_OPEN; - break; - case 3: - m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; - break; + case DOOR_TYPE_NEW: default: m_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_OPEN; break; + case DOOR_TYPE_TRUCK: + m_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_OPEN; + break; + case DOOR_TYPE_AIRBREAK: + m_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES; + break; } m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10; @@ -1983,7 +1993,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) iWheelIndex = 82; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BUMP); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - if (params->m_nIndex == 41) { + if (params->m_nIndex == RCBANDIT) { m_sQueueSample.m_nFrequency *= 2; emittingVol /= 2; } @@ -2516,7 +2526,7 @@ cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) int32 vol; float multiplier; - if (params->m_fDistance > 2500.f) + if (params->m_fDistance > SQR(50)) return false; velocityChange = Abs(params->m_fVelocityChange); @@ -2528,7 +2538,7 @@ cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); vol = (30.f * multiplier); m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 38; m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -2567,7 +2577,7 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params) int32 emittingVol; static const tHelicopterSampleData gHeliSfxRanges[3] = {{400.f, 380.f, 100}, {100.f, 70.f, MAX_VOLUME}, {60.f, 30.f, MAX_VOLUME}}; - if (gHeliSfxRanges[0].m_fMaxDistance * gHeliSfxRanges[0].m_fMaxDistance <= params->m_fDistance) + if (SQR(gHeliSfxRanges[0].m_fMaxDistance) <= params->m_fDistance) return false; CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); @@ -2584,7 +2594,7 @@ cAudioManager::ProcessHelicopter(cVehicleParams *params) emittingVol = gHeliSfxRanges[i].m_bBaseVolume; m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, gHeliSfxRanges[i].m_fMaxDistance, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = i + 65; m_sQueueSample.m_nSampleIndex = i + SFX_HELI_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -2639,7 +2649,7 @@ cAudioManager::ProcessJumbo(cVehicleParams *params) CPlane *plane; float position; - if (params->m_fDistance < 193600.0f) { + if (params->m_fDistance < SQR(440)) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); plane = (CPlane *)params->m_pVehicle; DoJumboVolOffset(); @@ -2948,7 +2958,7 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params) CAutomobile *veh; uint8 emittingVol; - if (params->m_fDistance < 49.f) { + if (params->m_fDistance < SQR(7)) { ped = params->m_pPed; if (!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); @@ -2956,7 +2966,7 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params) emittingVol = 10; veh = (CAutomobile *)ped->m_pMyVehicle; if (veh && veh->IsCar()) { - for (int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) { + for (int32 i = DOOR_FRONT_LEFT; i < ARRAY_SIZE(veh->Doors); i++) { if (!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) { emittingVol = 42; break; @@ -3438,7 +3448,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 0.0f; m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; + maxDist = SQR(60); m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_nLoopStart = 0; m_sQueueSample.m_nLoopEnd = -1; @@ -3499,7 +3509,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 0.0f; m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; + maxDist = SQR(60); m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_nLoopStart = 0; m_sQueueSample.m_nLoopEnd = -1; @@ -3522,7 +3532,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 1; m_sQueueSample.m_fSpeedMultiplier = 0.0f; m_sQueueSample.m_fSoundIntensity = 90.0f; - maxDist = 8100.f; + maxDist = SQR(90); m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_nLoopStart = 0; m_sQueueSample.m_nLoopEnd = -1; @@ -3544,7 +3554,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 4.0f; m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; + maxDist = SQR(60); m_sQueueSample.m_nLoopCount = 0; m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); @@ -3647,7 +3657,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 3; m_sQueueSample.m_fSpeedMultiplier = 4.0f; m_sQueueSample.m_fSoundIntensity = 60.0f; - maxDist = 3600.f; + maxDist = SQR(60); m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_nLoopStart = 0; m_sQueueSample.m_nLoopEnd = -1; @@ -3684,7 +3694,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) m_sQueueSample.m_nReleasingVolumeModificator = 1; m_sQueueSample.m_fSpeedMultiplier = 0.0f; m_sQueueSample.m_fSoundIntensity = 40.0f; - maxDist = 1600.f; + maxDist = SQR(40); m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_nLoopStart = 0; emittingVol = m_anRandomTable[2] % 30 + 70; @@ -3707,7 +3717,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) if (m_sQueueSample.m_nVolume) { if (noReflection) { if (0.2f * m_sQueueSample.m_fSoundIntensity <= m_sQueueSample.m_fDistance) { - noReflection = 0; + noReflection = false; } else { m_sQueueSample.m_bIs2D = true; m_sQueueSample.m_nOffset = 0; @@ -6476,7 +6486,7 @@ cAudioManager::ProcessWaterCannon(int32) if (distSquared < SOUND_INTENSITY) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(50, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -6501,8 +6511,8 @@ cAudioManager::ProcessWaterCannon(int32) } #pragma region SCRIPT_OBJECTS -const int scriptObjectIntensityS = 30; -const int scriptObjectIntensityL = 80; +const int SCRIPT_OBJECT_INTENSITY_S = 30; +const int SCRIPT_OBJECT_INTENSITY_L = 80; void cAudioManager::ProcessScriptObject(int32 id) @@ -6773,7 +6783,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) switch (sound) { case SCRIPT_SOUND_PARTY_1_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6783,7 +6793,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_1_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6793,7 +6803,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_2_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6803,7 +6813,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_2_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6813,7 +6823,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_3_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6823,7 +6833,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_3_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_3; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6833,7 +6843,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_4_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6843,7 +6853,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_4_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_4; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6853,7 +6863,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_5_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6863,7 +6873,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_5_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_5; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6873,7 +6883,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_6_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6883,7 +6893,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_6_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_6; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6893,7 +6903,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_7_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6903,7 +6913,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_7_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_7; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6913,7 +6923,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_8_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6923,7 +6933,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_8_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_8; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6933,7 +6943,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_9_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6943,7 +6953,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_9_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_9; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6953,7 +6963,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_10_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6963,7 +6973,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_10_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_10; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6973,7 +6983,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_11_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6983,7 +6993,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_11_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_11; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -6993,7 +7003,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_12_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7003,7 +7013,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_12_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_12; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7013,7 +7023,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_13_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7023,7 +7033,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_13_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_RAGGA; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7033,7 +7043,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_STRIP_CLUB_LOOP_1_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7043,7 +7053,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_STRIP_CLUB_LOOP_1_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7053,7 +7063,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_STRIP_CLUB_LOOP_2_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7063,7 +7073,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_STRIP_CLUB_LOOP_2_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_STRIP_CLUB_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7081,7 +7091,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) ProcessSawMillScriptObject(sound); return; case SCRIPT_SOUND_38: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_DOG_FOOD_FACTORY; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7091,7 +7101,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_39: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_DOG_FOOD_FACTORY; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7105,7 +7115,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) ProcessLaunderetteScriptObject(sound); return; case SCRIPT_SOUND_CHINATOWN_RESTAURANT_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_CHINATOWN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7115,7 +7125,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_CHINATOWN_RESTAURANT_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_CHINATOWN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7125,7 +7135,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_CIPRIANI_RESAURANT_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_ITALY; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7135,7 +7145,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_CIPRIANI_RESAURANT_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_ITALY; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7145,7 +7155,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_46_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7155,7 +7165,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_47_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7165,7 +7175,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_MARCO_BISTRO_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7175,7 +7185,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_MARCO_BISTRO_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RESTAURANT_GENERIC_2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 110; @@ -7205,7 +7215,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) ProcessHomeScriptObject(sound); return; case SCRIPT_SOUND_FRANKIE_PIANO: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_PIANO_BAR_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7215,7 +7225,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_PARTY_1_LOOP: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_CLUB_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7235,7 +7245,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) ProcessPornCinema(sound); return; case SCRIPT_SOUND_BANK_ALARM_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_BANK_ALARM_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 90; @@ -7245,7 +7255,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_BANK_ALARM_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_BANK_ALARM_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = 90; @@ -7255,7 +7265,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_POLICE_BALL_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7265,7 +7275,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_POLICE_BALL_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_POLICE_BALL_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7275,7 +7285,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7285,7 +7295,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_RAVE_LOOP_INDUSTRIAL_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RAVE_INDUSTRIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7300,7 +7310,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) return; case SCRIPT_SOUND_RAVE_1_LOOP_S: case SCRIPT_SOUND_RAVE_2_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7311,7 +7321,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) break; case SCRIPT_SOUND_RAVE_1_LOOP_L: case SCRIPT_SOUND_RAVE_2_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RAVE_COMMERCIAL; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7321,7 +7331,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_RAVE_3_LOOP_S: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7331,7 +7341,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) m_sQueueSample.m_fSpeedMultiplier = 2.0f; break; case SCRIPT_SOUND_RAVE_3_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; m_sQueueSample.m_nSampleIndex = SFX_RAVE_SUBURBAN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; emittingVolume = MAX_VOLUME; @@ -7358,7 +7368,7 @@ cAudioManager::ProcessLoopingScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 0; @@ -7395,7 +7405,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) m_sQueueSample.m_nSampleIndex = SFX_PORN_1_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; sample = SFX_PORN_1_GROAN_1; - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; case SCRIPT_SOUND_PORN_CINEMA_2_S: m_sQueueSample.m_nSampleIndex = SFX_PORN_2_LOOP; @@ -7407,7 +7417,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) m_sQueueSample.m_nSampleIndex = SFX_PORN_2_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; sample = SFX_PORN_2_GROAN_1; - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; case SCRIPT_SOUND_PORN_CINEMA_3_S: m_sQueueSample.m_nSampleIndex = SFX_PORN_3_LOOP; @@ -7418,7 +7428,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) case SCRIPT_SOUND_PORN_CINEMA_3_L: m_sQueueSample.m_nSampleIndex = SFX_PORN_3_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; sample = SFX_PORN_3_GROAN_1; break; default: @@ -7518,7 +7528,7 @@ cAudioManager::ProcessSawMillScriptObject(uint8 sound) switch (sound) { case SCRIPT_SOUND_SAWMILL_LOOP_S: case SCRIPT_SOUND_SAWMILL_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; default: return; @@ -7574,7 +7584,7 @@ cAudioManager::ProcessLaunderetteScriptObject(uint8 sound) switch (sound) { case SCRIPT_SOUND_LAUNDERETTE_LOOP_S: case SCRIPT_SOUND_LAUNDERETTE_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; default: return; @@ -7631,7 +7641,7 @@ cAudioManager::ProcessShopScriptObject(uint8 sound) switch (sound) { case SCRIPT_SOUND_SHOP_LOOP_S: case SCRIPT_SOUND_SHOP_LOOP_L: - m_sQueueSample.m_fSoundIntensity = 30.0f; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; default: return; @@ -7692,10 +7702,10 @@ cAudioManager::ProcessAirportScriptObject(uint8 sound) if (time > gAirportNextTime) { switch (sound) { case SCRIPT_SOUND_AIRPORT_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; case SCRIPT_SOUND_AIRPORT_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; default: return; @@ -7704,7 +7714,7 @@ cAudioManager::ProcessAirportScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(110, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_AIRPORT_ANNOUNCEMENT_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); @@ -7737,10 +7747,10 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound) if (time > gCinemaNextTime) { switch (sound) { case SCRIPT_SOUND_CINEMA_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; case SCRIPT_SOUND_CINEMA_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; default: return; @@ -7786,10 +7796,10 @@ cAudioManager::ProcessDocksScriptObject(uint8 sound) if (time > gDocksNextTime) { switch (sound) { case SCRIPT_SOUND_DOCKS_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; case SCRIPT_SOUND_DOCKS_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; default: return; @@ -7834,10 +7844,10 @@ cAudioManager::ProcessHomeScriptObject(uint8 sound) if (time > gHomeNextTime) { switch (sound) { case SCRIPT_SOUND_HOME_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; case SCRIPT_SOUND_HOME_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; default: return; @@ -7883,10 +7893,10 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) if (time > gCellNextTime) { switch (sound) { case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_S: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityS; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_S; break; case SCRIPT_SOUND_POLICE_CELL_BEATING_LOOP_L: - m_sQueueSample.m_fSoundIntensity = scriptObjectIntensityL; + m_sQueueSample.m_fSoundIntensity = SCRIPT_OBJECT_INTENSITY_L; break; default: return; @@ -7901,7 +7911,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) m_sQueueSample.m_nSampleIndex = sampleIndex; emittingVol = m_anRandomTable[0] % 50 + 55; m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); @@ -8411,7 +8421,7 @@ cAudioManager::ProcessFireHydrant() if (distSquared < SQR(intensity)) { CalculateDistance(distCalculated, distSquared); m_sQueueSample.m_nVolume = ComputeVolume(40, 35.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -8445,7 +8455,7 @@ cAudioManager::ProcessBridge() if (CBridge::pLiftRoad) { m_sQueueSample.m_vecPos = CBridge::pLiftRoad->GetPosition(); dist = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (dist < 202500.0f) { + if (dist < SQR(450.0f)) { CalculateDistance(distCalculated, dist); switch (CBridge::State) { case STATE_BRIDGE_LOCKED: @@ -8522,25 +8532,19 @@ cAudioManager::ProcessBridgeMotor() void cAudioManager::ProcessBridgeOneShots() { - if (CBridge::State == STATE_LIFT_PART_IS_UP && CBridge::OldState == STATE_LIFT_PART_MOVING_UP) { + if (CBridge::State == STATE_LIFT_PART_IS_UP && CBridge::OldState == STATE_LIFT_PART_MOVING_UP) m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else { - if (CBridge::State == STATE_LIFT_PART_IS_DOWN && CBridge::OldState == STATE_LIFT_PART_MOVING_DOWN) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else { - if (CBridge::State == STATE_LIFT_PART_MOVING_UP && CBridge::OldState == STATE_LIFT_PART_ABOUT_TO_MOVE_UP) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else { - if (CBridge::State == STATE_LIFT_PART_MOVING_DOWN && CBridge::OldState == STATE_LIFT_PART_IS_UP) { - m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; - } else - return; - } - } - } + else if (CBridge::State == STATE_LIFT_PART_IS_DOWN && CBridge::OldState == STATE_LIFT_PART_MOVING_DOWN) + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + else if (CBridge::State == STATE_LIFT_PART_MOVING_UP && CBridge::OldState == STATE_LIFT_PART_ABOUT_TO_MOVE_UP) + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + else if (CBridge::State == STATE_LIFT_PART_MOVING_DOWN && CBridge::OldState == STATE_LIFT_PART_IS_UP) + m_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1; + else return; + if (m_sQueueSample.m_fDistance < bridgeIntensity) { m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, bridgeIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 2; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_bIs2D = false; @@ -8657,13 +8661,13 @@ cAudioManager::PreloadMissionAudio(const char *name) } } -bool +uint8 cAudioManager::GetMissionAudioLoadingStatus() const { if (m_bIsInitialised) return m_sMissionAudio.m_nLoadingStatus; - return true; + return LOADING_STATUS_LOADED; } void @@ -8679,9 +8683,8 @@ void cAudioManager::PlayLoadedMissionAudio() { if (m_bIsInitialised && m_sMissionAudio.m_nSampleIndex != NO_SAMPLE && m_sMissionAudio.m_nLoadingStatus == LOADING_STATUS_LOADED && - !m_sMissionAudio.m_nPlayStatus) { + m_sMissionAudio.m_nPlayStatus == PLAY_STATUS_STOPPED) m_sMissionAudio.m_bIsPlayed = true; - } } bool @@ -8704,7 +8707,7 @@ cAudioManager::ClearMissionAudio() m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; m_sMissionAudio.field_22 = 0; m_sMissionAudio.m_bIsPlayed = false; - m_sMissionAudio.m_bPredefinedProperties = 1; + m_sMissionAudio.m_bPredefinedProperties = true; m_sMissionAudio.m_nMissionAudioCounter = 0; } } @@ -8722,115 +8725,116 @@ cAudioManager::ProcessMissionAudio() static uint8 nFramesUntilFailedLoad = 0; static uint8 nFramesForPretendPlaying = 0; - if (m_bIsInitialised) { - if (m_sMissionAudio.m_nSampleIndex != NO_SAMPLE) { - switch (m_sMissionAudio.m_nLoadingStatus) { - case LOADING_STATUS_NOT_LOADED: - SampleManager.PreloadStreamedFile(m_sMissionAudio.m_nSampleIndex, 1); - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; + if (!m_bIsInitialised) return; + if (m_sMissionAudio.m_nSampleIndex == NO_SAMPLE) return; + + switch (m_sMissionAudio.m_nLoadingStatus) { + case LOADING_STATUS_NOT_LOADED: + SampleManager.PreloadStreamedFile(m_sMissionAudio.m_nSampleIndex, 1); + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; + nFramesUntilFailedLoad = 0; + break; + case LOADING_STATUS_LOADED: + if (!m_sMissionAudio.m_bIsPlayed) + return; + if (g_bMissionAudioLoadFailed) { + if (m_bTimerJustReset) { + ClearMissionAudio(); + SampleManager.StopStreamedFile(1); + nFramesForPretendPlaying = 0; + nCheckPlayingDelay = 0; nFramesUntilFailedLoad = 0; - return; - case LOADING_STATUS_LOADED: - if (!m_sMissionAudio.m_bIsPlayed) - return; - if (g_bMissionAudioLoadFailed) { - if (m_bTimerJustReset) { - ClearMissionAudio(); - SampleManager.StopStreamedFile(1); - nFramesForPretendPlaying = 0; - nCheckPlayingDelay = 0; - nFramesUntilFailedLoad = 0; - } else if (!m_nUserPause) { - if (++nFramesForPretendPlaying < 120) { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; - } else { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - } - } + } else if (!m_nUserPause) { + if (++nFramesForPretendPlaying < 120) { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; } else { - if (m_sMissionAudio.m_nPlayStatus) { - if (m_sMissionAudio.m_nPlayStatus != PLAY_STATUS_PLAYING) - return; - if (m_bTimerJustReset) { - ClearMissionAudio(); - SampleManager.StopStreamedFile(1); - return; - } - if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { - if (!m_nUserPause) { - if (nCheckPlayingDelay) { - --nCheckPlayingDelay; - } else if (GetMissionScriptPoliceAudioPlayingStatus() == PLAY_STATUS_FINISHED || - m_sMissionAudio.m_nMissionAudioCounter-- == 0) { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - SampleManager.StopStreamedFile(1); - m_sMissionAudio.m_nMissionAudioCounter = 0; - } - } - } else if (m_sMissionAudio.field_22) { - if (SampleManager.IsStreamPlaying(1) || m_nUserPause || m_nPreviousUserPause) { - if (m_nUserPause) - SampleManager.PauseStream(1, 1); - else - SampleManager.PauseStream(0, 1); - } else { - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; - m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; - SampleManager.StopStreamedFile(1); - m_sMissionAudio.m_nMissionAudioCounter = 0; - } - } else { - if (m_nUserPause) - return; - if (nCheckPlayingDelay--) { - if (!SampleManager.IsStreamPlaying(1)) - return; - nCheckPlayingDelay = 0; - } - m_sMissionAudio.field_22 = 1; - } + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + } + } + break; + } + switch (m_sMissionAudio.m_nPlayStatus) { + case PLAY_STATUS_STOPPED: + if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { + SetMissionScriptPoliceAudio(m_sMissionAudio.m_nSampleIndex); + } else { + if (m_nUserPause) + SampleManager.PauseStream(1, 1); + if (m_sMissionAudio.m_bPredefinedProperties) { + SampleManager.SetStreamedVolumeAndPan(80, 63, 1, 1); + } else { + distSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos); + if (distSquared >= SQR(50.0f)) { + emittingVol = 0; + pan = 63; } else { - if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { - SetMissionScriptPoliceAudio(m_sMissionAudio.m_nSampleIndex); - } else { - if (m_nUserPause) - SampleManager.PauseStream(1, 1); - if (m_sMissionAudio.m_bPredefinedProperties) { - SampleManager.SetStreamedVolumeAndPan(80, 63, 1, 1); - } else { - distSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos); - if (distSquared >= 2500.f) { - emittingVol = 0; - pan = 63; - } else { - dist = Sqrt(distSquared); - emittingVol = ComputeVolume(80, 50.0f, dist); - TranslateEntity(&m_sMissionAudio.m_vecPos, &vec); - pan = ComputePan(50.f, &vec); - } - SampleManager.SetStreamedVolumeAndPan(emittingVol, pan, 1, 1); - } - SampleManager.StartPreloadedStreamedFile(1); - } - m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; - nCheckPlayingDelay = 30; + dist = Sqrt(distSquared); + emittingVol = ComputeVolume(80, 50.0f, dist); + TranslateEntity(&m_sMissionAudio.m_vecPos, &vec); + pan = ComputePan(50.f, &vec); + } + SampleManager.SetStreamedVolumeAndPan(emittingVol, pan, 1, 1); + } + SampleManager.StartPreloadedStreamedFile(1); + } + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_PLAYING; + nCheckPlayingDelay = 30; + break; + case PLAY_STATUS_PLAYING: + if (m_bTimerJustReset) { + ClearMissionAudio(); + SampleManager.StopStreamedFile(1); + break; + } + if (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex)) { + if (!m_nUserPause) { + if (nCheckPlayingDelay) { + --nCheckPlayingDelay; + } else if (GetMissionScriptPoliceAudioPlayingStatus() == PLAY_STATUS_FINISHED || m_sMissionAudio.m_nMissionAudioCounter-- == 0) { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + SampleManager.StopStreamedFile(1); + m_sMissionAudio.m_nMissionAudioCounter = 0; } } - break; - case 2: - if (++nFramesUntilFailedLoad >= 90) { - nFramesForPretendPlaying = 0; - g_bMissionAudioLoadFailed = true; - nFramesUntilFailedLoad = 0; - m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; + } else if (m_sMissionAudio.field_22) { + if (SampleManager.IsStreamPlaying(1) || m_nUserPause || m_nPreviousUserPause) { + if (m_nUserPause) + SampleManager.PauseStream(1, 1); + else + SampleManager.PauseStream(0, 1); + } else { + m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_FINISHED; + m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; + SampleManager.StopStreamedFile(1); + m_sMissionAudio.m_nMissionAudioCounter = 0; } - return; - default: - return; + } else { + if (m_nUserPause) + break; + if (nCheckPlayingDelay--) { + if (!SampleManager.IsStreamPlaying(1)) + break; + nCheckPlayingDelay = 0; + } + m_sMissionAudio.field_22 = 1; } + break; + default: + break; } + break; + case LOADING_STATUS_FAILED: + if (++nFramesUntilFailedLoad >= 90) { + nFramesForPretendPlaying = 0; + g_bMissionAudioLoadFailed = true; + nFramesUntilFailedLoad = 0; + m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_LOADED; + } + break; + default: + break; } } #pragma endregion All the mission audio stuff \ No newline at end of file diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index b2b44c07..8e1c9590 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -328,7 +328,7 @@ public: float GetCollisionRatio(float a, float b, float c, float d) const; float GetDistanceSquared(const CVector &v) const; int32 GetJumboTaxiFreq() const; - bool GetMissionAudioLoadingStatus() const; + uint8 GetMissionAudioLoadingStatus() const; int8 GetMissionScriptPoliceAudioPlayingStatus() const; uint8 GetNum3DProvidersAvailable() const; int32 GetPedCommentSfx(CPed *ped, int32 sound); From ac208ce02cd23d534e50a453080919d4f491c0fd Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 23 May 2020 23:25:14 +0300 Subject: [PATCH 114/148] Even more small audio cleanup --- src/audio/AudioLogic.cpp | 6 +++--- src/audio/AudioManager.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 07f80d72..6ac0ea4b 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1158,7 +1158,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * static int16 LastBrake = 0; static uint8 CurrentPretendGear = 1; static bool bLostTractionLastFrame = false; - static bool bHandbrakeOnLastFrame = 0; + static bool bHandbrakeOnLastFrame = false; static int32 nCruising = 0; static bool bAccelSampleStopped = true; @@ -1171,7 +1171,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * LastAccel = 0; bLostTractionLastFrame = false; LastBrake = 0; - bHandbrakeOnLastFrame = 0; + bHandbrakeOnLastFrame = false; CurrentPretendGear = 1; } if (CReplay::IsPlayingBack()) { @@ -1720,7 +1720,7 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params) for (int32 i = 0; i < ARRAY_SIZE(automobile->Doors); i++) { if (automobile->Damage.GetDoorStatus(i) == DOOR_STATUS_SWINGING) { doorState = automobile->Doors[i].m_nDoorState; - if (doorState == DOOR_STATUS_SMASHED || doorState == DOOR_STATUS_SWINGING) { + if (doorState == DOORST_OPEN || doorState == DOORST_CLOSED) { velocity = Min(0.3f, Abs(automobile->Doors[i].m_fAngVel)); if (velocity > 0.0035f) { emittingVol = (100.f * velocity * 10.f / 3.f); diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index bd1ac84b..c34ad90a 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -39,8 +39,8 @@ cAudioManager::cAudioManager() } m_nAudioEntitiesTotal = 0; m_FrameCounter = 0; - m_bFifthFrameFlag = 0; - m_bTimerJustReset = 0; + m_bFifthFrameFlag = false; + m_bTimerJustReset = false; m_nTimer = 0; } From 7d30878418e037bcfda4121f59193e25a89c1824 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 24 May 2020 01:06:19 +0300 Subject: [PATCH 115/148] Fix OAL crash --- premake5.lua | 2 -- src/audio/oal/aldlist.cpp | 3 +-- src/audio/oal/aldlist.h | 11 ++++++++--- src/audio/sampman.h | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/premake5.lua b/premake5.lua index fd6da6ac..2331c0b3 100644 --- a/premake5.lua +++ b/premake5.lua @@ -185,8 +185,6 @@ project "re3" includedirs { "src/weapons" } includedirs { "src/extras" } includedirs { "eax" } - - includedirs { "eax" } filter "platforms:*mss" defines { "AUDIO_MSS" } diff --git a/src/audio/oal/aldlist.cpp b/src/audio/oal/aldlist.cpp index 7401e036..9834ffb4 100644 --- a/src/audio/oal/aldlist.cpp +++ b/src/audio/oal/aldlist.cpp @@ -35,7 +35,6 @@ */ ALDeviceList::ALDeviceList() { - ALDEVICEINFO ALDeviceInfo; char *devices; int index; const char *defaultDeviceName; @@ -71,7 +70,7 @@ ALDeviceList::ALDeviceList() } } if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) { - memset(&ALDeviceInfo, 0, sizeof(ALDEVICEINFO)); + ALDEVICEINFO ALDeviceInfo; ALDeviceInfo.bSelected = true; ALDeviceInfo.strDeviceName = actualDeviceName; alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion); diff --git a/src/audio/oal/aldlist.h b/src/audio/oal/aldlist.h index 694c9d01..3afa6bfe 100644 --- a/src/audio/oal/aldlist.h +++ b/src/audio/oal/aldlist.h @@ -8,15 +8,20 @@ #include #include -typedef struct -{ +struct ALDEVICEINFO { std::string strDeviceName; int iMajorVersion; int iMinorVersion; unsigned int uiSourceCount; std::vector *pvstrExtensions; bool bSelected; -} ALDEVICEINFO, *LPALDEVICEINFO; + + ALDEVICEINFO() : iMajorVersion(0), iMinorVersion(0), uiSourceCount(0), pvstrExtensions(NULL), bSelected(false) + { + } +}; + +typedef ALDEVICEINFO *LPALDEVICEINFO; class ALDeviceList { diff --git a/src/audio/sampman.h b/src/audio/sampman.h index d3c82943..621d4015 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -3,7 +3,7 @@ #include "AudioSamples.h" #define MAX_VOLUME 127 -#define MAX_FREQ 22050 +#define MAX_FREQ DIGITALRATE struct tSample { int32 nOffset; From f92770f74affa700abcec27f872b2627054f27b6 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 24 May 2020 01:44:10 +0300 Subject: [PATCH 116/148] Optimize ALDeviceList --- src/audio/oal/aldlist.cpp | 108 ++++++++++++++------------------------ src/audio/oal/aldlist.h | 39 +++++++++----- src/audio/sampman_oal.cpp | 8 +-- 3 files changed, 70 insertions(+), 85 deletions(-) diff --git a/src/audio/oal/aldlist.cpp b/src/audio/oal/aldlist.cpp index 9834ffb4..3e86b1d7 100644 --- a/src/audio/oal/aldlist.cpp +++ b/src/audio/oal/aldlist.cpp @@ -41,8 +41,7 @@ ALDeviceList::ALDeviceList() const char *actualDeviceName; // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support - vDeviceInfo.empty(); - vDeviceInfo.reserve(10); + nNumOfDevices = 0; defaultDeviceIndex = 0; @@ -64,7 +63,7 @@ ALDeviceList::ALDeviceList() // if new actual device name isn't already in the list, then add it... actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER); bool bNewName = true; - for (int i = 0; i < GetNumDevices(); i++) { + for (unsigned int i = 0; i < GetNumDevices(); i++) { if (strcmp(GetDeviceName(i), actualDeviceName) == 0) { bNewName = false; } @@ -76,39 +75,37 @@ ALDeviceList::ALDeviceList() alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion); alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion); - ALDeviceInfo.pvstrExtensions = new std::vector; - // Check for ALC Extensions if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE"); + ALDeviceInfo.Extensions |= ADEXT_EXT_CAPTURE; if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX"); + ALDeviceInfo.Extensions |= ADEXT_EXT_EFX; // Check for AL Extensions if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET"); + ALDeviceInfo.Extensions |= ADEXT_EXT_OFFSET; if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE"); + ALDeviceInfo.Extensions |= ADEXT_EXT_LINEAR_DISTANCE; if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE"); + ALDeviceInfo.Extensions |= ADEXT_EXT_EXPONENT_DISTANCE; if (alIsExtensionPresent("EAX2.0") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("EAX2.0"); + ALDeviceInfo.Extensions |= ADEXT_EAX2; if (alIsExtensionPresent("EAX3.0") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("EAX3.0"); + ALDeviceInfo.Extensions |= ADEXT_EAX3; if (alIsExtensionPresent("EAX4.0") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("EAX4.0"); + ALDeviceInfo.Extensions |= ADEXT_EAX4; if (alIsExtensionPresent("EAX5.0") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("EAX5.0"); + ALDeviceInfo.Extensions |= ADEXT_EAX5; if (alIsExtensionPresent("EAX-RAM") == AL_TRUE) - ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM"); + ALDeviceInfo.Extensions |= ADEXT_EAX_RAM; // Get Source Count ALDeviceInfo.uiSourceCount = GetMaxNumSources(); - vDeviceInfo.push_back(ALDeviceInfo); + aDeviceInfo[nNumOfDevices++] = ALDeviceInfo; } alcMakeContextCurrent(NULL); alcDestroyContext(context); @@ -128,31 +125,23 @@ ALDeviceList::ALDeviceList() */ ALDeviceList::~ALDeviceList() { - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) { - if (vDeviceInfo[i].pvstrExtensions) { - vDeviceInfo[i].pvstrExtensions->empty(); - delete vDeviceInfo[i].pvstrExtensions; - } - } - - vDeviceInfo.empty(); } /* * Returns the number of devices in the complete device list */ -int ALDeviceList::GetNumDevices() +unsigned int ALDeviceList::GetNumDevices() { - return (int)vDeviceInfo.size(); + return nNumOfDevices; } /* * Returns the device name at an index in the complete device list */ -char * ALDeviceList::GetDeviceName(int index) +const char * ALDeviceList::GetDeviceName(unsigned int index) { if (index < GetNumDevices()) - return (char *)vDeviceInfo[index].strDeviceName.c_str(); + return aDeviceInfo[index].strDeviceName; else return NULL; } @@ -160,13 +149,13 @@ char * ALDeviceList::GetDeviceName(int index) /* * Returns the major and minor version numbers for a device at a specified index in the complete list */ -void ALDeviceList::GetDeviceVersion(int index, int *major, int *minor) +void ALDeviceList::GetDeviceVersion(unsigned int index, int *major, int *minor) { if (index < GetNumDevices()) { if (major) - *major = vDeviceInfo[index].iMajorVersion; + *major = aDeviceInfo[index].iMajorVersion; if (minor) - *minor = vDeviceInfo[index].iMinorVersion; + *minor = aDeviceInfo[index].iMinorVersion; } return; } @@ -174,10 +163,10 @@ void ALDeviceList::GetDeviceVersion(int index, int *major, int *minor) /* * Returns the maximum number of Sources that can be generate on the given device */ -unsigned int ALDeviceList::GetMaxNumSources(int index) +unsigned int ALDeviceList::GetMaxNumSources(unsigned int index) { if (index < GetNumDevices()) - return vDeviceInfo[index].uiSourceCount; + return aDeviceInfo[index].uiSourceCount; else return 0; } @@ -185,20 +174,9 @@ unsigned int ALDeviceList::GetMaxNumSources(int index) /* * Checks if the extension is supported on the given device */ -bool ALDeviceList::IsExtensionSupported(int index, const char *szExtName) +bool ALDeviceList::IsExtensionSupported(int index, unsigned short ext) { - bool bReturn = false; - - if (index < GetNumDevices()) { - for (unsigned int i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) { - if (!_stricmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) { - bReturn = true; - break; - } - } - } - - return bReturn; + return !!(aDeviceInfo[index].Extensions & ext); } /* @@ -215,10 +193,10 @@ int ALDeviceList::GetDefaultDevice() void ALDeviceList::FilterDevicesMinVer(int major, int minor) { int dMajor, dMinor; - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) { + for (unsigned int i = 0; i < nNumOfDevices; i++) { GetDeviceVersion(i, &dMajor, &dMinor); if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) { - vDeviceInfo[i].bSelected = false; + aDeviceInfo[i].bSelected = false; } } } @@ -229,10 +207,10 @@ void ALDeviceList::FilterDevicesMinVer(int major, int minor) void ALDeviceList::FilterDevicesMaxVer(int major, int minor) { int dMajor, dMinor; - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) { + for (unsigned int i = 0; i < nNumOfDevices; i++) { GetDeviceVersion(i, &dMajor, &dMinor); if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) { - vDeviceInfo[i].bSelected = false; + aDeviceInfo[i].bSelected = false; } } } @@ -240,20 +218,12 @@ void ALDeviceList::FilterDevicesMaxVer(int major, int minor) /* * Deselects device which don't support the given extension name */ -void ALDeviceList::FilterDevicesExtension(char *szExtName) +void +ALDeviceList::FilterDevicesExtension(unsigned short ext) { - bool bFound; - - for (unsigned int i = 0; i < vDeviceInfo.size(); i++) { - bFound = false; - for (unsigned int j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) { - if (!_stricmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) { - bFound = true; - break; - } - } - if (!bFound) - vDeviceInfo[i].bSelected = false; + for (unsigned int i = 0; i < nNumOfDevices; i++) { + if (!IsExtensionSupported(i, ext)) + aDeviceInfo[i].bSelected = false; } } @@ -262,8 +232,8 @@ void ALDeviceList::FilterDevicesExtension(char *szExtName) */ void ALDeviceList::ResetFilters() { - for (int i = 0; i < GetNumDevices(); i++) { - vDeviceInfo[i].bSelected = true; + for (unsigned int i = 0; i < GetNumDevices(); i++) { + aDeviceInfo[i].bSelected = true; } filterIndex = 0; } @@ -273,10 +243,10 @@ void ALDeviceList::ResetFilters() */ int ALDeviceList::GetFirstFilteredDevice() { - int i; + unsigned int i; for (i = 0; i < GetNumDevices(); i++) { - if (vDeviceInfo[i].bSelected == true) { + if (aDeviceInfo[i].bSelected == true) { break; } } @@ -289,10 +259,10 @@ int ALDeviceList::GetFirstFilteredDevice() */ int ALDeviceList::GetNextFilteredDevice() { - int i; + unsigned int i; for (i = filterIndex; i < GetNumDevices(); i++) { - if (vDeviceInfo[i].bSelected == true) { + if (aDeviceInfo[i].bSelected == true) { break; } } diff --git a/src/audio/oal/aldlist.h b/src/audio/oal/aldlist.h index 3afa6bfe..417bd314 100644 --- a/src/audio/oal/aldlist.h +++ b/src/audio/oal/aldlist.h @@ -5,19 +5,33 @@ #ifdef AUDIO_OAL #pragma warning(disable: 4786) //disable warning "identifier was truncated to '255' characters in the browser information" -#include -#include + +enum +{ + ADEXT_EXT_CAPTURE = (1 << 0), + ADEXT_EXT_EFX = (1 << 1), + ADEXT_EXT_OFFSET = (1 << 2), + ADEXT_EXT_LINEAR_DISTANCE = (1 << 3), + ADEXT_EXT_EXPONENT_DISTANCE = (1 << 4), + ADEXT_EAX2 = (1 << 5), + ADEXT_EAX3 = (1 << 6), + ADEXT_EAX4 = (1 << 7), + ADEXT_EAX5 = (1 << 8), + ADEXT_EAX_RAM = (1 << 9), +}; struct ALDEVICEINFO { - std::string strDeviceName; + const char *strDeviceName; int iMajorVersion; int iMinorVersion; unsigned int uiSourceCount; - std::vector *pvstrExtensions; + unsigned short Extensions; bool bSelected; - ALDEVICEINFO() : iMajorVersion(0), iMinorVersion(0), uiSourceCount(0), pvstrExtensions(NULL), bSelected(false) + ALDEVICEINFO() : iMajorVersion(0), iMinorVersion(0), uiSourceCount(0), bSelected(false) { + strDeviceName = NULL; + Extensions = 0; } }; @@ -26,22 +40,23 @@ typedef ALDEVICEINFO *LPALDEVICEINFO; class ALDeviceList { private: - std::vector vDeviceInfo; + ALDEVICEINFO aDeviceInfo[64]; + unsigned int nNumOfDevices; int defaultDeviceIndex; int filterIndex; public: ALDeviceList (); ~ALDeviceList (); - int GetNumDevices(); - char *GetDeviceName(int index); - void GetDeviceVersion(int index, int *major, int *minor); - unsigned int GetMaxNumSources(int index); - bool IsExtensionSupported(int index, const char *szExtName); + unsigned int GetNumDevices(); + const char *GetDeviceName(unsigned int index); + void GetDeviceVersion(unsigned int index, int *major, int *minor); + unsigned int GetMaxNumSources(unsigned int index); + bool IsExtensionSupported(int index, unsigned short ext); int GetDefaultDevice(); void FilterDevicesMinVer(int major, int minor); void FilterDevicesMaxVer(int major, int minor); - void FilterDevicesExtension(char *szExtName); + void FilterDevicesExtension(unsigned short ext); void ResetFilters(); int GetFirstFilteredDevice(); int GetNextFilteredDevice(); diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index f6f3a393..1952f370 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -174,10 +174,10 @@ add_providers() } if ( alGetEnumValue("AL_EFFECT_EAXREVERB") != 0 - || pDeviceList->IsExtensionSupported(i, "EAX2.0") - || pDeviceList->IsExtensionSupported(i, "EAX3.0") - || pDeviceList->IsExtensionSupported(i, "EAX4.0") - || pDeviceList->IsExtensionSupported(i, "EAX5.0") ) + || pDeviceList->IsExtensionSupported(i, ADEXT_EAX2) + || pDeviceList->IsExtensionSupported(i, ADEXT_EAX3) + || pDeviceList->IsExtensionSupported(i, ADEXT_EAX4) + || pDeviceList->IsExtensionSupported(i, ADEXT_EAX5) ) { if ( n < MAXPROVIDERS ) { From 4870d9a31be6302037eb7ddcf0b99ea25ebccabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 24 May 2020 02:59:30 +0300 Subject: [PATCH 117/148] Menu borders and weapon fixes --- src/core/Cam.cpp | 4 +- src/core/Camera.cpp | 14 +- src/core/Frontend.cpp | 409 ++++++++++++++++++++++++------------ src/core/Frontend.h | 50 ++++- src/core/Game.cpp | 19 +- src/core/main.cpp | 28 +-- src/peds/PlayerPed.cpp | 29 ++- src/render/Draw.cpp | 29 ++- src/render/Draw.h | 6 +- src/render/Font.h | 2 +- src/render/Sprite2d.cpp | 15 +- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Boat.cpp | 2 +- 13 files changed, 384 insertions(+), 225 deletions(-) diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 24d32511..d465fb5d 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -1596,7 +1596,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient CWorld::pIgnoreEntity = nil; float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); - float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV; + float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV; float Near = RwCameraGetNearClipPlane(Scene.camera); float radius = ViewPlaneWidth*Near; entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false); @@ -4574,7 +4574,7 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient CWorld::pIgnoreEntity = nil; float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); - float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV; + float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV; float Near = RwCameraGetNearClipPlane(Scene.camera); float radius = ViewPlaneWidth*Near; entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false); diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 486c2c9e..3b7bdbaf 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -3117,15 +3117,6 @@ CCamera::Fade(float timeout, int16 direction) m_iMusicFadingDirection = direction; m_fTimeToFadeMusic = timeout; m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds(); -// Not on PS2 - if(!m_bJustJumpedOutOf1stPersonBecauseOfTarget && m_iMusicFadingDirection == FADE_OUT){ - unknown++; - if(unknown >= 2){ - m_bJustJumpedOutOf1stPersonBecauseOfTarget = true; - unknown = 0; - }else - m_bMoveCamToAvoidGeom = true; - } } } @@ -3314,8 +3305,9 @@ CCamera::CalculateDerivedValues(void) // left plane m_vecFrustumNormals[1] = CVector(-c, -s, 0.0f); - c /= CDraw::FindAspectRatio(); - s /= CDraw::FindAspectRatio(); + CDraw::CalculateAspectRatio(); + c /= SCREEN_ASPECT_RATIO; + s /= SCREEN_ASPECT_RATIO; // bottom plane m_vecFrustumNormals[2] = CVector(0.0f, -s, -c); // top plane diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index a9229c1c..60a17aee 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -37,6 +37,9 @@ #include "Messages.h" #include "FileLoader.h" +// TODO(Miami): This is -3 on VC but still -1 on AudioManager?!? What the hell? +#define INVALID_AUDIO_PROVIDER -1 + // Similar story to Hud.cpp: // Game has colors inlined in code. // For easier modification we collect them here: @@ -178,43 +181,6 @@ ScaleAndCenterX(float x) #define MENU_Y(y) StretchY(y) #endif -#ifdef PS2_LIKE_MENU -#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \ - do { \ - if (reverseAlpha) { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = pendingScreen; \ - m_nCurrOption = pendingOption; \ - reverseAlpha = false; \ - if (updateDelay) \ - m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); \ - } \ - if (withReverseAlpha) { \ - pendingOption = option; \ - pendingScreen = screen; \ - reverseAlpha = true; \ - } else { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = screen; \ - m_nCurrOption = option; \ - if (updateDelay) \ - m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); \ - } \ - m_nMenuFadeAlpha = 255; \ - } while(0) -#else -#define ChangeScreen(screen, option, updateDelay, clearAlpha) \ - do { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = screen; \ - m_nCurrOption = option; \ - if(updateDelay) \ - m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); \ - if(clearAlpha) \ - m_nMenuFadeAlpha = 0; \ - } while(0) -#endif - #define PREPARE_MENU_HEADER \ CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \ CFont::SetRightJustifyOn(); \ @@ -248,6 +214,76 @@ ScaleAndCenterX(float x) // --- Functions not in the game/inlined starts +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +void DoRWStuffEndOfFrame(void); + +#ifdef PS2_LIKE_MENU +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + if (reverseAlpha) { + m_nPrevScreen = m_nCurrScreen; + m_nCurrScreen = pendingScreen; + m_nCurrOption = pendingOption; + reverseAlpha = false; + if (updateDelay) + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); + } + if (withReverseAlpha) { + pendingOption = option; + pendingScreen = screen; + reverseAlpha = true; + } else { + m_nPrevScreen = m_nCurrScreen; + m_nCurrScreen = screen; + m_nCurrOption = option; + if (updateDelay) + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); + } + m_nMenuFadeAlpha = 255; +} +#else + +// --MIAMI: Done except using VC's gMenuPages +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + bMenuChangeOngoing = true; + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + m_nPrevScreen = m_nCurrScreen; + m_ShowEmptyBindingError = false; + ResetHelperText(); + + ThingsToDoBeforeLeavingPage(); + + if (screen == -2) { + int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; + int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : + (m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry[0]))); + + m_nCurrOption = oldOption; + m_nCurrScreen = oldScreen; + } else if (screen == 0) { + m_nCurrScreen = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu; + m_nCurrOption = 0; + } else { + m_nCurrOption = 0; + m_nCurrScreen = screen; + } + + if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) + m_nCurrOption = 8; + m_nMenuFadeAlpha = 0; + bOptionHighlightTransitionBlend = 0; + m_LastScreenSwitch = CTimer::GetTimeInMilliseconds(); +} +#endif + inline void CMenuManager::ScrollUpListByOne() { @@ -314,13 +350,14 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) } } +// TODO(Miami) inline void CMenuManager::ThingsToDoBeforeLeavingPage() { if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - if (m_nPrefsAudio3DProviderIndex != -1) + if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); #ifdef TIDY_UP_PBP DMAudio.StopFrontEndTrack(); @@ -381,7 +418,7 @@ CMenuManager::CMenuManager() OS_Language = LANG_ENGLISH; m_ControlMethod = CONTROL_STANDARD; CCamera::m_bUseMouse3rdPerson = true; - m_3DProviderOnLastSaveLoad = 0; + m_lastWorking3DAudioProvider = 0; m_nFirstVisibleRowOnList = 0; m_nScrollbarTopMargin = 0.0f; m_nSelectedListRow = 0; @@ -421,9 +458,6 @@ CMenuManager::SetFrontEndRenderStates(void) RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); } -bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); -void DoRWStuffEndOfFrame(void); - void CMenuManager::Initialise(void) { @@ -762,11 +796,6 @@ CMenuManager::DrawStandardMenus() case MENUPAGE_BRIEFS: PrintBriefs(); break; -#ifdef MENU_MAP - case MENUPAGE_MAP: - PrintMap(); - break; -#endif } // Header height isn't accounted, we will add that later. @@ -1079,7 +1108,7 @@ CMenuManager::DrawStandardMenus() break; #endif case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex == -1) + if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) rightText = TheText.Get("FEA_NAH"); else { char *provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); @@ -1094,7 +1123,7 @@ CMenuManager::DrawStandardMenus() } break; case MENUACTION_SPEAKERCONF: { - if (m_nPrefsAudio3DProviderIndex == -1) + if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) rightText = TheText.Get("FEA_NAH"); else { switch (m_PrefsSpeakers) { @@ -1233,7 +1262,7 @@ CMenuManager::DrawStandardMenus() } if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 - && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != -1) { + && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); SetHelperText(3); @@ -2005,10 +2034,7 @@ CMenuManager::DrawFrontEnd() if (m_menuTransitionProgress == 255 && m_nMenuFadeAlpha == 255) bMenuChangeOngoing = false; - DrawBackground(); - - // TODO(Miami): Delete dis - PrintErrorMessage(); + DrawBackground(false); } #ifdef PS2_LIKE_MENU @@ -2204,8 +2230,10 @@ CMenuManager::DrawBackground() } } #else + +// --MIAMI: Done except commented things void -CMenuManager::DrawBackground() +CMenuManager::DrawBackground(bool transitionCall) { if (!m_bSpritesLoaded) return; @@ -2216,34 +2244,174 @@ CMenuManager::DrawBackground() CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } + if (m_nMenuFadeAlpha != 0) { - if (m_nMenuFadeAlpha < 255) { + if (m_nMenuFadeAlpha < 255) { - // Famous transparent menu bug -#ifdef FIX_BUGS - static float fadeAlpha = 0.0f; - if (m_nMenuFadeAlpha == 0 && fadeAlpha > 1.0f) fadeAlpha = 0.0f; + menuBg.Translate(m_nMenuFadeAlpha); + SetFrontEndRenderStates(); + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_MAP) + PrintMap(); - // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) - fadeAlpha += (frameTime) * 20.f / 33.f; - m_nMenuFadeAlpha = fadeAlpha; - m_menuTransitionProgress = clamp(fadeAlpha, 0, 255); -#else - static uint32 LastFade = 0; + // Left border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT, + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); - if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ - m_nMenuFadeAlpha += 20; - LastFade = CTimer::GetTimeInMillisecondsPauseMode(); + // Top border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Bottom border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255)); + + // Right border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255)); + } else { + m_nMenuFadeAlpha = 255; + m_menuTransitionProgress = 255; + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_MAP) + PrintMap(); + + // Left border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT, + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Top border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Bottom border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255)); + + // Right border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255)); } -#endif } else { - m_nMenuFadeAlpha = 255; - m_menuTransitionProgress = 255; + menuBg.SaveCurrentCoors(); + switch (m_nCurrScreen) { + case MENUPAGE_STATS: + menuBg.topLeft_x = 70.0f; + menuBg.topLeft_y = 75.0f; + menuBg.topRight_x = 550.0f; + menuBg.topRight_y = 16.0f; + menuBg.bottomLeft_x = 74.0f; + menuBg.bottomLeft_y = 354.0f; + menuBg.bottomRight_x = 581.0f; + menuBg.bottomRight_y = 340.0f; + break; + case MENUPAGE_SOUND_SETTINGS: + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 438.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 410.0f; + break; + case MENUPAGE_SKIN_SELECT: + case MENUPAGE_KEYBOARD_CONTROLS: + menuBg.topLeft_x = 14.0f; + menuBg.topLeft_y = 39.0f; + menuBg.topRight_x = 636.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 630.0f; + menuBg.bottomRight_y = 398.0f; + break; + case MENUPAGE_BRIEFS: + case MENUPAGE_GRAPHICS_SETTINGS: + case MENUPAGE_MAP: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + case MENUPAGE_MOUSE_CONTROLS: + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 398.0f; + break; + default: + menuBg.topLeft_x = CGeneral::GetRandomNumber() % 40 + 65; + menuBg.topLeft_y = CGeneral::GetRandomNumber() % 40 + 21; + menuBg.topRight_x = CGeneral::GetRandomNumber() % 40 + 568; + menuBg.topRight_y = CGeneral::GetRandomNumber() % 40 + 44; + menuBg.bottomLeft_x = CGeneral::GetRandomNumber() % 40 + 36; + menuBg.bottomLeft_y = CGeneral::GetRandomNumber() % 40 + 382; + menuBg.bottomRight_x = CGeneral::GetRandomNumber() % 40 + 593; + menuBg.bottomRight_y = CGeneral::GetRandomNumber() % 40 + 342; + break; + } + + menuBg.UpdateMultipliers(); + if (m_menuTransitionProgress == 255) + bOptionHighlightTransitionBlend = 0; } - m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + // Congrats R*, instead of solving the bug you just hacked your million dolar product. +#if 0 - SetFrontEndRenderStates(); + // This is how I fixed it in III, but I can't apply it here because "forceFadeInCounter > 30" gives it a unique effect. + static float fadeAlpha = 0.0f; + if (m_nMenuFadeAlpha == 0 && fadeAlpha > 1.0f) fadeAlpha = 0.0f; + + // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) + fadeAlpha += (frameTime) * 20.f / 33.f; + m_nMenuFadeAlpha = clamp(fadeAlpha, 0, 255); + m_menuTransitionProgress = clamp(fadeAlpha, 0, 255); +#else + static uint32 LastFade = 0; + static uint8 forceFadeInCounter = 0; + + if (m_nMenuFadeAlpha >= 255) { + if (m_nMenuFadeAlpha > 255) + m_nMenuFadeAlpha = 255; + } else { + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 30 || forceFadeInCounter > 30) { + m_nMenuFadeAlpha += 20; + m_menuTransitionProgress = Min(m_menuTransitionProgress + 20, 255); + LastFade = CTimer::GetTimeInMillisecondsPauseMode(); + } + forceFadeInCounter++; + } +#endif + + if (!transitionCall && m_menuTransitionProgress == 255) { + float oldAlpha = m_nMenuFadeAlpha; + if (oldAlpha < 255) { + int oldScreen = m_nCurrScreen; + SetFrontEndRenderStates(); + m_nCurrScreen = m_nPrevScreen; + m_nMenuFadeAlpha = 255 - m_nMenuFadeAlpha; + switch (m_nCurrScreen) { + case MENUPAGE_SKIN_SELECT: + CMenuManager::DrawPlayerSetupScreen(); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + CMenuManager::DrawControllerSetupScreen(); + break; + /* case MENUPAGE_OUTRO: + CMenuManager::DrawQuitGameScreen(); + break; */ // TODO(Miami) + default: + CMenuManager::DrawStandardMenus(); + break; + } + m_nCurrScreen = oldScreen; + m_nMenuFadeAlpha = oldAlpha; + } + } switch (m_nCurrScreen) { case MENUPAGE_SKIN_SELECT: @@ -2252,20 +2420,24 @@ CMenuManager::DrawBackground() case MENUPAGE_KEYBOARD_CONTROLS: DrawControllerSetupScreen(); break; + /* case MENUPAGE_OUTRO: + CMenuManager::DrawQuitGameScreen(); + break; */ // TODO(Miami) default: DrawStandardMenus(); break; } CFont::DrawFonts(); - SetFrontEndRenderStates(); - if (m_menuTransitionProgress == 255) { - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); - } else { - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); - } +// TODO(Miami) +// if (m_nCurrScreen != MENUPAGE_OUTRO) + if (m_menuTransitionProgress == 255) { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); + } else { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); + } if (m_bShowMouse) { CRect mouse(0.0f, 0.0f, MENU_X(40.0f), MENU_Y(40.0f)); @@ -2936,9 +3108,11 @@ CMenuManager::LoadSettings() m_PrefsVsync = m_PrefsVsyncDisp; CRenderer::ms_lodDistScale = m_PrefsLOD; - if (m_nPrefsAudio3DProviderIndex == -1) + if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = -2; + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; + if (m_PrefsLanguage == prevLang) m_bLanguageLoaded = false; else { @@ -3021,6 +3195,7 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); #endif } + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; CFileMgr::CloseFile(fileHandle); CFileMgr::SetDir(""); @@ -3109,30 +3284,6 @@ CMenuManager::PrintBriefs() #endif } -// Not sure about name. Not to be confused with CPad::PrintErrorMessage -void -CMenuManager::PrintErrorMessage() -{ - if (!CPad::bDisplayNoControllerMessage && !CPad::bObsoleteControllerMessage) - return; - - CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(140.0f), SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f)), CRGBA(64, 16, 16, 224)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetBackgroundOff(); - CFont::SetPropOn(); - CFont::SetCentreOff(); - CFont::SetJustifyOn(); - CFont::SetRightJustifyOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f)); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(180.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); -#else - CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(40.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); -#endif - CFont::DrawFonts(); -} - void CMenuManager::PrintStats() { @@ -3224,6 +3375,7 @@ CMenuManager::PrintStats() CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); } +// --MIAMI: Done void CMenuManager::Process(void) { @@ -4022,10 +4174,7 @@ CMenuManager::ProcessButtonPresses(void) CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); } else { - if (!m_bGameNotLoaded) - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - else - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); + SwitchToNewScreen(-2); } } else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; @@ -4125,11 +4274,7 @@ CMenuManager::ProcessButtonPresses(void) if (changeMenu) { if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0) { #ifndef TIDY_UP_PBP - ResetHelperText(); - if (!m_bGameNotLoaded) - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); - else - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[0], aScreens[m_nCurrScreen].m_ParentEntry[0], true, true); + RequestFrontEndShutDown(); #else goBack = true; break; @@ -4141,7 +4286,7 @@ CMenuManager::ProcessButtonPresses(void) } #endif - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + SwitchToNewScreen(0); } } break; @@ -4153,7 +4298,7 @@ CMenuManager::ProcessButtonPresses(void) if (saveSlot >= 2 && saveSlot <= 9) { m_nCurrSaveSlot = saveSlot - 2; if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY && Slots[m_nCurrSaveSlot + 1] != SLOT_CORRUPTED) { - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); + SwitchToNewScreen(0); } } break; @@ -4176,7 +4321,7 @@ CMenuManager::ProcessButtonPresses(void) RequestFrontEndShutDown(); break; case MENUACTION_REDEFCTRL: - ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); + SwitchToNewScreen(MENUPAGE_KEYBOARD_CONTROLS); m_nSelectedListRow = 0; m_nCurrExLayer = HOVEROPTION_LIST; break; @@ -4202,7 +4347,7 @@ CMenuManager::ProcessButtonPresses(void) #endif break; case MENUACTION_DONTCANCEL: - ChangeScreen(aScreens[m_nCurrScreen].m_PreviousPage[1], aScreens[m_nCurrScreen].m_ParentEntry[1], true, true); + SwitchToNewScreen(-2); break; case MENUACTION_SCREENRES: if (m_nDisplayVideoMode != m_nPrefsVideoMode) { @@ -4231,7 +4376,7 @@ CMenuManager::ProcessButtonPresses(void) case MENUACTION_AUDIOHW: { int selectedProvider = m_nPrefsAudio3DProviderIndex; - if (selectedProvider != -1) { + if (selectedProvider != INVALID_AUDIO_PROVIDER) { m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); if (selectedProvider == m_nPrefsAudio3DProviderIndex) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); @@ -4246,7 +4391,7 @@ CMenuManager::ProcessButtonPresses(void) } case MENUACTION_SPEAKERCONF: #ifndef TIDY_UP_PBP - if (m_nPrefsAudio3DProviderIndex != -1) { + if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { if (--m_PrefsSpeakers < 0) m_PrefsSpeakers = 2; DMAudio.SetSpeakerConfig(m_PrefsSpeakers); @@ -4258,7 +4403,7 @@ CMenuManager::ProcessButtonPresses(void) break; case MENUACTION_PLAYERSETUP: CPlayerSkin::BeginFrontendSkinEdit(); - ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); + SwitchToNewScreen(MENUPAGE_SKIN_SELECT); m_nCurrExLayer = HOVEROPTION_LIST; m_bSkinsEnumerated = false; break; @@ -4339,7 +4484,7 @@ CMenuManager::ProcessButtonPresses(void) #endif break; case MENUACTION_LOADRADIO: - ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); + SwitchToNewScreen(MENUPAGE_SOUND_SETTINGS); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); break; @@ -4384,7 +4529,6 @@ CMenuManager::ProcessButtonPresses(void) #endif int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; - int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; if (oldScreen != -1) { ThingsToDoBeforeLeavingPage(); @@ -4396,7 +4540,7 @@ CMenuManager::ProcessButtonPresses(void) } else #endif { - ChangeScreen(oldScreen, oldOption, true, true); + SwitchToNewScreen(-2); } // We will go back for sure at this point, why process other things?! @@ -4523,14 +4667,14 @@ CMenuManager::ProcessButtonPresses(void) break; #endif case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex != -1) { + if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { m_nPrefsAudio3DProviderIndex += changeValueBy; m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); break; case MENUACTION_SPEAKERCONF: - if (m_nPrefsAudio3DProviderIndex != -1) { + if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { m_PrefsSpeakers -= changeValueBy; m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); DMAudio.SetSpeakerConfig(m_PrefsSpeakers); @@ -4679,20 +4823,20 @@ CMenuManager::SaveLoadFileError_SetUpErrorScreen() case SAVESTATUS_ERR_SAVE_CREATE: case SAVESTATUS_ERR_SAVE_WRITE: case SAVESTATUS_ERR_SAVE_CLOSE: - ChangeScreen(MENUPAGE_SAVE_FAILED, 0, true, false); + SwitchToNewScreen(MENUPAGE_SAVE_FAILED); break; case SAVESTATUS_ERR_LOAD_OPEN: case SAVESTATUS_ERR_LOAD_READ: case SAVESTATUS_ERR_LOAD_CLOSE: - ChangeScreen(MENUPAGE_LOAD_FAILED, 0, true, false); + SwitchToNewScreen(MENUPAGE_LOAD_FAILED); break; case SAVESTATUS_ERR_DATA_INVALID: - ChangeScreen(MENUPAGE_LOAD_FAILED_2, 0, true, false); + SwitchToNewScreen(MENUPAGE_LOAD_FAILED_2); break; case SAVESTATUS_DELETEFAILED8: case SAVESTATUS_DELETEFAILED9: case SAVESTATUS_DELETEFAILED10: - ChangeScreen(MENUPAGE_DELETE_FAILED, 0, true, false); + SwitchToNewScreen(MENUPAGE_DELETE_FAILED); break; default: break; } @@ -4736,7 +4880,7 @@ CMenuManager::ProcessFileActions() } if (SlotPopulated) - ChangeScreen(MENUPAGE_DELETE_SUCCESS, 0, true, false); + SwitchToNewScreen(MENUPAGE_DELETE_SUCCESS); else SaveLoadFileError_SetUpErrorScreen(); } @@ -4744,7 +4888,7 @@ CMenuManager::ProcessFileActions() int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); PcSaveHelper.PopulateSlotInfo(); if (SaveSlot) - ChangeScreen(MENUPAGE_SAVE_SUCCESSFUL, 0, true, false); + SwitchToNewScreen(MENUPAGE_SAVE_SUCCESSFUL); else SaveLoadFileError_SetUpErrorScreen(); } @@ -4758,6 +4902,7 @@ CMenuManager::ProcessFileActions() } } +// --MIAMI: Done except DxInput things, are they even needed? void CMenuManager::SwitchMenuOnAndOff() { diff --git a/src/core/Frontend.h b/src/core/Frontend.h index ca77d448..e40efeea 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -433,10 +433,10 @@ struct CMenuScreen struct MenuTrapezoid { - float topRight_x; - float topRight_y; float topLeft_x; float topLeft_y; + float topRight_x; + float topRight_y; float bottomLeft_x; float bottomLeft_y; float bottomRight_x; @@ -459,15 +459,48 @@ struct MenuTrapezoid float mult_bottomRight_y; MenuTrapezoid(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { - topRight_x = x1; - topRight_y = y1; - topLeft_x = x2; - topLeft_y = y2; + topLeft_x = x1; + topLeft_y = y1; + topRight_x = x2; + topRight_y = y2; bottomLeft_x = x3; bottomLeft_y = y3; bottomRight_x = x4; bottomRight_y = y4; }; + + void SaveCurrentCoors() { + old_topLeft_x = topLeft_x; + old_topLeft_y = topLeft_y; + old_topRight_x = topRight_x; + old_topRight_y = topRight_y; + old_bottomLeft_x = bottomLeft_x; + old_bottomLeft_y = bottomLeft_y; + old_bottomRight_x = bottomRight_x; + old_bottomRight_y = bottomRight_y; + } + + void Translate(int delta) { + bottomRight_x = delta * mult_bottomRight_x + old_bottomRight_x; + bottomRight_y = delta * mult_bottomRight_y + old_bottomRight_y; + bottomLeft_x = delta * mult_bottomLeft_x + old_bottomLeft_x; + bottomLeft_y = delta * mult_bottomLeft_y + old_bottomLeft_y; + topRight_x = delta * mult_topRight_x + old_topRight_x; + topRight_y = delta * mult_topRight_y + old_topRight_y; + topLeft_x = delta * mult_topLeft_x + old_topLeft_x; + topLeft_y = delta * mult_topLeft_y + old_topLeft_y; + } + + void UpdateMultipliers() { + mult_bottomRight_x = (bottomRight_x - old_bottomRight_x) / 255.0f; + mult_bottomRight_y = (bottomRight_y - old_bottomRight_y) / 255.0f; + mult_bottomLeft_x = (bottomLeft_x - old_bottomLeft_x) / 255.0f; + mult_bottomLeft_y = (bottomLeft_y - old_bottomLeft_y) / 255.0f; + mult_topRight_x = (topRight_x - old_topRight_x) / 255.0f; + mult_topRight_y = (topRight_y - old_topRight_y) / 255.0f; + mult_topLeft_x = (topLeft_x - old_topLeft_x) / 255.0f; + mult_topLeft_y = (topLeft_y - old_topLeft_y) / 255.0f; + } }; class CMenuManager @@ -523,7 +556,7 @@ public: int32 m_nMouseTempPosX; int32 m_nMouseTempPosY; bool m_bGameNotLoaded; - int8 m_3DProviderOnLastSaveLoad; + int8 m_lastWorking3DAudioProvider; bool m_bFrontEnd_ReloadObrTxtGxt; int32 *pEditString; uint8 field_74[4]; @@ -625,7 +658,7 @@ public: void DrawControllerScreenExtraText(int, int, int); void DrawControllerSetupScreen(); void DrawFrontEnd(); - void DrawBackground(); + void DrawBackground(bool transitionCall); void DrawPlayerSetupScreen(); int FadeIn(int alpha); void FilterOutColorMarkersFromString(wchar*, CRGBA &); @@ -656,6 +689,7 @@ public: void WaitForUserCD(); int GetNumOptionsCntrlConfigScreens(); int ConstructStatLine(int); + void SwitchToNewScreen(int8); // New (not in function or inlined in the game) void ThingsToDoBeforeLeavingPage(); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 437bd5ec..0a4e7d87 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -541,7 +541,14 @@ void CGame::InitialiseWhenRestarting(void) CTimer::Initialise(); CSprite2d::SetRecipNearClip(); - + + if (b_FoundRecentSavedGameWantToLoad || FrontEndMenuManager.m_bWantToLoad) + { + LoadSplash("splash1"); + if (FrontEndMenuManager.m_bWantToLoad) + FrontEndMenuManager.MessageScreen("FELD_WR", true); + } + b_FoundRecentSavedGameWantToLoad = false; TheCamera.Init(); @@ -667,14 +674,8 @@ void CGame::Process(void) void CGame::InitAfterFocusLoss() { - /* - byte_869656 = byte_86969D; - result = cDMAudio::SetCurrent3DProvider(byte_86969D); - if ( !bGameStarted && !bMenuVisible ) - byte_869642 = 1; - */ - - //cDMAudio::SetCurrent3DProvider( ? ? ? ); + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = FrontEndMenuManager.m_lastWorking3DAudioProvider; + DMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_lastWorking3DAudioProvider); if (!FrontEndMenuManager.m_bGameNotLoaded && !FrontEndMenuManager.m_bMenuActive) FrontEndMenuManager.m_bStartUpFrontEndRequested = true; diff --git a/src/core/main.cpp b/src/core/main.cpp index 28ce73b8..aefabfc7 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -137,9 +137,10 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR CRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha); CRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha); + CDraw::CalculateAspectRatio(); CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); CVisibilityPlugins::SetRenderWareCamera(Scene.camera); - RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ); + RwCameraClear(Scene.camera, &TopColor.rwRGBA, rwCAMERACLEARZ); if(!RsCameraBeginUpdate(Scene.camera)) return false; @@ -155,6 +156,7 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha) { + CDraw::CalculateAspectRatio(); CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ); @@ -948,15 +950,12 @@ Render2dStuffAfterFade(void) CHud::DrawAfterFade(); CFont::DrawFonts(); + CCredits::Render(); } void Idle(void *arg) { -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif - CTimer::Update(); #ifdef TIMEBARS @@ -1062,6 +1061,7 @@ Idle(void *arg) tbEndTimer("Render2dStuff"); #endif }else{ + CDraw::CalculateAspectRatio(); #ifdef ASPECT_RATIO_SCALE CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); #else @@ -1090,7 +1090,7 @@ Idle(void *arg) #ifdef TIMEBARS tbEndTimer("Render2dStuff-Fade"); #endif - CCredits::Render(); + // CCredits::Render(); // They added it to function above and also forgot it here #ifdef TIMEBARS tbDisplay(); @@ -1105,10 +1105,7 @@ Idle(void *arg) void FrontendIdle(void) { -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif - + CDraw::CalculateAspectRatio(); CTimer::Update(); CSprite2d::SetRecipNearClip(); // this should be on InitialiseRenderWare according to PS2 asm. seems like a bug fix CSprite2d::InitPerFrame(); @@ -1119,11 +1116,7 @@ FrontendIdle(void) if(RsGlobal.quit) return; -#ifdef ASPECT_RATIO_SCALE CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); -#else - CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO); -#endif CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ); if(!RsCameraBeginUpdate(Scene.camera)) @@ -1133,7 +1126,7 @@ FrontendIdle(void) RenderMenus(); DoFade(); Render2dStuffAfterFade(); -// CFont::DrawFonts(); // redundant + CFont::DrawFonts(); DoRWStuffEndOfFrame(); } @@ -1239,9 +1232,8 @@ TheModelViewer(void) #if (defined(GTA_PS2) || defined(GTA_XBOX)) //TODO #else -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif + + CDraw::CalculateAspectRatio(); CAnimViewer::Update(); CTimer::Update(); SetLightsWithTimeOfDayColour(Scene.world); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index bbdf57ed..37a0b191 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -680,7 +680,7 @@ CPlayerPed::ProcessWeaponSwitch(CPad *padUsed) spentAmmoCheck: if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_eWeaponFire != WEAPON_FIRE_MELEE - /*&& (!padUsed->GetWeapon() || GetWeapon()->m_eWeaponType != WEAPONTYPE_MINIGUN) */) { + && (!padUsed->GetWeapon() || GetWeapon()->m_eWeaponType != WEAPONTYPE_MINIGUN)) { if (GetWeapon()->m_nAmmoTotal <= 0) { if (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER @@ -1019,8 +1019,8 @@ CPlayerPed::ProcessAnimGroups(void) if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETLEFT; else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || - GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER - /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/ ) + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) groupToSet = ASSOCGRP_CHAINSAWLEFT; else groupToSet = ASSOCGRP_PLAYERLEFT; @@ -1028,8 +1028,8 @@ CPlayerPed::ProcessAnimGroups(void) if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETRIGHT; else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || - GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER - /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/) + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) groupToSet = ASSOCGRP_CHAINSAWRIGHT; else groupToSet = ASSOCGRP_PLAYERRIGHT; @@ -1038,8 +1038,8 @@ CPlayerPed::ProcessAnimGroups(void) if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) groupToSet = ASSOCGRP_ROCKETBACK; else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || - GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER - /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/) + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) groupToSet = ASSOCGRP_CHAINSAWBACK; else groupToSet = ASSOCGRP_PLAYERBACK; @@ -1052,16 +1052,15 @@ CPlayerPed::ProcessAnimGroups(void) || GetWeapon()->m_eWeaponType == WEAPONTYPE_MACHETE) groupToSet = ASSOCGRP_PLAYERBBBAT; else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW || - GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER - /* || GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN*/) + GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) groupToSet = ASSOCGRP_PLAYERCHAINSAW; else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI - // I hope this was inlined... - /* - && GetWeapon()->m_eWeaponType != WEAPONTYPE_PYTHON*/ && GetWeapon()->m_eWeaponType != WEAPONTYPE_TEC9 + // I hope this is a inlined function... + && GetWeapon()->m_eWeaponType != WEAPONTYPE_PYTHON && GetWeapon()->m_eWeaponType != WEAPONTYPE_TEC9 && GetWeapon()->m_eWeaponType != WEAPONTYPE_SILENCED_INGRAM && GetWeapon()->m_eWeaponType != WEAPONTYPE_MP5 && GetWeapon()->m_eWeaponType != WEAPONTYPE_GOLFCLUB && GetWeapon()->m_eWeaponType != WEAPONTYPE_KATANA - /* && GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA */) { + && GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA) { if (!GetWeapon()->IsType2Handed()) { groupToSet = ASSOCGRP_PLAYER; } else { @@ -1093,7 +1092,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M4 || GetWeapon()->m_eWeaponType == WEAPONTYPE_RUGER) { - if (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) { + if (padUsed->TargetJustDown()/* || TheCamera.m_bAllow1rstPersonWeaponsCamera */) { // TODO(Miami): Cam SetStoredState(); m_nPedState = PED_SNIPER_MODE; #ifdef FREE_CAM @@ -1240,7 +1239,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) #else else if (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson) { #endif - if (padUsed->TargetJustDown()) + if (padUsed->TargetJustDown()/* || TheCamera.m_bAllow1rstPersonWeaponsCamera */) // TODO(Miami): Cam FindWeaponLockOnTarget(); } } else if (m_pPointGunAt) { diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index b31cc624..e2dfc8d9 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -19,24 +19,23 @@ uint8 CDraw::FadeGreen; uint8 CDraw::FadeBlue; float -CDraw::FindAspectRatio(void) +CDraw::CalculateAspectRatio(void) { -#ifndef ASPECT_RATIO_SCALE - if(FrontEndMenuManager.m_PrefsUseWideScreen) - return 16.0f/9.0f; - else - return 4.0f/3.0f; + if (FrontEndMenuManager.m_PrefsUseWideScreen) { + if (TheCamera.m_WideScreenOn) + CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki + else +#ifdef ASPECT_RATIO_SCALE + CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? SCREEN_WIDTH / SCREEN_HEIGHT : 16.f / 9.f; #else - switch (FrontEndMenuManager.m_PrefsUseWideScreen) { - case AR_AUTO: - return SCREEN_WIDTH / SCREEN_HEIGHT; - default: - case AR_4_3: - return 4.0f / 3.0f; - case AR_16_9: - return 16.0f / 9.0f; - }; + CDraw::ms_fAspectRatio = 16.f / 9.f; #endif + } else if (TheCamera.m_WideScreenOn) { + CDraw::ms_fAspectRatio = 5.f/4.f; + } else { + CDraw::ms_fAspectRatio = 4.f/3.f; + } + return CDraw::ms_fAspectRatio; } #ifdef ASPECT_RATIO_SCALE diff --git a/src/render/Draw.h b/src/render/Draw.h index 55958a2a..46e85e49 100644 --- a/src/render/Draw.h +++ b/src/render/Draw.h @@ -38,12 +38,10 @@ public: static void SetFOV(float fov); static float GetFOV(void) { return ms_fFOV; } - static float FindAspectRatio(void); + static float CalculateAspectRatio(void); #ifdef ASPECT_RATIO_SCALE static float ConvertFOV(float fov); +#endif static float GetAspectRatio(void) { return ms_fAspectRatio; } static void SetAspectRatio(float ratio) { ms_fAspectRatio = ratio; } -#else - static float GetAspectRatio(void) { return FindAspectRatio(); } -#endif }; diff --git a/src/render/Font.h b/src/render/Font.h index 9b4e7132..48f5703d 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -68,8 +68,8 @@ class CFont static int16 Size[MAX_FONTS][193]; #endif static int16 NewLine; - static CSprite2d Sprite[MAX_FONTS]; public: + static CSprite2d Sprite[MAX_FONTS]; static CFontDetails Details; static void Initialise(void); diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 189c9797..2675c95f 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -4,11 +4,11 @@ #include "Draw.h" #include "Camera.h" #include "Sprite2d.h" +#include "Font.h" RwIm2DVertex CSprite2d::maVertices[8]; float CSprite2d::RecipNearClip; int32 CSprite2d::mCurrentBank; -RwTexture *CSprite2d::mpBankTextures[10]; int32 CSprite2d::mCurrentSprite[10]; int32 CSprite2d::mBankStart[10]; RwIm2DVertex CSprite2d::maBankVertices[500]; @@ -16,7 +16,7 @@ RwIm2DVertex CSprite2d::maBankVertices[500]; void CSprite2d::SetRecipNearClip(void) { - RecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera); + // Used but empty in VC, instead they set in InitPerFrame. Isn't that great? } void @@ -24,17 +24,15 @@ CSprite2d::InitPerFrame(void) { int i; + RecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera); mCurrentBank = 0; for(i = 0; i < 10; i++) mCurrentSprite[i] = 0; - for(i = 0; i < 10; i++) - mpBankTextures[i] = nil; } int32 CSprite2d::GetBank(int32 n, RwTexture *tex) { - mpBankTextures[mCurrentBank] = tex; mCurrentSprite[mCurrentBank] = 0; mBankStart[mCurrentBank+1] = mBankStart[mCurrentBank] + n; return mCurrentBank++; @@ -59,13 +57,14 @@ CSprite2d::DrawBank(int32 bank) { if(mCurrentSprite[bank] == 0) return; - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, - mpBankTextures[bank] ? RwTextureGetRaster(mpBankTextures[bank]) : nil); + + // This is hacked III function to make it work with VC frontend. + CFont::Sprite[bank].SetRenderState(); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, &maBankVertices[6*mBankStart[bank]], 6*mCurrentSprite[bank]); mCurrentSprite[bank] = 0; - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + //RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); } diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index e260df93..dc406237 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -3030,7 +3030,7 @@ CAutomobile::ProcessBuoyancy(void) void CAutomobile::DoDriveByShootings(void) { - CAnimBlendAssociation *anim; + CAnimBlendAssociation *anim = nil; CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); if (playerInfo && !playerInfo->m_bDriveByAllowed) return; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 483aa562..b9d97716 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -930,7 +930,7 @@ CBoat::AddWakePoint(CVector point) void CBoat::DoDriveByShootings(void) { - CAnimBlendAssociation *anim; + CAnimBlendAssociation *anim = nil; CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); if (playerInfo && !playerInfo->m_bDriveByAllowed) return; From e95de89c9a748005d4495c0e7bfd0281ef39cd7c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 24 May 2020 12:01:07 +0300 Subject: [PATCH 118/148] script fix --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 082beda9..406b11b7 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -6212,7 +6212,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) } CCranes::ActivateCrane(infX, supX, infY, supY, *(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8], - DEGTORAD(*(float*)&ScriptParams[8]), true, false, + DEGTORAD(*(float*)&ScriptParams[9]), true, false, *(float*)&ScriptParams[0], *(float*)&ScriptParams[1]); return 0; } From cda37528383cb9802d107fcf8cdb30580010e686 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 24 May 2020 13:48:17 +0300 Subject: [PATCH 119/148] comments --- src/control/CarAI.cpp | 23 ++--------------------- src/control/CarCtrl.cpp | 2 ++ src/control/Curves.cpp | 2 ++ src/control/SetPieces.cpp | 2 +- 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index 589cc53b..121518f4 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -22,19 +22,18 @@ #define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f -//--MIAMI: done +//--MIAMI: file done + float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle) { return pVehicle->AutoPilot.m_nSwitchDistance; } -//--MIAMI: done float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle) { return FindSwitchDistanceClose(pVehicle) + 5.0f; } -//--MIAMI: done float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle) { if (pVehicle->bIsLawEnforcer) @@ -42,7 +41,6 @@ float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle) return FindSwitchDistanceFarNormalVehicle(pVehicle); } -//--MIAMI: done void CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle) { if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer && @@ -56,7 +54,6 @@ void CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::UpdateCarAI(CVehicle* pVehicle) { if (pVehicle->bIsLawEnforcer){ @@ -507,13 +504,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::CarHasReasonToStop(CVehicle* pVehicle) { pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); } -//--MIAMI: done float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget) { if (pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS && pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT){ @@ -531,7 +526,6 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget) return (pVehicle->GetPosition() - *pTarget).Magnitude2D(); } -//--MIAMI: done float CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget) { GetCarToGoToCoors(pVehicle, pTarget); @@ -540,7 +534,6 @@ float CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget) return (pVehicle->GetPosition() - *pTarget).Magnitude2D(); } -//--MIAMI: TODO: MI_VICECHEE void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle) { if (pVehicle->bOccupantsHaveBeenGenerated) @@ -577,21 +570,18 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::AddAmbulanceOccupants(CVehicle* pVehicle) { pVehicle->SetUpDriver(); pVehicle->SetupPassenger(1); } -//--MIAMI: done void CCarAI::AddFiretruckOccupants(CVehicle* pVehicle) { pVehicle->SetUpDriver(); pVehicle->SetupPassenger(0); } -//--MIAMI: done void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle) { if (pVehicle->pDriver){ @@ -609,7 +599,6 @@ void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle) { if (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) { @@ -627,7 +616,6 @@ void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget) { pVehicle->AutoPilot.m_pTargetCar = pTarget; @@ -637,7 +625,6 @@ void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); } -//--MIAMI: done void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) { pVehicle->AutoPilot.m_pTargetCar = pTarget; @@ -647,7 +634,6 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); } -//--MIAMI: done eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){ @@ -662,7 +648,6 @@ eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() } } -//--MIAMI: done eCarMission CCarAI::FindPoliceBoatMissionForWantedLevel() { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) { @@ -677,7 +662,6 @@ eCarMission CCarAI::FindPoliceBoatMissionForWantedLevel() } } -//--MIAMI: done int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle) { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) { @@ -692,7 +676,6 @@ int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle) { if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel == 1){ @@ -737,7 +720,6 @@ void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle) { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) { @@ -751,7 +733,6 @@ void CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle) } } -//--MIAMI: done void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) { float flatSpeed = pVehicle->GetMoveSpeed().Magnitude2D(); diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 5e8324ed..073195a4 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -105,6 +105,8 @@ int32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP]; +//--MIAMI: done except heli/plane functions + void CCarCtrl::GenerateRandomCars() { diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp index 31a2767a..29471608 100644 --- a/src/control/Curves.cpp +++ b/src/control/Curves.cpp @@ -2,6 +2,8 @@ #include "Curves.h" +//--MIAMI: file done + float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float dir1X, float dir1Y, float dir2X, float dir2Y) { CVector2D dir1(dir1X, dir1Y); diff --git a/src/control/SetPieces.cpp b/src/control/SetPieces.cpp index fb2a1f14..9b4e0075 100644 --- a/src/control/SetPieces.cpp +++ b/src/control/SetPieces.cpp @@ -13,7 +13,7 @@ #define TIME_BETWEEN_SETPIECE_SPAWNS 20000 -// MIAMI: file done +//--MIAMI: file done bool CSetPieces::bDebug; uint32 CSetPieces::NumSetPieces; From e248cbcc7d7edb2912dcf3c669c3868ae502d713 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 24 May 2020 14:01:01 +0300 Subject: [PATCH 120/148] say goodbye to your saves --- src/save/GenericGameStorage.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 4eff4fb7..839ad8b9 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -29,6 +29,7 @@ #include "Radar.h" #include "Restart.h" #include "Script.h" +#include "SetPieces.h" #include "Stats.h" #include "Streaming.h" #include "Timer.h" @@ -206,6 +207,7 @@ GenericSave(int file) WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects); WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo); WriteSaveDataBlock(CStats::SaveStats); + WriteSaveDataBlock(CSetPieces::Save); WriteSaveDataBlock(CStreaming::MemoryCardSave); WriteSaveDataBlock(CPedType::Save); @@ -337,6 +339,8 @@ GenericLoad() LoadSaveDataBlock(); ReadDataFromBlock("Loading Stats \n", CStats::LoadStats); LoadSaveDataBlock(); + ReadDataFromBlock("Loading Set Pieces \n", CSetPieces::Load); + LoadSaveDataBlock(); ReadDataFromBlock("Loading Streaming Stuff \n", CStreaming::MemoryCardLoad); LoadSaveDataBlock(); ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load); From 8c510a8d5bf5b68f4e5be69c9c8110991686504e Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 24 May 2020 15:00:45 +0300 Subject: [PATCH 121/148] script fix --- src/control/Script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index e029ad35..cf2545c0 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11364,7 +11364,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_CLEAR_CHAR_FOLLOW_PATH: { CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); if (pPed->GetPedState() == PED_FOLLOW_PATH) { pPed->RestorePreviousState(); @@ -11375,7 +11375,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command) case COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE: { CollectParameters(&m_nIp, 2); - CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); pPed->bCanBeShotInVehicle = ScriptParams[1]; return 0; From 8705562559c37d44f113ad71adf09e4b1ace3523 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 24 May 2020 15:58:25 +0300 Subject: [PATCH 122/148] how did saving even work in original III? --- src/control/Garages.cpp | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index a177343b..615ba77f 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -2119,12 +2119,8 @@ void CGarages::SetAllDoorsBackToOriginalHeight() // TODO(MIAMI) void CGarages::Save(uint8 * buf, uint32 * size) { -#ifdef FIX_GARAGE_SIZE - INITSAVEBUF - *size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); -#else - * size = 5484; -#endif +INITSAVEBUF + *size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + TOTAL_HIDEOUT_GARAGES * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); CloseHideOutGaragesBeforeSave(); WriteSaveBuf(buf, NumGarages); WriteSaveBuf(buf, (uint32)BombsAreFree); @@ -2142,9 +2138,7 @@ void CGarages::Save(uint8 * buf, uint32 * size) } for (int i = 0; i < NUM_GARAGES; i++) WriteSaveBuf(buf, aGarages[i]); -#ifdef FIX_GARAGE_SIZE - VALIDATESAVEBUF(*size); -#endif +VALIDATESAVEBUF(*size); } const CStoredCar &CStoredCar::operator=(const CStoredCar & other) @@ -2169,12 +2163,8 @@ const CStoredCar &CStoredCar::operator=(const CStoredCar & other) //TODO(MIAMI) void CGarages::Load(uint8* buf, uint32 size) { -#ifdef FIX_GARAGE_SIZE - INITSAVEBUF - assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); -#else - assert(size == 5484); -#endif +INITSAVEBUF + assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + TOTAL_HIDEOUT_GARAGES * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage))); CloseHideOutGaragesBeforeSave(); NumGarages = ReadSaveBuf(buf); BombsAreFree = ReadSaveBuf(buf); @@ -2203,9 +2193,7 @@ void CGarages::Load(uint8* buf, uint32 size) else aGarages[i].UpdateDoorsHeight(); } -#ifdef FIX_GARAGE_SIZE - VALIDATESAVEBUF(size); -#endif +VALIDATESAVEBUF(size); MessageEndTime = 0; bCamShouldBeOutisde = false; From 3fdd352ca26c45007c813b7c2c8a5fc5c896cf9d Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 24 May 2020 15:14:56 +0200 Subject: [PATCH 123/148] CVehicle fixes --- src/vehicles/Automobile.cpp | 10 ++-- src/vehicles/Automobile.h | 2 +- src/vehicles/Vehicle.cpp | 94 +++++++++++++++++++------------------ src/vehicles/Vehicle.h | 2 +- 4 files changed, 55 insertions(+), 53 deletions(-) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 2212ddff..9617c9be 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -175,7 +175,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) m_nNumPassengers = 0; m_bombType = CARBOMB_NONE; - bHadDriver = false; + bDriverLastFrame = false; m_pBombRigger = nil; if(m_nDoorLock == CARLOCK_UNLOCKED && @@ -276,7 +276,7 @@ CAutomobile::ProcessControl(void) // Process driver if(pDriver){ - if(!bHadDriver && m_bombType == CARBOMB_ONIGNITIONACTIVE){ + if(!bDriverLastFrame && m_bombType == CARBOMB_ONIGNITIONACTIVE){ // If someone enters the car and there is a bomb, detonate m_nBombTimer = 1000; m_pBlowUpEntity = m_pBombRigger; @@ -284,7 +284,7 @@ CAutomobile::ProcessControl(void) m_pBlowUpEntity->RegisterReference((CEntity**)&m_pBlowUpEntity); DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TICK, 1.0f); } - bHadDriver = true; + bDriverLastFrame = true; if(IsUpsideDown() && CanPedEnterCar()){ if(!pDriver->IsPlayer() && @@ -293,7 +293,7 @@ CAutomobile::ProcessControl(void) pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); } }else - bHadDriver = false; + bDriverLastFrame = false; // Process passengers if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){ @@ -3928,7 +3928,7 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) if(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){ mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM])); - colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF); + colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM])); colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); colModel->numSpheres = 6; diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index a3e8ac17..a2ff2616 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -86,7 +86,7 @@ public: uint8 field_4D8; uint8 m_bombType : 3; uint8 bTaxiLight : 1; - uint8 bHadDriver : 1; // for bombs + uint8 bDriverLastFrame : 1; // for bombs uint8 bFixedColour : 1; uint8 bBigWheels : 1; uint8 bWaterTight : 1; // no damage for non-player peds diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 0dd95faf..d8c7c4c8 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -50,8 +50,8 @@ CVehicle::CVehicle(uint8 CreatedBy) { int i; - m_nCurrentGear = 0; - m_fChangeGearTime = 0; + m_nCurrentGear = 1; + m_fChangeGearTime = 0.0f; m_fSteerRatio = 0.0f; m_type = ENTITY_TYPE_VEHICLE; VehicleCreatedBy = CreatedBy; @@ -280,8 +280,8 @@ CVehicle::FlyingControl(eFlightModel flightModel) float turnSpeed = m_vecTurnSpeed.MagnitudeSqr(); if(turnSpeed > SQR(0.2f)) m_vecTurnSpeed *= 0.2f/Sqrt(turnSpeed); - } break; + } case FLIGHT_MODEL_RCPLANE: case FLIGHT_MODEL_SEAPLANE: @@ -294,76 +294,77 @@ CVehicle::FlyingControl(eFlightModel flightModel) fThrust += 1.0f; else if (fForwSpeed > 0.0f && fThrust < 0.0f) fThrust = 0.0f; - float fThrustImpulse; + float fThrustAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fThrustImpulse = (fThrust - fRCPropFallOff * fForwSpeed) * fRCAeroThrust; + fThrustAccel = (fThrust - fRCPropFallOff * fForwSpeed) * fRCAeroThrust; else - fThrustImpulse = (fThrust - fSeaPropFallOff * fForwSpeed) * fSeaThrust; - ApplyMoveForce(fThrustImpulse * GetForward() * m_fMass * CTimer::GetTimeStep()); + fThrustAccel = (fThrust - fSeaPropFallOff * fForwSpeed) * fSeaThrust; + ApplyMoveForce(fThrustAccel * GetForward() * m_fMass * CTimer::GetTimeStep()); // left/right float fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight()); float fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; - float fSideSlipImpulse; + float fSideSlipAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fRCSideSlipMult; + fSideSlipAccel = Abs(fSideSpeed) * fSideSpeed * fRCSideSlipMult; else - fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fSeaSideSlipMult; - ApplyMoveForce(m_fMass * GetRight() * fSideSlipImpulse * CTimer::GetTimeStep()); + fSideSlipAccel = Abs(fSideSpeed) * fSideSpeed * fSeaSideSlipMult; + ApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep()); - float fYaw = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetRight()); - float fYawImpulse; + float fYaw = -DotProduct(GetSpeed(vecWidthForward), GetRight()); + float fYawAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fYawImpulse = fRCRudderMult * fYaw * Abs(fYaw) + fRCYawMult * fSteerLR * fForwSpeed; + fYawAccel = fRCRudderMult * fYaw * Abs(fYaw) + fRCYawMult * fSteerLR * fForwSpeed; else - fYawImpulse = fSeaRudderMult * fYaw * Abs(fYaw) + fSeaYawMult * fSteerLR * fForwSpeed; - ApplyTurnForce(fYawImpulse * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward); + fYawAccel = fSeaRudderMult * fYaw * Abs(fYaw) + fSeaYawMult * fSteerLR * fForwSpeed; + ApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward); - float fRollImpulse; + float fRollAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) { float fDirectionMultiplier = CPad::GetPad(0)->GetLookRight(); if (CPad::GetPad(0)->GetLookLeft()) fDirectionMultiplier = -1; - fRollImpulse = (0.5f * fDirectionMultiplier + fSteerLR) * fRCRollMult; + fRollAccel = (0.5f * fDirectionMultiplier + fSteerLR) * fRCRollMult; } else - fRollImpulse = fSteerLR * fSeaRollMult; - ApplyTurnForce(GetRight() * fRollImpulse * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); + fRollAccel = fSteerLR * fSeaRollMult; + ApplyTurnForce(GetRight() * fRollAccel * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); CVector vecFRight = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f)); CVector vecStabilise = (GetUp().z > 0.0f) ? vecFRight : -vecFRight; float fStabiliseDirection = (GetRight().z > 0.0f) ? -1.0f : 1.0f; - float fStabiliseImpulse; + float fStabiliseSpeed; if (flightModel == FLIGHT_MODEL_RCPLANE) - fStabiliseImpulse = fRCRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); + fStabiliseSpeed = fRCRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); else - fStabiliseImpulse = fSeaRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); - ApplyTurnForce(fStabiliseImpulse * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? VC doesn't have it too + fStabiliseSpeed = fSeaRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); + ApplyTurnForce(fStabiliseSpeed * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? VC doesn't have it too // up/down - float fTail = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetUp()); + float fTail = -DotProduct(GetSpeed(vecWidthForward), GetUp()); float fSteerUD = -CPad::GetPad(0)->GetSteeringUpDown() / 128.0f; - float fPitchImpulse; + float fPitchAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fPitchImpulse = fRCTailMult * fTail * Abs(fTail) + fRCPitchMult * fSteerUD * fForwSpeed; + fPitchAccel = fRCTailMult * fTail * Abs(fTail) + fRCPitchMult * fSteerUD * fForwSpeed; else - fPitchImpulse = fSeaTailMult * fTail * Abs(fTail) + fSeaPitchMult * fSteerUD * fForwSpeed; - ApplyTurnForce(fPitchImpulse * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward); + fPitchAccel = fSeaTailMult * fTail * Abs(fTail) + fSeaPitchMult * fSteerUD * fForwSpeed; + ApplyTurnForce(fPitchAccel * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward); float fLift = -DotProduct(GetMoveSpeed(), GetUp()) / Max(0.01f, GetMoveSpeed().Magnitude()); - float fLiftImpluse; + float fLiftAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fLiftImpluse = (fRCAttackLiftMult * fLift + fRCFormLiftMult) * fForwSpeed * fForwSpeed; + fLiftAccel = (fRCAttackLiftMult * fLift + fRCFormLiftMult) * fForwSpeed * fForwSpeed; else - fLiftImpluse = (fSeaAttackLiftMult * fLift + fSeaFormLiftMult) * fForwSpeed * fForwSpeed; - float fLiftForce = fLiftImpluse * m_fMass * CTimer::GetTimeStep(); - if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpluse) { + fLiftAccel = (fSeaAttackLiftMult * fLift + fSeaFormLiftMult) * fForwSpeed * fForwSpeed; + float fLiftImpulse = fLiftAccel * m_fMass * CTimer::GetTimeStep(); + if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpulse) { if (flightModel == FLIGHT_MODEL_RCPLANE && GetPosition().z > 50.0f) - fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass; + fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass; else if (flightModel == FLIGHT_MODEL_SEAPLANE && GetPosition().z > 80.0f) - fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass; + fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass; } - ApplyMoveForce(fLiftForce * GetUp()); + ApplyMoveForce(fLiftImpulse * GetUp()); + CVector vecResistance; if (flightModel == FLIGHT_MODEL_RCPLANE) vecResistance = vecRCAeroResistance; @@ -425,10 +426,9 @@ CVehicle::FlyingControl(eFlightModel flightModel) } if (CPad::GetPad(0)->GetHorn()) { fYaw = 0.0f; - fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetUp()), -200.0f, 1.3f); + fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetForward()), -200.0f, 1.3f); fRoll = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f); } - debug("fPitch: %f\n", fPitch); ApplyTurnForce(fPitch * GetUp() * fPitchVar * m_fTurnMass * CTimer::GetTimeStep(), GetForward()); ApplyTurnForce(fRoll * GetUp() * fRollVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); ApplyTurnForce(fYaw * GetForward() * fYawVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); @@ -442,11 +442,11 @@ CVehicle::FlyingControl(eFlightModel flightModel) float rY = Pow(vecResistance.y, CTimer::GetTimeStep()); float rZ = Pow(vecResistance.z, CTimer::GetTimeStep()); CVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); - float fResistanceMultiplier = Pow(1.0f / (fSpinSpeedRes * SQR(vecTurnSpeed.z) + 1.0f), CTimer::GetTimeStep()); + float fResistanceMultiplier = Pow(1.0f / (fSpinSpeedRes * SQR(vecTurnSpeed.z) + 1.0f) * rZ, CTimer::GetTimeStep()); float fResistance = vecTurnSpeed.z * fResistanceMultiplier - vecTurnSpeed.z; vecTurnSpeed.x *= rX; vecTurnSpeed.y *= rY; - vecTurnSpeed.z *= rZ; + vecTurnSpeed.z *= fResistanceMultiplier; m_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed); ApplyTurnForce(-GetRight() * fResistance * m_fTurnMass, GetForward() + Multiply3x3(GetMatrix(), m_vecCentreOfMass)); break; @@ -454,6 +454,9 @@ CVehicle::FlyingControl(eFlightModel flightModel) } } +float fBurstSpeedMax = 0.3f; +float fBurstTyreMod = 0.1f; + void CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus) @@ -494,8 +497,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon #endif if(wheelStatus == WHEEL_STATUS_BURST){ - float fwdspeed = Min(contactSpeedFwd, 0.3f); - right += fwdspeed * CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + float fwdspeed = Min(contactSpeedFwd, fBurstSpeedMax); + right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod); } } @@ -671,7 +674,7 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage break; } } - if (oldHealth > DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { + if (oldHealth >= DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { if (IsCar()) { CAutomobile* pThisCar = (CAutomobile*)this; pThisCar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE); @@ -990,9 +993,8 @@ CVehicle::CanPedOpenLocks(CPed *ped) bool CVehicle::CanPedEnterCar(void) { - CVector up = GetUp(); // can't enter when car is on side - if(up.z > 0.1f || up.z < -0.1f){ + if(GetUp().z > 0.1f || GetUp().z < -0.1f){ // also when car is moving too fast if(m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f)) return false; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 06bdf714..de4d3f88 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -86,8 +86,8 @@ enum CAR_PIECE_WING_LR, CAR_PIECE_WING_RR, CAR_PIECE_WHEEL_LF, - CAR_PIECE_WHEEL_LR, CAR_PIECE_WHEEL_RF, + CAR_PIECE_WHEEL_LR, CAR_PIECE_WHEEL_RR, CAR_PIECE_WINDSCREEN, }; From 14755a4ff4668e2cf2fa580797321141770e3b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 24 May 2020 16:41:29 +0300 Subject: [PATCH 124/148] all my fixes live in exes --- src/core/main.cpp | 10 ++++++++- src/peds/PlayerPed.cpp | 2 +- src/weapons/Weapon.cpp | 48 ++++++++++++++++++++-------------------- src/weapons/Weapon.h | 4 ++-- src/weapons/WeaponInfo.h | 4 ++-- 5 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index acdf6f4e..666758c8 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -137,9 +137,13 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR CRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha); CRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha); +#ifndef ASPECT_RATIO_SCALE + CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, (CMenuManager::m_PrefsUseWideScreen ? 16.f / 9.f : 4.f / 3.f)); +#else CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); +#endif CVisibilityPlugins::SetRenderWareCamera(Scene.camera); - RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ); + RwCameraClear(Scene.camera, &TopColor.rwRGBA, rwCAMERACLEARZ); if(!RsCameraBeginUpdate(Scene.camera)) return false; @@ -155,7 +159,11 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha) { +#ifndef ASPECT_RATIO_SCALE + CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, (CMenuManager::m_PrefsUseWideScreen ? 16.f/9.f : 4.f/3.f)); +#else CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); +#endif CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 3c6fad57..eb4ac09e 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -227,7 +227,7 @@ CPlayerPed::SetInitialState(void) { m_bAdrenalineActive = false; m_nAdrenalineTime = 0; - CTimer::SetTimeStep(1.0f); + CTimer::SetTimeScale(1.0f); m_pSeekTarget = nil; m_vecSeekPos = { 0.0f, 0.0f, 0.0f }; m_fleeFromPosX = 0.0f; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 88c4788c..93481105 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -241,51 +241,51 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } } - if ( fired ) + if (fired) { bool isPlayer = false; - if ( shooter->IsPed() ) + if (shooter->IsPed()) { - CPed *shooterPed = (CPed*)shooter; + CPed* shooterPed = (CPed*)shooter; shooterPed->bIsShooting = true; - if ( shooterPed->IsPlayer() ) + if (shooterPed->IsPlayer()) isPlayer = true; DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); } - if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; - if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--; + if (m_nAmmoInClip > 0) m_nAmmoInClip--; + if (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer)) m_nAmmoTotal--; - if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) + if (m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER) DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); m_eWeaponState = WEAPONSTATE_FIRING; - } - if ( m_nAmmoInClip == 0 ) - { - if ( m_nAmmoTotal == 0 ) - return true; - - m_eWeaponState = WEAPONSTATE_RELOADING; - m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; - - if ( shooter == FindPlayerPed() ) + if (m_nAmmoInClip == 0) { - if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload ) - m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; + if (m_nAmmoTotal == 0) + return true; + + m_eWeaponState = WEAPONSTATE_RELOADING; + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + + if (shooter == FindPlayerPed()) + { + if (CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; + } + + return true; } - return true; + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; + if (shooter == FindPlayerPed()) + CStats::RoundsFiredByPlayer++; } - - m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; - if ( shooter == FindPlayerPed() ) - CStats::RoundsFiredByPlayer++; } else { diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 1b2c0320..c7685e0d 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -16,8 +16,8 @@ class CWeapon public: eWeaponType m_eWeaponType; eWeaponState m_eWeaponState; - uint32 m_nAmmoInClip; - uint32 m_nAmmoTotal; + int32 m_nAmmoInClip; + int32 m_nAmmoTotal; uint32 m_nTimer; bool m_bAddRotOffset; diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index b5882082..c89dd482 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -5,13 +5,13 @@ class CWeaponInfo { // static CWeaponInfo(&ms_apWeaponInfos)[14]; - static CWeaponInfo ms_apWeaponInfos[14]; + static CWeaponInfo ms_apWeaponInfos[WEAPONTYPE_LAST_WEAPONTYPE]; public: eWeaponFire m_eWeaponFire; float m_fRange; uint32 m_nFiringRate; uint32 m_nReload; - uint32 m_nAmountofAmmunition; + int32 m_nAmountofAmmunition; uint32 m_nDamage; float m_fSpeed; float m_fRadius; From 6235e2140eecce3341aca661246f375d19ea2812 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 24 May 2020 17:23:14 +0300 Subject: [PATCH 125/148] fixed filename --- src/peds/{PedAttactor.cpp => PedAttractor.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/peds/{PedAttactor.cpp => PedAttractor.cpp} (100%) diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttractor.cpp similarity index 100% rename from src/peds/PedAttactor.cpp rename to src/peds/PedAttractor.cpp From d59862eb5e9b56fe5b9fb0b2332e07b5266dcd22 Mon Sep 17 00:00:00 2001 From: nrb Date: Sun, 24 May 2020 17:27:12 +0200 Subject: [PATCH 126/148] fixed compiler errors --- src/control/Script.cpp | 5 +++-- src/core/Streaming.cpp | 3 ++- src/core/Zones.cpp | 12 ++++++------ src/peds/CopPed.cpp | 2 +- src/peds/EmergencyPed.cpp | 16 ++++++++-------- src/peds/Ped.cpp | 10 +++++----- src/peds/{PedAttactor.cpp => PedAttractor.cpp} | 4 ++-- src/peds/PlayerPed.cpp | 2 +- src/render/Timecycle.cpp | 2 +- src/save/GenericGameStorage.h | 3 ++- src/weapons/ShotInfo.cpp | 2 +- src/weapons/Weapon.cpp | 4 ++-- src/weapons/WeaponInfo.cpp | 3 ++- src/weapons/WeaponInfo.h | 1 + 14 files changed, 37 insertions(+), 32 deletions(-) rename src/peds/{PedAttactor.cpp => PedAttractor.cpp} (99%) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index cf2545c0..cbaaf32e 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11,6 +11,7 @@ #include "CarAI.h" #include "CarCtrl.h" #include "CarGen.h" +#include "Ped.h" #include "CivilianPed.h" #include "Clock.h" #include "ColStore.h" @@ -7298,7 +7299,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD: { CollectParameters(&m_nIp, 4); - CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) @@ -10655,7 +10656,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) CVector pos = *(CVector*)&ScriptParams[0]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - CCoronas::RegisterCorona((uint32)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], 255, pos, *(float*)&ScriptParams[3], + CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f, false, 0.2f); return 0; } diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 0ce8b50e..985b28c9 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1449,7 +1449,8 @@ CStreaming::StreamVehiclesAndPeds(void) timeBeforeNextLoad--; else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){ CZoneInfo zone; - CTheZones::GetZoneInfoForTimeOfDay(&FindPlayerCoors(), &zone); + CVector coors = FindPlayerCoors(); + CTheZones::GetZoneInfoForTimeOfDay(&coors, &zone); int32 maxReq = -1; int32 mostRequestedRating = 0; for(i = 0; i < CCarCtrl::TOTAL_CUSTOM_CLASSES; i++){ diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 0e8606f3..84b5ca29 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -725,17 +725,17 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ NavigationZoneArray[i] = ReadSaveBuf(buffer); - NavigationZoneArray[i].child = GetPointerForZoneIndex((int32)NavigationZoneArray[i].child); - NavigationZoneArray[i].parent = GetPointerForZoneIndex((int32)NavigationZoneArray[i].parent); - NavigationZoneArray[i].next = GetPointerForZoneIndex((int32)NavigationZoneArray[i].next); + NavigationZoneArray[i].child = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].child); + NavigationZoneArray[i].parent = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].parent); + NavigationZoneArray[i].next = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].next); } for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ InfoZoneArray[i] = ReadSaveBuf(buffer); - InfoZoneArray[i].child = GetPointerForZoneIndex((int32)InfoZoneArray[i].child); - InfoZoneArray[i].parent = GetPointerForZoneIndex((int32)InfoZoneArray[i].parent); - InfoZoneArray[i].next = GetPointerForZoneIndex((int32)InfoZoneArray[i].next); + InfoZoneArray[i].child = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].child); + InfoZoneArray[i].parent = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].parent); + InfoZoneArray[i].next = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].next); } for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index c24be62f..35acd675 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -257,7 +257,7 @@ CCopPed::ArrestPlayer(void) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ARREST_GUN, 4.0f); CVector suspMidPos; - suspect->m_pedIK.GetComponentPosition((RwV3d)suspMidPos, PED_MID); + suspect->m_pedIK.GetComponentPosition(*(RwV3d*)&suspMidPos, PED_MID); m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(suspMidPos.x, suspMidPos.y, GetPosition().x, GetPosition().y); diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 95811dab..1988366d 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -231,8 +231,8 @@ CEmergencyPed::MedicAI(void) if (nearestAccident) { m_pRevivedPed = nearestAccident->m_pVictim; m_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&headPos, PED_HEAD); SetSeek((headPos + midPos) * 0.5f, 1.0f); SetObjective(OBJECTIVE_NONE); bIsRunning = true; @@ -271,8 +271,8 @@ CEmergencyPed::MedicAI(void) m_nEmergencyPedState = EMERGENCY_PED_STOP; break; } - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&headPos, PED_HEAD); SetSeek((headPos + midPos) * 0.5f, nearestAccident->m_nMedicsPerformingCPR * 0.5f + 1.0f); SetObjective(OBJECTIVE_NONE); bIsRunning = true; @@ -326,8 +326,8 @@ CEmergencyPed::MedicAI(void) if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f) m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; else { - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&headPos, PED_HEAD); midPos = (headPos + midPos) * 0.5f; m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( midPos.x, midPos.y, @@ -348,8 +348,8 @@ CEmergencyPed::MedicAI(void) m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; break; } - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)midPos, PED_MID); - m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d)headPos, PED_HEAD); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&midPos, PED_MID); + m_pRevivedPed->m_pedIK.GetComponentPosition(*(RwV3d *)&headPos, PED_HEAD); midPos = (headPos + midPos) * 0.5f; m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( midPos.x, midPos.y, diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7eb2491b..8f6cc284 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -9713,7 +9713,7 @@ CPed::MoveHeadToLook(void) } if (m_pLookTarget->IsPed()) { - ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d)lookPos, PED_MID); + ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition(*(RwV3d *)&lookPos, PED_MID); } else { lookPos = m_pLookTarget->GetPosition(); } @@ -12804,7 +12804,7 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) } // --MIAMI: Done, but enumarate weapon slots -inline void +void CPed::ReplaceWeaponWhenExitingVehicle(void) { eWeaponType weaponType = GetWeapon()->m_eWeaponType; @@ -12821,7 +12821,7 @@ CPed::ReplaceWeaponWhenExitingVehicle(void) } // --MIAMI: Done -inline void +void CPed::RemoveWeaponWhenEnteringVehicle(void) { if (IsPlayer() && HasWeaponSlot(5) && GetWeapon(5).m_nAmmoTotal > 0 && ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed()->m_bDriveByAllowed) { @@ -13675,7 +13675,7 @@ CPed::ProcessObjective(void) CVector target; CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); if (m_pedInObjective->IsPed()) - m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d)target, PED_MID); + m_pedInObjective->m_pedIK.GetComponentPosition(*(RwV3d *)&target, PED_MID); else target = m_pedInObjective->GetPosition(); @@ -18682,4 +18682,4 @@ IsPedPointerValid(CPed* pPed) if (pPed->bInVehicle && pPed->m_pMyVehicle) return IsEntityPointerValid(pPed->m_pMyVehicle); return pPed->m_entryInfoList.first || pPed == FindPlayerPed(); -} \ No newline at end of file +} diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttractor.cpp similarity index 99% rename from src/peds/PedAttactor.cpp rename to src/peds/PedAttractor.cpp index 782d2770..3d35b8a3 100644 --- a/src/peds/PedAttactor.cpp +++ b/src/peds/PedAttractor.cpp @@ -108,7 +108,7 @@ const C2dEffect* CPedAttractorManager::GetEffectForIceCreamVan(CVehicle* pVehicl CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect) { if (vVehicleToEffect.empty()) - return false; + return nil; for (std::vector::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) { if (assoc->HasThisEffect(pEffect)) return assoc->GetVehicle(); @@ -625,7 +625,7 @@ CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, ComputeEffectPos(pAttractor->GetEffect(), matrix, vEffectPos); if (pAttractor->GetEffect() == pEffect && vEffectPos == pAttractor->GetEffectPos()) { if (!IsApproachable(pEffect, matrix, pAttractor->ComputeFreeSlot(), pPed)) - return false; + return nil; pRegisteredAttractor = pAttractor; break; } diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 37a0b191..aafb80c7 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1252,7 +1252,7 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) #else CVector markPos; if (m_pPointGunAt->IsPed()) { - ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d)markPos, PED_MID); + ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition(*(RwV3d *)&markPos, PED_MID); } else { markPos = m_pPointGunAt->GetPosition(); } diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index c120c003..8846fdf0 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -175,7 +175,7 @@ CTimeCycle::Initialise(void) bi++; bi++; } - while(work_buff[bi] != '\n') + while(work_buff[bi] != '\n' || work_buff[bi] != '\0') line[li++] = work_buff[bi++]; line[li] = '\0'; bi++; diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h index b913c305..2d83385b 100644 --- a/src/save/GenericGameStorage.h +++ b/src/save/GenericGameStorage.h @@ -1,5 +1,6 @@ #pragma once +#include "Game.h" #include "PCSave.h" #define SLOT_COUNT (8) @@ -40,4 +41,4 @@ extern uint32 TimeToStayFadedBeforeFadeOut; extern char SaveFileNameJustSaved[260]; // 8F2570 -const char TopLineEmptyFile[] = "THIS FILE IS NOT VALID YET"; \ No newline at end of file +const char TopLineEmptyFile[] = "THIS FILE IS NOT VALID YET"; diff --git a/src/weapons/ShotInfo.cpp b/src/weapons/ShotInfo.cpp index f09ae052..6fc6341d 100644 --- a/src/weapons/ShotInfo.cpp +++ b/src/weapons/ShotInfo.cpp @@ -128,4 +128,4 @@ CShotInfo::Update() if (!((CTimer::GetFrameCounter() + slot) & 3)) CWorld::SetCarsOnFire(shot.m_startPos.x, shot.m_startPos.y, shot.m_startPos.z, 4.0f, shot.m_sourceEntity); } -} \ No newline at end of file +} diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index ebdeb38b..6908abab 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -817,7 +817,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; if ( threatAttack->IsPed() ) { - threatAttack->m_pedIK.GetComponentPosition((RwV3d)target, PED_MID); + threatAttack->m_pedIK.GetComponentPosition(*(RwV3d *)&target, PED_MID); threatAttack->ReactToPointGun(shooter); } else @@ -1483,7 +1483,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { CVector pos; if (shooterPed->m_pPointGunAt->IsPed()) { - ((CPed*)shooterPed->m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d)pos, PED_MID); + ((CPed*)shooterPed->m_pPointGunAt)->m_pedIK.GetComponentPosition(*(RwV3d *)&pos, PED_MID); } else { pos = ((CPed*)shooterPed->m_pPointGunAt)->GetPosition(); } diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index 104fa2ec..bd53d8c5 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -59,7 +59,8 @@ static char ms_aWeaponNames[][32] = { }; CWeaponInfo* -CWeaponInfo::GetWeaponInfo(eWeaponType weaponType) { +CWeaponInfo::GetWeaponInfo(eWeaponType weaponType) +{ return &CWeaponInfo::ms_apWeaponInfos[weaponType]; } diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index 41450047..e7013004 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -1,5 +1,6 @@ #pragma once +#include "AnimManager.h" #include "AnimationId.h" #include "WeaponType.h" From 55ece14f423f65b09c8c3d8849a3eb8a7fd7d4c4 Mon Sep 17 00:00:00 2001 From: blingu <36486731+blingu@users.noreply.github.com> Date: Sun, 24 May 2020 17:36:37 +0200 Subject: [PATCH 127/148] Update CopPed.cpp --- src/peds/CopPed.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 35acd675..6fb858f6 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -257,7 +257,7 @@ CCopPed::ArrestPlayer(void) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ARREST_GUN, 4.0f); CVector suspMidPos; - suspect->m_pedIK.GetComponentPosition(*(RwV3d*)&suspMidPos, PED_MID); + suspect->m_pedIK.GetComponentPosition(*(RwV3d *)&suspMidPos, PED_MID); m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(suspMidPos.x, suspMidPos.y, GetPosition().x, GetPosition().y); From 79c652e1152cecd228a7cef9e0f4b93d051a485d Mon Sep 17 00:00:00 2001 From: blingu <36486731+blingu@users.noreply.github.com> Date: Sun, 24 May 2020 17:48:13 +0200 Subject: [PATCH 128/148] Ped.h include not needed --- src/control/Script.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index cbaaf32e..ee1b9fed 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11,7 +11,6 @@ #include "CarAI.h" #include "CarCtrl.h" #include "CarGen.h" -#include "Ped.h" #include "CivilianPed.h" #include "Clock.h" #include "ColStore.h" From 56683dbed350354865e324f2e0ba28cff9743ead Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 24 May 2020 20:33:30 +0300 Subject: [PATCH 129/148] Clean cAudioManager::ProcessGarages up a bit --- src/audio/AudioLogic.cpp | 168 ++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 89 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 6ac0ea4b..d418adf4 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -8278,6 +8278,8 @@ cAudioManager::ProcessProjectiles() void cAudioManager::ProcessGarages() { + const float SOUND_INTENSITY = 80.0f; + CEntity *entity; eGarageState state; uint32 sampleIndex; @@ -8287,109 +8289,57 @@ cAudioManager::ProcessGarages() static uint8 iSound = 32; -#define LOOP_HELPER \ - for (j = 0; j < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; ++j) { \ - switch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j]) { \ - case SOUND_GARAGE_DOOR_CLOSED: \ - case SOUND_GARAGE_DOOR_OPENED: \ - if (distSquared < 6400.f) { \ - CalculateDistance(distCalculated, distSquared); \ - m_sQueueSample.m_nVolume = ComputeVolume(60, 80.f, m_sQueueSample.m_fDistance); \ - if (m_sQueueSample.m_nVolume) { \ - if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { \ - m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; \ - m_sQueueSample.m_nFrequency = 6735; \ - } else if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j] == 69) { \ - m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; \ - m_sQueueSample.m_nFrequency = 22000; \ - } else { \ - m_sQueueSample.m_nSampleIndex = SFX_COL_GARAGE_DOOR_1; \ - m_sQueueSample.m_nFrequency = 18000; \ - } \ - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; \ - m_sQueueSample.m_nReleasingVolumeModificator = 4; \ - m_sQueueSample.m_nEmittingVolume = 60; \ - m_sQueueSample.m_fSpeedMultiplier = 0.0f; \ - m_sQueueSample.m_fSoundIntensity = 80.0f; \ - /*m_sQueueSample.m_nReleasingVolumeModificator = 4;*/ \ - m_sQueueSample.m_bReverbFlag = true; \ - /*m_sQueueSample.m_bReverbFlag = true;*/ \ - m_sQueueSample.m_bIs2D = false; \ - m_sQueueSample.m_bReleasingSoundFlag = true; \ - m_sQueueSample.m_nLoopCount = 1; \ - m_sQueueSample.m_nLoopStart = 0; \ - m_sQueueSample.m_nLoopEnd = -1; \ - m_sQueueSample.m_nCounter = iSound++; \ - if (iSound < 32) \ - iSound = 32; \ - m_sQueueSample.m_bRequireReflection = true; \ - AddSampleToRequestedQueue(); \ - } \ - } \ - break; \ - default: \ - continue; \ - } \ - } - for (uint32 i = 0; i < CGarages::NumGarages; ++i) { if (CGarages::aGarages[i].m_eGarageType == GARAGE_NONE) continue; entity = CGarages::aGarages[i].m_pDoor1; - if (!entity) + if (entity == nil) continue; m_sQueueSample.m_vecPos = entity->GetPosition(); distCalculated = false; distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos); - if (distSquared < 6400.f) { + if (distSquared < SQR(SOUND_INTENSITY)) { state = CGarages::aGarages[i].m_eGarageState; - if (state == GS_OPENING || state == GS_CLOSING || state == GS_AFTERDROPOFF) { + // while is here just to exit prematurely and avoid goto + while (state == GS_OPENING || state == GS_CLOSING || state == GS_AFTERDROPOFF) { CalculateDistance(distCalculated, distSquared); - m_sQueueSample.m_nVolume = ComputeVolume(90, 80.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + m_sQueueSample.m_nVolume = ComputeVolume(90, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume != 0) { if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { if (CGarages::aGarages[i].m_eGarageState == GS_AFTERDROPOFF) { - if (!(m_FrameCounter & 1)) { - LOOP_HELPER - continue; - } - if (m_anRandomTable[1] & 1) { - sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_CAR_1; - } else { - sampleIndex = m_anRandomTable[2] % 6 + SFX_COL_CAR_PANEL_1; - } - m_sQueueSample.m_nSampleIndex = sampleIndex; - m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2; - m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nLoopCount = 1; - m_sQueueSample.m_bReleasingSoundFlag = true; - m_sQueueSample.m_nCounter = iSound++; - if (iSound < 32) - iSound = 32; - m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; - m_sQueueSample.m_bIs2D = false; - m_sQueueSample.m_nReleasingVolumeModificator = 3; - m_sQueueSample.m_nEmittingVolume = 90; - m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; - m_sQueueSample.m_bReverbFlag = true; - m_sQueueSample.m_bRequireReflection = false; - AddSampleToRequestedQueue(); - LOOP_HELPER - continue; + if (m_FrameCounter & 1) { + if (m_anRandomTable[1] & 1) + sampleIndex = m_anRandomTable[2] % 5 + SFX_COL_CAR_1; + else + sampleIndex = m_anRandomTable[2] % 6 + SFX_COL_CAR_PANEL_1; + m_sQueueSample.m_nSampleIndex = sampleIndex; + m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2; + m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nCounter = iSound++; + if (iSound < 32) + iSound = 32; + } else break; // premature exit to go straight to the for loop + } else { + m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; + m_sQueueSample.m_nFrequency = 6543; + + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReleasingSoundFlag = false; } - m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; - m_sQueueSample.m_nFrequency = 6543; } else { m_sQueueSample.m_nSampleIndex = SFX_GARAGE_DOOR_LOOP; m_sQueueSample.m_nFrequency = 13961; + + m_sQueueSample.m_nCounter = i; + m_sQueueSample.m_nLoopCount = 0; + m_sQueueSample.m_nReleasingVolumeDivider = 3; + m_sQueueSample.m_bReleasingSoundFlag = false; } - m_sQueueSample.m_nCounter = i; - m_sQueueSample.m_nLoopCount = 0; - m_sQueueSample.m_nReleasingVolumeDivider = 3; - m_sQueueSample.m_bReleasingSoundFlag = false; + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nReleasingVolumeModificator = 3; @@ -8397,16 +8347,56 @@ cAudioManager::ProcessGarages() m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_fSpeedMultiplier = 2.0f; - m_sQueueSample.m_fSoundIntensity = 80.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; m_sQueueSample.m_bReverbFlag = true; m_sQueueSample.m_bRequireReflection = false; AddSampleToRequestedQueue(); } + break; + } + } + for (j = 0; j < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; ++j) { + switch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j]) { + case SOUND_GARAGE_DOOR_CLOSED: + case SOUND_GARAGE_DOOR_OPENED: + if (distSquared < SQR(SOUND_INTENSITY)) { + CalculateDistance(distCalculated, distSquared); + m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance); + if (m_sQueueSample.m_nVolume) { + if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { + m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; + m_sQueueSample.m_nFrequency = 6735; + } else if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j] == SOUND_GARAGE_DOOR_OPENED) { + m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; + m_sQueueSample.m_nFrequency = 22000; + } else { + m_sQueueSample.m_nSampleIndex = SFX_COL_GARAGE_DOOR_1; + m_sQueueSample.m_nFrequency = 18000; + } + m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; + m_sQueueSample.m_nReleasingVolumeModificator = 4; + m_sQueueSample.m_nEmittingVolume = 60; + m_sQueueSample.m_fSpeedMultiplier = 0.0f; + m_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY; + m_sQueueSample.m_bReverbFlag = true; + m_sQueueSample.m_bIs2D = false; + m_sQueueSample.m_bReleasingSoundFlag = true; + m_sQueueSample.m_nLoopCount = 1; + m_sQueueSample.m_nLoopStart = 0; + m_sQueueSample.m_nLoopEnd = -1; + m_sQueueSample.m_nCounter = iSound++; + if (iSound < 32) + iSound = 32; + m_sQueueSample.m_bRequireReflection = true; + AddSampleToRequestedQueue(); + } + } + break; + default: + break; } - LOOP_HELPER } } -#undef LOOP_HELPER } void From 80c2018b518b2d7028acf1bc33efc2c3334c690b Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 25 May 2020 03:40:47 +0300 Subject: [PATCH 130/148] cAudioManager::ProcessPlayersVehicleEngine cleanup and fixes --- src/audio/AudioLogic.cpp | 269 +++++++++++++++++---------------------- 1 file changed, 114 insertions(+), 155 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index d418adf4..84db5d3b 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1146,7 +1146,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * int freqModifier; int soundOffset; uint8 engineSoundType; - int32 accelerateState; + int16 accelerateState; bool channelUsed; bool lostTraction; bool processedAccelSampleStopped; @@ -1174,47 +1174,47 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * bHandbrakeOnLastFrame = false; CurrentPretendGear = 1; } - if (CReplay::IsPlayingBack()) { - accelerateState = 255.f * Max(0.0f, Min(1.0f, automobile->m_fGasPedal)); - } else { - accelerateState = Pads->GetAccelerate(); - } + if (CReplay::IsPlayingBack()) + accelerateState = 255.f * clamp(automobile->m_fGasPedal, 0.0f, 1.0f); + else + accelerateState = Pads[0].GetAccelerate(); + channelUsed = SampleManager.GetChannelUsedFlag(m_nActiveSamples); transmission = params->m_pTransmission; velocityChange = params->m_fVelocityChange; relativeVelocityChange = 2.0f * velocityChange / transmission->fMaxVelocity; - accelerationMultipler = Min(Min(1.f, relativeVelocityChange), 0.f); + accelerationMultipler = clamp(relativeVelocityChange, 0.0f, 1.0f); gasPedalAudio = accelerationMultipler; currentGear = params->m_pVehicle->m_nCurrentGear; if (transmission->nDriveType == '4') { wheelInUseCounter = 0; for (uint8 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { - if (automobile->m_aWheelState[i]) + if (automobile->m_aWheelState[i] != WHEEL_STATE_NORMAL) ++wheelInUseCounter; } if (wheelInUseCounter > 2) lostTraction = true; - } else if (transmission->nDriveType == 'F') { - if ((automobile->m_aWheelState[0] || automobile->m_aWheelState[2]) && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { + } else if (transmission->nDriveType == 'F') + if ((automobile->m_aWheelState[VEHWHEEL_FRONT_LEFT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[VEHWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL) && + (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) lostTraction = true; - } - } else if (transmission->nDriveType == 'R' && (automobile->m_aWheelState[1] || automobile->m_aWheelState[3])) { - lostTraction = true; - } - if (0.0f != velocityChange) { + else if (transmission->nDriveType == 'R' && (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL || + automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) + lostTraction = true; + + if (velocityChange != 0.0f) { time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; - if (time <= 0.0f) { - freqModifier = Max(-0.2f, time) * -15000.f; - } else { - freqModifier = -(Min(0.2f, time) * 15000.f); - } + if (time > 0.0f) + freqModifier = -(Min(0.2f, time) * 3000.0f * 5.0f); + else + freqModifier = (Max(-0.2f, time) * 3000.0f * -5.0f); if (params->m_fVelocityChange < -0.001f) freqModifier = -freqModifier; - } else { + } else freqModifier = 0; - } + engineSoundType = aVehicleSettings[params->m_nIndex].m_bEngineSoundType; soundOffset = 3 * (engineSoundType - 1); if (accelerateState <= 0) { @@ -1223,11 +1223,11 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * SampleManager.StopChannel(m_nActiveSamples); bAccelSampleStopped = true; } - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { + if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) gasPedalAudio = automobile->m_fGasPedalAudio; - } else { + else gasPedalAudio = Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity); - } + gasPedalAudio = Max(0.0f, gasPedalAudio); automobile->m_fGasPedalAudio = gasPedalAudio; } else if (LastAccel > 0) { @@ -1238,154 +1238,113 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * nCruising = 0; if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || params->m_fVelocityChange >= 0.01f && automobile->m_fGasPedalAudio > 0.2f) { - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.6f; + automobile->m_fGasPedalAudio *= 0.6f; gasPedalAudio = automobile->m_fGasPedalAudio; } if (gasPedalAudio > 0.05f) { freq = (5000.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 19000; if (engineSoundType == 6) freq /= 2; - AddPlayerCarSample((25.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 40, freq, (soundOffset + SFX_CAR_FINGER_OFF_ACCEL_1), engineSoundType, 63, 0); + AddPlayerCarSample((25.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 40, freq, (soundOffset + SFX_CAR_FINGER_OFF_ACCEL_1), engineSoundType, 63, + false); } } freq = (10000.f * gasPedalAudio) + 22050; if (engineSoundType == 6) freq /= 2; - AddPlayerCarSample(110 - (40.f * gasPedalAudio), freq, (engineSoundType + SFX_CAR_REV_10), 0, 52, 1); + AddPlayerCarSample(110 - (40.f * gasPedalAudio), freq, (engineSoundType - 1 + SFX_CAR_IDLE_1), 0, 52, true); CurrentPretendGear = Max(1, currentGear); - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - if (!nCruising) { - if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || - currentGear < 2 && velocityChange - automobile->m_fVelocityChangeForAudio < 0.01f) { // here could be used abs - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { - if (!automobile->m_nWheelsOnGround && automobile->m_nDriveWheelsOnGround || - (automobile->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame) && automobile->m_nWheelsOnGround) { - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.6f; - } - freqModifier = 0; - baseFreq = (15000.f * automobile->m_fGasPedalAudio) + 14000; - vol = (25.0f * automobile->m_fGasPedalAudio) + 60; - } else { - baseFreq = (8000.f * accelerationMultipler) + 16000; - vol = (25.0f * accelerationMultipler) + 60; - automobile->m_fGasPedalAudio = accelerationMultipler; - } - freq = freqModifier + baseFreq; - if (engineSoundType == 6) - freq /= 2; - if (channelUsed) { - SampleManager.StopChannel(m_nActiveSamples); - bAccelSampleStopped = true; - } - AddPlayerCarSample(vol, freq, (engineSoundType + SFX_PHONE_RING), 0, 2, 1); - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - TranslateEntity(&m_sQueueSample.m_vecPos, &pos); - if (bAccelSampleStopped) { - if (CurrentPretendGear != 1 || currentGear != 2) { - gearNr = currentGear - 1; - if (gearNr < 1) - gearNr = 1; - CurrentPretendGear = gearNr; - } - processedAccelSampleStopped = true; - bAccelSampleStopped = false; - } - if (channelUsed) { - SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); - SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); - SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); - if (engineSoundType == 6) - freq = (GearFreqAdj[CurrentPretendGear] + freqModifier + 22050) / 2; - else - freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; - SampleManager.SetChannelFrequency(m_nActiveSamples, freq); - if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); - SampleManager.StartChannel(m_nActiveSamples); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - if (processedAccelSampleStopped) { - if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) - return; - SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); - SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); - SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); - SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); - SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); - freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; - if (engineSoundType == 6) - freq /= 2; - SampleManager.SetChannelFrequency(m_nActiveSamples, freq); - if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); - SampleManager.StartChannel(m_nActiveSamples); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1) { - ++CurrentPretendGear; - if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, 0)) - return; - SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); - SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); - SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); - SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); - SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); - freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; - if (engineSoundType == 6) - freq /= 2; - SampleManager.SetChannelFrequency(m_nActiveSamples, freq); - if (!channelUsed) { - SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); - SampleManager.StartChannel(m_nActiveSamples); - } - LastAccel = accelerateState; - - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; - bLostTractionLastFrame = lostTraction; - return; - } - nCruising = 1; - } - bAccelSampleStopped = true; - if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || - currentGear < params->m_pTransmission->nNumberOfGears - 1) { - nCruising = 0; } else { - if (accelerateState >= 220 && 0.001f + params->m_fVelocityChange < automobile->m_fVelocityChangeForAudio) { - if (nCruising < 800) - ++nCruising; - } else if (nCruising > 3) { - --nCruising; + while (nCruising == 0) { + if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + currentGear < 2 && velocityChange - automobile->m_fVelocityChangeForAudio < 0.01f) { // here could be used abs + if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { + if (!automobile->m_nWheelsOnGround && automobile->m_nDriveWheelsOnGround || + (automobile->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame) && automobile->m_nWheelsOnGround) { + automobile->m_fGasPedalAudio *= 0.6f; + } + freqModifier = 0; + baseFreq = (15000.f * automobile->m_fGasPedalAudio) + 14000; + vol = (25.0f * automobile->m_fGasPedalAudio) + 60; + } else { + baseFreq = (8000.f * accelerationMultipler) + 16000; + vol = (25.0f * accelerationMultipler) + 60; + automobile->m_fGasPedalAudio = accelerationMultipler; + } + freq = freqModifier + baseFreq; + if (engineSoundType == 6) + freq /= 2; + if (channelUsed) { + SampleManager.StopChannel(m_nActiveSamples); + bAccelSampleStopped = true; + } + AddPlayerCarSample(vol, freq, (engineSoundType - 1 + SFX_CAR_REV_1), 0, 2, true); + } else { + TranslateEntity(&m_sQueueSample.m_vecPos, &pos); + if (bAccelSampleStopped) { + if (CurrentPretendGear != 1 || currentGear != 2) { + gearNr = currentGear - 1; + if (gearNr < 1) + gearNr = 1; + CurrentPretendGear = gearNr; + } + processedAccelSampleStopped = true; + bAccelSampleStopped = false; + } + + if (!channelUsed) { + if (!processedAccelSampleStopped) { + if (CurrentPretendGear < params->m_pTransmission->nNumberOfGears - 1) + ++CurrentPretendGear; + else { + nCruising = 1; + break; // while was used just for this fucking place + } + } + + if (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, SAMPLEBANK_MAIN)) + return; + SampleManager.SetChannelLoopCount(m_nActiveSamples, 1); + SampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1); + } + + SampleManager.SetChannelEmittingVolume(m_nActiveSamples, 85); + SampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z); + SampleManager.SetChannel3DDistances(m_nActiveSamples, 50.f, 12.5f); + freq = GearFreqAdj[CurrentPretendGear] + freqModifier + 22050; + if (engineSoundType == 6) + freq /= 2; + SampleManager.SetChannelFrequency(m_nActiveSamples, freq); + if (!channelUsed) { + SampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false); + SampleManager.StartChannel(m_nActiveSamples); + } + } + break; + } + if (nCruising != 0) { + bAccelSampleStopped = true; + if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + currentGear < params->m_pTransmission->nNumberOfGears - 1) { + nCruising = 0; + } else { + if (accelerateState >= 220 && 0.001f + params->m_fVelocityChange < automobile->m_fVelocityChangeForAudio) { + if (nCruising < 800) + ++nCruising; + } else if (nCruising > 3) { + --nCruising; + } + freq = 27 * nCruising + freqModifier + 22050; + if (engineSoundType == 6) + freq /= 2; + AddPlayerCarSample(85, freq, (soundOffset + SFX_CAR_AFTER_ACCEL_1), engineSoundType, 64, true); + } } - freq = 27 * nCruising + freqModifier + 22050; - if (engineSoundType == 6) - freq /= 2; - AddPlayerCarSample(85, freq, (soundOffset + SFX_CAR_AFTER_ACCEL_1), engineSoundType, 64, 1); } LastAccel = accelerateState; - bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; + bHandbrakeOnLastFrame = !!automobile->bIsHandbrakeOn; bLostTractionLastFrame = lostTraction; } From fd06ab4db8a3c875c53ab7e1bc14068a41fdd46a Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 25 May 2020 03:56:17 +0300 Subject: [PATCH 131/148] Fix names of static variables --- src/audio/AudioLogic.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 84db5d3b..e223eeb1 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -3353,7 +3353,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) noReflection = true; break; case SOUND_WEAPON_SHOT_FIRED: - weapon = &ped->m_weapons[ped->m_currentWeapon]; + weapon = ped->GetWeapon(); switch (weapon->m_eWeaponType) { case WEAPONTYPE_COLT45: m_sQueueSample.m_nSampleIndex = SFX_COLT45_LEFT; @@ -7655,7 +7655,7 @@ cAudioManager::ProcessShopScriptObject(uint8 sound) void cAudioManager::ProcessAirportScriptObject(uint8 sound) { - static uint8 counter = 0; + static uint8 iSound = 0; uint32 time = CTimer::GetTimeInMilliseconds(); if (time > gAirportNextTime) { @@ -7677,7 +7677,7 @@ cAudioManager::ProcessAirportScriptObject(uint8 sound) m_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_AIRPORT_ANNOUNCEMENT_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -7700,7 +7700,7 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound) { uint8 rand; - static uint8 counter = 0; + static uint8 iSound = 0; uint32 time = CTimer::GetTimeInMilliseconds(); if (time > gCinemaNextTime) { @@ -7720,11 +7720,11 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound) rand = m_anRandomTable[0] % 90 + 30; m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); if (m_sQueueSample.m_nVolume) { - m_sQueueSample.m_nSampleIndex = counter % 3 + SFX_CINEMA_BASS_1; + m_sQueueSample.m_nSampleIndex = iSound % 3 + SFX_CINEMA_BASS_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 4); - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -7749,7 +7749,7 @@ cAudioManager::ProcessDocksScriptObject(uint8 sound) uint8 rand; float distSquared; - static uint32 counter = 0; + static uint8 iSound = 0; time = CTimer::GetTimeInMilliseconds(); if (time > gDocksNextTime) { @@ -7773,7 +7773,7 @@ cAudioManager::ProcessDocksScriptObject(uint8 sound) m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOCKS_FOGHORN); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8); - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -7797,7 +7797,7 @@ cAudioManager::ProcessHomeScriptObject(uint8 sound) uint8 rand; float dist; - static uint8 counter = 0; + static uint8 iSound = 0; time = CTimer::GetTimeInMilliseconds(); if (time > gHomeNextTime) { @@ -7821,7 +7821,7 @@ cAudioManager::ProcessHomeScriptObject(uint8 sound) m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -7847,7 +7847,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) float distSquared; cPedParams params; - static uint8 counter = 0; + static uint8 iSound = 0; if (time > gCellNextTime) { switch (sound) { @@ -7874,7 +7874,7 @@ cAudioManager::ProcessPoliceCellBeatingScriptObject(uint8 sound) m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16); - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -7901,7 +7901,7 @@ void cAudioManager::ProcessWeather(int32 id) { uint8 vol; - static uint8 counter = 0; + static uint8 iSound = 0; if (m_asAudioEntities[id].m_AudioEvents && m_asAudioEntities[id].m_awAudioEvent[0] == SOUND_LIGHTNING) { if (m_asAudioEntities[id].m_afVolume[0] >= 10.f) { @@ -7918,9 +7918,9 @@ cAudioManager::ProcessWeather(int32 id) m_sQueueSample.m_nVolume = vol; if (TheCamera.SoundDistUp < 20.f) m_sQueueSample.m_nVolume /= 2; - if (counter == 4) - counter = 0; - m_sQueueSample.m_nCounter = counter++; + if (iSound == 4) + iSound = 0; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_nReleasingVolumeModificator = 0; m_sQueueSample.m_nOffset = (m_anRandomTable[2] & 15) + 55; m_sQueueSample.m_bIs2D = true; @@ -7962,7 +7962,7 @@ cAudioManager::ProcessFrontEnd() bool processedMission; int16 sample; - static uint8 counter = 0; + static uint8 iSound = 0; static uint32 cPickupNextFrame = 0; static uint32 cPartMisComNextFrame = 0; @@ -8104,7 +8104,7 @@ cAudioManager::ProcessFrontEnd() m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); } m_sQueueSample.m_nVolume = 110; - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -8122,7 +8122,7 @@ cAudioManager::ProcessFrontEnd() AddSampleToRequestedQueue(); if (stereo) { ++m_sQueueSample.m_nSampleIndex; - m_sQueueSample.m_nCounter = counter++; + m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_nOffset = MAX_VOLUME - m_sQueueSample.m_nOffset; AddSampleToRequestedQueue(); } From cebc3bbd488fc67ace2db1c7da6f41833cd82c26 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 25 May 2020 18:39:16 +0300 Subject: [PATCH 132/148] More audio cleanup and bugfixes --- src/audio/AudioLogic.cpp | 99 ++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index e223eeb1..b6f883d4 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -524,7 +524,7 @@ cAudioManager::ProcessVehicle(CVehicle *veh) params.m_nIndex = 0; params.m_fVelocityChange = 0.0f; - if (handling) + if (handling != nil) params.m_pTransmission = &handling->Transmission; params.m_nIndex = veh->GetModelIndex() - MI_FIRST_VEHICLE; @@ -540,14 +540,12 @@ cAudioManager::ProcessVehicle(CVehicle *veh) ProcessModelCarEngine(¶ms); ProcessVehicleOneShots(¶ms); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); break; } if (params.m_nIndex == DODO) { if (!ProcessVehicleRoadNoise(¶ms)) { ProcessVehicleOneShots(¶ms); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); break; } if (CWeather::WetRoads > 0.f) @@ -557,7 +555,6 @@ cAudioManager::ProcessVehicle(CVehicle *veh) if (!ProcessVehicleRoadNoise(¶ms)) { ProcessVehicleOneShots(¶ms); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); break; } ProcessReverseGear(¶ms); @@ -575,35 +572,31 @@ cAudioManager::ProcessVehicle(CVehicle *veh) ProcessVehicleEngine(¶ms); ProcessEngineDamage(¶ms); ProcessVehicleDoors(¶ms); + ProcessVehicleOneShots(¶ms); ((CAutomobile *)veh)->m_fVelocityChangeForAudio = params.m_fVelocityChange; - ProcessRainOnVehicle(¶ms); break; case VEHICLE_TYPE_BOAT: ProcessBoatEngine(¶ms); ProcessBoatMovingOverWater(¶ms); ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); break; case VEHICLE_TYPE_TRAIN: ProcessTrainNoise(¶ms); ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); break; case VEHICLE_TYPE_HELI: ProcessHelicopter(¶ms); ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); break; case VEHICLE_TYPE_PLANE: ProcessPlane(¶ms); ProcessVehicleOneShots(¶ms); - ProcessRainOnVehicle(¶ms); break; default: - ProcessRainOnVehicle(¶ms); break; } + ProcessRainOnVehicle(¶ms); } void @@ -655,14 +648,14 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params) if (params->m_fDistance >= SQR(reverseGearIntensity)) return false; veh = params->m_pVehicle; - if (veh->bEngineOn && (veh->m_fGasPedal < 0.0f || !veh->m_nCurrentGear)) { + if (veh->bEngineOn && (veh->m_fGasPedal < 0.0f || veh->m_nCurrentGear == 0)) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); automobile = (CAutomobile *)params->m_pVehicle; - if (automobile->m_nWheelsOnGround) { + if (automobile->m_nWheelsOnGround != 0) { modificator = params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity; } else { - if (automobile->m_nDriveWheelsOnGround) - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.4f; + if (automobile->m_nDriveWheelsOnGround != 0) + automobile->m_fGasPedalAudio *= 0.4f; modificator = automobile->m_fGasPedalAudio; } modificator = Abs(modificator); @@ -708,12 +701,12 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params) if (params->m_fDistance < SQR(SOUND_INTENSITY)) { automobile = (CAutomobile *)params->m_pVehicle; if (automobile->bEngineOn) { - if (automobile->m_nWheelsOnGround) { - velocityChange = Abs(params->m_fVelocityChange); - } else { - if (automobile->m_nDriveWheelsOnGround) - automobile->m_fGasPedalAudio = automobile->m_fGasPedalAudio * 0.4f; + if (automobile->m_nWheelsOnGround == 0) { + if (automobile->m_nDriveWheelsOnGround != 0) + automobile->m_fGasPedalAudio *= 0.4f; velocityChange = automobile->m_fGasPedalAudio * params->m_pTransmission->fMaxVelocity; + } else { + velocityChange = Abs(params->m_fVelocityChange); } if (velocityChange > 0.001f) { allowedVelocity = 0.5f * params->m_pTransmission->fMaxVelocity; @@ -764,14 +757,14 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) if (params->m_fDistance >= SQR(SOUND_INTENSITY)) return false; - if (params->m_pTransmission) { - if (params->m_pVehicle->m_vecMoveSpeed.z) { + if (params->m_pTransmission != nil) { + if (((CAutomobile*)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) { velocity = Abs(params->m_fVelocityChange); if (velocity > 0.0f) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); emittingVol = 30.f * Min(1.f, velocity / (0.5f * params->m_pTransmission->fMaxVelocity)); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_bIs2D = false; @@ -817,8 +810,8 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) if (params->m_fDistance >= SQR(SOUND_INTENSITY)) return false; - if (params->m_pTransmission) { - if (params->m_pVehicle->m_vecMoveSpeed.z) { + if (params->m_pTransmission != 0) { + if (((CAutomobile *)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) { velChange = Abs(params->m_fVelocityChange); if (velChange > 0.f) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); @@ -863,7 +856,7 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) float relativeGearChange; float relativeChange; uint8 volume; - int32 freq = 0; // uinitialized variable + int32 freq = 0; // uninitialized variable uint8 emittingVol; cTransmission *transmission; uint8 currentGear; @@ -889,9 +882,9 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) return; } transmission = params->m_pTransmission; - if (transmission) { + if (transmission != nil) { currentGear = params->m_pVehicle->m_nCurrentGear; - if (automobile->m_nWheelsOnGround) { + if (automobile->m_nWheelsOnGround != 0) { if (automobile->bIsHandbrakeOn) { if (params->m_fVelocityChange == 0.0f) traction = 0.9f; @@ -921,7 +914,7 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) } if (transmission->fMaxVelocity <= 0.f) { relativeChange = 0.f; - } else if (currentGear) { + } else if (currentGear != 0) { relativeGearChange = Min(1.0f, (params->m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f); if (traction == 0.0f && automobile->GetStatus() != STATUS_SIMPLE && @@ -933,7 +926,7 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) relativeChange = Min(1.0f, 1.0f - Abs((params->m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity)); } else { - if (automobile->m_nDriveWheelsOnGround) + if (automobile->m_nDriveWheelsOnGround != 0) automobile->m_fGasPedalAudio *= 0.4f; relativeChange = automobile->m_fGasPedalAudio; } @@ -955,7 +948,7 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) volume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); } m_sQueueSample.m_nVolume = volume; - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { if (automobile->GetStatus() == STATUS_SIMPLE) { if (modificator < 0.02f) { m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_bEngineSoundType - 1 + SFX_CAR_IDLE_1; @@ -1000,29 +993,20 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) void cAudioManager::UpdateGasPedalAudio(CAutomobile *automobile) { - float newGasPedalAudio; - float gasPedal = Abs(automobile->m_fGasPedal); float gasPedalAudio = automobile->m_fGasPedalAudio; - if (gasPedalAudio < gasPedal) { - newGasPedalAudio = gasPedalAudio + 0.09f; - if (gasPedal <= newGasPedalAudio) - newGasPedalAudio = gasPedal; - } else { - newGasPedalAudio = gasPedalAudio - 0.07f; - if (gasPedal >= newGasPedalAudio) - newGasPedalAudio = gasPedal; - } - automobile->m_fGasPedalAudio = newGasPedalAudio; + if (gasPedalAudio < gasPedal) + automobile->m_fGasPedalAudio = Min(gasPedalAudio + 0.09f, gasPedal); + else + automobile->m_fGasPedalAudio = Max(gasPedalAudio - 0.07f, gasPedal); } void cAudioManager::PlayerJustGotInCar() const { - if (m_bIsInitialised) { + if (m_bIsInitialised) bPlayerJustEnteredCar = true; - } } void @@ -1188,7 +1172,9 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * gasPedalAudio = accelerationMultipler; currentGear = params->m_pVehicle->m_nCurrentGear; - if (transmission->nDriveType == '4') { + switch (transmission->nDriveType) + { + case '4': wheelInUseCounter = 0; for (uint8 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { if (automobile->m_aWheelState[i] != WHEEL_STATE_NORMAL) @@ -1196,20 +1182,24 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * } if (wheelInUseCounter > 2) lostTraction = true; - } else if (transmission->nDriveType == 'F') + break; + case 'F': if ((automobile->m_aWheelState[VEHWHEEL_FRONT_LEFT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[VEHWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL) && (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) lostTraction = true; - else if (transmission->nDriveType == 'R' && (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL || - automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) + break; + case 'R': + if ((automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL) || (automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) lostTraction = true; + break; + } if (velocityChange != 0.0f) { time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; if (time > 0.0f) freqModifier = -(Min(0.2f, time) * 3000.0f * 5.0f); else - freqModifier = (Max(-0.2f, time) * 3000.0f * -5.0f); + freqModifier = -(Max(-0.2f, time) * 3000.0f * 5.0f); if (params->m_fVelocityChange < -0.001f) freqModifier = -freqModifier; } else @@ -1580,7 +1570,7 @@ cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) #endif CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 5; if (UsesSiren(params->m_nIndex)) { if (params->m_pVehicle->GetStatus() == STATUS_ABANDONED) @@ -1614,7 +1604,6 @@ cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) m_sQueueSample.m_bReverbFlag = true; m_sQueueSample.m_bRequireReflection = false; AddSampleToRequestedQueue(); - return; } } } @@ -1684,7 +1673,7 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params) if (velocity > 0.0035f) { emittingVol = (100.f * velocity * 10.f / 3.f); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = i + 6; m_sQueueSample.m_nSampleIndex = m_anRandomTable[1] % 6 + SFX_COL_CAR_PANEL_1; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) + RandomDisplacement(1000); @@ -1817,7 +1806,7 @@ cAudioManager::ProcessCarBombTick(cVehicleParams *params) if (automobile->bEngineOn && automobile->m_bombType == CARBOMB_TIMEDACTIVE) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(60, 40.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 35; m_sQueueSample.m_nSampleIndex = SFX_COUNTDOWN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -2351,7 +2340,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) if (params->m_nIndex == REEFER) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, 50.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 39; m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; m_sQueueSample.m_nFrequency = 10386; @@ -2489,7 +2478,7 @@ cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) return false; velocityChange = Abs(params->m_fVelocityChange); - if (velocityChange <= 0.0005f && params->m_pVehicle->GetPosition().y) + if (velocityChange <= 0.0005f && ((CBoat*)params->m_pVehicle)->bBoatInWater) return true; velocityChange = Min(0.75f, velocityChange); From ad896d5f8191f008642c8e90d2741baa5c0d0d58 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 25 May 2020 19:10:15 +0300 Subject: [PATCH 133/148] Ped comments cleanup --- src/audio/AudioLogic.cpp | 96 ++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index b6f883d4..86805733 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -3975,17 +3975,18 @@ cAudioManager::GetCopTalkSfx(int16 sound) PedState pedState; static uint32 lastSfx = NO_SAMPLE; - if (sound == SOUND_PED_ARREST_COP) { + switch (sound) { + case SOUND_PED_ARREST_COP: GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_ARREST_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_COP) { - return GetGenericMaleTalkSfx(sound); - } - + break; + case SOUND_PED_PURSUIT_COP: pedState = FindPlayerPed()->m_nPedState; if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; GetPhrase(&sfx, &lastSfx, SFX_COP_VOICE_1_CHASE_1, 7); + break; + default: + return GetGenericMaleTalkSfx(sound); } return (SFX_COP_VOICE_2_ARREST_1 - SFX_COP_VOICE_1_ARREST_1) * (m_sQueueSample.m_nEntityIndex % 5) + sfx; @@ -3998,17 +3999,18 @@ cAudioManager::GetSwatTalkSfx(int16 sound) PedState pedState; static uint32 lastSfx = NO_SAMPLE; - if (sound == SOUND_PED_ARREST_SWAT) { + switch (sound) { + case SOUND_PED_ARREST_SWAT: GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_SWAT) { - return GetGenericMaleTalkSfx(sound); - } - + break; + case SOUND_PED_PURSUIT_SWAT: pedState = FindPlayerPed()->m_nPedState; if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; GetPhrase(&sfx, &lastSfx, SFX_SWAT_VOICE_1_CHASE_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); } return (SFX_SWAT_VOICE_2_CHASE_1 - SFX_SWAT_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 4) + sfx; @@ -4021,17 +4023,18 @@ cAudioManager::GetFBITalkSfx(int16 sound) PedState pedState; static uint32 lastSfx = NO_SAMPLE; - if (sound == SOUND_PED_ARREST_FBI) { + switch (sound) { + case SOUND_PED_ARREST_FBI: GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); - } else { - if (sound != SOUND_PED_PURSUIT_FBI) { - return GetGenericMaleTalkSfx(sound); - } - + break; + case SOUND_PED_PURSUIT_FBI: pedState = FindPlayerPed()->m_nPedState; if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) return NO_SAMPLE; GetPhrase(&sfx, &lastSfx, SFX_FBI_VOICE_1_CHASE_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); } return (SFX_FBI_VOICE_2_CHASE_1 - SFX_FBI_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 3) + sfx; @@ -4044,15 +4047,16 @@ cAudioManager::GetArmyTalkSfx(int16 sound) PedState pedState; static uint32 lastSfx = NO_SAMPLE; - if (sound != SOUND_PED_PURSUIT_ARMY) { + switch (sound) { + case SOUND_PED_PURSUIT_ARMY: + pedState = FindPlayerPed()->m_nPedState; + if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) + return NO_SAMPLE; + GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); + default: return GetGenericMaleTalkSfx(sound); } - pedState = FindPlayerPed()->m_nPedState; - if (pedState == PED_ARRESTED || pedState == PED_DEAD || pedState == PED_DIE) - return NO_SAMPLE; - GetPhrase(&sfx, &lastSfx, SFX_ARMY_VOICE_1_CHASE_1, 15); - return (SFX_ARMY_VOICE_2_CHASE_1 - SFX_ARMY_VOICE_1_CHASE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; } @@ -4133,13 +4137,17 @@ cAudioManager::GetTaxiDriverTalkSfx(int16 sound) uint32 sfx; static uint32 lastSfx = NO_SAMPLE; - if (sound == SOUND_PED_CAR_JACKED) { + switch (sound) { + case SOUND_PED_CAR_JACKED: GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_CARJACKED_1, 7); - } else { - if (sound != SOUND_PED_CAR_COLLISION) - return GetGenericMaleTalkSfx(sound); + break; + case SOUND_PED_CAR_COLLISION: GetPhrase(&sfx, &lastSfx, SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1, 6); + break; + default: + return GetGenericMaleTalkSfx(sound); } + return (SFX_ASIAN_TAXI_DRIVER_VOICE_2_DRIVER_ABUSE_1 - SFX_ASIAN_TAXI_DRIVER_VOICE_1_DRIVER_ABUSE_1) * (m_sQueueSample.m_nEntityIndex % 2) + sfx; } @@ -6052,10 +6060,14 @@ cAudioManager::GetBomberTalkSfx(int16 sound) uint32 sfx; static uint32 lastSfx = NO_SAMPLE; - if (sound != SOUND_PED_BOMBER) + switch (sound) + { + case SOUND_PED_BOMBER: + GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7); + break; + default: return GetGenericMaleTalkSfx(sound); - - GetPhrase(&sfx, &lastSfx, SFX_BOMBERMAN_1, 7); + } return sfx; } @@ -6098,13 +6110,17 @@ cAudioManager::GetChunkyTalkSfx(int16 sound) uint32 sfx; static uint32 lastSfx = NO_SAMPLE; - if (sound == SOUND_PED_DEATH) + switch (sound) + { + case SOUND_PED_DEATH: return SFX_CHUNKY_DEATH; - - if (sound != SOUND_PED_FLEE_RUN) + case SOUND_PED_FLEE_RUN: + GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5); + break; + default: return GetGenericMaleTalkSfx(sound); + } - GetPhrase(&sfx, &lastSfx, SFX_CHUNKY_RUN_1, 5); return sfx; } @@ -6160,8 +6176,6 @@ cAudioManager::GetGenericFemaleTalkSfx(int16 sound) return sfx; } - - void cPedComments::Add(tPedComment *com) { @@ -6175,11 +6189,7 @@ cPedComments::Add(tPedComment *com) index = m_nCommentsInBank[m_nActiveBank]++; } - m_asPedComments[m_nActiveBank][index].m_nSampleIndex = com->m_nSampleIndex; - m_asPedComments[m_nActiveBank][index].m_nEntityIndex = com->m_nEntityIndex; - m_asPedComments[m_nActiveBank][index].m_vecPos = com->m_vecPos; - m_asPedComments[m_nActiveBank][index].m_fDistance = com->m_fDistance; - m_asPedComments[m_nActiveBank][index].m_bVolume = com->m_bVolume; + m_asPedComments[m_nActiveBank][index] = *com; uint32 i = 0; if (index != 0) { @@ -6466,7 +6476,7 @@ void cAudioManager::ProcessScriptObject(int32 id) { cAudioScriptObject *entity = (cAudioScriptObject *)m_asAudioEntities[id].m_pEntity; - if (entity) { + if (entity != 0) { m_sQueueSample.m_vecPos = entity->Posn; if (m_asAudioEntities[id].m_AudioEvents == 1) ProcessOneShotScriptObject(m_asAudioEntities[id].m_awAudioEvent[0]); From 7bf833785411955c2bcf35ed55e9d206facbc575 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 24 May 2020 15:14:27 +0200 Subject: [PATCH 134/148] CVehicle --- src/control/CarCtrl.cpp | 2 +- src/control/RoadBlocks.cpp | 4 +- src/control/RoadBlocks.h | 2 +- src/control/Script.cpp | 4 +- src/control/TrafficLights.cpp | 2 + src/core/Camera.cpp | 12 + src/core/Camera.h | 5 +- src/core/Collision.cpp | 9 +- src/core/Collision.h | 6 +- src/core/PlayerInfo.h | 1 + src/core/World.cpp | 62 +- src/core/World.h | 7 +- src/core/re3.cpp | 10 +- src/entities/Entity.cpp | 2 +- src/math/Vector2D.h | 4 +- src/math/math.cpp | 13 - src/modelinfo/ModelIndices.h | 3 +- src/peds/Ped.cpp | 15 +- src/peds/Ped.h | 3 +- src/render/Coronas.cpp | 6 +- src/render/Shadows.cpp | 8 +- src/render/Skidmarks.cpp | 4 +- src/render/SpecialFX.cpp | 1 + src/render/SpecialFX.h | 2 + src/render/Timecycle.cpp | 2 +- src/render/Timecycle.h | 2 +- src/render/Weather.cpp | 6 +- src/vehicles/Automobile.cpp | 73 +- src/vehicles/Automobile.h | 5 +- src/vehicles/Heli.cpp | 54 +- src/vehicles/Vehicle.cpp | 1481 ++++++++++++++++++++++++++++----- src/vehicles/Vehicle.h | 72 +- src/weapons/Weapon.cpp | 4 +- 33 files changed, 1448 insertions(+), 438 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 073195a4..1004e5de 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -913,7 +913,7 @@ CCarCtrl::RemoveDistantCars() PossiblyRemoveVehicle(pVehicle); if (pVehicle->bCreateRoadBlockPeds){ if ((pVehicle->GetPosition() - FindPlayerCentreOfWorld(CWorld::PlayerInFocus)).Magnitude2D() < DISTANCE_TO_SPAWN_ROADBLOCK_PEDS) { - CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType, pVehicle->m_nRoadblockNode); + CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType); pVehicle->bCreateRoadBlockPeds = false; } } diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 0261cd4a..a26e19f5 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -47,7 +47,7 @@ CRoadBlocks::Init(void) } void -CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode) +CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType) { static const CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f}, {1.5f, -1.8f, 0.0f}, {-1.5f, 0.0f, 0.0f}, {1.5, 0.0, 0.0} }; @@ -90,7 +90,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType pCopPed->SetIdle(); pCopPed->bKindaStayInSamePlace = true; pCopPed->bNotAllowedToDuck = false; - pCopPed->m_nRoadblockNode = roadBlockNode; +// pCopPed->m_nRoadblockNode = roadBlockNode; pCopPed->bCrouchWhenShooting = roadBlockType != 2; if (pEntityToAttack) { pCopPed->m_pPointGunAt = pEntityToAttack; diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h index 439fd6e7..c8469ba5 100644 --- a/src/control/RoadBlocks.h +++ b/src/control/RoadBlocks.h @@ -15,6 +15,6 @@ public: static bool InOrOut[NUMROADBLOCKS]; static void Init(void); - static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode); + static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType); static void GenerateRoadBlocks(void); }; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index cf2545c0..abcb29bc 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -10943,10 +10943,10 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) ScriptParams[1] = 0; else if (ScriptParams[1] == 3) ScriptParams[1] = 1; - pVehicle->BurstTyre(ScriptParams[1]); // TODO(MIAMI): second param is true + pVehicle->BurstTyre(ScriptParams[1], true); } else { - pVehicle->BurstTyre(ScriptParams[1]); // TODO(MIAMI): second param is true + pVehicle->BurstTyre(ScriptParams[1], true); } return 0; } diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 8487847f..54c97d06 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -108,6 +108,7 @@ CTrafficLights::DisplayActualLight(CEntity *ent) CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN); CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN); +/* static const float top = -0.127f; static const float bot = -0.539f; static const float mid = bot + (top-bot)/3.0f; @@ -131,6 +132,7 @@ CTrafficLights::DisplayActualLight(CEntity *ent) 1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, SHINYTEXT_WALK, 255, 255, 255, 60.0f); } +*/ } void diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 3b7bdbaf..f618c652 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -3281,6 +3281,18 @@ CCamera::Find3rdPersonQuickAimPitch(void) return -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot); } +bool +CCamera::Using1stPersonWeaponMode(void) +{ + switch(PlayerWeaponMode.Mode) + case CCam::MODE_SNIPER: + case CCam::MODE_M16_1STPERSON: + case CCam::MODE_ROCKETLAUNCHER: + case CCam::MODE_HELICANNON_1STPERSON: + case CCam::MODE_CAMERA: + return true; + return false; +} void diff --git a/src/core/Camera.h b/src/core/Camera.h index 135f9d8f..4e90855b 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -91,7 +91,9 @@ public: MODE_M16_1STPERSON_RUNABOUT, MODE_FIGHT_CAM_RUNABOUT, MODE_EDITOR, - MODE_HELICANNON_1STPERSON, // vice city leftover + MODE_HELICANNON_1STPERSON, + MODE_45, + MODE_CAMERA, }; bool bBelowMinDist; //used for follow ped mode @@ -625,6 +627,7 @@ public: void UpdateAimingCoors(CVector const &coors); void Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target); float Find3rdPersonQuickAimPitch(void); + bool Using1stPersonWeaponMode(void); // Physical camera void SetRwCamera(RwCamera *cam); diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index c29c1d28..d2e08f7c 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -414,8 +414,9 @@ CCollision::TestSphereTriangle(const CColSphere &sphere, return dist < sphere.radius; } +//--MIAMI: TODO bool -CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough) +CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough) { static CMatrix matTransform; int i; @@ -1042,10 +1043,11 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere, return true; } +//--MIAMI: TODO bool CCollision::ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, - CColPoint &point, float &mindist, bool ignoreSeeThrough) + CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough) { static CMatrix matTransform; int i; @@ -1081,10 +1083,11 @@ CCollision::ProcessLineOfSight(const CColLine &line, return false; } +//--MIAMI: TODO bool CCollision::ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, - CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly) + CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly) { static CStoredCollPoly TempStoredPoly; int i; diff --git a/src/core/Collision.h b/src/core/Collision.h index 4b0c2fb9..12af5225 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -151,7 +151,7 @@ public: static bool TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); static bool TestLineSphere(const CColLine &line, const CColSphere &sph); static bool TestSphereTriangle(const CColSphere &sphere, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); - static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough); + static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough); static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq); static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq); @@ -160,8 +160,8 @@ public: static bool ProcessLineTriangle(const CColLine &line , const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist); static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist); static bool ProcessSphereTriangle(const CColSphere &sph, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq); - static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough); - static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly); + static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough); + static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly); static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists); static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly); diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 119f0b2c..e2e874e6 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -51,6 +51,7 @@ public: int32 field_268; int32 field_272; uint32 m_nHavocLevel; + float m_fMediaAttention; bool m_bInfiniteSprint; bool m_bFastReload; bool m_bFireproof; diff --git a/src/core/World.cpp b/src/core/World.cpp index 433f9745..06108c5c 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -33,22 +33,24 @@ CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; -CPtrList CWorld::ms_bigBuildingsList[4];// = (CPtrList*)0x6FAB60; -CPtrList CWorld::ms_listMovingEntityPtrs;// = *(CPtrList*)0x8F433C; -CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];// = (CSector (*)[NUMSECTORS_Y])0x665608; -uint16 CWorld::ms_nCurrentScanCode;// = *(uint16*)0x95CC64; +CPtrList CWorld::ms_bigBuildingsList[4]; +CPtrList CWorld::ms_listMovingEntityPtrs; +CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X]; +uint16 CWorld::ms_nCurrentScanCode; -uint8 CWorld::PlayerInFocus;// = *(uint8 *)0x95CD61; +uint8 CWorld::PlayerInFocus; CPlayerInfo CWorld::Players[NUMPLAYERS]; -bool CWorld::bNoMoreCollisionTorque;// = *(bool*)0x95CDCC; -CEntity *CWorld::pIgnoreEntity;// = *(CEntity**)0x8F6494; -bool CWorld::bIncludeDeadPeds;// = *(bool*)0x95CD8F; -bool CWorld::bSecondShift;// = *(bool*)0x95CD54; -bool CWorld::bForceProcessControl;// = *(bool*)0x95CD6C; -bool CWorld::bProcessCutsceneOnly;// = *(bool*)0x95CD8B; +bool CWorld::bNoMoreCollisionTorque; +CEntity *CWorld::pIgnoreEntity; +bool CWorld::bIncludeDeadPeds; +bool CWorld::bSecondShift; +bool CWorld::bForceProcessControl; +bool CWorld::bProcessCutsceneOnly; -bool CWorld::bDoingCarCollisions;// = *(bool*)0x95CD8C; -bool CWorld::bIncludeCarTyres;// = *(bool*)0x95CDAA; +bool CWorld::bDoingCarCollisions; +bool CWorld::bIncludeCarTyres; + +CColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS]; void CWorld::Initialise() @@ -165,7 +167,7 @@ CWorld::CameraToIgnoreThisObject(CEntity *ent) bool CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, - bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) + bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { int x, xstart, xend; int y, ystart, yend; @@ -184,7 +186,7 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi #define LOSARGS \ CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, \ - checkDummies, ignoreSeeThrough, ignoreSomeObjects + checkDummies, ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough if(xstart == xend && ystart == yend) { // Only one sector @@ -266,7 +268,7 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi bool CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, - bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) + bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { float mindist = dist; bool deadPeds = !!bIncludeDeadPeds; @@ -274,39 +276,39 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin if(checkBuildings) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); } if(checkVehicles) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); } if(checkPeds) { if(deadPeds) bIncludeDeadPeds = true; ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); bIncludeDeadPeds = false; } if(checkObjects) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, - ignoreSeeThrough, ignoreSomeObjects); + ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough, ignoreSomeObjects); + ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough); } if(checkDummies) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); } bIncludeDeadPeds = deadPeds; @@ -320,7 +322,7 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin bool CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, - CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects) + CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { bool deadPeds = false; float mindist = dist; @@ -347,7 +349,7 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist, - ignoreSeeThrough)) + ignoreSeeThrough, ignoreShootThrough)) entity = e; } } @@ -436,7 +438,7 @@ CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CCol colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, - ignoreSeeThrough, poly)) + ignoreSeeThrough, false, poly)) entity = e; } } @@ -637,7 +639,7 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); - if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough)) + if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough, false)) return false; } } diff --git a/src/core/World.h b/src/core/World.h index 89f05cfd..3da774ba 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -71,6 +71,7 @@ public: static bool bProcessCutsceneOnly; static bool bDoingCarCollisions; static bool bIncludeCarTyres; + static CColPoint m_aTempColPts[MAX_COLLISION_POINTS]; static void Remove(CEntity *entity); static void Add(CEntity *entity); @@ -90,9 +91,9 @@ public: static bool CameraToIgnoreThisObject(CEntity *ent); - static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false); - static bool ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false); - static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects = false); + static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false, bool ignoreShootThrough = false); + static bool ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough); + static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough); static bool ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly); static bool ProcessVerticalLineSector(CSector §or, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly); static bool ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 8f808b61..a74e5ffa 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -273,7 +273,7 @@ DebugMenuPopulate(void) { if(1){ static const char *weathers[] = { - "Sunny", "Cloudy", "Rainy", "Foggy" + "Sunny", "Cloudy", "Rainy", "Foggy", "Extrasunny", "Stormy" }; DebugMenuEntry *e; e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil); @@ -281,9 +281,9 @@ DebugMenuPopulate(void) e = DebugMenuAddVar("Time & Weather", "Current Minute", &CClock::GetMinutesRef(), [](){ CWeather::InterpolationValue = CClock::GetMinutes()/60.0f; }, 1, 0, 59, nil); DebugMenuEntrySetWrap(e, true); - e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 3, weathers); + e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 5, weathers); DebugMenuEntrySetWrap(e, true); - e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers); + e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 5, weathers); DebugMenuEntrySetWrap(e, true); DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f); DebugMenuAddVar("Time & Weather", "Time scale", (float*)&CTimer::GetTimeScale(), nil, 0.1f, 0.0f, 10.0f); @@ -337,7 +337,11 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); }); DebugMenuAddCmd("Spawn", "Spawn Cuban", [](){ SpawnCar(MI_CUBAN); }); DebugMenuAddCmd("Spawn", "Spawn Voodoo", [](){ SpawnCar(MI_VOODOO); }); + DebugMenuAddCmd("Spawn", "Spawn Maverick", [](){ SpawnCar(MI_MAVERICK); }); + DebugMenuAddCmd("Spawn", "Spawn VCN Maverick", [](){ SpawnCar(MI_VCNMAV); }); DebugMenuAddCmd("Spawn", "Spawn Sparrow", [](){ SpawnCar(MI_SPARROW); }); + DebugMenuAddCmd("Spawn", "Spawn Sea Sparrow", [](){ SpawnCar(MI_SEASPAR); }); + DebugMenuAddCmd("Spawn", "Spawn Hunter", [](){ SpawnCar(MI_HUNTER); }); DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); }); DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); }); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index a0c5c484..68486a3c 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -910,7 +910,7 @@ CEntity::ProcessLightsForEntity(void) camDir *= 2.0f/dist; glareDir += camDir; glareDir.Normalise(); - float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunPosition()); + float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection()); if(camAngle > 0.0f){ float intens = Sqrt(camAngle) * CWeather::SunGlare; pos += camDir; diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h index 0885a5d2..7bfccae6 100644 --- a/src/math/Vector2D.h +++ b/src/math/Vector2D.h @@ -11,9 +11,7 @@ public: float Magnitude(void) const { return Sqrt(x*x + y*y); } float MagnitudeSqr(void) const { return x*x + y*y; } - void Normalise(void); - - void NormaliseSafe(void) { + void Normalise(void) { float sq = MagnitudeSqr(); if(sq > 0.0f){ float invsqrt = RecipSqrt(sq); diff --git a/src/math/math.cpp b/src/math/math.cpp index eeb9d3fa..e11d048c 100644 --- a/src/math/math.cpp +++ b/src/math/math.cpp @@ -4,19 +4,6 @@ // TODO: move more stuff into here -void -CVector2D::Normalise(void) -{ - float sq = MagnitudeSqr(); - assert(sq != 0.0f); // just be safe here - //if(sq > 0.0f){ - float invsqrt = RecipSqrt(sq); - x *= invsqrt; - y *= invsqrt; - //}else - // x = 1.0f; -} - void CMatrix::SetRotate(float xAngle, float yAngle, float zAngle) { diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 91ba650e..e7285b2f 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -302,7 +302,8 @@ enum MI_TRAIN = -1, MI_DODO = -2, - MI_NIGHTSTICK = 262, + MI_GOLFCLUB = 261, + MI_NIGHTSTICK, MI_KNIFE, MI_BASEBALL_BAT, MI_GRENADE = 270, diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7eb2491b..647ecef6 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -66,7 +66,7 @@ CPed *gapTempPedList[50]; uint16 gnNumTempPedList; -CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; +static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; // TODO(Miami) #define AUDIO_NOT_READY @@ -4558,7 +4558,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; } - if (m_pMyVehicle->CanPedExitCar()) { +// TODO(MIAMI): argument + if (m_pMyVehicle->CanPedExitCar(false)) { SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle); } else { m_fHealth = 0.0f; @@ -13372,7 +13373,8 @@ CPed::ProcessObjective(void) } else { bool targetHasVeh = m_pedInObjective->bInVehicle; if (!targetHasVeh - || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) { +// TODO(MIAMI): argument + || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar(false)) { m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); @@ -15427,13 +15429,13 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) } float minDist = 1.0f; belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol, - intersectionPoint, minDist, false, &m_collPoly); + intersectionPoint, minDist, false, false, &m_collPoly); if (collidedWithBoat && bWasStanding && !belowTorsoCollided) { ourLine.p0.z = ourLine.p1.z; ourLine.p1.z = ourLine.p1.z + gravityEffect; belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol, - intersectionPoint, minDist, false, &m_collPoly); + intersectionPoint, minDist, false, false, &m_collPoly); } if (belowTorsoCollided) { #ifndef VC_PED_PORTS @@ -16151,7 +16153,8 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) uint32 optedDoorNode = wantedDoorNode; bool teleportNeeded = false; bool isLow = !!veh->bLowVehicle; - if (!veh->CanPedExitCar()) { +// TODO(MIAMI): argument + if (!veh->CanPedExitCar(false)) { if (veh->pDriver && !veh->pDriver->IsPlayer()) { veh->AutoPilot.m_nCruiseSpeed = 0; veh->AutoPilot.m_nCarMission = MISSION_NONE; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 776aa1dd..155e6cea 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -447,7 +447,7 @@ public: uint32 bIsDrowning : 1; uint32 bDrownsInWater : 1; //uint32 b156_4 - //uint32 b156_8 + uint32 b156_8 : 1; uint32 bIsPlayerFriend : 1; #ifdef VC_PED_PORTS uint32 bHeadStuckInCollision : 1; @@ -864,6 +864,7 @@ public: static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); bool IsPlayer(void); + bool IsFemale(void) { return m_nPedType == PEDTYPE_CIVFEMALE || m_nPedType == PEDTYPE_PROSTITUTE; } bool UseGroundColModel(void); bool CanSetPedState(void); bool IsPedInControl(void); diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 8e832ab1..efe486fe 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -509,18 +509,18 @@ CCoronas::DoSunAndMoon(void) { // yeah, moon is done somewhere else.... - CVector sunCoors = CTimeCycle::GetSunPosition(); + CVector sunCoors = CTimeCycle::GetSunDirection(); sunCoors *= 150.0f; sunCoors += TheCamera.GetPosition(); - if(CTimeCycle::GetSunPosition().z > -0.2f){ + if(CTimeCycle::GetSunDirection().z > -0.2f){ float size = ((CGeneral::GetRandomNumber()&0xFF) * 0.005f + 10.0f) * CTimeCycle::GetSunSize(); RegisterCorona(SUN_CORE, CTimeCycle::GetSunCoreRed(), CTimeCycle::GetSunCoreGreen(), CTimeCycle::GetSunCoreBlue(), 255, sunCoors, size, 999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f); - if(CTimeCycle::GetSunPosition().z > 0.0f) + if(CTimeCycle::GetSunDirection().z > 0.0f) RegisterCorona(SUN_CORONA, CTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(), 255, sunCoors, 25.0f * CTimeCycle::GetSunSize(), diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index c512f35c..fac35aeb 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -643,12 +643,12 @@ CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, flo PolePos.y += fOffsetX * pPole->GetRight().y + fOffsetY * pPole->GetForward().y; PolePos.z += fOffsetZ; - PolePos.x += -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2); - PolePos.y += -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2); + PolePos.x += -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2); + PolePos.y += -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2); StoreStaticShadow((uintptr)pPole + nID + _TODOCONST(51), SHADOWTYPE_DARK, gpPostShadowTex, &PolePos, - -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2), - -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2), + -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2), + -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2), CTimeCycle::GetShadowSideX() * fPoleWidth, CTimeCycle::GetShadowSideY() * fPoleWidth, 2 * (int32)((pPole->GetUp().z - 0.5f) * CTimeCycle::GetShadowStrength() * 2.0f) / 3, diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index 7f057319..961c38a6 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -199,8 +199,8 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos; CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1]; - dist.NormaliseSafe(); - fwd.NormaliseSafe(); + dist.Normalise(); + fwd.Normalise(); CVector2D right(dist.y, -dist.x); float turn = DotProduct2D(fwd, right); turn = Abs(turn) + 1.0f; diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 7e08fbad..79ae21a5 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -28,6 +28,7 @@ RwImVertexIndex StreakIndexList[12]; RwIm3DVertex TraceVertices[6]; RwImVertexIndex TraceIndexList[12]; +bool CSpecialFX::bSnapShotActive; void CSpecialFX::Init(void) diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h index 2d9f18b1..7bc3750a 100644 --- a/src/render/SpecialFX.h +++ b/src/render/SpecialFX.h @@ -3,6 +3,8 @@ class CSpecialFX { public: + static bool bSnapShotActive; + static void Render(void); static void Update(void); static void Init(void); diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index c120c003..ab94f874 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -350,7 +350,7 @@ CTimeCycle::Update(void) m_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF; float sunAngle = 2*PI*(CClock::GetSeconds()/60.0f + CClock::GetMinutes() + CClock::GetHours()*60)/(24*60); - CVector &sunPos = GetSunPosition(); + CVector &sunPos = GetSunDirection(); sunPos.x = Sin(sunAngle); sunPos.y = 1.0f; sunPos.z = 0.2f - Cos(sunAngle); diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index 2d873e6d..60c9e29f 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -180,7 +180,7 @@ public: static void Initialise(void); static void Update(void); - static CVector &GetSunPosition(void) { return m_VectorToSun[m_CurrentStoredValue]; } + static CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; } static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; } static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; } static float GetShadowSideX(void) { return m_fShadowSideX[m_CurrentStoredValue]; } diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index fc3e0d61..324c63ea 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -18,6 +18,7 @@ #include "Vehicle.h" #include "World.h" #include "ZoneCull.h" +#include "SpecialFX.h" int32 CWeather::SoundHandle = -1; @@ -271,9 +272,10 @@ void CWeather::Update(void) SunGlare += InterpolationValue; if (SunGlare > 0.0f) { - SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunPosition().z); + SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunDirection().z); SunGlare = clamp(SunGlare, 0.0f, 1.0f); - // TODO(MIAMI): if (CSpecialFX::bSnapShotActive)... + if (!CSpecialFX::bSnapShotActive) + SunGlare *= (1.0f - (CGeneral::GetRandomNumber()&0x1F)*0.007f); } Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType]; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index dc406237..364415e9 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -77,6 +77,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) SetModelIndex(id); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); + pFlyingHandling = mod_HandlingManager.GetFlyingPointer((eHandlingId)mi->m_handlingId); field_49C = 20.0f; field_4D8 = 0; @@ -176,7 +177,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) m_nNumPassengers = 0; m_bombType = CARBOMB_NONE; - bHadDriver = false; + bDriverLastFrame = false; m_pBombRigger = nil; if(m_nDoorLock == CARLOCK_UNLOCKED && @@ -272,25 +273,14 @@ CAutomobile::ProcessControl(void) } // Process driver - if(pDriver){ - if(!bHadDriver && m_bombType == CARBOMB_ONIGNITIONACTIVE){ - // If someone enters the car and there is a bomb, detonate - m_nBombTimer = 1000; - m_pBlowUpEntity = m_pBombRigger; - if(m_pBlowUpEntity) - m_pBlowUpEntity->RegisterReference((CEntity**)&m_pBlowUpEntity); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TICK, 1.0f); - } - bHadDriver = true; + if(IsUpsideDown() && CanPedEnterCar()){ + if(!pDriver->IsPlayer() && + !(pDriver->m_leader && pDriver->m_leader->bInVehicle) && + pDriver->CharCreatedBy != MISSION_CHAR) + pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + } - if(IsUpsideDown() && CanPedEnterCar()){ - if(!pDriver->IsPlayer() && - !(pDriver->m_leader && pDriver->m_leader->bInVehicle) && - pDriver->CharCreatedBy != MISSION_CHAR) - pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); - } - }else - bHadDriver = false; + ActivateBombWhenEntered(); // Process passengers if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){ @@ -304,18 +294,7 @@ CAutomobile::ProcessControl(void) CRubbish::StirUp(this); - // blend in clump - int clumpAlpha = CVisibilityPlugins::GetClumpAlpha((RpClump*)m_rwObject); - if(bFadeOut){ - clumpAlpha -= 8; - if(clumpAlpha < 0) - clumpAlpha = 0; - }else if(clumpAlpha < 255){ - clumpAlpha += 16; - if(clumpAlpha > 255) - clumpAlpha = 255; - } - CVisibilityPlugins::SetClumpAlpha((RpClump*)m_rwObject, clumpAlpha); + UpdateClumpAlpha(); AutoPilot.m_bSlowedDownBecauseOfCars = false; AutoPilot.m_bSlowedDownBecauseOfPeds = false; @@ -726,19 +705,8 @@ CAutomobile::ProcessControl(void) traction *= 4.0f; if(FindPlayerVehicle() && FindPlayerVehicle() == this){ - if(CPad::GetPad(0)->WeaponJustDown()){ - if(m_bombType == CARBOMB_TIMED){ - m_bombType = CARBOMB_TIMEDACTIVE; - m_nBombTimer = 7000; - m_pBlowUpEntity = FindPlayerPed(); - CGarages::TriggerMessage("GA_12", -1, 3000, -1); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TIMED_ACTIVATED, 1.0f); - }else if(m_bombType == CARBOMB_ONIGNITION){ - m_bombType = CARBOMB_ONIGNITIONACTIVE; - CGarages::TriggerMessage("GA_12", -1, 3000, -1); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_ONIGNITION_ACTIVATED, 1.0f); - } - } + if(CPad::GetPad(0)->WeaponJustDown()) + ActivateBomb(); }else if(strongGrip1 || CVehicle::bCheat3){ traction *= 1.2f; acceleration *= 1.4f; @@ -1934,6 +1902,8 @@ CAutomobile::PreRender(void) } CShadows::StoreShadowForCar(this); + + DoSunGlare(); } void @@ -3939,7 +3909,7 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) if(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){ mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM])); - colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF); + colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM])); colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); colModel->numSpheres = 6; @@ -3949,9 +3919,8 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) return true; } -// this probably isn't used in III yet void -CAutomobile::BurstTyre(uint8 wheel) +CAutomobile::BurstTyre(uint8 wheel, bool applyForces) { switch(wheel){ case CAR_PIECE_WHEEL_LF: wheel = VEHWHEEL_FRONT_LEFT; break; @@ -3969,8 +3938,10 @@ CAutomobile::BurstTyre(uint8 wheel) CCarCtrl::SwitchVehicleToRealPhysics(this); } - ApplyMoveForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f)); - ApplyTurnForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f), GetForward()); + if(applyForces){ + ApplyMoveForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f)); + ApplyTurnForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f), GetForward()); + } } } @@ -4337,7 +4308,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data) return object; } -CColPoint spherepoints[MAX_COLLISION_POINTS]; +static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; CObject* CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) @@ -4457,7 +4428,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), this->GetMatrix(), *this->GetColModel(), - spherepoints, nil, nil) > 0) + aTempPedColPts, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index e096465e..883177aa 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -83,9 +83,10 @@ public: float m_aWheelRotation[4]; float m_aWheelPosition[4]; float m_aWheelSpeed[4]; + float m_fRotorSpeed; uint8 field_4D8; uint8 bTaxiLight : 1; - uint8 bHadDriver : 1; // for bombs + //uint8 bHadDriver : 1; // for bombs uint8 bFixedColour : 1; uint8 bBigWheels : 1; uint8 bWaterTight : 1; // no damage for non-player peds @@ -146,7 +147,7 @@ public: void RemoveRefsToVehicle(CEntity *ent); void BlowUpCar(CEntity *ent); bool SetUpWheelColModel(CColModel *colModel); - void BurstTyre(uint8 tyre); + void BurstTyre(uint8 tyre, bool applyForces); bool IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset); float GetHeightAboveRoad(void); void PlayCarHorn(void); diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 5cd6488a..1e0a8c27 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -558,60 +558,8 @@ CHeli::ProcessControl(void) void CHeli::PreRender(void) { - float angle; - uint8 i; - CColPoint point; - CEntity *entity; - uint8 r, g, b; - float testLowZ = FindPlayerCoors().z - 10.0f; float radius = (GetPosition().z - FindPlayerCoors().z - 10.0f - 1.0f) * 0.3f + 10.0f; - int frm = CTimer::GetFrameCounter() & 7; - - i = 0; - for(angle = 0.0f; angle < TWOPI; angle += TWOPI/32){ - CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f); - CVector dir = pos*0.01f; - pos += GetPosition(); - - if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)) - m_fHeliDustZ[frm] = point.point.z; - else - m_fHeliDustZ[frm] = -101.0f; - - switch(point.surfaceB){ - default: - case SURFACE_TARMAC: - r = 10; - g = 10; - b = 10; - break; - case SURFACE_GRASS: - r = 10; - g = 6; - b = 3; - break; - case SURFACE_DIRT: - r = 10; - g = 8; - b = 7; - break; - case SURFACE_DIRTTRACK: - r = 10; - g = 6; - b = 3; - break; - } - RwRGBA col = { r, g, b, 32 }; -#ifdef FIX_BUGS - pos.z = m_fHeliDustZ[frm]; -#else - // What the hell is the point of this? - pos.z = m_fHeliDustZ[(i - (i&3))/4]; // advance every 4 iterations, why not just /4? -#endif - if(pos.z > -200.0f && GetPosition().z - pos.z < 20.0f) - CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, 0.0f, col); - i++; - } + HeliDustGenerate(this, radius, FindPlayerCoors().z, Max(16.0f - 4.0f*CTimer::GetTimeStep(), 2.0f)); } void diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index f07b633c..c988bf3d 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -14,11 +14,22 @@ #include "Lights.h" #include "PointLights.h" #include "Renderer.h" +#include "VisibilityPlugins.h" #include "DMAudio.h" #include "Radar.h" #include "Fire.h" #include "Darkel.h" #include "Streaming.h" +#include "Camera.h" +#include "Stats.h" +#include "Garages.h" +#include "Wanted.h" +#include "SurfaceTable.h" +#include "Particle.h" +#include "WaterLevel.h" +#include "TimeCycle.h" +#include "Weather.h" +#include "Coronas.h" bool CVehicle::bWheelsOnlyCheat; bool CVehicle::bAllDodosCheat; @@ -53,8 +64,8 @@ CVehicle::CVehicle(uint8 CreatedBy) { int i; - m_nCurrentGear = 0; - m_fChangeGearTime = 0; + m_nCurrentGear = 1; + m_fChangeGearTime = 0.0f; m_fSteerRatio = 0.0f; m_type = ENTITY_TYPE_VEHICLE; VehicleCreatedBy = CreatedBy; @@ -106,10 +117,22 @@ CVehicle::CVehicle(uint8 CreatedBy) m_nCarHornDelay = 0; bPartOfConvoy = false; bHeliMinimumTilt = false; + bAudioChangingGear = false; bIsDrowning = false; bTyresDontBurst = false; bCreatedAsPoliceVehicle = false; + bRestingOnPhysical = false; bParking = false; + bCanPark = CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.0f; // BUG? this makes no sense + bIsVan = false; + bIsBus = false; + bIsBig = false; + bLowVehicle = false; + + m_bombType = CARBOMB_NONE; + bDriverLastFrame = false; + m_pBombRigger = nil; + m_nSetPieceExtendedRangeTime = 0; m_nAlarmState = 0; m_nDoorLock = CARLOCK_UNLOCKED; @@ -118,6 +141,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this); if(m_audioEntityId >= 0) DMAudio.SetEntityStatus(m_audioEntityId, true); +// TODO(MIAMI): m_nRadioStation = CGeneral::GetRandomNumber() % USERTRACK; m_pCurGroundEntity = nil; m_bRainAudioCounter = 0; @@ -131,9 +155,6 @@ CVehicle::CVehicle(uint8 CreatedBy) AutoPilot.m_bStayInCurrentLevel = false; AutoPilot.m_bIgnorePathfinding = false; AutoPilot.m_nSwitchDistance = 20; - -// TODO(MIAMI) - bRestingOnPhysical = false; } CVehicle::~CVehicle() @@ -198,57 +219,30 @@ CVehicle::RemoveLighting(bool reset) CRenderer::RemoveVehiclePedLights(this, reset); } +bool +CVehicle::IsClearToDriveAway(void) +{ + CColPoint point; + float length = GetColModel()->boundingBox.GetSize().y; + CEntity *ent = nil; + CVector front = GetForward() * (length*0.5f + 3.0f); + return !CWorld::ProcessLineOfSight(GetPosition() + front, GetPosition(), + point, ent, true, true, false, false, false, true, true) || + ent == this; +} + float CVehicle::GetHeightAboveRoad(void) { return -1.0f * GetColModel()->boundingBox.min.z; } -const float fRCPropFallOff = 3.0f; -const float fRCAeroThrust = 0.003f; -const float fRCSideSlipMult = 0.1f; -const float fRCRudderMult = 0.2f; -const float fRCYawMult = -0.01f; -const float fRCRollMult = 0.02f; -const float fRCRollStabilise = -0.08f; -const float fRCPitchMult = 0.005f; -const float fRCTailMult = 0.3f; -const float fRCFormLiftMult = 0.02f; -const float fRCAttackLiftMult = 0.25f; -const CVector vecRCAeroResistance(0.998f, 0.998f, 0.9f); - -const float fSeaPropFallOff = 2.3f; -const float fSeaThrust = 0.002f; -const float fSeaSideSlipMult = 0.1f; -const float fSeaRudderMult = 0.01f; -const float fSeaYawMult = -0.0003f; -const float fSeaRollMult = 0.0015f; -const float fSeaRollStabilise = -0.01f; -const float fSeaPitchMult = 0.0002f; -const float fSeaTailMult = 0.01f; -const float fSeaFormLiftMult = 0.012f; -const float fSeaAttackLiftMult = 0.1f; -const CVector vecSeaAeroResistance(0.995f, 0.995f, 0.85f); - -const float fSpeedResistanceY = 500.0f; -const float fSpeedResistanceZ = 500.0f; - -const CVector vecHeliMoveRes(0.995f, 0.995f, 0.99f); -const CVector vecRCHeliMoveRes(0.99f, 0.99f, 0.99f); -const float fThrustVar = 0.3f; -const float fRotorFallOff = 0.75f; -const float fStabiliseVar = 0.015f; -const float fPitchBrake = 10.0f; -const float fPitchVar = 0.006f; -const float fRollVar = 0.006f; -const float fYawVar = -0.001f; -const CVector vecHeliResistance(0.81f, 0.85f, 0.99f); -const CVector vecRCHeliResistance(0.92f, 0.92f, 0.998f); -const float fSpinSpeedRes = 20.0f; - void CVehicle::FlyingControl(eFlightModel flightModel) { + if(pFlyingHandling == nil) + return; + switch(flightModel){ case FLIGHT_MODEL_DODO: { @@ -289,6 +283,8 @@ CVehicle::FlyingControl(eFlightModel flightModel) m_vecTurnSpeed.y *= Pow(0.9f, CTimer::GetTimeStep()); + + moveSpeed = m_vecMoveSpeed.MagnitudeSqr(); if(moveSpeed > SQR(1.5f)) m_vecMoveSpeed *= 1.5f/Sqrt(moveSpeed); @@ -296,172 +292,199 @@ CVehicle::FlyingControl(eFlightModel flightModel) float turnSpeed = m_vecTurnSpeed.MagnitudeSqr(); if(turnSpeed > SQR(0.2f)) m_vecTurnSpeed *= 0.2f/Sqrt(turnSpeed); - } break; + } case FLIGHT_MODEL_RCPLANE: case FLIGHT_MODEL_SEAPLANE: + case FLIGHT_MODEL_PLANE_UNUSED: + case FLIGHT_MODEL_PLANE: { + float fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; + float fSteerUD = -CPad::GetPad(0)->GetSteeringUpDown() / 128.0f; + float fGunUD = Abs(CPad::GetPad(0)->GetCarGunUpDown()); + if(fGunUD > 1.0f) + fSteerUD = -CPad::GetPad(0)->GetCarGunUpDown() / 128.0f; + + float fSteerAngle = Atan2(fSteerUD, fSteerLR); + float fSteerMult = 1.0f; + if(fSteerAngle > -PI/4.0f && fSteerAngle <= PI/4.0f) + fSteerMult = 1.0f/Cos(fSteerAngle); + else if(fSteerAngle > PI/4.0f && fSteerAngle <= PI*3.0f/4.0f) + fSteerMult = 1.0f/Cos(fSteerAngle - HALFPI); + else if(fSteerAngle > PI*3.0f/4.0f) + fSteerMult = 1.0f/Cos(fSteerAngle - PI); + else if(fSteerAngle <= -PI*3.0f/4.0f) + fSteerMult = 1.0f/Cos(fSteerAngle + PI); + else if(fSteerAngle > -PI*3.0f/4.0f && fSteerAngle < -PI/4.0f) + fSteerMult = 1.0f/Cos(fSteerAngle + HALFPI); + + fSteerLR *= fSteerMult; + fSteerUD *= -fSteerMult; + // thrust float fForwSpeed = DotProduct(GetMoveSpeed(), GetForward()); CVector vecWidthForward = GetColModel()->boundingBox.min.y * GetForward(); float fThrust = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f; - if (fForwSpeed > 0.1f || (flightModel == FLIGHT_MODEL_RCPLANE && fForwSpeed > 0.02f)) - fThrust += 1.0f; - else if (fForwSpeed > 0.0f && fThrust < 0.0f) - fThrust = 0.0f; - float fThrustImpulse; - if (flightModel == FLIGHT_MODEL_RCPLANE) - fThrustImpulse = (fThrust - fRCPropFallOff * fForwSpeed) * fRCAeroThrust; + float fThrustAccel; + if(fForwSpeed > 0.0f || fThrust > 0.0f) + fThrustAccel = (fThrust - pFlyingHandling->fThrustFallOff * fForwSpeed) * pFlyingHandling->fThrust; else - fThrustImpulse = (fThrust - fSeaPropFallOff * fForwSpeed) * fSeaThrust; - ApplyMoveForce(fThrustImpulse * GetForward() * m_fMass * CTimer::GetTimeStep()); + fThrustAccel = Min(fThrust - 8.0f * pFlyingHandling->fThrustFallOff * fForwSpeed, 0.0f) * pFlyingHandling->fThrust; + if(flightModel == FLIGHT_MODEL_PLANE_UNUSED) + fThrustAccel *= 0.3f; + else if(flightModel == FLIGHT_MODEL_PLANE) + fThrustAccel *= 0.1f; + ApplyMoveForce(fThrustAccel * GetForward() * m_fMass * CTimer::GetTimeStep()); // left/right float fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight()); - float fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; - float fSideSlipImpulse; - if (flightModel == FLIGHT_MODEL_RCPLANE) - fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fRCSideSlipMult; - else - fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fSeaSideSlipMult; - ApplyMoveForce(m_fMass * GetRight() * fSideSlipImpulse * CTimer::GetTimeStep()); + float fSideSlipAccel = pFlyingHandling->fSideSlip * fSideSpeed * Abs(fSideSpeed); + ApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep()); - float fYaw = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetRight()); - float fYawImpulse; - if (flightModel == FLIGHT_MODEL_RCPLANE) - fYawImpulse = fRCRudderMult * fYaw * Abs(fYaw) + fRCYawMult * fSteerLR * fForwSpeed; - else - fYawImpulse = fSeaRudderMult * fYaw * Abs(fYaw) + fSeaYawMult * fSteerLR * fForwSpeed; - ApplyTurnForce(fYawImpulse * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward); + float fYaw = -DotProduct(GetSpeed(vecWidthForward), GetRight()); + float fYawAccel = pFlyingHandling->fYawStab * fYaw * Abs(fYaw) + pFlyingHandling->fYaw * fSteerLR * fForwSpeed; + ApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward); - float fRollImpulse; + float fRollAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) { float fDirectionMultiplier = CPad::GetPad(0)->GetLookRight(); if (CPad::GetPad(0)->GetLookLeft()) fDirectionMultiplier = -1; - fRollImpulse = (0.5f * fDirectionMultiplier + fSteerLR) * fRCRollMult; + fRollAccel = (0.5f * fDirectionMultiplier + fSteerLR) * pFlyingHandling->fRoll; } else - fRollImpulse = fSteerLR * fSeaRollMult; - ApplyTurnForce(GetRight() * fRollImpulse * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); + fRollAccel = fSteerLR * pFlyingHandling->fRoll; + ApplyTurnForce(GetRight() * fRollAccel * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); CVector vecFRight = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f)); CVector vecStabilise = (GetUp().z > 0.0f) ? vecFRight : -vecFRight; float fStabiliseDirection = (GetRight().z > 0.0f) ? -1.0f : 1.0f; - float fStabiliseImpulse; - if (flightModel == FLIGHT_MODEL_RCPLANE) - fStabiliseImpulse = fRCRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); - else - fStabiliseImpulse = fSeaRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); - ApplyTurnForce(fStabiliseImpulse * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? VC doesn't have it too + float fStabiliseSpeed = pFlyingHandling->fRollStab * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); + ApplyTurnForce(fStabiliseSpeed * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? // up/down - float fTail = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetUp()); - float fSteerUD = -CPad::GetPad(0)->GetSteeringUpDown() / 128.0f; - float fPitchImpulse; - if (flightModel == FLIGHT_MODEL_RCPLANE) - fPitchImpulse = fRCTailMult * fTail * Abs(fTail) + fRCPitchMult * fSteerUD * fForwSpeed; - else - fPitchImpulse = fSeaTailMult * fTail * Abs(fTail) + fSeaPitchMult * fSteerUD * fForwSpeed; - ApplyTurnForce(fPitchImpulse * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward); + float fTail = -DotProduct(GetSpeed(vecWidthForward), GetUp()); + float fPitchAccel = pFlyingHandling->fPitchStab * fTail * Abs(fTail) + pFlyingHandling->fPitch * fSteerUD * fForwSpeed; + ApplyTurnForce(fPitchAccel * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward); float fLift = -DotProduct(GetMoveSpeed(), GetUp()) / Max(0.01f, GetMoveSpeed().Magnitude()); - float fLiftImpluse; - if (flightModel == FLIGHT_MODEL_RCPLANE) - fLiftImpluse = (fRCAttackLiftMult * fLift + fRCFormLiftMult) * fForwSpeed * fForwSpeed; - else - fLiftImpluse = (fSeaAttackLiftMult * fLift + fSeaFormLiftMult) * fForwSpeed * fForwSpeed; - float fLiftForce = fLiftImpluse * m_fMass * CTimer::GetTimeStep(); - if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpluse) { + float fLiftAccel = (pFlyingHandling->fAttackLift * fLift + pFlyingHandling->fFormLift) * fForwSpeed * fForwSpeed; + float fLiftImpulse = fLiftAccel * m_fMass * CTimer::GetTimeStep(); + if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpulse) { if (flightModel == FLIGHT_MODEL_RCPLANE && GetPosition().z > 50.0f) - fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass; + fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass; else if (flightModel == FLIGHT_MODEL_SEAPLANE && GetPosition().z > 80.0f) - fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass; + fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass; } - ApplyMoveForce(fLiftForce * GetUp()); + ApplyMoveForce(fLiftImpulse * GetUp()); + CVector vecResistance; - if (flightModel == FLIGHT_MODEL_RCPLANE) - vecResistance = vecRCAeroResistance; - else - vecResistance = vecSeaAeroResistance; + vecResistance = pFlyingHandling->vecTurnRes; float rX = Pow(vecResistance.x, CTimer::GetTimeStep()); float rY = Pow(vecResistance.y, CTimer::GetTimeStep()); float rZ = Pow(vecResistance.z, CTimer::GetTimeStep()); CVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); vecTurnSpeed.x *= rX; - float fResistance = vecTurnSpeed.y * (1.0f / (fSpeedResistanceY * SQR(vecTurnSpeed.y) + 1.0f)) * rY - vecTurnSpeed.y; + float fResistance = vecTurnSpeed.y * (1.0f / (pFlyingHandling->vecSpeedRes.y * SQR(vecTurnSpeed.y) + 1.0f)) * rY - vecTurnSpeed.y; vecTurnSpeed.z *= rZ; m_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed); ApplyTurnForce(-GetUp() * fResistance * m_fTurnMass, GetRight() + Multiply3x3(GetMatrix(), m_vecCentreOfMass)); + + + float fMoveSpeed = m_vecMoveSpeed.MagnitudeSqr(); + if(fMoveSpeed > SQR(1.5f)) + m_vecMoveSpeed *= 1.5f/Sqrt(fMoveSpeed); + + float fTurnSpeed = m_vecTurnSpeed.MagnitudeSqr(); + if(fTurnSpeed > SQR(0.2f)) + m_vecTurnSpeed *= 0.2f/Sqrt(fTurnSpeed); break; } + case FLIGHT_MODEL_RCHELI: case FLIGHT_MODEL_HELI: { - CVector vecMoveResistance; - if (GetModelIndex() == MI_SPARROW) - vecMoveResistance = vecHeliMoveRes; - else - vecMoveResistance = vecRCHeliMoveRes; - float rmX = Pow(vecMoveResistance.x, CTimer::GetTimeStep()); - float rmY = Pow(vecMoveResistance.y, CTimer::GetTimeStep()); - float rmZ = Pow(vecMoveResistance.z, CTimer::GetTimeStep()); - m_vecMoveSpeed.x *= rmX; - m_vecMoveSpeed.y *= rmY; - m_vecMoveSpeed.z *= rmZ; + float rm = Pow(pFlyingHandling->fMoveRes, CTimer::GetTimeStep()); + m_vecMoveSpeed *= rm; if (GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE) return; - float fThrust; - if (bCheat5) - fThrust = CPad::GetPad(0)->GetSteeringUpDown() * fThrustVar / 128.0f + 0.95f; - else - fThrust = fThrustVar * (CPad::GetPad(0)->GetAccelerate() - 2 * CPad::GetPad(0)->GetBrake()) / 255.0f + 0.95f; - fThrust -= fRotorFallOff * DotProduct(m_vecMoveSpeed, GetUp()); -#ifdef GTA3_1_1_PATCH - if (fThrust > 0.9f && GetPosition().z > 80.0f) - fThrust = 0.9f; -#endif + float fUpSpeed = DotProduct(m_vecMoveSpeed, GetUp()); + float fThrust = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f; + if(fThrust < 0.0f) + fThrust *= 2.0f; + if(flightModel == FLIGHT_MODEL_RCHELI){ + fThrust = pFlyingHandling->fThrust * fThrust + 0.45f; + ApplyMoveForce(GRAVITY * CVector(0.0f, 0.0f, 0.5f) * m_fMass * CTimer::GetTimeStep()); + }else + fThrust = pFlyingHandling->fThrust * fThrust + 0.95f; + fThrust -= pFlyingHandling->fThrustFallOff * fUpSpeed; + if(flightModel == FLIGHT_MODEL_RCHELI && GetPosition().z > 40.0f) + fThrust *= 10.0f/(GetPosition().z - 30.0f); + else if(GetPosition().z > 80.0f) + fThrust *= 10.0f/(GetPosition().z - 70.0f); ApplyMoveForce(GRAVITY * GetUp() * fThrust * m_fMass * CTimer::GetTimeStep()); - if (GetUp().z > 0.0f) - ApplyTurnForce(-CVector(GetUp().x, GetUp().y, 0.0f) * fStabiliseVar * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); + if (GetUp().z > 0.0f){ + float upRight = clamp(GetRight().z, -pFlyingHandling->fFormLift, pFlyingHandling->fFormLift); + float upImpulseRight = -upRight * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep(); + ApplyTurnForce(upImpulseRight * GetUp(), GetRight()); + + float upFwd = clamp(GetForward().z, -pFlyingHandling->fFormLift, pFlyingHandling->fFormLift); + float upImpulseFwd = -upFwd * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep(); + ApplyTurnForce(upImpulseFwd * GetUp(), GetForward()); + }else{ + float upRight = GetRight().z < 0.0f ? -pFlyingHandling->fFormLift : pFlyingHandling->fFormLift; + float upImpulseRight = -upRight * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep(); + ApplyTurnForce(upImpulseRight * GetUp(), GetRight()); + + float upFwd = GetForward().z < 0.0f ? -pFlyingHandling->fFormLift : pFlyingHandling->fFormLift; + float upImpulseFwd = -upFwd * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep(); + ApplyTurnForce(upImpulseFwd * GetUp(), GetForward()); + } float fRoll, fPitch, fYaw; if (bCheat5) { - fPitch = CPad::GetPad(0)->GetCarGunUpDown() / 128.0f; - fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; - fYaw = CPad::GetPad(0)->GetCarGunLeftRight() / 128.0f; - } - else { fPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f; + fRoll = CPad::GetPad(0)->GetLookLeft(); + if (CPad::GetPad(0)->GetLookRight()) + fRoll = -1.0f; + fYaw = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; + } else { + fPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f; + fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; fYaw = CPad::GetPad(0)->GetLookRight(); if (CPad::GetPad(0)->GetLookLeft()) fYaw = -1.0f; - fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; + if(Abs(CPad::GetPad(0)->GetCarGunLeftRight()) > 1.0f) + fYaw = CPad::GetPad(0)->GetCarGunLeftRight() / 128.0f; } + if(Abs(CPad::GetPad(0)->GetCarGunUpDown()) > 1.0f) + fPitch = -CPad::GetPad(0)->GetCarGunUpDown() / 128.0f; if (CPad::GetPad(0)->GetHorn()) { fYaw = 0.0f; - fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetUp()), -200.0f, 1.3f); - fRoll = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f); + fPitch = clamp(pFlyingHandling->fPitchStab * DotProduct(m_vecMoveSpeed, GetForward()), -200.0f, 1.3f); + fRoll = clamp(pFlyingHandling->fRollStab * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f); } - ApplyTurnForce(fPitch * GetUp() * fPitchVar * m_fTurnMass * CTimer::GetTimeStep(), GetForward()); - ApplyTurnForce(fRoll * GetUp() * fRollVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); - ApplyTurnForce(fYaw * GetForward() * fYawVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); + ApplyTurnForce(fPitch * GetUp() * pFlyingHandling->fPitch * m_fTurnMass * CTimer::GetTimeStep(), GetForward()); + ApplyTurnForce(fRoll * GetUp() * pFlyingHandling->fRoll * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); - CVector vecResistance; - if (GetModelIndex() == MI_SPARROW) - vecResistance = vecHeliResistance; - else - vecResistance = vecRCHeliResistance; - float rX = Pow(vecResistance.x, CTimer::GetTimeStep()); - float rY = Pow(vecResistance.y, CTimer::GetTimeStep()); - float rZ = Pow(vecResistance.z, CTimer::GetTimeStep()); + float fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight()); + float fSideSlipAccel = pFlyingHandling->fSideSlip * fSideSpeed * Abs(fSideSpeed); + ApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep()); + float fYawAccel = pFlyingHandling->fYawStab * fSideSpeed * Abs(fSideSpeed) + pFlyingHandling->fYaw * fYaw; + ApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), -GetForward()); + + ApplyTurnForce(fYaw * GetForward() * pFlyingHandling->fYaw * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); + + float rX = Pow(pFlyingHandling->vecTurnRes.x, CTimer::GetTimeStep()); + float rY = Pow(pFlyingHandling->vecTurnRes.y, CTimer::GetTimeStep()); + float rZ = Pow(pFlyingHandling->vecTurnRes.z, CTimer::GetTimeStep()); CVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); - float fResistanceMultiplier = Pow(1.0f / (fSpinSpeedRes * SQR(vecTurnSpeed.z) + 1.0f), CTimer::GetTimeStep()); + float fResistanceMultiplier = Pow(1.0f / (pFlyingHandling->vecSpeedRes.z * SQR(vecTurnSpeed.z) + 1.0f) * rZ, CTimer::GetTimeStep()); float fResistance = vecTurnSpeed.z * fResistanceMultiplier - vecTurnSpeed.z; vecTurnSpeed.x *= rX; vecTurnSpeed.y *= rY; - vecTurnSpeed.z *= rZ; + vecTurnSpeed.z *= fResistanceMultiplier; m_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed); ApplyTurnForce(-GetRight() * fResistance * m_fTurnMass, GetForward() + Multiply3x3(GetMatrix(), m_vecCentreOfMass)); break; @@ -469,6 +492,228 @@ CVehicle::FlyingControl(eFlightModel flightModel) } } +static CColModel rotorColModel; +static CColSphere rotorColSphere; +float ROTOR_SEMI_THICKNESS = 0.05f; +float ROTOR_TURN_SPEED = 0.2f; +float ROTOR_DISGUARD_MULT = 0.3f; +float ROTOR_COL_ELASTICITY = 1.0f; +float ROTOR_COL_TURNMULT = -0.001f; +float ROTOR_DEFAULT_DAMAGE = 100.0f; + +bool +CVehicle::DoBladeCollision(CVector pos, CMatrix &matrix, int16 rotorType, float radius, float damageMult) +{ + CVector max(radius, radius, radius); + CVector min(-radius, -radius, -radius); + + switch(rotorType){ + case ROTOR_TOP: + case ROTOR_BOTTOM: + min.z = -ROTOR_SEMI_THICKNESS; + max.z = ROTOR_SEMI_THICKNESS; + break; + case ROTOR_FRONT: + case ROTOR_BACK: + min.y = -ROTOR_SEMI_THICKNESS; + max.y = ROTOR_SEMI_THICKNESS; + break; + case ROTOR_RIGHT: + case ROTOR_LEFT: + min.x = -ROTOR_SEMI_THICKNESS; + max.x = ROTOR_SEMI_THICKNESS; + break; + } + + min += pos; + max += pos; + rotorColModel.boundingBox.Set(min, max); + rotorColModel.boundingSphere.Set(radius, pos); + rotorColSphere.Set(radius, pos, 0, 0); + rotorColModel.spheres = &rotorColSphere; + rotorColModel.numSpheres = 1; + + pos = matrix * pos; + bool hadCollision; + int minX = CWorld::GetSectorIndexX(pos.x - radius); + if(minX <= 0) minX = 0; + + int minY = CWorld::GetSectorIndexY(pos.y - radius); + if(minY <= 0) minY = 0; + + int maxX = CWorld::GetSectorIndexX(pos.x + radius); +#ifdef FIX_BUGS + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; +#else + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; +#endif + + int maxY = CWorld::GetSectorIndexY(pos.y + radius); +#ifdef FIX_BUGS + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; +#else + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; +#endif + + CWorld::AdvanceCurrentScanCode(); + for(int curY = minY; curY <= maxY; curY++) { + for(int curX = minX; curX <= maxX; curX++) { + CSector *sector = CWorld::GetSector(curX, curY); + if(BladeColSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], rotorColModel, matrix, rotorType, damageMult)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], rotorColModel, matrix, rotorType, damageMult)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_VEHICLES], rotorColModel, matrix, rotorType, damageMult)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], rotorColModel, matrix, rotorType, damageMult)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_PEDS], rotorColModel, matrix, rotorType, 0.0f)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], rotorColModel, matrix, rotorType, 0.0f)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_OBJECTS], rotorColModel, matrix, rotorType, damageMult)) + hadCollision = true; + if(BladeColSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], rotorColModel, matrix, rotorType, damageMult)) + hadCollision = true; + } + } + rotorColModel.spheres = nil; + rotorColModel.numSpheres = 0; + + return hadCollision; +} + +bool +CVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &matrix, int16 rotorType, float damageMult) +{ + int i; + CVector axis; + CVector turnSpeed(0.0f, 0.0f, 0.0f); + switch(rotorType){ + case ROTOR_TOP: + turnSpeed.z = -ROTOR_TURN_SPEED; + axis = -matrix.GetUp(); + break; + case ROTOR_BOTTOM: + turnSpeed.z = ROTOR_TURN_SPEED; + axis = matrix.GetUp(); + break; + + case ROTOR_FRONT: + turnSpeed.y = -ROTOR_TURN_SPEED; + axis = -matrix.GetForward(); + break; + case ROTOR_BACK: + turnSpeed.y = ROTOR_TURN_SPEED; + axis = matrix.GetForward(); + break; + + case ROTOR_RIGHT: + turnSpeed.x = -ROTOR_TURN_SPEED; + axis = -matrix.GetRight(); + break; + case ROTOR_LEFT: + turnSpeed.x = ROTOR_TURN_SPEED; + axis = matrix.GetRight(); + break; + } + turnSpeed = Multiply3x3(matrix, turnSpeed); + CVector center = rotorColModel.boundingSphere.center; + center = matrix*center; + + for(CPtrNode *node = list.first; node; node = node->next) { + CEntity *entity = (CEntity *)node->item; + if(entity == (CEntity*)this || + !entity->bUsesCollision || + entity->m_scanCode == CWorld::GetCurrentScanCode()) + continue; + + entity->m_scanCode = CWorld::GetCurrentScanCode(); + + int numCollisions; + CColModel *entityCol; + if(entity->IsPed()) + entityCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex()))->AnimatePedColModelSkinned(entity->GetClump()); + else + entityCol = CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel(); + if(entityCol) + numCollisions = CCollision::ProcessColModels(matrix, rotorColModel, entity->GetMatrix(), *entityCol, + CWorld::m_aTempColPts, nil, nil); + else + numCollisions = 0; + + if(numCollisions > 0 && entity->IsPed()){ + CPed *ped = (CPed*)entity; + CVector2D dirToRotor = GetPosition() - entity->GetPosition(); + dirToRotor.Normalise(); + int localDir = ped->GetLocalDirection(dirToRotor); + if(ped->m_attachedTo == nil){ + ped->bIsStanding = false; + ped->ApplyMoveForce(-5.0f*dirToRotor.x, -5.0f*dirToRotor.y, 5.0f); + } + ped->InflictDamage(this, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, localDir); + + if(CGame::nastyGame && ped->GetIsOnScreen()){ + for(i = 0; i < 16; i++) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, ped->GetPosition(), CVector(dirToRotor.x, dirToRotor.y, 1.0f) * 0.01f); + CParticle::AddParticle(PARTICLE_TEST, ped->GetPosition(), CVector(0.0f, 0.0f, 0.02f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_TEST, ped->GetPosition()+CVector(0.0f, 0.0f, 0.2f), CVector(0.0f, 0.0f, -0.01f), nil, 0.1f); + } + }else if(numCollisions > 0 && entity->GetModelIndex() != MI_MISSILE){ + float impulse = 0.0f; + bool hadCollision = false; + float savedElasticity = m_fElasticity; + m_fElasticity = ROTOR_COL_ELASTICITY; + + for(i = 0; i < numCollisions; i++){ + CVector colpos = CWorld::m_aTempColPts[i].point; + CVector localColpos = colpos - center; + float axisDir = DotProduct(axis, localColpos); + float colDir = DotProduct(CWorld::m_aTempColPts[i].normal, localColpos); + if(2.0f*ROTOR_SEMI_THICKNESS < Abs(axisDir) && + ROTOR_DISGUARD_MULT*Abs(colDir) < Abs(axisDir)) + continue; + + colpos -= axisDir*axis; // get rid of axis component + + CVector tangentSpeed = CrossProduct(turnSpeed, colpos - center); + + // Particles + for(int j = 0; j < 4; j++){ + CParticle::AddParticle(PARTICLE_SPARK_SMALL, colpos, (tangentSpeed+m_vecMoveSpeed)/2.0f); + CParticle::AddParticle(PARTICLE_SPARK, colpos, 0.1f*CWorld::m_aTempColPts[i].normal); + } + + // Apply Collision + if(IsCar()){ + CAutomobile *heli = (CAutomobile*)this; + if(heli->m_fRotorSpeed > 0.15f){ + ApplyCollision(CWorld::m_aTempColPts[i], impulse); + ApplyTurnForce(m_fTurnMass*ROTOR_COL_TURNMULT*tangentSpeed, colpos - center); + heli->m_fRotorSpeed = 0.15f; + }else if(heli->m_fRotorSpeed < 0.075f && heli->m_fRotorSpeed > 0.0f) + heli->m_fRotorSpeed *= -1.0f; + } + + float damageImpulse = damageMult * Max(impulse, ROTOR_DEFAULT_DAMAGE*m_fMass/3000.0f); + if(damageImpulse > m_fDamageImpulse) + SetDamagedPieceRecord(0, damageImpulse, entity, CWorld::m_aTempColPts[i].normal); + + hadCollision = true; + } + + if(hadCollision && !entity->IsPed()) + DMAudio.ReportCollision(this, entity, SURFACE_BILLBOARD, SURFACE_TARMAC, 50.0f, 0.09f); + m_fElasticity = savedElasticity; + } + } + return false; +} + + +float fBurstSpeedMax = 0.3f; +float fBurstTyreMod = 0.13f; + void CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus) @@ -478,6 +723,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon static bool bBraking; static bool bDriving; +#ifdef FIX_BUGS + bAlreadySkidding = false; +#endif + // how much force we want to apply in these axes float fwd = 0.0f; float right = 0.0f; @@ -509,8 +758,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon #endif if(wheelStatus == WHEEL_STATUS_BURST){ - float fwdspeed = Min(contactSpeedFwd, 0.3f); - right += fwdspeed * CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + float fwdspeed = Min(contactSpeedFwd, fBurstSpeedMax); + right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod); } } @@ -535,7 +784,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(!bBraking){ if(m_fGasPedal < 0.01f){ - if(GetModelIndex() == MI_RCBANDIT) + if(IsBike()) + brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f); + else if(pHandling->fMass < 500.0f) + brake = mod_HandlingManager.fWheelFriction / m_fMass; + else if(GetModelIndex() == MI_RCBANDIT) brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass; else brake = mod_HandlingManager.fWheelFriction / m_fMass; @@ -559,7 +812,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } } - if(sq(adhesion) < sq(right) + sq(fwd)){ + float speedSq = sq(right) + sq(fwd); + if(sq(adhesion) < speedSq){ if(*wheelState != WHEEL_STATE_FIXED){ if(bDriving && contactSpeedFwd < 0.2f) *wheelState = WHEEL_STATE_SPINNING; @@ -567,22 +821,205 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon *wheelState = WHEEL_STATE_SKIDDING; } - float l = Sqrt(sq(right) + sq(fwd)); + float l = Sqrt(speedSq); float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss; right *= adhesion * tractionLoss / l; fwd *= adhesion * tractionLoss / l; } + if(fwd != 0.0f || right != 0.0f){ + CVector totalSpeed = fwd*wheelFwd + right*wheelRight; + + CVector turnDirection = totalSpeed; + bool separateTurnForce = false; // BUG: not initialized on PC + if(pHandling->fSuspensionAntidiveMultiplier > 0.0f){ + if(bBraking){ + separateTurnForce = true; + turnDirection = totalSpeed - pHandling->fSuspensionAntidiveMultiplier*fwd*wheelFwd; + }else if(bDriving){ + separateTurnForce = true; + turnDirection = totalSpeed - 0.5f*pHandling->fSuspensionAntidiveMultiplier*fwd*wheelFwd; + } + } + + CVector direction = totalSpeed; + + float speed = totalSpeed.Magnitude(); + float turnSpeed; + if(separateTurnForce) + turnSpeed = turnDirection.Magnitude(); + else + turnSpeed = speed; + direction.Normalise(); + if(separateTurnForce) + turnDirection.Normalise(); + else + turnDirection = direction; + + float impulse = speed*m_fMass; + float turnImpulse = turnSpeed*GetMass(wheelContactPoint, turnDirection); + + ApplyMoveForce(impulse * direction); + ApplyTurnForce(turnImpulse * direction, wheelContactPoint); + } +} + +float fBurstBikeSpeedMax = 0.12f; +float fBurstBikeTyreMod = 0.05f; +float fTweakBikeWheelTurnForce = 2.0f; + +void +CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, + int32 wheelsOnGround, float thrust, float brake, float adhesion, float unk, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus) +{ + // BUG: using statics here is probably a bad idea + static bool bAlreadySkidding = false; // this is never reset + static bool bBraking; + static bool bDriving; + static bool bReversing; + +#ifdef FIX_BUGS + bAlreadySkidding = false; +#endif + + // how much force we want to apply in these axes + float fwd = 0.0f; + float right = 0.0f; + + bBraking = brake != 0.0f; + if(bBraking) + thrust = 0.0f; + bDriving = thrust != 0.0f; + bReversing = thrust < 0.0f; + + float contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd); + float contactSpeedRight; + + if(*wheelState != WHEEL_STATE_NORMAL) + bAlreadySkidding = true; + *wheelState = WHEEL_STATE_NORMAL; + + adhesion *= CTimer::GetTimeStep(); + if(bAlreadySkidding) + adhesion *= pHandling->fTractionLoss; + + if(special == BIKE_WHEEL_2 || special == BIKE_WHEEL_3) + contactSpeedRight = 0.0f; + else + contactSpeedRight = DotProduct(wheelContactSpeed, wheelRight); + + // moving sideways + if(contactSpeedRight != 0.0f){ + // exert opposing force + right = -contactSpeedRight/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedRight is independent of framerate but right has timestep as a factor + // so we probably have to fix this + right *= CTimer::GetTimeStepFix(); +#endif + + if(wheelStatus == WHEEL_STATUS_BURST){ + float fwdspeed = Min(contactSpeedFwd, fBurstBikeSpeedMax); + right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstBikeTyreMod, fBurstBikeTyreMod); + } + } + + if(bDriving){ + fwd = thrust; + + // limit sideways force (why?) + if(right > 0.0f){ + if(right > adhesion) + right = adhesion; + }else{ + if(right < -adhesion) + right = -adhesion; + } + }else if(contactSpeedFwd != 0.0f){ + fwd = -contactSpeedFwd/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedFwd is independent of framerate but fwd has timestep as a factor + // so we probably have to fix this + fwd *= CTimer::GetTimeStepFix(); +#endif + + if(!bBraking){ + if(m_fGasPedal < 0.01f){ + if(IsBike()) + brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f); + else if(pHandling->fMass < 500.0f) + brake = mod_HandlingManager.fWheelFriction / m_fMass; + else if(GetModelIndex() == MI_RCBANDIT) + brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass; + else + brake = mod_HandlingManager.fWheelFriction / m_fMass; +#ifdef FIX_BUGS + brake *= CTimer::GetTimeStepFix(); +#endif + } + } + + if(brake > adhesion){ + if(Abs(contactSpeedFwd) > 0.005f) + *wheelState = WHEEL_STATE_FIXED; + }else { + if(fwd > 0.0f){ + if(fwd > brake) + fwd = brake; + }else{ + if(fwd < -brake) + fwd = -brake; + } + } + } + + float speedSq = sq(right) + sq(fwd); + if(sq(adhesion) < speedSq){ + if(*wheelState != WHEEL_STATE_FIXED){ + if(bDriving && contactSpeedFwd < 0.2f) + *wheelState = WHEEL_STATE_SPINNING; + else + *wheelState = WHEEL_STATE_SKIDDING; + } + + float l = Sqrt(speedSq); + float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss; + right *= adhesion * tractionLoss / l; + fwd *= adhesion * tractionLoss / l; + + if(unk < 1.0f) + right *= unk; + }else if(unk < 1.0f){ + if(!bAlreadySkidding) + unk *= pHandling->fTractionLoss; + if(sq(adhesion*unk) < speedSq){ + float l = Sqrt(speedSq); + right *= adhesion * unk / l; + } + } + if(fwd != 0.0f || right != 0.0f){ CVector direction = fwd*wheelFwd + right*wheelRight; + float speed = direction.Magnitude(); direction.Normalise(); float impulse = speed*m_fMass; float turnImpulse = speed*GetMass(wheelContactPoint, direction); + CVector vTurnImpulse = turnImpulse * direction; + float turnRight = DotProduct(vTurnImpulse, GetRight()); ApplyMoveForce(impulse * direction); - ApplyTurnForce(turnImpulse * direction, wheelContactPoint); + + float contactRight = DotProduct(wheelContactPoint, GetRight()); + float contactFwd = DotProduct(wheelContactPoint, GetForward()); + + if(wheelId != CARWHEEL_REAR_LEFT || + !bBraking && !bReversing) + ApplyTurnForce((vTurnImpulse - turnRight*GetRight()) * fTweakBikeWheelTurnForce, + wheelContactPoint - contactRight*GetRight()); + + ApplyTurnForce(turnRight*GetRight(), contactFwd*GetForward()); } } @@ -604,40 +1041,81 @@ CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVec return angularVelocity * CTimer::GetTimeStep(); } +int +CVehicle::FindTyreNearestPoint(float x, float y) +{ + CVector pos = CVector(x - GetPosition().x, y - GetPosition().y, 0.0f); + float fwd = DotProduct(GetForward(), pos); + float right = DotProduct(GetRight(), pos); + + int piece; + if(IsBike()){ + piece = fwd > 0.0f ? CAR_PIECE_WHEEL_LF : CAR_PIECE_WHEEL_LR; + }else{ + piece = fwd > 0.0f ? + right > 0.0f ? CAR_PIECE_WHEEL_RF : CAR_PIECE_WHEEL_LF : + right > 0.0f ? CAR_PIECE_WHEEL_RR : CAR_PIECE_WHEEL_LR; + } + return piece - CAR_PIECE_WHEEL_LF; +} + void -CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage) +CVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage, CVector pos) { if (!bCanBeDamaged) return; - if (bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle())) + if(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f) + damage *= 0.5f; + if (GetStatus() != STATUS_PLAYER && bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle())) return; + + if(damage > 10.0f && (damagedBy == FindPlayerPed() || damagedBy == FindPlayerVehicle()) && GetStatus() != STATUS_WRECKED){ + CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 2; + CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 1.0f; + CStats::PropertyDestroyed += CGeneral::GetRandomNumberInRange(5, 25); + } + bool bFrightensDriver = false; switch (weaponType) { case WEAPONTYPE_UNARMED: + case WEAPONTYPE_BRASSKNUCKLE: + case WEAPONTYPE_SCREWDRIVER: + case WEAPONTYPE_GOLFCLUB: + case WEAPONTYPE_NIGHTSTICK: + case WEAPONTYPE_KNIFE: case WEAPONTYPE_BASEBALLBAT: + case WEAPONTYPE_HAMMER: + case WEAPONTYPE_CLEAVER: + case WEAPONTYPE_MACHETE: + case WEAPONTYPE_KATANA: + case WEAPONTYPE_CHAINSAW: if (bMeleeProof) return; break; case WEAPONTYPE_COLT45: - case WEAPONTYPE_UZI: - case WEAPONTYPE_TEC9: - case WEAPONTYPE_SILENCED_INGRAM: - case WEAPONTYPE_MP5: + case WEAPONTYPE_PYTHON: case WEAPONTYPE_SHOTGUN: case WEAPONTYPE_SPAS12_SHOTGUN: case WEAPONTYPE_STUBBY_SHOTGUN: - case WEAPONTYPE_RUGER: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: case WEAPONTYPE_HELICANNON: case WEAPONTYPE_UZI_DRIVEBY: if (bBulletProof) return; bFrightensDriver = true; break; - case WEAPONTYPE_ROCKETLAUNCHER: - case WEAPONTYPE_MOLOTOV: case WEAPONTYPE_GRENADE: + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_ROCKET: case WEAPONTYPE_EXPLOSION: if (bExplosionProof) return; @@ -654,6 +1132,52 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage default: break; } + + if(bFrightensDriver && GetStatus() == STATUS_PLAYER && m_fHealth < 250.0f) + return; + + // Pop tires + if(damagedBy && damagedBy->IsPed() && (IsCar() || IsBike())){ + int accuracy = 0; + switch(weaponType){ + case WEAPONTYPE_COLT45: + accuracy = 10; + break; + case WEAPONTYPE_PYTHON: + if(!((CPed*)damagedBy)->IsPlayer()) + accuracy = 64; + break; + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + case WEAPONTYPE_M60: + case WEAPONTYPE_HELICANNON: + accuracy = 25; + break; + case WEAPONTYPE_TEC9: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + case WEAPONTYPE_UZI_DRIVEBY: + accuracy = 15; + break; + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + if(!((CPed*)damagedBy)->IsPlayer()) + accuracy = 15; + break; + } + + if(((CPed*)damagedBy)->IsPlayer() && (CCamera::m_bUseMouse3rdPerson || TheCamera.Using1stPersonWeaponMode())) + accuracy = 0; + + if(accuracy != 0 && !bTyresDontBurst && (CGeneral::GetRandomNumber()&0x7F) < accuracy){ + if(IsBike()) + BurstTyre(FindTyreNearestPoint(pos.x, pos.y) + CAR_PIECE_WHEEL_LF, false); + else if(GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR) + BurstTyre(FindTyreNearestPoint(pos.x, pos.y) + CAR_PIECE_WHEEL_LF, true); + } + } + if (m_fHealth > 0.0f) { if (VehicleCreatedBy == RANDOM_VEHICLE && pDriver && (GetStatus() == STATUS_SIMPLE || GetStatus() == STATUS_PHYSICS) && @@ -666,24 +1190,43 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage } } m_nLastWeaponDamage = weaponType; + m_pLastDamageEntity = damagedBy; float oldHealth = m_fHealth; if (m_fHealth > damage) { m_fHealth -= damage; - if (VehicleCreatedBy == RANDOM_VEHICLE && - (m_fHealth < DAMAGE_HEALTH_TO_FLEE_ALWAYS || - bFrightensDriver && m_randomSeed > DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE)) { + if (VehicleCreatedBy == RANDOM_VEHICLE && !IsBoat()){ switch (GetStatus()) { case STATUS_SIMPLE: case STATUS_PHYSICS: - if (pDriver) { - SetStatus(STATUS_ABANDONED); - pDriver->bFleeAfterExitingCar = true; - pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); - } - for (int i = 0; i < m_nNumMaxPassengers; i++) { - if (pPassengers[i]) { - pPassengers[i]->bFleeAfterExitingCar = true; - pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + if(AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH || + CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.5f && AutoPilot.m_nCarMission == MISSION_CRUISE){ + // Drive away like a maniac + if(pDriver && pDriver->m_objective != OBJECTIVE_LEAVE_VEHICLE){ + if(AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH) + AutoPilot.m_nCruiseSpeed *= 1.5f; + AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH; + } + }else{ + // Leave vehicle + if (pDriver && pDriver->CharCreatedBy != MISSION_CHAR) { + SetStatus(STATUS_ABANDONED); + pDriver->bFleeAfterExitingCar = true; + pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); +// TODO(MIAMI): +// pDriver->Say(120); + } + int time = 200; + for (int i = 0; i < m_nNumMaxPassengers; i++) { + if (pPassengers[i] && + pPassengers[i]->m_objective != OBJECTIVE_LEAVE_VEHICLE && + pPassengers[i]->CharCreatedBy != MISSION_CHAR) { + pPassengers[i]->bFleeAfterExitingCar = true; + pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + pPassengers[i]->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time; +// TODO(MIAMI): +// pPassengers[i]->Say(120); + time += 200; + } } } break; @@ -691,7 +1234,7 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage break; } } - if (oldHealth > DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { + if (oldHealth >= DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { if (IsCar()) { CAutomobile* pThisCar = (CAutomobile*)this; pThisCar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE); @@ -725,11 +1268,13 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage void CVehicle::DoFixedMachineGuns(void) { - if(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){ - FireFixedMachineGuns(); - }else{ - if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400) - m_nAmmoInClip = 20; + if(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD){ + if(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){ + FireFixedMachineGuns(); + }else{ + if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400) + m_nAmmoInClip = 20; + } } } @@ -777,10 +1322,44 @@ CVehicle::FireFixedMachineGuns(void) } } +void +CVehicle::ActivateBomb(void) +{ + if(m_bombType == CARBOMB_TIMED){ + m_bombType = CARBOMB_TIMEDACTIVE; + m_nBombTimer = 7000; + m_pBlowUpEntity = FindPlayerPed(); + CGarages::TriggerMessage("GA_12", -1, 3000, -1); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TIMED_ACTIVATED, 1.0f); + }else if(m_bombType == CARBOMB_ONIGNITION){ + m_bombType = CARBOMB_ONIGNITIONACTIVE; + CGarages::TriggerMessage("GA_12", -1, 3000, -1); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_ONIGNITION_ACTIVATED, 1.0f); + } +} + +void +CVehicle::ActivateBombWhenEntered(void) +{ + if(pDriver){ + if(!bDriverLastFrame && m_bombType == CARBOMB_ONIGNITIONACTIVE){ + // If someone enters the car and there is a bomb, detonate + m_nBombTimer = 1000; + m_pBlowUpEntity = m_pBombRigger; + if(m_pBlowUpEntity) + m_pBlowUpEntity->RegisterReference((CEntity**)&m_pBlowUpEntity); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TICK, 1.0f); + } + bDriverLastFrame = true; + }else + bDriverLastFrame = false; +} + void CVehicle::ExtinguishCarFire(void) { - m_fHealth = Max(m_fHealth, 300.0f); + if(GetStatus() != STATUS_WRECKED) + m_fHealth = Max(m_fHealth, 300.0f); if(m_pCarFire) m_pCarFire->Extinguish(); if(IsCar()){ @@ -850,6 +1429,69 @@ CVehicle::ShufflePassengersToMakeSpace(void) return false; } +void +CVehicle::MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&player, CCopPed *&cop) +{ + int i; + player = nil; + cop = nil; + + if(ped1->IsPlayer() && ped2->m_nPedType == PEDTYPE_COP && + ((CPlayerPed*)ped1)->m_pWanted->m_nWantedLevel > 0 && + ped2->m_pedInObjective == ped1){ + player = (CPlayerPed*)ped1; + cop = (CCopPed*)ped2; + return; + } + + bool ped1IsDriver = ped1 == pDriver; + + // Just what the hell is this weird code? + CPed *peds[9]; + CPed *peds2[9]; + int numPeds = 0; + int numPeds2 = 0; + for(i = 0; i < m_nNumMaxPassengers; i++){ + CPed *p = pPassengers[i]; + if(p && p != ped1 && !p->bStayInCarOnJack){ + peds[numPeds++] = p; + // uhh what? + if(i < 1 && !ped1IsDriver) + continue; + peds2[numPeds2++] = p; + } + } + + // So we're copying this array for no reason... + CPed *peds3[9]; + int numPeds3 = 0; + for(i = 0; i < numPeds; i++){ + if(peds[i]->IsPlayer() && ped2->m_nPedType == PEDTYPE_COP && + ((CPlayerPed*)peds[i])->m_pWanted->m_nWantedLevel > 0 && + ped2->m_pedInObjective == peds[i]){ + player = (CPlayerPed*)peds[i]; + cop = (CCopPed*)ped2; + return; + } + peds3[numPeds3++] = peds[i]; + } + + int time = 1800; + for(i = 0; i < numPeds3; i++){ + peds3[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + time; + peds3[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + time += CGeneral::GetRandomNumberInRange(300.0f, 600.0f); + } + + if(IsCar() && numPeds2 > 0 && CGeneral::GetRandomTrueFalse()) + for(i = 0; i < numPeds2; i++) + if(peds2[i]->IsFemale() || CGeneral::GetRandomTrueFalse()){ + peds2[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 10000; + peds2[i]->b156_8 = true; + peds2[i]->bFleeAfterExitingCar = true; + } +} + void CVehicle::ProcessDelayedExplosion(void) { @@ -869,8 +1511,6 @@ CVehicle::ProcessDelayedExplosion(void) if (m_nBombTimer != 0) return; - if(FindPlayerVehicle() != this && m_pBlowUpEntity == FindPlayerPed()) - CWorld::Players[CWorld::PlayerInFocus].AwardMoneyForExplosion(this); BlowUpCar(m_pBlowUpEntity); } @@ -878,12 +1518,13 @@ bool CVehicle::IsLawEnforcementVehicle(void) { switch(GetModelIndex()){ - case MI_FBICAR: case MI_POLICE: case MI_ENFORCER: case MI_PREDATOR: case MI_RHINO: case MI_BARRACKS: + case MI_FBIRANCH: + case MI_VICECHEE: return true; default: return false; @@ -901,6 +1542,8 @@ CVehicle::UsesSiren(uint32 id) case MI_POLICE: case MI_ENFORCER: case MI_PREDATOR: + case MI_FBIRANCH: + case MI_VICECHEE: return true; default: return false; @@ -989,19 +1632,27 @@ CVehicle::CanPedOpenLocks(CPed *ped) { if(m_nDoorLock == CARLOCK_LOCKED || m_nDoorLock == CARLOCK_LOCKED_INITIALLY || - m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) + m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE || + m_nDoorLock == CARLOCK_SKIP_SHUT_DOORS) return false; if(ped->IsPlayer() && m_nDoorLock == CARLOCK_LOCKOUT_PLAYER_ONLY) return false; return true; } +bool +CVehicle::CanDoorsBeDamaged(void) +{ + return m_nDoorLock == CARLOCK_NOT_USED || + m_nDoorLock == CARLOCK_UNLOCKED || + m_nDoorLock == CARLOCK_SKIP_SHUT_DOORS; +} + bool CVehicle::CanPedEnterCar(void) { - CVector up = GetUp(); // can't enter when car is on side - if(up.z > 0.1f || up.z < -0.1f){ + if(IsBike() || GetUp().z > 0.1f || GetUp().z < -0.1f){ // also when car is moving too fast if(m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f)) return false; @@ -1013,16 +1664,14 @@ CVehicle::CanPedEnterCar(void) } bool -CVehicle::CanPedExitCar(void) +CVehicle::CanPedExitCar(bool jumpExit) { CVector up = GetUp(); if(up.z > 0.1f || up.z < -0.1f){ -#ifdef VC_PED_PORTS if (IsBoat()) return true; -#endif // can't exit when car is moving too fast - if(m_vecMoveSpeed.MagnitudeSqr() > 0.005f) + if(m_vecMoveSpeed.MagnitudeSqr() > 0.005f && !jumpExit) return false; // if car is slow enough, check turn speed if(Abs(m_vecTurnSpeed.x) > 0.01f || @@ -1045,6 +1694,14 @@ CVehicle::CanPedExitCar(void) } } +bool +CVehicle::CanPedJumpOffBike(void) +{ + if(pPassengers[0]) + return false; + return m_vecMoveSpeed.MagnitudeSqr() < 0.07f ? false : true; +} + void CVehicle::ChangeLawEnforcerState(uint8 enable) { @@ -1082,14 +1739,30 @@ CVehicle::SetUpDriver(void) CPed* CVehicle::SetupPassenger(int n) { + int i; + if(pPassengers[n]) return pPassengers[n]; - pPassengers[n] = CPopulation::AddPedInCar(this, false); - pPassengers[n]->m_pMyVehicle = this; - pPassengers[n]->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle); - pPassengers[n]->bInVehicle = true; - pPassengers[n]->SetPedState(PED_DRIVING); + if((IsTaxi() || IsLimo()) && n == 0) + pPassengers[0] = nil; + else{ + CPed *passenger = CPopulation::AddPedInCar(this, false); + pPassengers[n] = passenger; + passenger->m_pMyVehicle = this; + passenger->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle); + passenger->bInVehicle = true; + passenger->SetPedState(PED_DRIVING); + + if(passenger->m_nPedType == PEDTYPE_CIVMALE || passenger->m_nPedType == PEDTYPE_CIVFEMALE) + for(i = 0; i < n; i++) + if(pPassengers[i] && pPassengers[n] && + pPassengers[i]->m_nPedType == PEDTYPE_CIVMALE || pPassengers[i]->m_nPedType == PEDTYPE_CIVFEMALE && + passenger->GetModelIndex() == pPassengers[i]->GetModelIndex()){ + pPassengers[n] = nil; + CPopulation::RemovePed(passenger); + } + } if(bIsBus) pPassengers[n]->bRenderPedInCar = false; ++m_nNumPassengers; @@ -1103,24 +1776,42 @@ CVehicle::SetDriver(CPed *driver) pDriver->RegisterReference((CEntity**)&pDriver); if(bFreebies && driver == FindPlayerPed()){ - if(GetModelIndex() == MI_AMBULAN) - FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth); - else if(GetModelIndex() == MI_TAXI) - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; - else if (GetModelIndex() == MI_POLICE) { - CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE); - driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5); - } else if (GetModelIndex() == MI_ENFORCER) - driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour); - else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA) // TODO(MIAMI): check zebra - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; bFreebies = false; + switch(GetModelIndex()){ + case MI_AMBULAN: + FindPlayerPed()->m_fHealth = Max(FindPlayerPed()->m_fHealth, Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth)); + break; + + case MI_TAXI: + case MI_CABBIE: + case MI_ZEBRA: + case MI_KAUFMAN: + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 12; + break; + + case MI_POLICE: + CStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE); + bFreebies = true; + break; + + case MI_ENFORCER: + driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour); + break; + + case MI_CADDY: + if(!(driver->IsPlayer() && ((CPlayerPed*)driver)->DoesPlayerWantNewWeapon(WEAPONTYPE_GOLFCLUB, true))) + CStreaming::RequestModel(MI_GOLFCLUB, STREAMFLAGS_DONT_REMOVE); + break; + } } - ApplyTurnForce(0.0f, 0.0f, -0.2f*driver->m_fMass, - driver->GetPosition().x - GetPosition().x, - driver->GetPosition().y - GetPosition().y, - 0.0f); + if(IsBike()) + ApplyMoveForce(-0.2f*driver->m_fMass * GetUp()); + else + ApplyTurnForce(0.0f, 0.0f, -0.2f*driver->m_fMass, + driver->GetPosition().x - GetPosition().x, + driver->GetPosition().y - GetPosition().y, + 0.0f); } bool @@ -1128,10 +1819,13 @@ CVehicle::AddPassenger(CPed *passenger) { int i; - ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass, - passenger->GetPosition().x - GetPosition().x, - passenger->GetPosition().y - GetPosition().y, - 0.0f); + if(IsBike()) + ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward()); + else + ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass, + passenger->GetPosition().x - GetPosition().x, + passenger->GetPosition().y - GetPosition().y, + 0.0f); for(i = 0; i < m_nNumMaxPassengers; i++) if(pPassengers[i] == nil){ @@ -1148,10 +1842,13 @@ CVehicle::AddPassenger(CPed *passenger, uint8 n) if(bIsBus) return AddPassenger(passenger); - ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass, - passenger->GetPosition().x - GetPosition().x, - passenger->GetPosition().y - GetPosition().y, - 0.0f); + if(IsBike()) + ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward()); + else + ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass, + passenger->GetPosition().x - GetPosition().x, + passenger->GetPosition().y - GetPosition().y, + 0.0f); if(n < m_nNumMaxPassengers && pPassengers[n] == nil){ pPassengers[n] = passenger; @@ -1165,6 +1862,22 @@ void CVehicle::RemoveDriver(void) { SetStatus(STATUS_ABANDONED); + if(pDriver == FindPlayerPed()){ + if(GetModelIndex() == MI_POLICE && CStreaming::HasModelLoaded(MI_SHOTGUN)){ + if(bFreebies){ + if(((CPlayerPed*)pDriver)->DoesPlayerWantNewWeapon(WEAPONTYPE_SHOTGUN, true)) + pDriver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5, true); + else + pDriver->GrantAmmo(WEAPONTYPE_SHOTGUN, 5); + bFreebies = false; + } + CStreaming::SetModelIsDeletable(MI_SHOTGUN); + }else if(GetModelIndex() == MI_CADDY && CStreaming::HasModelLoaded(MI_GOLFCLUB)){ + if(((CPlayerPed*)pDriver)->DoesPlayerWantNewWeapon(WEAPONTYPE_GOLFCLUB, true)) + pDriver->GiveWeapon(WEAPONTYPE_GOLFCLUB, 1, true); + CStreaming::SetModelIsDeletable(MI_GOLFCLUB); + } + } pDriver = nil; } @@ -1190,6 +1903,57 @@ CVehicle::RemovePassenger(CPed *p) } } +bool +CVehicle::IsDriver(CPed *ped) +{ + if(ped == nil) + return false; + return ped == pDriver; +} + +bool +CVehicle::IsDriver(int32 model) +{ + return pDriver && pDriver->GetModelIndex() == model; +} + +bool +CVehicle::IsPassenger(CPed *ped) +{ + int i; + if(ped == nil) + return false; + for(i = 0; i < 8; i++) + if(pPassengers[i] == ped) + return true; + return false; +} + +bool +CVehicle::IsPassenger(int32 model) +{ + int i; + for(i = 0; i < 8; i++) + if(pPassengers[i] && pPassengers[i]->GetModelIndex() == model) + return true; + return false; +} + +void +CVehicle::UpdatePassengerList(void) +{ + int i; + bool hasPassenger = false; + if(m_nNumPassengers) + for(i = 0; i < 8; i++) + if(pPassengers[i]){ + hasPassenger = true; + break; + } + if(!hasPassenger) + m_nNumPassengers = 0; +} + void CVehicle::ProcessCarAlarm(void) { @@ -1199,9 +1963,10 @@ CVehicle::ProcessCarAlarm(void) return; step = CTimer::GetTimeStepInMilliseconds(); - if((uint16)m_nAlarmState < step) + if((uint16)m_nAlarmState < step){ m_nAlarmState = 0; - else + m_nCarHornTimer = 0; + }else m_nAlarmState -= step; } @@ -1229,6 +1994,261 @@ CVehicle::IsSphereTouchingVehicle(float sx, float sy, float sz, float radius) return true; } +RpMaterial* +SetCompAlphaCB(RpMaterial *material, void *data) +{ + uint32 alpha = (uint32)(uintptr)data; + RwRGBA *col = (RwRGBA*)RpMaterialGetColor(material); // get rid of const + col->alpha = alpha; + return material; +} + +void +CVehicle::SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha) +{ + RpGeometry *geo = RpAtomicGetGeometry(atomic); + RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR); + RpGeometryForAllMaterials(geo, SetCompAlphaCB, (void*)alpha); +} + +void +CVehicle::UpdateClumpAlpha(void) +{ + int clumpAlpha = CVisibilityPlugins::GetClumpAlpha((RpClump*)m_rwObject); + if(bFadeOut){ + clumpAlpha -= 8; + if(clumpAlpha < 0) + clumpAlpha = 0; + }else if(clumpAlpha < 255){ + clumpAlpha += 16; + if(clumpAlpha > 255) + clumpAlpha = 255; + } + CVisibilityPlugins::SetClumpAlpha((RpClump*)m_rwObject, clumpAlpha); +} + +void +CVehicle::HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd) +{ + int i; + float angle; + CColPoint point; + CEntity *entity; + uint8 r, g, b; + + if(heli == nil) + return; + + uint8 surface = SURFACE_TARMAC; + int frm = CTimer::GetFrameCounter() & 7; + float testLowZ = ground - 10.0f; + float dustSize = 0.0f; + float baseSize = 1.0f; + float offset = 1.0f; // when heli is tilted + float particleZ = -101.0f; + int n = 0; + + if(heli->GetModelIndex() == MI_RCGOBLIN || heli->GetModelIndex() == MI_RCRAIDER){ + radius = 3.0f; + dustSize = 0.04f; + baseSize = 0.07f; + offset = 0.3f; + } + + CVector heliPos = heli->GetPosition(); + + if(heli->IsVehicle() && ((CVehicle*)heli)->IsCar()){ + heliPos.x -= (heliPos.z - ground)*heli->GetUp().x*offset*0.5f; + heliPos.y -= (heliPos.z - ground)*heli->GetUp().y*offset*0.5f; + } + + float steamSize = 0.25f * radius * baseSize; + float splashSize = 0.3f * radius * baseSize; + + i = 0; + for(i = 0; i < 32+rnd; i++){ + angle = i * TWOPI/32.0f; + CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f); + CVector dir = CVector(pos.x, pos.y, 1.0f)*0.01f; + pos += heliPos; + + if(i < 32 && i == 4*frm){ + if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)){ + n = rnd; + particleZ = point.point.z; + surface = point.surfaceB; + }else + n = 0; + + float waterLevel = 0.0f; + if(CWaterLevel::GetWaterLevel(pos, &waterLevel, false) && waterLevel > particleZ){ + surface = SURFACE_PUDDLE; + n = rnd; + particleZ = waterLevel; + } + } + + if(n){ + pos.z = particleZ; + if(surface == SURFACE_PUDDLE){ + float red = (0.3*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj())*255.0f/4.0f; + float green = (0.3*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj())*255.0f/4.0f; + float blue = (0.3*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj())*255.0f/4.0f; + r = clamp(red, 0.0f, 255.0f); + g = clamp(green, 0.0f, 255.0f); + b = clamp(blue, 0.0f, 255.0f); + RwRGBA col1 = { r, g, b, CGeneral::GetRandomNumberInRange(8, 32) }; + RwRGBA col2 = { 255, 255, 255, 32 }; + + if(n&1) + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, pos, dir, nil, steamSize, col2); + else + CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, dir, nil, splashSize, col1, + CGeneral::GetRandomNumberInRange(0.0f, 10.0f), + CGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1); + }else{ + switch(surface){ + default: + case SURFACE_TARMAC: + r = 10; + g = 10; + b = 10; + break; + case SURFACE_GRASS: + r = 10; + g = 10; + b = 3; + break; + case SURFACE_DIRT: + r = 10; + g = 8; + b = 7; + break; + case SURFACE_DIRTTRACK: + r = 10; + g = 6; + b = 3; + break; + case SURFACE_SAND: + case SURFACE_SAND33: + r = 10; + g = 10; + b = 7; + break; + } + RwRGBA col = { r, g, b, 32 }; + if(heliPos.z - pos.z < 20.0f) + CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, dustSize, col); + } + + n--; + } + } +} + +#define GLARE_MIN_DIST (13.0f) +#define GLARE_FULL_DIST (30.0f) +#define GLARE_MIN_ANGLE (0.99f) +#define GLARE_FULL_ANGLE (0.995f) + +void +CVehicle::DoSunGlare(void) +{ + if(bRenderScorched || GetPosition().z < 0.0f || + GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR || CWeather::SunGlare <= 0.0f) + return; + + CVector camDir = TheCamera.GetPosition() - GetPosition(); + float dist = camDir.Magnitude(); + camDir *= 2.0f/dist; + CVector glareVec = camDir + CTimeCycle::GetSunDirection(); + CVector localGlareVec; + localGlareVec.x = DotProduct(glareVec, GetRight()); + localGlareVec.y = DotProduct(glareVec, GetForward()); + localGlareVec.z = 0.0; + localGlareVec.Normalise(); + + CVector2D fwd2D = GetForward(); + fwd2D.Normalise(); + CVector2D camDir2D = camDir; + camDir2D.Normalise(); + float fwdness = Abs(DotProduct2D(fwd2D, camDir2D)); + + // check angle + float strength; + if(fwdness > GLARE_FULL_ANGLE) + strength = 1.0f; + else if(fwdness > GLARE_MIN_ANGLE) + strength = (fwdness - GLARE_MIN_ANGLE)/(GLARE_FULL_ANGLE-GLARE_MIN_ANGLE); + else + return; + // check distance + if(dist > GLARE_FULL_DIST){ + // no max distance + }else if(dist > GLARE_MIN_DIST) + strength *= (dist - GLARE_MIN_DIST)/(GLARE_FULL_DIST - GLARE_MIN_DIST); + else + return; + + float intens = 0.8f * strength * CWeather::SunGlare; + int r = intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f; + int g = intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f; + int b = intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f; + + CColModel *colmodel = GetColModel(); + CCollision::CalculateTrianglePlanes(colmodel); + + int i; + for(i = 0; i < colmodel->numTriangles-2; i += 2){ + int a1 = colmodel->triangles[i].a; + int b1 = colmodel->triangles[i].b; + int c1 = colmodel->triangles[i].c; + int a2 = colmodel->triangles[i+1].a; + int b2 = colmodel->triangles[i+1].b; + int c2 = colmodel->triangles[i+1].c; + CVector vert1 = colmodel->vertices[a1]; + CVector vert4; + // Need an upward surface + if(vert1.z <= 0.0f) + continue; + + // trying to find a quad here + int numTri2Verts = 0; + if(a2 != a1 && a2 != b1 && a2 != c1){ + // a2 is not in tri1 + numTri2Verts++; + vert4 = colmodel->vertices[a2]; + } + if(b2 != a1 && b2 != b1 && b2 != c1){ + // b2 is not in tri1 + numTri2Verts++; + vert4 = colmodel->vertices[b2]; + } + if(c2 != a1 && c2 != b1 && c2 != c1){ + // c2 is not in tri1 + numTri2Verts++; + vert4 = colmodel->vertices[c2]; + } + // Need exactly one vertex from tri2 for a quad with tri1 + if(numTri2Verts != 1) + continue; + + CVector mid = (vert1 + colmodel->vertices[b1] + colmodel->vertices[c1] + vert4)/4.0f; + float dy = mid.y - vert1.y; + float dx = mid.x - vert1.x; + float dist = 1.4f * Min(Abs(dx), Abs(dy)); + if(dist > 0.6f){ + CVector pos = GetMatrix() * (dist * localGlareVec + mid) + camDir; + CCoronas::RegisterCorona((uintptr)this + 27 + i, + r, g, b, 255, + pos, 0.9f*CWeather::SunGlare, 90.0f, + CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, + CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, + CCoronas::STREAK_OFF, 0.0f); + } + } +} + void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle) { @@ -1372,20 +2392,19 @@ CVehicle::Load(uint8*& buf) #endif eVehicleAppearance -//--MIAMI: TODO, implement VC version, appearance != type -// This would work for cars, boats and bikes but not for planes and helis CVehicle::GetVehicleAppearance(void) { - if (IsCar()) + uint32 flags = pHandling->Flags & 0xF0000; + if (flags == 0) return VEHICLE_APPEARANCE_CAR; - if (IsBoat()) - return VEHICLE_APPEARANCE_BOAT; - if (IsBike()) + if (flags == HANDLING_IS_BIKE) return VEHICLE_APPEARANCE_BIKE; - if (IsPlane()) - return VEHICLE_APPEARANCE_PLANE; - if (IsHeli()) + if (flags == HANDLING_IS_HELI) return VEHICLE_APPEARANCE_HELI; + if (flags == HANDLING_IS_PLANE) + return VEHICLE_APPEARANCE_PLANE; + if (flags == HANDLING_IS_BOAT) + return VEHICLE_APPEARANCE_BOAT; return VEHICLE_APPEARANCE_NONE; } diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 7b5a1e11..083a8a15 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -8,6 +8,8 @@ #include "HandlingMgr.h" class CPed; +class CPlayerPed; +class CCopPed; class CFire; struct tHandlingData; @@ -87,8 +89,8 @@ enum CAR_PIECE_WING_LR, CAR_PIECE_WING_RR, CAR_PIECE_WHEEL_LF, - CAR_PIECE_WHEEL_LR, CAR_PIECE_WHEEL_RF, + CAR_PIECE_WHEEL_LR, CAR_PIECE_WHEEL_RR, CAR_PIECE_WINDSCREEN, }; @@ -104,10 +106,12 @@ enum tWheelState enum eFlightModel { FLIGHT_MODEL_DODO, - // not used in III FLIGHT_MODEL_RCPLANE, - FLIGHT_MODEL_HELI, - FLIGHT_MODEL_SEAPLANE + FLIGHT_MODEL_RCHELI, + FLIGHT_MODEL_SEAPLANE, + FLIGHT_MODEL_PLANE_UNUSED, + FLIGHT_MODEL_PLANE, + FLIGHT_MODEL_HELI }; enum eVehicleAppearance @@ -120,10 +124,28 @@ enum eVehicleAppearance VEHICLE_APPEARANCE_PLANE, }; +// TODO +enum eBikeWheelSpecial +{ + BIKE_WHEEL_2 = 2, + BIKE_WHEEL_3, +}; + +enum +{ + ROTOR_TOP = 3, + ROTOR_FRONT = 4, + ROTOR_RIGHT = 5, + ROTOR_LEFT = 7, + ROTOR_BACK = 8, + ROTOR_BOTTOM = 9, +}; + class CVehicle : public CPhysical { public: tHandlingData *pHandling; + tFlyingHandlingData *pFlyingHandling; CAutoPilot AutoPilot; uint8 m_currentColour1; uint8 m_currentColour2; @@ -180,28 +202,28 @@ public: uint8 bHasAlreadyBeenRecorded : 1; // Used for replays uint8 bPartOfConvoy : 1; uint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really - //uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear + uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water) uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc) uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed uint8 bParking : 1; - //uint8 bCanPark : 1; + uint8 bCanPark : 1; uint8 m_bombType : 3; + uint8 bDriverLastFrame : 1; int8 m_numPedsUseItAsCover; uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default) int8 m_nPacManPickupsCarried; uint8 m_nRoadblockType; - int16 m_nRoadblockNode; float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode uint8 m_nCurrentGear; float m_fChangeGearTime; CEntity* m_pBombRigger; - uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats) uint32 m_nSetPieceExtendedRangeTime; + uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats) uint32 m_nTimeOfDeath; uint16 m_nTimeBlocked; int16 m_nBombTimer; // goes down with each frame @@ -214,7 +236,7 @@ public: int8 m_nRadioStation; uint8 m_bRainAudioCounter; uint8 m_bRainSamplesCounter; - uint8 m_nCarHornTimer; + uint32 m_nCarHornTimer; uint8 m_nCarHornPattern; bool m_bSirenOrAlarm; uint8 m_nCarHornDelay; @@ -247,11 +269,15 @@ public: virtual bool IsDoorFullyOpen(eDoors door) { return false; } virtual bool IsDoorClosed(eDoors door) { return false; } virtual bool IsDoorMissing(eDoors door) { return false; } + virtual bool IsDoorReady(uint32 door) { return false; } + virtual bool IsDoorMissing(uint32 door) { return false; } + virtual bool IsOpenTopCar(void) { return false; } virtual void RemoveRefsToVehicle(CEntity *ent) {} virtual void BlowUpCar(CEntity *ent) {} virtual bool SetUpWheelColModel(CColModel *colModel) { return false; } - virtual void BurstTyre(uint8 tyre) {} + virtual void BurstTyre(uint8 tyre, bool applyForces) {} virtual bool IsRoomForPedToLeaveCar(uint32 component, CVector *forcedDoorPos) { return false;} + virtual bool IsClearToDriveAway(void); virtual float GetHeightAboveRoad(void); virtual void PlayCarHorn(void) {} #ifdef COMPATIBLE_SAVES @@ -268,11 +294,17 @@ public: bool IsBike(void) { return m_vehType == VEHICLE_TYPE_BIKE; } void FlyingControl(eFlightModel flightModel); + bool DoBladeCollision(CVector pos, CMatrix &matrix, int16 rotorType, float radius, float damageMult); + bool BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &matrix, int16 rotorType, float damageMult); + void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus); + void ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, + int32 wheelsOnGround, float thrust, float brake, float adhesion, float unk, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus); void ExtinguishCarFire(void); void ProcessDelayedExplosion(void); float ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius); + int FindTyreNearestPoint(float x, float y); bool IsLawEnforcementVehicle(void); void ChangeLawEnforcerState(uint8 enable); bool UsesSiren(uint32 id); @@ -282,8 +314,10 @@ public: bool IsOnItsSide(void); bool CanBeDeleted(void); bool CanPedOpenLocks(CPed *ped); + bool CanDoorsBeDamaged(void); bool CanPedEnterCar(void); - bool CanPedExitCar(void); + bool CanPedExitCar(bool jumpExit); + bool CanPedJumpOffBike(void); // do these two actually return something? CPed *SetUpDriver(void); CPed *SetupPassenger(int n); @@ -292,17 +326,31 @@ public: bool AddPassenger(CPed *passenger, uint8 n); void RemovePassenger(CPed *passenger); void RemoveDriver(void); + bool IsDriver(CPed *ped); + bool IsDriver(int32 model); + bool IsPassenger(CPed *ped); + bool IsPassenger(int32 model); + void UpdatePassengerList(void); void ProcessCarAlarm(void); bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius); bool ShufflePassengersToMakeSpace(void); - void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage); + void MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&player, CCopPed *&cop); + void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage, CVector pos = CVector(0.0f, 0.0f, 0.0f)); void DoFixedMachineGuns(void); void FireFixedMachineGuns(void); + void ActivateBomb(void); + void ActivateBombWhenEntered(void); + void SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha); + void UpdateClumpAlpha(void); + + static void HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd); + void DoSunGlare(void); bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA || GetModelIndex() == MI_KAUFMAN; } + bool IsLimo(void) { return GetModelIndex() == MI_STRETCH || GetModelIndex() == MI_LOVEFIST; } bool IsRealHeli(void) { return !!(pHandling->Flags & HANDLING_IS_HELI); } static bool bWheelsOnlyCheat; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index ebdeb38b..a6217d70 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1271,7 +1271,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } case ENTITY_TYPE_VEHICLE: { - ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, point->point); for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); @@ -1648,7 +1648,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) case ENTITY_TYPE_VEHICLE: { if (point.pieceB >= SURFACE_STREET_LIGHT && point.pieceB <= SURFACE_METAL_FENCE) { - ((CVehicle*)victim)->BurstTyre(point.pieceB); // TODO(Miami): New parameter: ,true); + ((CVehicle*)victim)->BurstTyre(point.pieceB, true); for (int32 i = 0; i < 4; i++) CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point.point, point.normal * 0.05f); From 52644192e37bad31a3f88e2bc271619e265c7507 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 25 May 2020 19:36:09 +0300 Subject: [PATCH 135/148] Even more audio cleanups --- src/audio/AudioLogic.cpp | 209 +++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 106 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 86805733..f516e43c 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -611,7 +611,7 @@ cAudioManager::ProcessRainOnVehicle(cVehicleParams *params) CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); float emittingVol = 30.f * CWeather::Rain; m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, rainOnVehicleIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = veh->m_bRainSamplesCounter++; if (veh->m_bRainSamplesCounter > 4) veh->m_bRainSamplesCounter = 68; @@ -661,7 +661,7 @@ cAudioManager::ProcessReverseGear(cVehicleParams *params) modificator = Abs(modificator); emittingVol = (24.f * modificator); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, reverseGearIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { if (params->m_pVehicle->m_fGasPedal >= 0.0f) { m_sQueueSample.m_nCounter = 62; m_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR_2; @@ -717,7 +717,7 @@ cAudioManager::ProcessModelCarEngine(cVehicleParams *params) if (emittingVol) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 30.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 2; m_sQueueSample.m_nSampleIndex = SFX_REMOTE_CONTROLLED_CAR; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -810,7 +810,7 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) if (params->m_fDistance >= SQR(SOUND_INTENSITY)) return false; - if (params->m_pTransmission != 0) { + if (params->m_pTransmission != nil) { if (((CAutomobile *)params->m_pVehicle)->m_nDriveWheelsOnGround != 0) { velChange = Abs(params->m_fVelocityChange); if (velChange > 0.f) { @@ -818,7 +818,7 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) relativeVelocity = Min(1.0f, velChange / (0.5f * params->m_pTransmission->fMaxVelocity)); emittingVol = 23.0f * relativeVelocity * CWeather::WetRoads; m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 1; m_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -1019,7 +1019,7 @@ void cAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 unk1, uint8 counter, bool notLooping) { m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, 50.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = counter; m_sQueueSample.m_nSampleIndex = sample; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -1054,20 +1054,20 @@ cAudioManager::ProcessCesna(cVehicleParams *params) if (FindPlayerVehicle() == params->m_pVehicle) { if (params->m_nIndex == DODO) { if (Pads[0].GetAccelerate() <= 0) { - if (nAccel) + if (nAccel != 0) --nAccel; } else if (nAccel < 60) { ++nAccel; } - AddPlayerCarSample(85 * (60 - nAccel) / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_IDLE, 0, 52, 1); - AddPlayerCarSample(85 * nAccel / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_REV, 0, 2, 1); + AddPlayerCarSample(85 * (60 - nAccel) / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_IDLE, 0, 52, true); + AddPlayerCarSample(85 * nAccel / 60 + 20, 8500 * nAccel / 60 + 17000, SFX_CESNA_REV, 0, 2, true); } } else if (params->m_nIndex == DODO) { - AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, 0, 52, 1); + AddPlayerCarSample(105, 17000, SFX_CESNA_IDLE, 0, 52, true); } else if (params->m_fDistance < SQR(200)) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 52; m_sQueueSample.m_nSampleIndex = SFX_CESNA_IDLE; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -1088,7 +1088,7 @@ cAudioManager::ProcessCesna(cVehicleParams *params) } if (params->m_fDistance < SQR(90)) { m_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 2; m_sQueueSample.m_nSampleIndex = SFX_CESNA_REV; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -1500,7 +1500,7 @@ cAudioManager::ProcessVehicleHorn(cVehicleParams *params) CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(80, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 4; m_sQueueSample.m_nSampleIndex = aVehicleSettings[params->m_nIndex].m_nHornSample; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -1981,7 +1981,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) case SOUND_CAR_HYDRAULIC_1: case SOUND_CAR_HYDRAULIC_2: { const float SOUND_INTENSITY = 35.0f; - if (event == MOONBEAM) // todo check + if (event == SOUND_CAR_HYDRAULIC_1) m_sQueueSample.m_nFrequency = 15600; else m_sQueueSample.m_nFrequency = 13118; @@ -2926,7 +2926,7 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params) } m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 7.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 64; m_sQueueSample.m_nSampleIndex = SFX_HEADPHONES; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -3662,13 +3662,13 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) if (params->m_fDistance < maxDist) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { if (noReflection) { - if (0.2f * m_sQueueSample.m_fSoundIntensity <= m_sQueueSample.m_fDistance) { - noReflection = false; - } else { + if (m_sQueueSample.m_fDistance < 0.2f * m_sQueueSample.m_fSoundIntensity) { m_sQueueSample.m_bIs2D = true; m_sQueueSample.m_nOffset = 0; + } else { + noReflection = false; } } m_sQueueSample.m_bReverbFlag = true; @@ -6213,78 +6213,75 @@ cPedComments::Process() uint8 actualUsedBank; tPedComment *comment; - static const int defaultIntensity = 50; - static const int policeHeliIntensity = 400; + if (AudioManager.m_nUserPause != 0) return; - if (!AudioManager.m_nUserPause) { - if (m_nCommentsInBank[m_nActiveBank]) { - sampleIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nSampleIndex; - if (!SampleManager.IsPedCommentLoaded(sampleIndex)) - SampleManager.LoadPedComment(sampleIndex); + if (m_nCommentsInBank[m_nActiveBank]) { + sampleIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nSampleIndex; + if (!SampleManager.IsPedCommentLoaded(sampleIndex)) + SampleManager.LoadPedComment(sampleIndex); - AudioManager.m_sQueueSample.m_nEntityIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nEntityIndex; - AudioManager.m_sQueueSample.m_nCounter = 0; - AudioManager.m_sQueueSample.m_nSampleIndex = sampleIndex; - AudioManager.m_sQueueSample.m_nBankIndex = SAMPLEBANK_PED; - AudioManager.m_sQueueSample.m_nReleasingVolumeModificator = 3; - AudioManager.m_sQueueSample.m_nVolume = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_bVolume; - AudioManager.m_sQueueSample.m_fDistance = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_fDistance; - AudioManager.m_sQueueSample.m_nLoopCount = 1; - AudioManager.m_sQueueSample.m_nLoopStart = 0; - AudioManager.m_sQueueSample.m_nLoopEnd = -1; - AudioManager.m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; - AudioManager.m_sQueueSample.m_fSpeedMultiplier = 3.0f; - switch (sampleIndex) { - case SFX_POLICE_HELI_1: - case SFX_POLICE_HELI_2: - case SFX_POLICE_HELI_3: - AudioManager.m_sQueueSample.m_fSoundIntensity = policeHeliIntensity; - break; - default: - AudioManager.m_sQueueSample.m_fSoundIntensity = defaultIntensity; - break; - } - AudioManager.m_sQueueSample.m_bReleasingSoundFlag = true; - AudioManager.m_sQueueSample.m_vecPos = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_vecPos; - - if (sampleIndex >= SFX_AMMU_D && sampleIndex <= SFX_AMMU_F) { - AudioManager.m_sQueueSample.m_bReverbFlag = false; - AudioManager.m_sQueueSample.m_bRequireReflection = false; - } else { - AudioManager.m_sQueueSample.m_bReverbFlag = true; - AudioManager.m_sQueueSample.m_bRequireReflection = true; - } - - AudioManager.m_sQueueSample.m_bIs2D = false; - AudioManager.m_sQueueSample.m_nFrequency = - SampleManager.GetSampleBaseFrequency(AudioManager.m_sQueueSample.m_nSampleIndex) + AudioManager.RandomDisplacement(750); - if (CTimer::GetIsSlowMotionActive()) - AudioManager.m_sQueueSample.m_nFrequency /= 2; - m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nProcess = -1; - AudioManager.AddSampleToRequestedQueue(); + AudioManager.m_sQueueSample.m_nEntityIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nEntityIndex; + AudioManager.m_sQueueSample.m_nCounter = 0; + AudioManager.m_sQueueSample.m_nSampleIndex = sampleIndex; + AudioManager.m_sQueueSample.m_nBankIndex = SAMPLEBANK_PED; + AudioManager.m_sQueueSample.m_nReleasingVolumeModificator = 3; + AudioManager.m_sQueueSample.m_nVolume = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_bVolume; + AudioManager.m_sQueueSample.m_fDistance = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_fDistance; + AudioManager.m_sQueueSample.m_nLoopCount = 1; + AudioManager.m_sQueueSample.m_nLoopStart = 0; + AudioManager.m_sQueueSample.m_nLoopEnd = -1; + AudioManager.m_sQueueSample.m_nEmittingVolume = MAX_VOLUME; + AudioManager.m_sQueueSample.m_fSpeedMultiplier = 3.0f; + switch (sampleIndex) { + case SFX_POLICE_HELI_1: + case SFX_POLICE_HELI_2: + case SFX_POLICE_HELI_3: + AudioManager.m_sQueueSample.m_fSoundIntensity = 400.0f; + break; + default: + AudioManager.m_sQueueSample.m_fSoundIntensity = 50.0f; + break; } + AudioManager.m_sQueueSample.m_bReleasingSoundFlag = true; + AudioManager.m_sQueueSample.m_vecPos = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_vecPos; - // Switch bank - if (m_nActiveBank) { - actualUsedBank = SAMPLEBANK_PED; - m_nActiveBank = SAMPLEBANK_MAIN; + if (sampleIndex >= SFX_AMMU_D && sampleIndex <= SFX_AMMU_F) { + AudioManager.m_sQueueSample.m_bReverbFlag = false; + AudioManager.m_sQueueSample.m_bRequireReflection = false; } else { - actualUsedBank = SAMPLEBANK_MAIN; - m_nActiveBank = SAMPLEBANK_PED; - } - comment = m_asPedComments[actualUsedBank]; - for (uint32 i = 0; i < m_nCommentsInBank[actualUsedBank]; i++) { - if (m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess > 0) { - --m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess; - Add(&comment[m_nIndexMap[actualUsedBank][i]]); - } + AudioManager.m_sQueueSample.m_bReverbFlag = true; + AudioManager.m_sQueueSample.m_bRequireReflection = true; } - for (uint32 i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) { - m_nIndexMap[actualUsedBank][i] = NUM_PED_COMMENTS_SLOTS; - } - m_nCommentsInBank[actualUsedBank] = 0; + AudioManager.m_sQueueSample.m_bIs2D = false; + AudioManager.m_sQueueSample.m_nFrequency = + SampleManager.GetSampleBaseFrequency(AudioManager.m_sQueueSample.m_nSampleIndex) + AudioManager.RandomDisplacement(750); + if (CTimer::GetIsSlowMotionActive()) + AudioManager.m_sQueueSample.m_nFrequency /= 2; + m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nProcess = -1; + AudioManager.AddSampleToRequestedQueue(); } + + // Switch bank + if (m_nActiveBank) { + actualUsedBank = SAMPLEBANK_PED; + m_nActiveBank = SAMPLEBANK_MAIN; + } else { + actualUsedBank = SAMPLEBANK_MAIN; + m_nActiveBank = SAMPLEBANK_PED; + } + comment = m_asPedComments[actualUsedBank]; + for (uint32 i = 0; i < m_nCommentsInBank[actualUsedBank]; i++) { + if (m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess > 0) { + --m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess; + Add(&comment[m_nIndexMap[actualUsedBank][i]]); + } + } + + for (uint32 i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) { + m_nIndexMap[actualUsedBank][i] = NUM_PED_COMMENTS_SLOTS; + } + m_nCommentsInBank[actualUsedBank] = 0; } #pragma endregion @@ -6344,7 +6341,7 @@ cAudioManager::ProcessExplosions(int32 explosion) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = i; m_sQueueSample.m_fSpeedMultiplier = 2.0f; m_sQueueSample.m_bIs2D = false; @@ -6412,7 +6409,7 @@ cAudioManager::ProcessFires(int32) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = i; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_fSpeedMultiplier = 2.0f; @@ -6476,7 +6473,7 @@ void cAudioManager::ProcessScriptObject(int32 id) { cAudioScriptObject *entity = (cAudioScriptObject *)m_asAudioEntities[id].m_pEntity; - if (entity != 0) { + if (entity != nil) { m_sQueueSample.m_vecPos = entity->Posn; if (m_asAudioEntities[id].m_AudioEvents == 1) ProcessOneShotScriptObject(m_asAudioEntities[id].m_awAudioEvent[0]); @@ -6675,7 +6672,7 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -6720,7 +6717,7 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = iSound++; m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_bReleasingSoundFlag = true; @@ -7397,7 +7394,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) m_sQueueSample.m_fDistance = Sqrt(distSquared); if (sound != SCRIPT_SOUND_MISTY_SEX_S && sound != SCRIPT_SOUND_MISTY_SEX_L) { m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_bIs2D = false; @@ -7417,7 +7414,7 @@ cAudioManager::ProcessPornCinema(uint8 sound) time = CTimer::GetTimeInMilliseconds(); if (time > gPornNextTime) { m_sQueueSample.m_nVolume = ComputeVolume(90, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { rand = m_anRandomTable[1] & 1; m_sQueueSample.m_nSampleIndex = rand + sample; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); @@ -7456,7 +7453,7 @@ cAudioManager::ProcessWorkShopScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_WORKSHOP_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_WORKSHOP_1); @@ -7495,7 +7492,7 @@ cAudioManager::ProcessSawMillScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_SAWMILL_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SAWMILL_LOOP); @@ -7515,7 +7512,7 @@ cAudioManager::ProcessSawMillScriptObject(uint8 sound) time = CTimer::GetTimeInMilliseconds(); if (time > gSawMillNextTime) { m_sQueueSample.m_nVolume = ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_SAWMILL_CUT_WOOD; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); @@ -7551,7 +7548,7 @@ cAudioManager::ProcessLaunderetteScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(45, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_LAUNDERETTE_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_LAUNDERETTE_LOOP); @@ -7569,7 +7566,7 @@ cAudioManager::ProcessLaunderetteScriptObject(uint8 sound) AddSampleToRequestedQueue(); } m_sQueueSample.m_nVolume = ComputeVolume(110, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_LAUNDERETTE_SONG_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_LAUNDERETTE_SONG_LOOP); @@ -7608,7 +7605,7 @@ cAudioManager::ProcessShopScriptObject(uint8 sound) if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(30, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_SHOP_LOOP; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOP_LOOP); @@ -7628,7 +7625,7 @@ cAudioManager::ProcessShopScriptObject(uint8 sound) time = CTimer::GetTimeInMilliseconds(); if (time > gShopNextTime) { m_sQueueSample.m_nVolume = ComputeVolume(70, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { rand = m_anRandomTable[1] & 1; m_sQueueSample.m_nSampleIndex = rand + SFX_SHOP_TILL_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -7718,7 +7715,7 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound) m_sQueueSample.m_fDistance = Sqrt(distSquared); rand = m_anRandomTable[0] % 90 + 30; m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = iSound % 3 + SFX_CINEMA_BASS_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); @@ -7767,7 +7764,7 @@ cAudioManager::ProcessDocksScriptObject(uint8 sound) m_sQueueSample.m_fDistance = Sqrt(distSquared); rand = m_anRandomTable[0] % 60 + 40; m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = SFX_DOCKS_FOGHORN; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_DOCKS_FOGHORN); @@ -7815,7 +7812,7 @@ cAudioManager::ProcessHomeScriptObject(uint8 sound) m_sQueueSample.m_fDistance = Sqrt(dist); rand = m_anRandomTable[0] % 30 + 40; m_sQueueSample.m_nVolume = ComputeVolume(rand, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 5 + SFX_HOME_1; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); @@ -8095,7 +8092,7 @@ cAudioManager::ProcessFrontEnd() if (sample == SFX_RAIN) { m_sQueueSample.m_nFrequency = 28509; } else if (sample == SFX_PICKUP_1_LEFT) { - if (1.f == m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]) + if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] == 1.0f) m_sQueueSample.m_nFrequency = 32000; else m_sQueueSample.m_nFrequency = 48000; @@ -8144,7 +8141,7 @@ cAudioManager::ProcessCrane() if (distSquared < SQR(intensity)) { CalculateDistance(distCalculated, distSquared); m_sQueueSample.m_nVolume = ComputeVolume(100, 80.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_nSampleIndex = SFX_CRANE_MAGNET; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -8216,7 +8213,7 @@ cAudioManager::ProcessProjectiles() if (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) { m_sQueueSample.m_fDistance = Sqrt(distSquared); m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = i; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nLoopCount = 0; @@ -8320,7 +8317,7 @@ cAudioManager::ProcessGarages() if (distSquared < SQR(SOUND_INTENSITY)) { CalculateDistance(distCalculated, distSquared); m_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { if (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) { m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; m_sQueueSample.m_nFrequency = 6735; @@ -8429,7 +8426,7 @@ cAudioManager::ProcessBridgeWarning() { if (CStats::CommercialPassed && m_sQueueSample.m_fDistance < 450.f) { m_sQueueSample.m_nVolume = ComputeVolume(100, 450.f, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 0; m_sQueueSample.m_nSampleIndex = SFX_BRIDGE_OPEN_WARNING; m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; @@ -8456,7 +8453,7 @@ cAudioManager::ProcessBridgeMotor() { if (m_sQueueSample.m_fDistance < bridgeIntensity) { m_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, bridgeIntensity, m_sQueueSample.m_fDistance); - if (m_sQueueSample.m_nVolume) { + if (m_sQueueSample.m_nVolume != 0) { m_sQueueSample.m_nCounter = 1; m_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; // todo check sfx name m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; From 3c3b1aadc0bfd3b8d58cc9dcc269d83f6a003235 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 25 May 2020 20:36:18 +0200 Subject: [PATCH 136/148] small fixes --- src/core/World.cpp | 26 +++++++++++++------------- src/peds/Ped.cpp | 2 +- src/render/Coronas.cpp | 6 +++--- src/render/Shadows.cpp | 8 ++++---- src/render/Timecycle.cpp | 2 +- src/render/Timecycle.h | 2 +- src/vehicles/Automobile.cpp | 4 ++-- src/vehicles/Heli.cpp | 2 +- src/vehicles/Vehicle.cpp | 9 +++++++-- 9 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index edcfd865..39681428 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -33,22 +33,22 @@ CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; -CPtrList CWorld::ms_bigBuildingsList[4];// = (CPtrList*)0x6FAB60; -CPtrList CWorld::ms_listMovingEntityPtrs;// = *(CPtrList*)0x8F433C; -CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];// = (CSector (*)[NUMSECTORS_Y])0x665608; -uint16 CWorld::ms_nCurrentScanCode;// = *(uint16*)0x95CC64; +CPtrList CWorld::ms_bigBuildingsList[4]; +CPtrList CWorld::ms_listMovingEntityPtrs; +CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X]; +uint16 CWorld::ms_nCurrentScanCode; -uint8 CWorld::PlayerInFocus;// = *(uint8 *)0x95CD61; +uint8 CWorld::PlayerInFocus; CPlayerInfo CWorld::Players[NUMPLAYERS]; -bool CWorld::bNoMoreCollisionTorque;// = *(bool*)0x95CDCC; -CEntity *CWorld::pIgnoreEntity;// = *(CEntity**)0x8F6494; -bool CWorld::bIncludeDeadPeds;// = *(bool*)0x95CD8F; -bool CWorld::bSecondShift;// = *(bool*)0x95CD54; -bool CWorld::bForceProcessControl;// = *(bool*)0x95CD6C; -bool CWorld::bProcessCutsceneOnly;// = *(bool*)0x95CD8B; +bool CWorld::bNoMoreCollisionTorque; +CEntity *CWorld::pIgnoreEntity; +bool CWorld::bIncludeDeadPeds; +bool CWorld::bSecondShift; +bool CWorld::bForceProcessControl; +bool CWorld::bProcessCutsceneOnly; -bool CWorld::bDoingCarCollisions;// = *(bool*)0x95CD8C; -bool CWorld::bIncludeCarTyres;// = *(bool*)0x95CDAA; +bool CWorld::bDoingCarCollisions; +bool CWorld::bIncludeCarTyres; void CWorld::Initialise() diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index d48a6a2f..e3fa2104 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -63,7 +63,7 @@ CPed *gapTempPedList[50]; uint16 gnNumTempPedList; -CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; +static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; // Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL) PedAudioData CommentWaitTime[39] = { diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index de3b5c78..5bf89403 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -506,18 +506,18 @@ CCoronas::DoSunAndMoon(void) { // yeah, moon is done somewhere else.... - CVector sunCoors = CTimeCycle::GetSunPosition(); + CVector sunCoors = CTimeCycle::GetSunDirection(); sunCoors *= 150.0f; sunCoors += TheCamera.GetPosition(); - if(CTimeCycle::GetSunPosition().z > -0.2f){ + if(CTimeCycle::GetSunDirection().z > -0.2f){ float size = ((CGeneral::GetRandomNumber()&0xFF) * 0.005f + 10.0f) * CTimeCycle::GetSunSize(); RegisterCorona(SUN_CORE, CTimeCycle::GetSunCoreRed(), CTimeCycle::GetSunCoreGreen(), CTimeCycle::GetSunCoreBlue(), 255, sunCoors, size, 999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f); - if(CTimeCycle::GetSunPosition().z > 0.0f) + if(CTimeCycle::GetSunDirection().z > 0.0f) RegisterCorona(SUN_CORONA, CTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(), 255, sunCoors, 25.0f * CTimeCycle::GetSunSize(), diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 69f9dce0..d07c302a 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -642,12 +642,12 @@ CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, flo PolePos.y += fOffsetX * pPole->GetRight().y + fOffsetY * pPole->GetForward().y; PolePos.z += fOffsetZ; - PolePos.x += -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2); - PolePos.y += -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2); + PolePos.x += -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2); + PolePos.y += -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2); StoreStaticShadow((uintptr)pPole + nID + _TODOCONST(51), SHADOWTYPE_DARK, gpPostShadowTex, &PolePos, - -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2), - -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2), + -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2), + -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2), CTimeCycle::GetShadowSideX() * fPoleWidth, CTimeCycle::GetShadowSideY() * fPoleWidth, 2 * (int32)((pPole->GetUp().z - 0.5f) * CTimeCycle::GetShadowStrength() * 2.0f) / 3, diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index cf3426d7..1989db5c 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -298,7 +298,7 @@ CTimeCycle::Update(void) m_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF; float sunAngle = 2*PI*(CClock::GetMinutes() + CClock::GetHours()*60)/(24*60); - CVector &sunPos = GetSunPosition(); + CVector &sunPos = GetSunDirection(); sunPos.x = Sin(sunAngle); sunPos.y = 1.0f; sunPos.z = 0.2f - Cos(sunAngle); diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index 9af4df49..0cb02b67 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -142,7 +142,7 @@ public: static void Initialise(void); static void Update(void); - static CVector &GetSunPosition(void) { return m_VectorToSun[m_CurrentStoredValue]; } + static CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; } static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; } static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; } static float GetShadowSideX(void) { return m_fShadowSideX[m_CurrentStoredValue]; } diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 9617c9be..c968a147 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -4314,7 +4314,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data) return object; } -CColPoint spherepoints[MAX_COLLISION_POINTS]; +static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; CObject* CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) @@ -4434,7 +4434,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), this->GetMatrix(), *this->GetColModel(), - spherepoints, nil, nil) > 0) + aTempPedColPts, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 7b62b461..bb266a80 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -570,7 +570,7 @@ CHeli::PreRender(void) i = 0; for(angle = 0.0f; angle < TWOPI; angle += TWOPI/32){ CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f); - CVector dir = pos*0.01f; + CVector dir = CVector(pos.x, pos.y, 1.0f)*0.01f; pos += GetPosition(); if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index d8c7c4c8..e264d7ed 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -466,6 +466,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon static bool bBraking; static bool bDriving; +#ifdef FIX_BUGS + bAlreadySkidding = false; +#endif + // how much force we want to apply in these axes float fwd = 0.0f; float right = 0.0f; @@ -547,7 +551,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } } - if(sq(adhesion) < sq(right) + sq(fwd)){ + float speedSq = sq(right) + sq(fwd); + if(sq(adhesion) < speedSq){ if(*wheelState != WHEEL_STATE_FIXED){ if(bDriving && contactSpeedFwd < 0.2f) *wheelState = WHEEL_STATE_SPINNING; @@ -555,7 +560,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon *wheelState = WHEEL_STATE_SKIDDING; } - float l = Sqrt(sq(right) + sq(fwd)); + float l = Sqrt(speedSq); float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss; right *= adhesion * tractionLoss / l; fwd *= adhesion * tractionLoss / l; From 15a99da50e330f2116bbda57695064fa9cf5772b Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 25 May 2020 23:34:47 +0300 Subject: [PATCH 137/148] cranes fix --- src/vehicles/Cranes.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 936a4510..757974a6 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -243,8 +243,11 @@ void CCrane::Update(void) Abs(m_pVehiclePickedUp->GetMoveSpeed().x) > CAR_MOVING_SPEED_THRESHOLD || Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > CAR_MOVING_SPEED_THRESHOLD || Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > CAR_MOVING_SPEED_THRESHOLD || - FindPlayerPed()->GetPedState() == PED_ENTER_CAR && // TODO: fix carjack bug - FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) { + (FindPlayerPed()->GetPedState() == PED_ENTER_CAR +#ifdef FIX_BUGS + || FindPlayerPed()->GetPedState() == PED_CARJACK +#endif + ) && FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) { m_pVehiclePickedUp = nil; m_nCraneState = IDLE; } @@ -395,7 +398,7 @@ bool CCrane::RotateCarriedCarProperly() float fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep(); if (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied? return true; - m_pVehiclePickedUp->GetMatrix().RotateZ(Abs(fDeltaThisFrame)); + m_pVehiclePickedUp->GetMatrix().RotateZ(fAngleDelta < 0 ? -fDeltaThisFrame : fDeltaThisFrame); return false; } From ad8e8f434117894f052ced019d8b96a7144d0583 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 25 May 2020 23:59:55 +0300 Subject: [PATCH 138/148] switch collision with debug menu --- src/core/re3.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 9bc6400c..883caec5 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -160,6 +160,13 @@ TeleportToWaypoint(void) } #endif +static void +SwitchCarCollision(void) +{ + if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) + FindPlayerVehicle()->bUsesCollision = !FindPlayerVehicle()->bUsesCollision; +} + static int engineStatus; static void SetEngineStatus(void) @@ -362,6 +369,7 @@ DebugMenuPopulate(void) #ifdef MENU_MAP DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); #endif + DebugMenuAddCmd("Debug", "Switch car collision", SwitchCarCollision); DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil); DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus); DebugMenuAddCmd("Debug", "Fix Car", FixCar); From 38d28542269b34450f1c893e43943c70e9d55086 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 26 May 2020 00:18:04 +0300 Subject: [PATCH 139/148] fixed FIX_BUGS --- src/control/CarCtrl.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index cd86ce4c..e8b3bfd9 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -463,10 +463,6 @@ CCarCtrl::GenerateOneRandomCar() directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; } #else - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; @@ -1647,12 +1643,18 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) +#ifdef FIX_BUGS + * currentPathLinkForwardY +#endif + ,pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) +#ifdef FIX_BUGS + * nextPathLinkForwardY +#endif + ,pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; From 5ca0d6c6cf8f567299d7698108c9f0e4cc97937f Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 26 May 2020 00:45:32 +0300 Subject: [PATCH 140/148] fixed NE bug --- src/control/Garages.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 5fc44974..e37df8d4 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1853,7 +1853,14 @@ CVehicle* CStoredCar::RestoreCar() CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY); if (!CStreaming::HasModelLoaded(m_nModelIndex)) return nil; - CVehicleModelInfo::SetComponentsToUse(m_nVariationA, m_nVariationB); +#ifdef FIX_BUGS + CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_nModelIndex); + assert(pModelInfo); + if (pModelInfo->m_numComps != 0) +#endif + { + CVehicleModelInfo::SetComponentsToUse(m_nVariationA, m_nVariationB); + } #ifdef FIX_BUGS CVehicle* pVehicle; if (CModelInfo::IsBoatModel(m_nModelIndex)) From d8528ebbbe760d1ca72842cb7a4c1389ff318e5d Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 11:34:20 +0200 Subject: [PATCH 141/148] eSurfaceType --- src/audio/AudioCollision.cpp | 74 +++++++++++----------- src/audio/AudioLogic.cpp | 56 ++++++++--------- src/core/Cam.cpp | 28 ++++----- src/core/Collision.cpp | 28 ++++----- src/core/SurfaceTable.cpp | 108 ++++++++++++++++----------------- src/core/SurfaceTable.h | 57 +++++++++-------- src/core/TempColModels.cpp | 28 ++++----- src/entities/Physical.cpp | 8 +-- src/modelinfo/PedModelInfo.cpp | 2 +- src/peds/Ped.cpp | 18 +++--- src/vehicles/Automobile.cpp | 32 +++++----- src/vehicles/Vehicle.cpp | 12 ++-- src/weapons/Weapon.cpp | 2 +- 13 files changed, 226 insertions(+), 227 deletions(-) diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp index ecd0299c..55d64714 100644 --- a/src/audio/AudioCollision.cpp +++ b/src/audio/AudioCollision.cpp @@ -70,36 +70,36 @@ cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const case SURFACE_DEFAULT: case SURFACE_TARMAC: case SURFACE_PAVEMENT: - case SURFACE_STONE: - case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break; + case SURFACE_STEEP_CLIFF: + case SURFACE_TRANSPARENT_STONE: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break; case SURFACE_GRASS: - case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break; + case SURFACE_CARDBOARDBOX: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; + case SURFACE_GRAVEL: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; + case SURFACE_MUD_DRY: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; + case SURFACE_CAR: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break; case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; - case SURFACE_SCAFFOLD: - case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break; - case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break; - case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break; - case SURFACE_METAL_POLE: - case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; - case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; - case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break; - case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break; - case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; - case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break; + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_THICK_METAL_PLATE: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break; + case SURFACE_GARAGE_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break; + case SURFACE_CAR_PANEL: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break; + case SURFACE_SCAFFOLD_POLE: + case SURFACE_METAL_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; + case SURFACE_LAMP_POST: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; + case SURFACE_FIRE_HYDRANT: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break; + case SURFACE_GIRDER: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break; + case SURFACE_METAL_CHAIN_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; + case SURFACE_PED: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break; case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break; - case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break; - case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break; - case SURFACE_TIRE: - case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break; + case SURFACE_WATER: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; + case SURFACE_WOOD_CRATES: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break; + case SURFACE_WOOD_BENCH: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break; + case SURFACE_WOOD_SOLID: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break; + case SURFACE_RUBBER: + case SURFACE_WHEELBASE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; + case SURFACE_PLASTIC: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break; case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break; - case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break; - case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break; + case SURFACE_CONTAINER: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break; + case SURFACE_NEWS_VENDOR: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break; default: result = 0.f; break; } @@ -130,18 +130,18 @@ cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollisio m_sQueueSample.m_nSampleIndex = SFX_RAIN; m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000; vol = 50.f * ratio; - } else if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) { + } else if(surface1 == SURFACE_WATER || surface2 == SURFACE_WATER) { ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f); m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000; vol = 30.f * ratio; - } else if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK || - surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) { + } else if(surface1 == SURFACE_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || + surface2 == SURFACE_MUD_DRY || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) { ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f); m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000; vol = 50.f * ratio; - } else if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { + } else if(surface1 == SURFACE_PED || surface2 == SURFACE_PED) { return 0; } else { ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f); @@ -240,9 +240,9 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) s2 = col.m_bSurface2; } ratio = GetCollisionOneShotRatio(s1, col.m_fIntensity1); - if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio /= 4.0f; - if(s1 == SURFACE_METAL6 && ratio < 0.6f) { - s1 = SURFACE_BILLBOARD; + if(s1 == SURFACE_CAR && s2 == SURFACE_PED) ratio /= 4.0f; + if(s1 == SURFACE_CAR && ratio < 0.6f) { + s1 = SURFACE_CAR_PANEL; ratio = Min(1.f, 2.f * ratio); } emittingVol = 40.f * ratio; @@ -290,13 +290,13 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) } switch(s1) { case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break; - case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break; - case SURFACE_PUDDLE: + case SURFACE_GIRDER: m_sQueueSample.m_nFrequency = 8819; break; + case SURFACE_WATER: m_sQueueSample.m_nFrequency = 2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); break; - case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break; - case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break; + case SURFACE_RUBBER: m_sQueueSample.m_nFrequency = 6000; break; + case SURFACE_PLASTIC: m_sQueueSample.m_nFrequency = 8000; break; default: m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 03cf391c..5b85587b 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -848,7 +848,7 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nReleasingVolumeModificator = 3; - if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_PUDDLE) { + if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) { m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; freq = 6050 * emittingVol / 30 + 16000; } else { @@ -1517,10 +1517,10 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) m_sQueueSample.m_nFrequency = 13000.f * skidVal + 35000.f; m_sQueueSample.m_nVolume /= 4; break; - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: case SURFACE_SAND: - case SURFACE_PUDDLE: + case SURFACE_WATER: m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; m_sQueueSample.m_nFrequency = 6000.f * skidVal + 10000.f; break; @@ -3053,32 +3053,32 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) case SURFACE_GRASS: sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1; break; - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1; break; - case SURFACE_METAL6: - case SURFACE_METAL_DOOR: - case SURFACE_BILLBOARD: - case SURFACE_STEEL: - case SURFACE_METAL_POLE: - case SURFACE_STREET_LIGHT: - case SURFACE_METAL14: - case SURFACE_METAL15: - case SURFACE_METAL_FENCE: - case SURFACE_METAL27: - case SURFACE_METAL28: + case SURFACE_CAR: + case SURFACE_GARAGE_DOOR: + case SURFACE_CAR_PANEL: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_SCAFFOLD_POLE: + case SURFACE_LAMP_POST: + case SURFACE_FIRE_HYDRANT: + case SURFACE_GIRDER: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_CONTAINER: + case SURFACE_NEWS_VENDOR: sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1; break; case SURFACE_SAND: sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1; break; - case SURFACE_PUDDLE: + case SURFACE_WATER: sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; break; - case SURFACE_WOOD: - case SURFACE_WOOD_BOX: - case SURFACE_WOOD_PLANK: + case SURFACE_WOOD_CRATES: + case SURFACE_WOOD_BENCH: + case SURFACE_WOOD_SOLID: sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1; break; case SURFACE_HEDGE: @@ -3125,7 +3125,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) if (!ped->bIsLooking) { maxDist = SQR(30); emittingVol = m_anRandomTable[3] % 20 + 80; - if (ped->m_nSurfaceTouched == SURFACE_PUDDLE) { + if (ped->m_nSurfaceTouched == SURFACE_WATER) { m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; } else if (sound == SOUND_FALL_LAND) { m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND; @@ -4353,12 +4353,12 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) if (playerPed) { switch (playerPed->m_nSurfaceTouched) { case SURFACE_GRASS: - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - case SURFACE_SCAFFOLD: - case SURFACE_FLESH: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_PED: case SURFACE_SAND: - case SURFACE_TIRE: + case SURFACE_RUBBER: case SURFACE_HEDGE: m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2; m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000; @@ -4384,7 +4384,7 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) } } return; - case SURFACE_PUDDLE: + case SURFACE_WATER: return; default: break; diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index d465fb5d..d04e8683 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -504,11 +504,11 @@ CCam::ProcessSpecialHeightRoutines(void) switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched) case SURFACE_GRASS: - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - case SURFACE_STEEL: - case SURFACE_TIRE: - case SURFACE_STONE: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_RUBBER: + case SURFACE_STEEP_CLIFF: OnRoad = true; if(CCullZones::PlayerNoRain()) @@ -565,9 +565,9 @@ CCam::ProcessSpecialHeightRoutines(void) if(PreviouslyFailedRoadHeightCheck && m_fCloseInPedHeightOffset < 0.0001f){ if(colPoint.surfaceB != SURFACE_TARMAC && colPoint.surfaceB != SURFACE_GRASS && - colPoint.surfaceB != SURFACE_DIRT && - colPoint.surfaceB != SURFACE_DIRTTRACK && - colPoint.surfaceB != SURFACE_STONE){ + colPoint.surfaceB != SURFACE_GRAVEL && + colPoint.surfaceB != SURFACE_MUD_DRY && + colPoint.surfaceB != SURFACE_STEEP_CLIFF){ if(m_fRoadOffSet > 1.4f) m_fRoadOffSet = 1.4f; }else{ @@ -1408,11 +1408,11 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl bool foo = false; switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched) case SURFACE_GRASS: - case SURFACE_DIRT: + case SURFACE_GRAVEL: case SURFACE_PAVEMENT: - case SURFACE_STEEL: - case SURFACE_TIRE: - case SURFACE_STONE: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_RUBBER: + case SURFACE_STEEP_CLIFF: foo = true; if(foo) WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.4f, 0.05f, false); @@ -1750,8 +1750,8 @@ CCam::WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation) else WellBufferMe(TargetZOffSet, &RoadHeightFix, &RoadHeightFixSpeed, 0.27f, 0.1f, false); - if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_METAL6) && - colpoint.surfaceB != SURFACE_STEEL && colpoint.surfaceB != SURFACE_STONE && + if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_CAR) && + colpoint.surfaceB != SURFACE_THICK_METAL_PLATE && colpoint.surfaceB != SURFACE_STEEP_CLIFF && RoadHeightFix > 1.4f) RoadHeightFix = 1.4f; diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index d2e08f7c..b68214af 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -430,18 +430,18 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod return false; for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) if(TestLineSphere(newline, model.spheres[i])) return true; for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) if(TestLineBox(newline, model.boxes[i])) return true; CalculateTrianglePlanes(&model); for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) return true; @@ -1062,16 +1062,16 @@ CCollision::ProcessLineOfSight(const CColLine &line, float coldist = mindist; for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineSphere(newline, model.spheres[i], point, coldist); for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineBox(newline, model.boxes[i], point, coldist); CalculateTrianglePlanes(&model); for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); if(coldist < mindist){ @@ -1103,17 +1103,17 @@ CCollision::ProcessVerticalLine(const CColLine &line, float coldist = mindist; for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineSphere(newline, model.spheres[i], point, coldist); for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineBox(newline, model.boxes[i], point, coldist); CalculateTrianglePlanes(&model); TempStoredPoly.valid = false; for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); if(coldist < mindist){ @@ -1642,15 +1642,15 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, b *= f; } - if(s == SURFACE_SCAFFOLD || s == SURFACE_METAL_FENCE || - s == SURFACE_BOLLARD || s == SURFACE_METAL_POLE) + if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || + s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) if(CTimer::GetFrameCounter() & 1){ r = 0; g = 0; b = 0; } - if(s > SURFACE_GATE){ + if(s > SURFACE_METAL_GATE){ r = CGeneral::GetRandomNumber(); g = CGeneral::GetRandomNumber(); b = CGeneral::GetRandomNumber(); @@ -1723,8 +1723,8 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, b *= f; } - if(s == SURFACE_SCAFFOLD || s == SURFACE_METAL_FENCE || - s == SURFACE_BOLLARD || s == SURFACE_METAL_POLE) + if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || + s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) if(CTimer::GetFrameCounter() & 1){ r = 0; g = 0; diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index f002bf49..9076a9a6 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -59,38 +59,38 @@ CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) case SURFACE_DEFAULT: return ADHESIVE_ROAD; case SURFACE_TARMAC: return ADHESIVE_ROAD; case SURFACE_GRASS: return ADHESIVE_LOOSE; - case SURFACE_DIRT: return ADHESIVE_LOOSE; - case SURFACE_DIRTTRACK: return ADHESIVE_HARD; + case SURFACE_GRAVEL: return ADHESIVE_LOOSE; + case SURFACE_MUD_DRY: return ADHESIVE_HARD; case SURFACE_PAVEMENT: return ADHESIVE_ROAD; - case SURFACE_METAL6: return ADHESIVE_HARD; + case SURFACE_CAR: return ADHESIVE_HARD; case SURFACE_GLASS: return ADHESIVE_HARD; - case SURFACE_SCAFFOLD: return ADHESIVE_HARD; - case SURFACE_METAL_DOOR: return ADHESIVE_HARD; - case SURFACE_BILLBOARD: return ADHESIVE_HARD; - case SURFACE_STEEL: return ADHESIVE_HARD; - case SURFACE_METAL_POLE: return ADHESIVE_HARD; - case SURFACE_STREET_LIGHT: return ADHESIVE_HARD; - case SURFACE_METAL14: return ADHESIVE_HARD; - case SURFACE_METAL15: return ADHESIVE_HARD; - case SURFACE_METAL_FENCE: return ADHESIVE_HARD; - case SURFACE_FLESH: return ADHESIVE_RUBBER; + case SURFACE_TRANSPARENT_CLOTH: return ADHESIVE_HARD; + case SURFACE_GARAGE_DOOR: return ADHESIVE_HARD; + case SURFACE_CAR_PANEL: return ADHESIVE_HARD; + case SURFACE_THICK_METAL_PLATE: return ADHESIVE_HARD; + case SURFACE_SCAFFOLD_POLE: return ADHESIVE_HARD; + case SURFACE_LAMP_POST: return ADHESIVE_HARD; + case SURFACE_FIRE_HYDRANT: return ADHESIVE_HARD; + case SURFACE_GIRDER: return ADHESIVE_HARD; + case SURFACE_METAL_CHAIN_FENCE: return ADHESIVE_HARD; + case SURFACE_PED: return ADHESIVE_RUBBER; case SURFACE_SAND: return ADHESIVE_SAND; - case SURFACE_PUDDLE: return ADHESIVE_WET; - case SURFACE_WOOD: return ADHESIVE_ROAD; - case SURFACE_WOOD_BOX: return ADHESIVE_ROAD; - case SURFACE_WOOD_PLANK: return ADHESIVE_ROAD; - case SURFACE_TIRE: return ADHESIVE_RUBBER; - case SURFACE_HARD24: return ADHESIVE_HARD; + case SURFACE_WATER: return ADHESIVE_WET; + case SURFACE_WOOD_CRATES: return ADHESIVE_ROAD; + case SURFACE_WOOD_BENCH: return ADHESIVE_ROAD; + case SURFACE_WOOD_SOLID: return ADHESIVE_ROAD; + case SURFACE_RUBBER: return ADHESIVE_RUBBER; + case SURFACE_PLASTIC: return ADHESIVE_HARD; case SURFACE_HEDGE: return ADHESIVE_LOOSE; - case SURFACE_STONE: return ADHESIVE_LOOSE; - case SURFACE_METAL27: return ADHESIVE_HARD; - case SURFACE_METAL28: return ADHESIVE_HARD; - case SURFACE_RUBBER29: return ADHESIVE_RUBBER; - case SURFACE_LOOSE30: return ADHESIVE_LOOSE; - case SURFACE_BOLLARD: return ADHESIVE_HARD; - case SURFACE_GATE: return ADHESIVE_HARD; - case SURFACE_SAND33: return ADHESIVE_SAND; - case SURFACE_ROAD34: return ADHESIVE_ROAD; + case SURFACE_STEEP_CLIFF: return ADHESIVE_LOOSE; + case SURFACE_CONTAINER: return ADHESIVE_HARD; + case SURFACE_NEWS_VENDOR: return ADHESIVE_HARD; + case SURFACE_WHEELBASE: return ADHESIVE_RUBBER; + case SURFACE_CARDBOARDBOX: return ADHESIVE_LOOSE; + case SURFACE_TRANSPARENT_STONE: return ADHESIVE_HARD; + case SURFACE_METAL_GATE: return ADHESIVE_HARD; + case SURFACE_SAND_BEACH: return ADHESIVE_SAND; + case SURFACE_CONCRETE_BEACH: return ADHESIVE_ROAD; default: return ADHESIVE_ROAD; } } @@ -101,41 +101,41 @@ CSurfaceTable::GetWetMultiplier(uint8 surfaceType) switch(surfaceType){ case SURFACE_DEFAULT: case SURFACE_TARMAC: - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: case SURFACE_PAVEMENT: - case SURFACE_SCAFFOLD: - case SURFACE_WOOD: - case SURFACE_WOOD_BOX: - case SURFACE_WOOD_PLANK: + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_WOOD_CRATES: + case SURFACE_WOOD_BENCH: + case SURFACE_WOOD_SOLID: case SURFACE_HEDGE: - case SURFACE_LOOSE30: - case SURFACE_BOLLARD: - case SURFACE_ROAD34: + case SURFACE_CARDBOARDBOX: + case SURFACE_TRANSPARENT_STONE: + case SURFACE_CONCRETE_BEACH: return 1.0f - CWeather::WetRoads*0.25f; case SURFACE_GRASS: - case SURFACE_METAL6: + case SURFACE_CAR: case SURFACE_GLASS: - case SURFACE_METAL_DOOR: - case SURFACE_BILLBOARD: - case SURFACE_STEEL: - case SURFACE_METAL_POLE: - case SURFACE_STREET_LIGHT: - case SURFACE_METAL14: - case SURFACE_METAL15: - case SURFACE_METAL_FENCE: - case SURFACE_FLESH: - case SURFACE_TIRE: - case SURFACE_HARD24: - case SURFACE_STONE: - case SURFACE_METAL27: - case SURFACE_METAL28: - case SURFACE_RUBBER29: - case SURFACE_GATE: + case SURFACE_GARAGE_DOOR: + case SURFACE_CAR_PANEL: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_SCAFFOLD_POLE: + case SURFACE_LAMP_POST: + case SURFACE_FIRE_HYDRANT: + case SURFACE_GIRDER: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_PED: + case SURFACE_RUBBER: + case SURFACE_PLASTIC: + case SURFACE_STEEP_CLIFF: + case SURFACE_CONTAINER: + case SURFACE_NEWS_VENDOR: + case SURFACE_WHEELBASE: + case SURFACE_METAL_GATE: return 1.0f - CWeather::WetRoads*0.4f; case SURFACE_SAND: - case SURFACE_SAND33: + case SURFACE_SAND_BEACH: return 1.0f - CWeather::WetRoads*0.5f; default: diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 5d8d2c4f..d8f9be3d 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -1,43 +1,42 @@ #pragma once -// TODO: check this enum eSurfaceType { SURFACE_DEFAULT, SURFACE_TARMAC, SURFACE_GRASS, - SURFACE_DIRT, - SURFACE_DIRTTRACK, + SURFACE_GRAVEL, + SURFACE_MUD_DRY, SURFACE_PAVEMENT, - SURFACE_METAL6, + SURFACE_CAR, SURFACE_GLASS, - SURFACE_SCAFFOLD, - SURFACE_METAL_DOOR, // garage door - SURFACE_BILLBOARD, - SURFACE_STEEL, //? - SURFACE_METAL_POLE, // ? - SURFACE_STREET_LIGHT, - SURFACE_METAL14, - SURFACE_METAL15, - SURFACE_METAL_FENCE, - SURFACE_FLESH, + SURFACE_TRANSPARENT_CLOTH, + SURFACE_GARAGE_DOOR, + SURFACE_CAR_PANEL, + SURFACE_THICK_METAL_PLATE, + SURFACE_SCAFFOLD_POLE, + SURFACE_LAMP_POST, + SURFACE_FIRE_HYDRANT, + SURFACE_GIRDER, + SURFACE_METAL_CHAIN_FENCE, + SURFACE_PED, SURFACE_SAND, - SURFACE_PUDDLE, - SURFACE_WOOD, - SURFACE_WOOD_BOX, - SURFACE_WOOD_PLANK, - SURFACE_TIRE, - SURFACE_HARD24, + SURFACE_WATER, + SURFACE_WOOD_CRATES, + SURFACE_WOOD_BENCH, + SURFACE_WOOD_SOLID, + SURFACE_RUBBER, + SURFACE_PLASTIC, SURFACE_HEDGE, - SURFACE_STONE, - SURFACE_METAL27, - SURFACE_METAL28, - SURFACE_RUBBER29, - SURFACE_LOOSE30, - SURFACE_BOLLARD, - SURFACE_GATE, - SURFACE_SAND33, - SURFACE_ROAD34, + SURFACE_STEEP_CLIFF, + SURFACE_CONTAINER, + SURFACE_NEWS_VENDOR, + SURFACE_WHEELBASE, + SURFACE_CARDBOARDBOX, + SURFACE_TRANSPARENT_STONE, + SURFACE_METAL_GATE, + SURFACE_SAND_BEACH, + SURFACE_CONCRETE_BEACH, }; enum diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index f20923f2..a4814759 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -66,7 +66,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) { #endif - s_aPedSpheres[i].surface = SURFACE_FLESH; + s_aPedSpheres[i].surface = SURFACE_PED; s_aPedSpheres[i].piece = 0; } @@ -85,7 +85,7 @@ CTempColModels::Initialise(void) s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f); for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { - s_aPed2Spheres[i].surface = SURFACE_FLESH; + s_aPed2Spheres[i].surface = SURFACE_PED; s_aPed2Spheres[i].piece = 0; } @@ -106,10 +106,10 @@ CTempColModels::Initialise(void) s_aPedGSpheres[2].center = CVector(0.0f, 0.25f, -0.9f); s_aPedGSpheres[3].center = CVector(0.0f, 0.65f, -0.9f); - s_aPedGSpheres[0].surface = SURFACE_FLESH; - s_aPedGSpheres[1].surface = SURFACE_FLESH; - s_aPedGSpheres[2].surface = SURFACE_FLESH; - s_aPedGSpheres[3].surface = SURFACE_FLESH; + s_aPedGSpheres[0].surface = SURFACE_PED; + s_aPedGSpheres[1].surface = SURFACE_PED; + s_aPedGSpheres[2].surface = SURFACE_PED; + s_aPedGSpheres[3].surface = SURFACE_PED; s_aPedGSpheres[0].piece = 4; s_aPedGSpheres[1].piece = 1; s_aPedGSpheres[2].piece = 0; @@ -131,7 +131,7 @@ CTempColModels::Initialise(void) s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { - s_aDoorSpheres[i].surface = SURFACE_BILLBOARD; + s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL; s_aDoorSpheres[i].piece = 0; } @@ -151,7 +151,7 @@ CTempColModels::Initialise(void) s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) { - s_aBumperSpheres[i].surface = SURFACE_BILLBOARD; + s_aBumperSpheres[i].surface = SURFACE_CAR_PANEL; s_aBumperSpheres[i].piece = 0; } @@ -171,7 +171,7 @@ CTempColModels::Initialise(void) s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) { - s_aPanelSpheres[i].surface = SURFACE_BILLBOARD; + s_aPanelSpheres[i].surface = SURFACE_CAR_PANEL; s_aPanelSpheres[i].piece = 0; } @@ -191,7 +191,7 @@ CTempColModels::Initialise(void) s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) { - s_aBonnetSpheres[i].surface = SURFACE_BILLBOARD; + s_aBonnetSpheres[i].surface = SURFACE_CAR_PANEL; s_aBonnetSpheres[i].piece = 0; } @@ -211,7 +211,7 @@ CTempColModels::Initialise(void) s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { - s_aBootSpheres[i].surface = SURFACE_BILLBOARD; + s_aBootSpheres[i].surface = SURFACE_CAR_PANEL; s_aBootSpheres[i].piece = 0; } @@ -233,7 +233,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif - s_aWheelSpheres[i].surface = SURFACE_RUBBER29; + s_aWheelSpheres[i].surface = SURFACE_WHEELBASE; s_aWheelSpheres[i].piece = 0; } @@ -255,7 +255,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif - s_aBodyPartSpheres1[i].surface = SURFACE_FLESH; + s_aBodyPartSpheres1[i].surface = SURFACE_PED; s_aBodyPartSpheres1[i].piece = 0; } @@ -277,7 +277,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif - s_aBodyPartSpheres2[i].surface = SURFACE_FLESH; + s_aBodyPartSpheres2[i].surface = SURFACE_PED; s_aBodyPartSpheres2[i].piece = 0; } diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index ec9f3f33..02feb5cb 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -951,7 +951,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV Abs(m_vecMoveSpeed.z) < minspeed*2.0f) impulse = -0.8f * normalSpeed * mass; else if(IsVehicle() && ((CVehicle*)this)->IsBoat() && - colpoint.surfaceB == SURFACE_WOOD_PLANK && colpoint.normal.z < 0.5f) + colpoint.surfaceB == SURFACE_WOOD_SOLID && colpoint.normal.z < 0.5f) impulse = -(2.0f * m_fElasticity + 1.0f) * normalSpeed * mass; else impulse = -(m_fElasticity + 1.0f) * normalSpeed * mass; @@ -1146,7 +1146,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint) ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos); if(fOtherSpeed > 0.1f && - colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_DIRTTRACK && + colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_MUD_DRY && CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){ CVector v = frictionDir * fOtherSpeed * 0.25f; for(int i = 0; i < 4; i++) @@ -1642,7 +1642,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(impulseA > maxImpulseA) maxImpulseA = impulseA; if(A->IsVehicle()){ - if(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_PLANK) && + if(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID) && impulseA > A->m_fDamageImpulse) A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); @@ -1679,7 +1679,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions; if(A->IsVehicle()){ - if(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_PLANK) + if(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID) adhesion = 0.0f; else if(impulseA > A->m_fDamageImpulse) A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index bf81bd8a..a9caa867 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -96,7 +96,7 @@ CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) center.x = pos.x + m_pColNodeInfos[i].x; center.y = pos.y + 0.0f; center.z = pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); + spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_PED, m_pColNodeInfos[i].pieceType); } RwMatrixDestroy(invmat); RwMatrixDestroy(mat); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 647ecef6..2c515428 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2413,7 +2413,7 @@ particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) switch (ped->m_nSurfaceTouched) { case SURFACE_TARMAC: - case SURFACE_DIRT: + case SURFACE_GRAVEL: case SURFACE_PAVEMENT: case SURFACE_SAND: for (int i = 0; i < times; ++i) { @@ -2566,7 +2566,7 @@ CPed::PlayFootSteps(void) } } - if (m_nSurfaceTouched == SURFACE_PUDDLE) { + if (m_nSurfaceTouched == SURFACE_WATER) { float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude(); if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) { #ifdef PC_PARTICLE @@ -2965,7 +2965,7 @@ CPed::CanPedDriveOff(void) bool CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil) { - if (m_nSurfaceTouched == SURFACE_PUDDLE) + if (m_nSurfaceTouched == SURFACE_WATER) return true; CVector pos = GetPosition(); @@ -5306,8 +5306,8 @@ CPed::SetAttack(CEntity *victim) aimPos += GetUp() * 0.35f; CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false); if (obstacle) { - if(gaTempSphereColPoints[0].surfaceB != SURFACE_SCAFFOLD && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_FENCE && - gaTempSphereColPoints[0].surfaceB != SURFACE_WOOD_BOX && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_POLE) { + if(gaTempSphereColPoints[0].surfaceB != SURFACE_TRANSPARENT_CLOTH && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_CHAIN_FENCE && + gaTempSphereColPoints[0].surfaceB != SURFACE_WOOD_BENCH && gaTempSphereColPoints[0].surfaceB != SURFACE_SCAFFOLD_POLE) { if (!IsPlayer()) { bObstacleShowedUpDuringKillObjective = true; m_shootTimer = 0; @@ -11647,7 +11647,7 @@ CPed::SetJump(void) #ifdef VC_PED_PORTS m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) && #endif - (m_nSurfaceTouched != SURFACE_STONE || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { + (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { SetStoredState(); m_nPedState = PED_JUMP; CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f); @@ -15473,7 +15473,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; #endif m_nSurfaceTouched = intersectionPoint.surfaceB; - if (m_nSurfaceTouched == SURFACE_STONE) { + if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) { bHitSteepSlope = true; m_vecDamageNormal = intersectionPoint.normal; } @@ -15559,7 +15559,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) #endif sphereNormal.Normalise(); collidingPoints[sphere].normal = sphereNormal; - if (collidingPoints[sphere].surfaceB == SURFACE_STONE) + if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF) bHitSteepSlope = true; } } @@ -17430,7 +17430,7 @@ CPed::UpdatePosition(void) velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed; m_fRotationCur += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); m_fRotationDest += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); - } else if (m_nSurfaceTouched != SURFACE_STONE || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) { + } else if (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) { velocityChange = m_moved - m_vecMoveSpeed; } else { // Ped got damaged by steep slope diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 364415e9..fbcf610c 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -609,7 +609,7 @@ CAutomobile::ProcessControl(void) m_aSuspensionSpringRatio[i], bias); m_aWheelSkidmarkMuddy[i] = m_aWheelColPoints[i].surfaceB == SURFACE_GRASS || - m_aWheelColPoints[i].surfaceB == SURFACE_DIRTTRACK || + m_aWheelColPoints[i].surfaceB == SURFACE_MUD_DRY || m_aWheelColPoints[i].surfaceB == SURFACE_SAND; }else{ contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1); @@ -733,7 +733,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB); @@ -767,7 +767,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB); @@ -848,7 +848,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB); @@ -882,7 +882,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB); @@ -1097,10 +1097,10 @@ CAutomobile::ProcessControl(void) } uint8 surf = m_aWheelColPoints[i].surfaceB; - if(surf == SURFACE_DIRT || surf == SURFACE_PUDDLE || surf == SURFACE_HEDGE){ + if(surf == SURFACE_GRAVEL || surf == SURFACE_WATER || surf == SURFACE_HEDGE){ if(surfShake < 0.2f) surfShake = 0.3f; - }else if(surf == SURFACE_DIRTTRACK || surf == SURFACE_SAND){ + }else if(surf == SURFACE_MUD_DRY || surf == SURFACE_SAND){ if(surfShake < 0.1f) surfShake = 0.2f; }else if(surf == SURFACE_GRASS){ @@ -2933,7 +2933,7 @@ CAutomobile::ProcessBuoyancy(void) static RwRGBA smokeCol = {255, 255, 255, 255}; for(i = 0; i < 4; i++){ - if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_PUDDLE){ + if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_WATER){ CVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition(); CVector vSpeed = GetSpeed(pos); vSpeed.z = 0.0f; @@ -3540,7 +3540,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) CGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol); } return 0; - case SURFACE_DIRT: + case SURFACE_GRAVEL: dir.x = -0.05f*m_vecMoveSpeed.x; dir.y = -0.05f*m_vecMoveSpeed.y; for(i = 0; i < 4; i++){ @@ -3549,7 +3549,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol); } return 1; - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: dir.x = -0.05f*m_vecMoveSpeed.x; dir.y = -0.05f*m_vecMoveSpeed.y; for(i = 0; i < 4; i++){ @@ -3899,19 +3899,19 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) CMatrix mat; mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF])); - colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LF); + colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LF); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB])); - colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); + colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF])); - colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF); + colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RF); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB])); - colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); + colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR); if(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){ mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM])); - colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); + colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM])); - colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); + colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR); colModel->numSpheres = 6; }else colModel->numSpheres = 4; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index c988bf3d..14ca4462 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -703,7 +703,7 @@ CVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix & } if(hadCollision && !entity->IsPed()) - DMAudio.ReportCollision(this, entity, SURFACE_BILLBOARD, SURFACE_TARMAC, 50.0f, 0.09f); + DMAudio.ReportCollision(this, entity, SURFACE_CAR_PANEL, SURFACE_TARMAC, 50.0f, 0.09f); m_fElasticity = savedElasticity; } } @@ -2082,7 +2082,7 @@ CVehicle::HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd) float waterLevel = 0.0f; if(CWaterLevel::GetWaterLevel(pos, &waterLevel, false) && waterLevel > particleZ){ - surface = SURFACE_PUDDLE; + surface = SURFACE_WATER; n = rnd; particleZ = waterLevel; } @@ -2090,7 +2090,7 @@ CVehicle::HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd) if(n){ pos.z = particleZ; - if(surface == SURFACE_PUDDLE){ + if(surface == SURFACE_WATER){ float red = (0.3*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj())*255.0f/4.0f; float green = (0.3*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj())*255.0f/4.0f; float blue = (0.3*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj())*255.0f/4.0f; @@ -2119,18 +2119,18 @@ CVehicle::HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd) g = 10; b = 3; break; - case SURFACE_DIRT: + case SURFACE_GRAVEL: r = 10; g = 8; b = 7; break; - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: r = 10; g = 6; b = 3; break; case SURFACE_SAND: - case SURFACE_SAND33: + case SURFACE_SAND_BEACH: r = 10; g = 10; b = 7; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index a6217d70..9edb3c51 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1647,7 +1647,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { case ENTITY_TYPE_VEHICLE: { - if (point.pieceB >= SURFACE_STREET_LIGHT && point.pieceB <= SURFACE_METAL_FENCE) { + if (point.pieceB >= SURFACE_LAMP_POST && point.pieceB <= SURFACE_METAL_CHAIN_FENCE) { ((CVehicle*)victim)->BurstTyre(point.pieceB, true); for (int32 i = 0; i < 4; i++) From 7e5dde1f1a6ffbba98572b7fad3a51538104c04b Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 11:37:46 +0200 Subject: [PATCH 142/148] eSurfaceType --- src/audio/AudioCollision.cpp | 74 ++++++++++++------------ src/audio/AudioLogic.cpp | 56 +++++++++--------- src/core/Cam.cpp | 28 ++++----- src/core/Collision.cpp | 28 ++++----- src/core/SurfaceTable.cpp | 100 ++++++++++++++++----------------- src/core/SurfaceTable.h | 57 +++++++++---------- src/core/TempColModels.cpp | 28 ++++----- src/entities/Physical.cpp | 2 +- src/modelinfo/PedModelInfo.cpp | 4 +- src/peds/Ped.cpp | 14 ++--- src/vehicles/Automobile.cpp | 32 +++++------ src/vehicles/Heli.cpp | 4 +- 12 files changed, 213 insertions(+), 214 deletions(-) diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp index ecd0299c..55d64714 100644 --- a/src/audio/AudioCollision.cpp +++ b/src/audio/AudioCollision.cpp @@ -70,36 +70,36 @@ cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const case SURFACE_DEFAULT: case SURFACE_TARMAC: case SURFACE_PAVEMENT: - case SURFACE_STONE: - case SURFACE_BOLLARD: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break; + case SURFACE_STEEP_CLIFF: + case SURFACE_TRANSPARENT_STONE: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break; case SURFACE_GRASS: - case SURFACE_LOOSE30: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_DIRT: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_DIRTTRACK: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; - case SURFACE_METAL6: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break; + case SURFACE_CARDBOARDBOX: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; + case SURFACE_GRAVEL: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; + case SURFACE_MUD_DRY: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break; + case SURFACE_CAR: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break; case SURFACE_GLASS: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; - case SURFACE_SCAFFOLD: - case SURFACE_STEEL: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break; - case SURFACE_METAL_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break; - case SURFACE_BILLBOARD: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break; - case SURFACE_METAL_POLE: - case SURFACE_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; - case SURFACE_STREET_LIGHT: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; - case SURFACE_METAL14: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break; - case SURFACE_METAL15: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break; - case SURFACE_METAL_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; - case SURFACE_FLESH: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break; + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_THICK_METAL_PLATE: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break; + case SURFACE_GARAGE_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break; + case SURFACE_CAR_PANEL: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break; + case SURFACE_SCAFFOLD_POLE: + case SURFACE_METAL_GATE: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; + case SURFACE_LAMP_POST: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break; + case SURFACE_FIRE_HYDRANT: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break; + case SURFACE_GIRDER: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break; + case SURFACE_METAL_CHAIN_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break; + case SURFACE_PED: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break; case SURFACE_SAND: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_PUDDLE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_WOOD: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break; - case SURFACE_WOOD_BOX: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break; - case SURFACE_WOOD_PLANK: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break; - case SURFACE_TIRE: - case SURFACE_RUBBER29: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; - case SURFACE_HARD24: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break; + case SURFACE_WATER: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; + case SURFACE_WOOD_CRATES: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break; + case SURFACE_WOOD_BENCH: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break; + case SURFACE_WOOD_SOLID: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break; + case SURFACE_RUBBER: + case SURFACE_WHEELBASE: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break; + case SURFACE_PLASTIC: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break; case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break; - case SURFACE_METAL27: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break; - case SURFACE_METAL28: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break; + case SURFACE_CONTAINER: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break; + case SURFACE_NEWS_VENDOR: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break; default: result = 0.f; break; } @@ -130,18 +130,18 @@ cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollisio m_sQueueSample.m_nSampleIndex = SFX_RAIN; m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000; vol = 50.f * ratio; - } else if(surface1 == SURFACE_PUDDLE || surface2 == SURFACE_PUDDLE) { + } else if(surface1 == SURFACE_WATER || surface2 == SURFACE_WATER) { ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f); m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000; vol = 30.f * ratio; - } else if(surface1 == SURFACE_DIRT || surface2 == SURFACE_DIRT || surface1 == SURFACE_DIRTTRACK || - surface2 == SURFACE_DIRTTRACK || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) { + } else if(surface1 == SURFACE_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || + surface2 == SURFACE_MUD_DRY || surface1 == SURFACE_SAND || surface2 == SURFACE_SAND) { ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f); m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000; vol = 50.f * ratio; - } else if(surface1 == SURFACE_FLESH || surface2 == SURFACE_FLESH) { + } else if(surface1 == SURFACE_PED || surface2 == SURFACE_PED) { return 0; } else { ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f); @@ -240,9 +240,9 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) s2 = col.m_bSurface2; } ratio = GetCollisionOneShotRatio(s1, col.m_fIntensity1); - if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio /= 4.0f; - if(s1 == SURFACE_METAL6 && ratio < 0.6f) { - s1 = SURFACE_BILLBOARD; + if(s1 == SURFACE_CAR && s2 == SURFACE_PED) ratio /= 4.0f; + if(s1 == SURFACE_CAR && ratio < 0.6f) { + s1 = SURFACE_CAR_PANEL; ratio = Min(1.f, 2.f * ratio); } emittingVol = 40.f * ratio; @@ -290,13 +290,13 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col) } switch(s1) { case SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break; - case SURFACE_METAL15: m_sQueueSample.m_nFrequency = 8819; break; - case SURFACE_PUDDLE: + case SURFACE_GIRDER: m_sQueueSample.m_nFrequency = 8819; break; + case SURFACE_WATER: m_sQueueSample.m_nFrequency = 2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); break; - case SURFACE_TIRE: m_sQueueSample.m_nFrequency = 6000; break; - case SURFACE_HARD24: m_sQueueSample.m_nFrequency = 8000; break; + case SURFACE_RUBBER: m_sQueueSample.m_nFrequency = 6000; break; + case SURFACE_PLASTIC: m_sQueueSample.m_nFrequency = 8000; break; default: m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index f516e43c..56e602fd 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -769,7 +769,7 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) m_sQueueSample.m_nBankIndex = SAMPLEBANK_MAIN; m_sQueueSample.m_bIs2D = false; m_sQueueSample.m_nReleasingVolumeModificator = 3; - if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_PUDDLE) { + if (params->m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) { m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP; freq = 6050 * emittingVol / 30 + 16000; } else { @@ -1394,10 +1394,10 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) m_sQueueSample.m_nFrequency = 13000.f * skidVal + 35000.f; m_sQueueSample.m_nVolume /= 4; break; - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: case SURFACE_SAND: - case SURFACE_PUDDLE: + case SURFACE_WATER: m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID; m_sQueueSample.m_nFrequency = 6000.f * skidVal + 10000.f; break; @@ -2984,32 +2984,32 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) case SURFACE_GRASS: sampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1; break; - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: sampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1; break; - case SURFACE_METAL6: - case SURFACE_METAL_DOOR: - case SURFACE_BILLBOARD: - case SURFACE_STEEL: - case SURFACE_METAL_POLE: - case SURFACE_STREET_LIGHT: - case SURFACE_METAL14: - case SURFACE_METAL15: - case SURFACE_METAL_FENCE: - case SURFACE_METAL27: - case SURFACE_METAL28: + case SURFACE_CAR: + case SURFACE_GARAGE_DOOR: + case SURFACE_CAR_PANEL: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_SCAFFOLD_POLE: + case SURFACE_LAMP_POST: + case SURFACE_FIRE_HYDRANT: + case SURFACE_GIRDER: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_CONTAINER: + case SURFACE_NEWS_VENDOR: sampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1; break; case SURFACE_SAND: sampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1; break; - case SURFACE_PUDDLE: + case SURFACE_WATER: sampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; break; - case SURFACE_WOOD: - case SURFACE_WOOD_BOX: - case SURFACE_WOOD_PLANK: + case SURFACE_WOOD_CRATES: + case SURFACE_WOOD_BENCH: + case SURFACE_WOOD_SOLID: sampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1; break; case SURFACE_HEDGE: @@ -3056,7 +3056,7 @@ cAudioManager::ProcessPedOneShots(cPedParams *params) if (!ped->bIsLooking) { maxDist = SQR(30); emittingVol = m_anRandomTable[3] % 20 + 80; - if (ped->m_nSurfaceTouched == SURFACE_PUDDLE) { + if (ped->m_nSurfaceTouched == SURFACE_WATER) { m_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1; } else if (sound == SOUND_FALL_LAND) { m_sQueueSample.m_nSampleIndex = SFX_BODY_LAND; @@ -6653,12 +6653,12 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) if (playerPed) { switch (playerPed->m_nSurfaceTouched) { case SURFACE_GRASS: - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - case SURFACE_SCAFFOLD: - case SURFACE_FLESH: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_PED: case SURFACE_SAND: - case SURFACE_TIRE: + case SURFACE_RUBBER: case SURFACE_HEDGE: m_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2; m_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000; @@ -6684,7 +6684,7 @@ cAudioManager::ProcessOneShotScriptObject(uint8 sound) } } return; - case SURFACE_PUDDLE: + case SURFACE_WATER: return; default: break; diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 6c79604c..247e77ce 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -504,11 +504,11 @@ CCam::ProcessSpecialHeightRoutines(void) switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched) case SURFACE_GRASS: - case SURFACE_DIRT: - case SURFACE_DIRTTRACK: - case SURFACE_STEEL: - case SURFACE_TIRE: - case SURFACE_STONE: + case SURFACE_GRAVEL: + case SURFACE_MUD_DRY: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_RUBBER: + case SURFACE_STEEP_CLIFF: OnRoad = true; if(CCullZones::PlayerNoRain()) @@ -565,9 +565,9 @@ CCam::ProcessSpecialHeightRoutines(void) if(PreviouslyFailedRoadHeightCheck && m_fCloseInPedHeightOffset < 0.0001f){ if(colPoint.surfaceB != SURFACE_TARMAC && colPoint.surfaceB != SURFACE_GRASS && - colPoint.surfaceB != SURFACE_DIRT && - colPoint.surfaceB != SURFACE_DIRTTRACK && - colPoint.surfaceB != SURFACE_STONE){ + colPoint.surfaceB != SURFACE_GRAVEL && + colPoint.surfaceB != SURFACE_MUD_DRY && + colPoint.surfaceB != SURFACE_STEEP_CLIFF){ if(m_fRoadOffSet > 1.4f) m_fRoadOffSet = 1.4f; }else{ @@ -1408,11 +1408,11 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl bool foo = false; switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched) case SURFACE_GRASS: - case SURFACE_DIRT: + case SURFACE_GRAVEL: case SURFACE_PAVEMENT: - case SURFACE_STEEL: - case SURFACE_TIRE: - case SURFACE_STONE: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_RUBBER: + case SURFACE_STEEP_CLIFF: foo = true; if(foo) WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.4f, 0.05f, false); @@ -1764,8 +1764,8 @@ CCam::WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation) else WellBufferMe(TargetZOffSet, &RoadHeightFix, &RoadHeightFixSpeed, 0.27f, 0.1f, false); - if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_METAL6) && - colpoint.surfaceB != SURFACE_STEEL && colpoint.surfaceB != SURFACE_STONE && + if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_CAR) && + colpoint.surfaceB != SURFACE_THICK_METAL_PLATE && colpoint.surfaceB != SURFACE_STEEP_CLIFF && RoadHeightFix > 1.4f) RoadHeightFix = 1.4f; diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 01cc323a..23eaa8dd 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -548,18 +548,18 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod return false; for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) if(TestLineSphere(newline, model.spheres[i])) return true; for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) if(TestLineBox(newline, model.boxes[i])) return true; CalculateTrianglePlanes(&model); for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) return true; @@ -1179,16 +1179,16 @@ CCollision::ProcessLineOfSight(const CColLine &line, float coldist = mindist; for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineSphere(newline, model.spheres[i], point, coldist); for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineBox(newline, model.boxes[i], point, coldist); CalculateTrianglePlanes(&model); for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); if(coldist < mindist){ @@ -1219,17 +1219,17 @@ CCollision::ProcessVerticalLine(const CColLine &line, float coldist = mindist; for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineSphere(newline, model.spheres[i], point, coldist); for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessLineBox(newline, model.boxes[i], point, coldist); CalculateTrianglePlanes(&model); TempStoredPoly.valid = false; for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_SCAFFOLD) + if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); if(coldist < mindist){ @@ -1758,15 +1758,15 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, b *= f; } - if(s == SURFACE_SCAFFOLD || s == SURFACE_METAL_FENCE || - s == SURFACE_BOLLARD || s == SURFACE_METAL_POLE) + if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || + s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) if(CTimer::GetFrameCounter() & 1){ r = 0; g = 0; b = 0; } - if(s > SURFACE_GATE){ + if(s > SURFACE_METAL_GATE){ r = CGeneral::GetRandomNumber(); g = CGeneral::GetRandomNumber(); b = CGeneral::GetRandomNumber(); @@ -1839,8 +1839,8 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, b *= f; } - if(s == SURFACE_SCAFFOLD || s == SURFACE_METAL_FENCE || - s == SURFACE_BOLLARD || s == SURFACE_METAL_POLE) + if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || + s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) if(CTimer::GetFrameCounter() & 1){ r = 0; g = 0; diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index e4f9c0cd..b1bcceb6 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -59,36 +59,36 @@ CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) case SURFACE_DEFAULT: return ADHESIVE_ROAD; case SURFACE_TARMAC: return ADHESIVE_ROAD; case SURFACE_GRASS: return ADHESIVE_LOOSE; - case SURFACE_DIRT: return ADHESIVE_LOOSE; - case SURFACE_DIRTTRACK: return ADHESIVE_HARD; + case SURFACE_GRAVEL: return ADHESIVE_LOOSE; + case SURFACE_MUD_DRY: return ADHESIVE_HARD; case SURFACE_PAVEMENT: return ADHESIVE_ROAD; - case SURFACE_METAL6: return ADHESIVE_HARD; + case SURFACE_CAR: return ADHESIVE_HARD; case SURFACE_GLASS: return ADHESIVE_HARD; - case SURFACE_SCAFFOLD: return ADHESIVE_HARD; - case SURFACE_METAL_DOOR: return ADHESIVE_HARD; - case SURFACE_BILLBOARD: return ADHESIVE_HARD; - case SURFACE_STEEL: return ADHESIVE_HARD; - case SURFACE_METAL_POLE: return ADHESIVE_HARD; - case SURFACE_STREET_LIGHT: return ADHESIVE_HARD; - case SURFACE_METAL14: return ADHESIVE_HARD; - case SURFACE_METAL15: return ADHESIVE_HARD; - case SURFACE_METAL_FENCE: return ADHESIVE_HARD; - case SURFACE_FLESH: return ADHESIVE_RUBBER; + case SURFACE_TRANSPARENT_CLOTH: return ADHESIVE_HARD; + case SURFACE_GARAGE_DOOR: return ADHESIVE_HARD; + case SURFACE_CAR_PANEL: return ADHESIVE_HARD; + case SURFACE_THICK_METAL_PLATE: return ADHESIVE_HARD; + case SURFACE_SCAFFOLD_POLE: return ADHESIVE_HARD; + case SURFACE_LAMP_POST: return ADHESIVE_HARD; + case SURFACE_FIRE_HYDRANT: return ADHESIVE_HARD; + case SURFACE_GIRDER: return ADHESIVE_HARD; + case SURFACE_METAL_CHAIN_FENCE: return ADHESIVE_HARD; + case SURFACE_PED: return ADHESIVE_RUBBER; case SURFACE_SAND: return ADHESIVE_LOOSE; - case SURFACE_PUDDLE: return ADHESIVE_WET; - case SURFACE_WOOD: return ADHESIVE_ROAD; - case SURFACE_WOOD_BOX: return ADHESIVE_ROAD; - case SURFACE_WOOD_PLANK: return ADHESIVE_ROAD; - case SURFACE_TIRE: return ADHESIVE_RUBBER; - case SURFACE_HARD24: return ADHESIVE_HARD; + case SURFACE_WATER: return ADHESIVE_WET; + case SURFACE_WOOD_CRATES: return ADHESIVE_ROAD; + case SURFACE_WOOD_BENCH: return ADHESIVE_ROAD; + case SURFACE_WOOD_SOLID: return ADHESIVE_ROAD; + case SURFACE_RUBBER: return ADHESIVE_RUBBER; + case SURFACE_PLASTIC: return ADHESIVE_HARD; case SURFACE_HEDGE: return ADHESIVE_LOOSE; - case SURFACE_STONE: return ADHESIVE_LOOSE; - case SURFACE_METAL27: return ADHESIVE_HARD; - case SURFACE_METAL28: return ADHESIVE_HARD; - case SURFACE_RUBBER29: return ADHESIVE_RUBBER; - case SURFACE_LOOSE30: return ADHESIVE_LOOSE; - case SURFACE_BOLLARD: return ADHESIVE_HARD; - case SURFACE_GATE: return ADHESIVE_HARD; + case SURFACE_STEEP_CLIFF: return ADHESIVE_LOOSE; + case SURFACE_CONTAINER: return ADHESIVE_HARD; + case SURFACE_NEWS_VENDOR: return ADHESIVE_HARD; + case SURFACE_WHEELBASE: return ADHESIVE_RUBBER; + case SURFACE_CARDBOARDBOX: return ADHESIVE_LOOSE; + case SURFACE_TRANSPARENT_STONE: return ADHESIVE_HARD; + case SURFACE_METAL_GATE: return ADHESIVE_HARD; default: return ADHESIVE_ROAD; } } @@ -99,36 +99,36 @@ CSurfaceTable::GetWetMultiplier(uint8 surfaceType) switch(surfaceType){ case SURFACE_DEFAULT: case SURFACE_TARMAC: - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: case SURFACE_PAVEMENT: - case SURFACE_SCAFFOLD: - case SURFACE_WOOD: - case SURFACE_WOOD_BOX: - case SURFACE_WOOD_PLANK: + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_WOOD_CRATES: + case SURFACE_WOOD_BENCH: + case SURFACE_WOOD_SOLID: case SURFACE_HEDGE: - case SURFACE_LOOSE30: - case SURFACE_BOLLARD: + case SURFACE_CARDBOARDBOX: + case SURFACE_TRANSPARENT_STONE: return 1.0f - CWeather::WetRoads*0.25f; case SURFACE_GRASS: - case SURFACE_METAL6: + case SURFACE_CAR: case SURFACE_GLASS: - case SURFACE_METAL_DOOR: - case SURFACE_BILLBOARD: - case SURFACE_STEEL: - case SURFACE_METAL_POLE: - case SURFACE_STREET_LIGHT: - case SURFACE_METAL14: - case SURFACE_METAL15: - case SURFACE_METAL_FENCE: - case SURFACE_FLESH: - case SURFACE_TIRE: - case SURFACE_HARD24: - case SURFACE_STONE: - case SURFACE_METAL27: - case SURFACE_METAL28: - case SURFACE_RUBBER29: - case SURFACE_GATE: + case SURFACE_GARAGE_DOOR: + case SURFACE_CAR_PANEL: + case SURFACE_THICK_METAL_PLATE: + case SURFACE_SCAFFOLD_POLE: + case SURFACE_LAMP_POST: + case SURFACE_FIRE_HYDRANT: + case SURFACE_GIRDER: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_PED: + case SURFACE_RUBBER: + case SURFACE_PLASTIC: + case SURFACE_STEEP_CLIFF: + case SURFACE_CONTAINER: + case SURFACE_NEWS_VENDOR: + case SURFACE_WHEELBASE: + case SURFACE_METAL_GATE: return 1.0f - CWeather::WetRoads*0.4f; default: diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 768521bf..25b5e57d 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -1,45 +1,44 @@ #pragma once -// TODO: check this enum eSurfaceType { SURFACE_DEFAULT, SURFACE_TARMAC, SURFACE_GRASS, - SURFACE_DIRT, - SURFACE_DIRTTRACK, + SURFACE_GRAVEL, + SURFACE_MUD_DRY, SURFACE_PAVEMENT, - SURFACE_METAL6, + SURFACE_CAR, SURFACE_GLASS, - SURFACE_SCAFFOLD, - SURFACE_METAL_DOOR, // garage door - SURFACE_BILLBOARD, - SURFACE_STEEL, //? - SURFACE_METAL_POLE, // ? - SURFACE_STREET_LIGHT, - SURFACE_METAL14, - SURFACE_METAL15, - SURFACE_METAL_FENCE, - SURFACE_FLESH, + SURFACE_TRANSPARENT_CLOTH, + SURFACE_GARAGE_DOOR, + SURFACE_CAR_PANEL, + SURFACE_THICK_METAL_PLATE, + SURFACE_SCAFFOLD_POLE, + SURFACE_LAMP_POST, + SURFACE_FIRE_HYDRANT, + SURFACE_GIRDER, + SURFACE_METAL_CHAIN_FENCE, + SURFACE_PED, SURFACE_SAND, - SURFACE_PUDDLE, - SURFACE_WOOD, - SURFACE_WOOD_BOX, - SURFACE_WOOD_PLANK, - SURFACE_TIRE, - SURFACE_HARD24, + SURFACE_WATER, + SURFACE_WOOD_CRATES, + SURFACE_WOOD_BENCH, + SURFACE_WOOD_SOLID, + SURFACE_RUBBER, + SURFACE_PLASTIC, SURFACE_HEDGE, - SURFACE_STONE, - SURFACE_METAL27, - SURFACE_METAL28, - SURFACE_RUBBER29, - SURFACE_LOOSE30, - SURFACE_BOLLARD, - SURFACE_GATE, + SURFACE_STEEP_CLIFF, + SURFACE_CONTAINER, + SURFACE_NEWS_VENDOR, + SURFACE_WHEELBASE, + SURFACE_CARDBOARDBOX, + SURFACE_TRANSPARENT_STONE, + SURFACE_METAL_GATE, // These are illegal - SURFACE_SAND33, - SURFACE_ROAD34, + SURFACE_SAND_BEACH, + SURFACE_CONCRETE_BEACH, }; enum diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index 79d6252b..b4d994ec 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -65,7 +65,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) { #endif - s_aPedSpheres[i].surface = SURFACE_FLESH; + s_aPedSpheres[i].surface = SURFACE_PED; s_aPedSpheres[i].piece = 0; } @@ -84,7 +84,7 @@ CTempColModels::Initialise(void) s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f); for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { - s_aPed2Spheres[i].surface = SURFACE_FLESH; + s_aPed2Spheres[i].surface = SURFACE_PED; s_aPed2Spheres[i].piece = 0; } @@ -105,10 +105,10 @@ CTempColModels::Initialise(void) s_aPedGSpheres[2].center = CVector(0.0f, 0.25f, -0.9f); s_aPedGSpheres[3].center = CVector(0.0f, 0.65f, -0.9f); - s_aPedGSpheres[0].surface = SURFACE_FLESH; - s_aPedGSpheres[1].surface = SURFACE_FLESH; - s_aPedGSpheres[2].surface = SURFACE_FLESH; - s_aPedGSpheres[3].surface = SURFACE_FLESH; + s_aPedGSpheres[0].surface = SURFACE_PED; + s_aPedGSpheres[1].surface = SURFACE_PED; + s_aPedGSpheres[2].surface = SURFACE_PED; + s_aPedGSpheres[3].surface = SURFACE_PED; s_aPedGSpheres[0].piece = 4; s_aPedGSpheres[1].piece = 1; s_aPedGSpheres[2].piece = 0; @@ -130,7 +130,7 @@ CTempColModels::Initialise(void) s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { - s_aDoorSpheres[i].surface = SURFACE_BILLBOARD; + s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL; s_aDoorSpheres[i].piece = 0; } @@ -150,7 +150,7 @@ CTempColModels::Initialise(void) s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) { - s_aBumperSpheres[i].surface = SURFACE_BILLBOARD; + s_aBumperSpheres[i].surface = SURFACE_CAR_PANEL; s_aBumperSpheres[i].piece = 0; } @@ -170,7 +170,7 @@ CTempColModels::Initialise(void) s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) { - s_aPanelSpheres[i].surface = SURFACE_BILLBOARD; + s_aPanelSpheres[i].surface = SURFACE_CAR_PANEL; s_aPanelSpheres[i].piece = 0; } @@ -190,7 +190,7 @@ CTempColModels::Initialise(void) s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) { - s_aBonnetSpheres[i].surface = SURFACE_BILLBOARD; + s_aBonnetSpheres[i].surface = SURFACE_CAR_PANEL; s_aBonnetSpheres[i].piece = 0; } @@ -210,7 +210,7 @@ CTempColModels::Initialise(void) s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f); for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { - s_aBootSpheres[i].surface = SURFACE_BILLBOARD; + s_aBootSpheres[i].surface = SURFACE_CAR_PANEL; s_aBootSpheres[i].piece = 0; } @@ -232,7 +232,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif - s_aWheelSpheres[i].surface = SURFACE_RUBBER29; + s_aWheelSpheres[i].surface = SURFACE_WHEELBASE; s_aWheelSpheres[i].piece = 0; } @@ -254,7 +254,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif - s_aBodyPartSpheres1[i].surface = SURFACE_FLESH; + s_aBodyPartSpheres1[i].surface = SURFACE_PED; s_aBodyPartSpheres1[i].piece = 0; } @@ -276,7 +276,7 @@ CTempColModels::Initialise(void) #else for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif - s_aBodyPartSpheres2[i].surface = SURFACE_FLESH; + s_aBodyPartSpheres2[i].surface = SURFACE_PED; s_aBodyPartSpheres2[i].piece = 0; } diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index f9f8ae7e..9fc5a853 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1018,7 +1018,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint) ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos); if(fOtherSpeed > 0.1f && - colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_DIRTTRACK && + colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_MUD_DRY && CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){ CVector v = frictionDir * fOtherSpeed * 0.25f; for(int i = 0; i < 4; i++) diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 473e8b63..1d8aa4dc 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -251,7 +251,7 @@ CPedModelInfo::CreateHitColModel(void) center.x = mat->pos.x + m_pColNodeInfos[i].x; center.y = mat->pos.y + 0.0f; center.z = mat->pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); + spheres[i].Set(radius, center, SURFACE_PED, m_pColNodeInfos[i].pieceType); } } RwMatrixDestroy(mat); @@ -335,7 +335,7 @@ CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) center.x = pos.x + m_pColNodeInfos[i].x; center.y = pos.y + 0.0f; center.z = pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); + spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_PED, m_pColNodeInfos[i].pieceType); } RwMatrixDestroy(invmat); RwMatrixDestroy(mat); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index e3fa2104..6b3b8686 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2037,7 +2037,7 @@ particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) switch (ped->m_nSurfaceTouched) { case SURFACE_TARMAC: - case SURFACE_DIRT: + case SURFACE_GRAVEL: case SURFACE_PAVEMENT: case SURFACE_SAND: for (int i = 0; i < times; ++i) { @@ -2190,7 +2190,7 @@ CPed::PlayFootSteps(void) } } - if (m_nSurfaceTouched == SURFACE_PUDDLE) { + if (m_nSurfaceTouched == SURFACE_WATER) { float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude(); if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) { #ifdef PC_PARTICLE @@ -2588,7 +2588,7 @@ CPed::CanPedDriveOff(void) bool CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil) { - if (m_nSurfaceTouched == SURFACE_PUDDLE) + if (m_nSurfaceTouched == SURFACE_WATER) return true; CVector pos = GetPosition(); @@ -11055,7 +11055,7 @@ CPed::SetJump(void) #ifdef VC_PED_PORTS m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) && #endif - (m_nSurfaceTouched != SURFACE_STONE || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { + (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { SetStoredState(); m_nPedState = PED_JUMP; CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f); @@ -14781,7 +14781,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z; #endif m_nSurfaceTouched = intersectionPoint.surfaceB; - if (m_nSurfaceTouched == SURFACE_STONE) { + if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) { bHitSteepSlope = true; m_vecDamageNormal = intersectionPoint.normal; } @@ -14889,7 +14889,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) #endif sphereNormal.Normalise(); collidingPoints[sphere].normal = sphereNormal; - if (collidingPoints[sphere].surfaceB == SURFACE_STONE) + if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF) bHitSteepSlope = true; } } @@ -16749,7 +16749,7 @@ CPed::UpdatePosition(void) velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed; m_fRotationCur += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); m_fRotationDest += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep(); - } else if (m_nSurfaceTouched != SURFACE_STONE || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) { + } else if (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) { velocityChange = m_moved - m_vecMoveSpeed; } else { // Ped got damaged by steep slope diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index c968a147..e572c123 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -634,7 +634,7 @@ CAutomobile::ProcessControl(void) m_aSuspensionSpringRatio[i], bias); m_aWheelSkidmarkMuddy[i] = m_aWheelColPoints[i].surfaceB == SURFACE_GRASS || - m_aWheelColPoints[i].surfaceB == SURFACE_DIRTTRACK || + m_aWheelColPoints[i].surfaceB == SURFACE_MUD_DRY || m_aWheelColPoints[i].surfaceB == SURFACE_SAND; }else{ contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1); @@ -771,7 +771,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB); @@ -805,7 +805,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB); @@ -886,7 +886,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB); @@ -920,7 +920,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB); @@ -1135,10 +1135,10 @@ CAutomobile::ProcessControl(void) } uint8 surf = m_aWheelColPoints[i].surfaceB; - if(surf == SURFACE_DIRT || surf == SURFACE_PUDDLE || surf == SURFACE_HEDGE){ + if(surf == SURFACE_GRAVEL || surf == SURFACE_WATER || surf == SURFACE_HEDGE){ if(surfShake < 0.2f) surfShake = 0.3f; - }else if(surf == SURFACE_DIRTTRACK || surf == SURFACE_SAND){ + }else if(surf == SURFACE_MUD_DRY || surf == SURFACE_SAND){ if(surfShake < 0.1f) surfShake = 0.2f; }else if(surf == SURFACE_GRASS){ @@ -2961,7 +2961,7 @@ CAutomobile::ProcessBuoyancy(void) static RwRGBA smokeCol = {255, 255, 255, 255}; for(i = 0; i < 4; i++){ - if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_PUDDLE){ + if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_WATER){ CVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition(); CVector vSpeed = GetSpeed(pos); vSpeed.z = 0.0f; @@ -3559,7 +3559,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) CGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol); } return 0; - case SURFACE_DIRT: + case SURFACE_GRAVEL: dir.x = -0.05f*m_vecMoveSpeed.x; dir.y = -0.05f*m_vecMoveSpeed.y; for(i = 0; i < 4; i++){ @@ -3568,7 +3568,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol); } return 1; - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: dir.x = -0.05f*m_vecMoveSpeed.x; dir.y = -0.05f*m_vecMoveSpeed.y; for(i = 0; i < 4; i++){ @@ -3918,19 +3918,19 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) CMatrix mat; mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF])); - colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LF); + colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LF); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB])); - colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); + colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF])); - colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF); + colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RF); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB])); - colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); + colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR); if(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){ mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM])); - colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); + colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM])); - colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); + colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR); colModel->numSpheres = 6; }else colModel->numSpheres = 4; diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index bb266a80..4966a228 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -590,12 +590,12 @@ CHeli::PreRender(void) g = 6; b = 3; break; - case SURFACE_DIRT: + case SURFACE_GRAVEL: r = 10; g = 8; b = 7; break; - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: r = 10; g = 6; b = 3; From dfa95002aa1813f1d2f68172f32f748d83b47d2c Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 12:10:08 +0200 Subject: [PATCH 143/148] fix --- src/render/Timecycle.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index 28156c7e..bf55d7bc 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -175,7 +175,11 @@ CTimeCycle::Initialise(void) bi++; bi++; } - while(work_buff[bi] != '\n' || work_buff[bi] != '\0') + while(work_buff[bi] != '\n' +#ifdef FIX_BUGS + && work_buff[bi] != '\0' +#endif + ) line[li++] = work_buff[bi++]; line[li] = '\0'; bi++; From 314e56b7b99b7897096e97f47484e1b1849e401a Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 12:11:04 +0200 Subject: [PATCH 144/148] fix2 --- src/vehicles/Vehicle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 14ca4462..a6f8719e 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -27,7 +27,7 @@ #include "SurfaceTable.h" #include "Particle.h" #include "WaterLevel.h" -#include "TimeCycle.h" +#include "Timecycle.h" #include "Weather.h" #include "Coronas.h" From f40677c7a4f12306c202bad8966bb19d993422ad Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 26 May 2020 16:17:40 +0300 Subject: [PATCH 145/148] fixed crash --- src/vehicles/Vehicle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index a6f8719e..1dc7af11 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1757,13 +1757,13 @@ CVehicle::SetupPassenger(int n) if(passenger->m_nPedType == PEDTYPE_CIVMALE || passenger->m_nPedType == PEDTYPE_CIVFEMALE) for(i = 0; i < n; i++) if(pPassengers[i] && pPassengers[n] && - pPassengers[i]->m_nPedType == PEDTYPE_CIVMALE || pPassengers[i]->m_nPedType == PEDTYPE_CIVFEMALE && + (pPassengers[i]->m_nPedType == PEDTYPE_CIVMALE || pPassengers[i]->m_nPedType == PEDTYPE_CIVFEMALE) && passenger->GetModelIndex() == pPassengers[i]->GetModelIndex()){ pPassengers[n] = nil; CPopulation::RemovePed(passenger); } } - if(bIsBus) + if(bIsBus && pPassengers[n]) pPassengers[n]->bRenderPedInCar = false; ++m_nNumPassengers; return pPassengers[n]; From 0cd883e2a13ed9e21404d413c3701124395c3ef7 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 15:26:44 +0200 Subject: [PATCH 146/148] updated librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 661feeab..84c582c1 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 661feeabf4a4f0a8b0bee23b53ba557a14352d00 +Subproject commit 84c582c1d7a64a213523b8e4c8211f8b7a4fdcd1 From c83b351887d5c4770912aa1b144df22a616dab01 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 15:26:54 +0200 Subject: [PATCH 147/148] updated librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 3971dda0..84c582c1 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 3971dda001cba9c7dc67e86bc0b54a2c7568578f +Subproject commit 84c582c1d7a64a213523b8e4c8211f8b7a4fdcd1 From 7f60be9814894fc5c6e9fbc9d52be492c8c92a11 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 26 May 2020 18:50:11 +0200 Subject: [PATCH 148/148] fix UB shit --- src/core/Camera.cpp | 2 +- src/render/Sprite.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index f618c652..b65b60f3 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -3193,7 +3193,7 @@ CCamera::GetLookDirection(void) Cams[ActiveCam].Mode == CCam::MODE_BEHINDBOAT || Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED) return Cams[ActiveCam].DirectionWasLooking; - return LOOKING_FORWARD;; + return LOOKING_FORWARD; } bool diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 9631aced..a6d2db7b 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -22,8 +22,8 @@ CSprite::CalcHorizonCoors(void) bool CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip) { - CVector viewvec = TheCamera.m_viewMatrix * *(CVector*)∈ - *out = *(RwV3d*)&viewvec; + CVector viewvec = TheCamera.m_viewMatrix * in; + *out = viewvec; if(out->z <= CDraw::GetNearClipZ() + 1.0f) return false; if(out->z >= CDraw::GetFarClipZ() && farclip) return false; float recip = 1.0f/out->z;