From 057b28e39b2e58aae1f47d44bd1ce6222a781978 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 5 Apr 2020 12:35:51 +0300 Subject: cranes init --- src/control/Cranes.cpp | 235 +++++++++++++++++++++++++++++++++++++++++++++++-- src/control/Cranes.h | 62 +++++++++---- 2 files changed, 277 insertions(+), 20 deletions(-) (limited to 'src/control') diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp index 4c1bf2c8..96c41f45 100644 --- a/src/control/Cranes.cpp +++ b/src/control/Cranes.cpp @@ -2,13 +2,238 @@ #include "patcher.h" #include "Cranes.h" +#include "Camera.h" +#include "DMAudio.h" +#include "Entity.h" +#include "ModelIndices.h" +#include "Replay.h" +#include "Object.h" +#include "World.h" + +#define MAX_DISTANCE_TO_FIND_CRANE (10.0f) +#define CRANE_UPDATE_RADIUS (300.0f) +#define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f) +#define CRUSHER_Z (-0.951f) +#define MILITARY_Z (10.7862f) + +void CCranes::InitCranes(void) +{ + CarsCollectedMilitaryCrane = 0; + NumCranes = 0; + for (int i = 0; i < NUMSECTORS_X; i++) { + for (int j = 0; j < NUMSECTORS_Y; j++) { + for (CPtrNode* pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + if (MODELID_CRANE_1 == pEntity->GetModelIndex() || + MODELID_CRANE_2 == pEntity->GetModelIndex() || + MODELID_CRANE_3 == pEntity->GetModelIndex()) + AddThisOneCrane(pEntity); + } + } + } + for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + if (MODELID_CRANE_1 == pEntity->GetModelIndex() || + MODELID_CRANE_2 == pEntity->GetModelIndex() || + MODELID_CRANE_3 == pEntity->GetModelIndex()) + AddThisOneCrane(pEntity); + } +} + +void CCranes::AddThisOneCrane(CEntity* pEntity) +{ + pEntity->GetMatrix().ResetOrientation(); + if (NumCranes >= NUM_CRANES) + return; + CCrane* pCrane = &aCranes[NumCranes]; + pCrane->Init(); + pCrane->m_pObject = pEntity; + pCrane->m_bCraneStatus = CCrane::NONE; + pCrane->m_fHeight = NumCranes; // lol wtf + while (pCrane->m_fHeight > TWOPI) + pCrane->m_fHeight -= TWOPI; + pCrane->m_fHookOffset = 20.0f; + pCrane->m_fHookHeight = 20.0f; + pCrane->m_nUpdateTimer = 0; + pCrane->m_bCraneState = CCrane::IDLE; + pCrane->m_bWasMilitaryCrane = 0; + pCrane->m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[NumCranes]); + if (pCrane->m_nAudioEntity >= 0) + DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1); + pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex()); + // W T F ? ? ? + // Is this used to avoid military crane? + if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) { + CObject* pMagnet = new CObject(MI_MAGNET, false); + pMagnet->ObjectCreatedBy = MISSION_OBJECT; + pMagnet->bUsesCollision = false; + pMagnet->bExplosionProof = true; + pMagnet->bAffectedByGravity = false; + pCrane->m_pMagnet = pMagnet; + pCrane->CalcHookCoordinates(&pCrane->m_vecHookCurPos.x, &pCrane->m_vecHookCurPos.y, &pCrane->m_vecHookCurPos.z); + pCrane->SetHookMatrix(); + } + else + pCrane->m_pMagnet = nil; + NumCranes++; +} + +void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY) +{ + float fMinDistance = 99999.9f; + float X = fPosX, Y = fPosY; + if (X <= -10000.0f || Y <= -10000.0f) { + X = fDropOffX; + Y = fDropOffY; + } + int index = 0; + for (int i = 0; i < NumCranes; i++) { + float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude(); + if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) { + fMinDistance = distance; + index = i; + } + } +#ifdef FIX_BUGS // classic + if (fMinDistance == 99999.9f) + return; +#endif + CCrane* pCrane = &aCranes[NumCranes]; + pCrane->m_fPickupX1 = fInfX; + pCrane->m_fPickupX2 = fSupX; + pCrane->m_fPickupY1 = fInfY; + pCrane->m_fPickupY2 = fSupY; + pCrane->m_vecDropoffTarget.x = fDropOffX; + pCrane->m_vecDropoffTarget.y = fDropOffY; + pCrane->m_vecDropoffTarget.z = fDropOffZ; + pCrane->m_bCraneStatus = CCrane::ACTIVATED; + pCrane->m_pVehiclePickedUp = nil; + pCrane->m_bVehiclesCollected = 0; + pCrane->m_bIsCrusher = bIsCrusher; + pCrane->m_bIsMilitaryCrane = bIsMilitary; + bool military = true; + if (!bIsMilitary && !pCrane->m_bWasMilitaryCrane) + military = false; + pCrane->m_bWasMilitaryCrane = military; + pCrane->m_nUpdateTimer = 0; + pCrane->m_bCraneState = CCrane::IDLE; + float Z; + if (bIsCrusher) + Z = CRUSHER_Z; + else if (bIsMilitary) + Z = MILITARY_Z; + else + Z = CWorld::FindGroundZForCoord((fInfX + fSupY) / 2, (fInfY + fSupY) / 2); + pCrane->FindParametersForTarget((fInfX + fSupY) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fAngle); + pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDistance); +} + +void CCranes::DeActivateCrane(float X, float Y) +{ + float fMinDistance = 99999.9f; + int index = 0; + for (int i = 0; i < NumCranes; i++) { + float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude(); + if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) { + fMinDistance = distance; + index = i; + } + } +#ifdef FIX_BUGS // classic + if (fMinDistance == 99999.9f) + return; +#endif + aCranes[index].m_bCraneStatus = CCrane::DEACTIVATED; + aCranes[index].m_bCraneState = CCrane::IDLE; +} + +bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle) +{ + int index = 0; + bool result = false; + for (int i = 0; i < NumCranes; i++) { + float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude(); + if (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) { + if (aCranes[i].m_bCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_bCraneStatus == CCrane::ROTATING_TARGET) + result = true; + } + } + return true; +} + +void CCranes::UpdateCranes(void) +{ + for (int i = 0; i < NumCranes; i++) { + if (aCranes[i].m_bIsTop || aCranes[i].m_bIsCrusher || + (TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pObject->GetPosition().x && + TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pObject->GetPosition().x && + TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pObject->GetPosition().y && + TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pObject->GetPosition().y)) + aCranes[i].Update(); + } +} + +void CCrane::Update(void) +{ + if (CReplay::IsPlayingBack()) + return; + if ((m_bCraneStatus == ACTIVATED || m_bCraneStatus == DEACTIVATED) && + Abs(TheCamera.GetGameCamPosition().x - m_pObject->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS && + Abs(TheCamera.GetGameCamPosition().y - m_pObject->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) { + switch (m_bCraneState) { + case IDLE: + if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, 4.0f + m_fAngle + m_bIsCrusher ? 4.5f : 0.0f, 1.0f) && + CTimer::GetTimeInMilliseconds() > m_nUpdateTimer) { + CWorld::AdvanceCurrentScanCode(); +#ifdef FIX_BUGS + int xstart = max(0, CWorld::GetSectorIndexX(m_fPickupX1)); + int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2)); + int ystart = max(0, CWorld::GetSectorIndexY(m_fPickupY1)); + int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2)); +#else + int xstart = CWorld::GetSectorIndexX(m_fPickupX1); + int xend = CWorld::GetSectorIndexX(m_fPickupX2); + int ystart = CWorld::GetSectorIndexY(m_fPickupY1); + int yend = CWorld::GetSectorIndexY(m_fPickupY1); +#endif + assert(xstart <= xend); + assert(ystart <= yend); + for (int i = xstart; i <= xend; i++) { + for (int j = ystart; j <= yend; j++) { + FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES]); + FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES_OVERLAP]); + } + } + } + break; + case GOING_TOWARDS_TARGET: + if (!m_pVehiclePickedUp) { + m_bCraneState = IDLE; + break; + } + if (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 || + m_pVehiclePickedUp->GetPosition().x > m_fPickupX2 || + m_pVehiclePickedUp->GetPosition().y > m_fPickupY1 || + m_pVehiclePickedUp->GetPosition().y > m_fPickupY2 || + m_pVehiclePickedUp->pDriver || + Abs(m_pVehiclePickedUp->GetMoveSpeed().x) > 0.01f || + Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > 0.01f || + Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > 0.01f || + FindPlayerPed()->GetPedState() == PED_ENTER_CAR && + FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) { + m_pVehiclePickedUp = nil; + m_bCraneState = IDLE; + break; + } + + } + } +} + WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); } WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); } -WRAPPER bool CCranes::IsThisCarPickedUp(float, float, CVehicle*) { EAXJMP(0x543940); } WRAPPER bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() { EAXJMP(0x544BE0); } -WRAPPER void CCranes::ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float) { EAXJMP(0x543650); } -WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); } -WRAPPER void CCranes::InitCranes(void) { EAXJMP(0x543360); } -WRAPPER void CCranes::UpdateCranes(void) { EAXJMP(0x5439E0); } + + WRAPPER void CCranes::Save(uint8*, uint32*) { EAXJMP(0x545210); } WRAPPER void CranesLoad(uint8*, uint32) { EAXJMP(0x5454d0); } diff --git a/src/control/Cranes.h b/src/control/Cranes.h index b40454ea..c121378b 100644 --- a/src/control/Cranes.h +++ b/src/control/Cranes.h @@ -1,6 +1,8 @@ #pragma once #include "common.h" +#include "World.h" + class CVehicle; class CEntity; class CObject; @@ -8,9 +10,22 @@ class CObject; class CCrane { public: + enum CraneState : uint8 { + IDLE = 0, + GOING_TOWARDS_TARGET = 1, + LIFTING_TARGET = 2, + GOING_TOWARDS_HEIGHT_TARGET = 3, + ROTATING_TARGET = 4, + DROPPING_TARGET = 5 + }; + enum CraneStatus : uint8 { + NONE = 0, + ACTIVATED = 1, + DEACTIVATED = 2 + }; CEntity *m_pObject; CObject *m_pMagnet; - int m_nAudioEntity; + int32 m_nAudioEntity; float m_fPickupX1; float m_fPickupX2; float m_fPickupY1; @@ -31,15 +46,25 @@ public: float m_fHookVelocityX; float m_fHookVelocityY; CVehicle *m_pVehiclePickedUp; - int m_nUpdateTimer; - char m_bCraneActive; - char m_bCraneStatus; - char m_bVehiclesCollected; - char m_bIsCrusher; - char m_bIsMilitaryCrane; - char field_125; - char m_bNotMilitaryCrane; - char gap_127[1]; + uint32 m_nUpdateTimer; + CraneStatus m_bCraneStatus; + CraneState m_bCraneState; + uint8 m_bVehiclesCollected; + bool m_bIsCrusher; + bool m_bIsMilitaryCrane; + bool m_bWasMilitaryCrane; + bool m_bIsTop; + + void Init(void) { memset(this, 0, sizeof(*this)); } + void Update(void); + bool RotateCarriedCarProperly(); + void FindCarInSectorList(CPtrList*); + bool DoesCranePickUpThisCarType(uint32); + bool GoTowardsTarget(float, float, float, float); + bool GoTowardsHeightTarget(float, float); + void FindParametersForTarget(float, float, float, float*, float*, float*); + void CalcHookCoordinates(float*, float*, float*); + void SetHookMatrix(); }; static_assert(sizeof(CCrane) == 128, "CCrane: error"); @@ -47,15 +72,22 @@ static_assert(sizeof(CCrane) == 128, "CCrane: error"); class CCranes { public: - static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*); - static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*); - static bool IsThisCarPickedUp(float, float, CVehicle*); - static bool HaveAllCarsBeenCollectedByMilitaryCrane(); + static void InitCranes(void); + static void AddThisOneCrane(CEntity*); static void ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float); static void DeActivateCrane(float, float); - static void InitCranes(void); + static bool IsThisCarPickedUp(float, float, CVehicle*); static void UpdateCranes(void); + static bool DoesMilitaryCraneHaveThisOneAlready(uint32); + static void RegisterCarForMilitaryCrane(uint32); + static bool HaveAllCarsBeenCollectedByMilitaryCrane(); + static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*); + static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*); static void Save(uint8*, uint32*); + + static int32& CarsCollectedMilitaryCrane; + static int32& NumCranes; + static CCrane(&aCranes)[NUM_CRANES]; }; void CranesLoad(uint8*, uint32); // is this really outside CCranes? -- cgit v1.2.3 From 7f8a78e5decdf23bf0d06674c336f4e3169eaa6a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 6 Apr 2020 02:01:03 +0300 Subject: Cranes done --- src/control/Cranes.cpp | 554 ++++++++++++++++++++++++++++++++++++++++++------ src/control/Cranes.h | 67 +++--- src/control/Garages.cpp | 41 ++-- src/control/Garages.h | 1 - src/control/Script.cpp | 7 +- src/control/Script.h | 2 +- 6 files changed, 560 insertions(+), 112 deletions(-) (limited to 'src/control') diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp index 96c41f45..cbfd2a35 100644 --- a/src/control/Cranes.cpp +++ b/src/control/Cranes.cpp @@ -4,6 +4,8 @@ #include "Camera.h" #include "DMAudio.h" +#include "Garages.h" +#include "General.h" #include "Entity.h" #include "ModelIndices.h" #include "Replay.h" @@ -15,6 +17,24 @@ #define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f) #define CRUSHER_Z (-0.951f) #define MILITARY_Z (10.7862f) +#define DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE (5.0f) +#define DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT (0.5f) +#define CAR_REWARD_MILITARY_CRANE (1500) +#define CAR_MOVING_SPEED_THRESHOLD (0.01f) +#define CRANE_SLOWDOWN_MULTIPLIER (0.3f) + +#define OSCILLATION_SPEED (0.002f) +#define CAR_ROTATION_SPEED (0.0035f) +#define CRANE_MOVEMENT_SPEED (0.001f) +#define HOOK_ANGLE_MOVEMENT_SPEED (0.004f) +#define HOOK_OFFSET_MOVEMENT_SPEED (0.1f) +#define HOOK_HEIGHT_MOVEMENT_SPEED (0.06f) + +uint32 TimerForCamInterpolation; + +uint32& CCranes::CarsCollectedMilitaryCrane = *(uint32*)0x8F6248; +int32& CCranes::NumCranes = *(int32*)0x8E28AC; +CCrane(&CCranes::aCranes)[NUM_CRANES] = *(CCrane(*)[NUM_CRANES])*(uintptr*)0x6FA4E0; void CCranes::InitCranes(void) { @@ -31,7 +51,7 @@ void CCranes::InitCranes(void) } } } - for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode->next) { + for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; if (MODELID_CRANE_1 == pEntity->GetModelIndex() || MODELID_CRANE_2 == pEntity->GetModelIndex() || @@ -47,34 +67,33 @@ void CCranes::AddThisOneCrane(CEntity* pEntity) return; CCrane* pCrane = &aCranes[NumCranes]; pCrane->Init(); - pCrane->m_pObject = pEntity; - pCrane->m_bCraneStatus = CCrane::NONE; - pCrane->m_fHeight = NumCranes; // lol wtf - while (pCrane->m_fHeight > TWOPI) - pCrane->m_fHeight -= TWOPI; + pCrane->m_pCraneEntity = (CBuilding*)pEntity; + pCrane->m_nCraneStatus = CCrane::NONE; + pCrane->m_fHookAngle = NumCranes; // lol wtf + while (pCrane->m_fHookAngle > TWOPI) + pCrane->m_fHookAngle -= TWOPI; pCrane->m_fHookOffset = 20.0f; pCrane->m_fHookHeight = 20.0f; - pCrane->m_nUpdateTimer = 0; - pCrane->m_bCraneState = CCrane::IDLE; - pCrane->m_bWasMilitaryCrane = 0; + pCrane->m_nTimeForNextCheck = 0; + pCrane->m_nCraneState = CCrane::IDLE; + pCrane->m_bWasMilitaryCrane = false; pCrane->m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[NumCranes]); if (pCrane->m_nAudioEntity >= 0) DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1); pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex()); - // W T F ? ? ? // Is this used to avoid military crane? if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) { - CObject* pMagnet = new CObject(MI_MAGNET, false); - pMagnet->ObjectCreatedBy = MISSION_OBJECT; - pMagnet->bUsesCollision = false; - pMagnet->bExplosionProof = true; - pMagnet->bAffectedByGravity = false; - pCrane->m_pMagnet = pMagnet; + CObject* pHook = new CObject(MI_MAGNET, false); + pHook->ObjectCreatedBy = MISSION_OBJECT; + pHook->bUsesCollision = false; + pHook->bExplosionProof = true; + pHook->bAffectedByGravity = false; + pCrane->m_pHook = pHook; pCrane->CalcHookCoordinates(&pCrane->m_vecHookCurPos.x, &pCrane->m_vecHookCurPos.y, &pCrane->m_vecHookCurPos.z); pCrane->SetHookMatrix(); } else - pCrane->m_pMagnet = nil; + pCrane->m_pHook = nil; NumCranes++; } @@ -88,7 +107,7 @@ void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, } int index = 0; for (int i = 0; i < NumCranes; i++) { - float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude(); + float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) { fMinDistance = distance; index = i; @@ -98,7 +117,7 @@ void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, if (fMinDistance == 99999.9f) return; #endif - CCrane* pCrane = &aCranes[NumCranes]; + CCrane* pCrane = &aCranes[index]; pCrane->m_fPickupX1 = fInfX; pCrane->m_fPickupX2 = fSupX; pCrane->m_fPickupY1 = fInfY; @@ -106,26 +125,27 @@ void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, pCrane->m_vecDropoffTarget.x = fDropOffX; pCrane->m_vecDropoffTarget.y = fDropOffY; pCrane->m_vecDropoffTarget.z = fDropOffZ; - pCrane->m_bCraneStatus = CCrane::ACTIVATED; + pCrane->m_nCraneStatus = CCrane::ACTIVATED; pCrane->m_pVehiclePickedUp = nil; - pCrane->m_bVehiclesCollected = 0; + pCrane->m_nVehiclesCollected = 0; + pCrane->m_fDropoffHeading = fHeading; pCrane->m_bIsCrusher = bIsCrusher; pCrane->m_bIsMilitaryCrane = bIsMilitary; bool military = true; if (!bIsMilitary && !pCrane->m_bWasMilitaryCrane) military = false; pCrane->m_bWasMilitaryCrane = military; - pCrane->m_nUpdateTimer = 0; - pCrane->m_bCraneState = CCrane::IDLE; + pCrane->m_nTimeForNextCheck = 0; + pCrane->m_nCraneState = CCrane::IDLE; float Z; if (bIsCrusher) Z = CRUSHER_Z; else if (bIsMilitary) Z = MILITARY_Z; else - Z = CWorld::FindGroundZForCoord((fInfX + fSupY) / 2, (fInfY + fSupY) / 2); - pCrane->FindParametersForTarget((fInfX + fSupY) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fAngle); - pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDistance); + Z = CWorld::FindGroundZForCoord((fInfX + fSupX) / 2, (fInfY + fSupY) / 2); + pCrane->FindParametersForTarget((fInfX + fSupX) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fPickupHeight); + pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDropoffHeight); } void CCranes::DeActivateCrane(float X, float Y) @@ -133,7 +153,7 @@ void CCranes::DeActivateCrane(float X, float Y) float fMinDistance = 99999.9f; int index = 0; for (int i = 0; i < NumCranes; i++) { - float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude(); + float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) { fMinDistance = distance; index = i; @@ -143,8 +163,8 @@ void CCranes::DeActivateCrane(float X, float Y) if (fMinDistance == 99999.9f) return; #endif - aCranes[index].m_bCraneStatus = CCrane::DEACTIVATED; - aCranes[index].m_bCraneState = CCrane::IDLE; + aCranes[index].m_nCraneStatus = CCrane::DEACTIVATED; + aCranes[index].m_nCraneState = CCrane::IDLE; } bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle) @@ -152,9 +172,9 @@ bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle) int index = 0; bool result = false; for (int i = 0; i < NumCranes; i++) { - float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude(); + float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); if (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) { - if (aCranes[i].m_bCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_bCraneStatus == CCrane::ROTATING_TARGET) + if (aCranes[i].m_nCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_nCraneStatus == CCrane::ROTATING_TARGET) result = true; } } @@ -165,10 +185,10 @@ void CCranes::UpdateCranes(void) { for (int i = 0; i < NumCranes; i++) { if (aCranes[i].m_bIsTop || aCranes[i].m_bIsCrusher || - (TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pObject->GetPosition().x && - TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pObject->GetPosition().x && - TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pObject->GetPosition().y && - TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pObject->GetPosition().y)) + (TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().x && + TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().x && + TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().y && + TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().y)) aCranes[i].Update(); } } @@ -177,13 +197,14 @@ void CCrane::Update(void) { if (CReplay::IsPlayingBack()) return; - if ((m_bCraneStatus == ACTIVATED || m_bCraneStatus == DEACTIVATED) && - Abs(TheCamera.GetGameCamPosition().x - m_pObject->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS && - Abs(TheCamera.GetGameCamPosition().y - m_pObject->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) { - switch (m_bCraneState) { + if (((m_nCraneStatus == ACTIVATED || m_nCraneStatus == DEACTIVATED) && + Abs(TheCamera.GetGameCamPosition().x - m_pCraneEntity->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS && + Abs(TheCamera.GetGameCamPosition().y - m_pCraneEntity->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) || + m_nCraneState != IDLE) { + switch (m_nCraneState) { case IDLE: - if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, 4.0f + m_fAngle + m_bIsCrusher ? 4.5f : 0.0f, 1.0f) && - CTimer::GetTimeInMilliseconds() > m_nUpdateTimer) { + if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, GetHeightToPickup()) && + CTimer::GetTimeInMilliseconds() > m_nTimeForNextCheck) { CWorld::AdvanceCurrentScanCode(); #ifdef FIX_BUGS int xstart = max(0, CWorld::GetSectorIndexX(m_fPickupX1)); @@ -207,33 +228,444 @@ void CCrane::Update(void) } break; case GOING_TOWARDS_TARGET: - if (!m_pVehiclePickedUp) { - m_bCraneState = IDLE; - break; + if (m_pVehiclePickedUp){ + if (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 || + m_pVehiclePickedUp->GetPosition().x > m_fPickupX2 || + m_pVehiclePickedUp->GetPosition().y < m_fPickupY1 || + m_pVehiclePickedUp->GetPosition().y > m_fPickupY2 || + m_pVehiclePickedUp->pDriver || + 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) { + m_pVehiclePickedUp = nil; + m_nCraneState = IDLE; + } + else { + float fAngle, fOffset, fHeight; + FindParametersForTarget( + m_pVehiclePickedUp->GetPosition().x, + m_pVehiclePickedUp->GetPosition().y, + m_pVehiclePickedUp->GetPosition().z + m_pVehiclePickedUp->GetColModel()->boundingBox.max.z, + &fAngle, &fOffset, &fHeight); + if (GoTowardsTarget(fAngle, fOffset, fHeight)) { + CVector distance = m_pVehiclePickedUp->GetPosition() - m_vecHookCurPos; + distance.z += m_pVehiclePickedUp->GetColModel()->boundingBox.max.z; + if (distance.MagnitudeSqr() < SQR(DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT)) { + m_nCraneState = GOING_TOWARDS_TARGET_ONLY_HEIGHT; + m_vecHookVelocity *= 0.4f; + m_pVehiclePickedUp->bLightsOn = false; + m_pVehiclePickedUp->bUsesCollision = false; + if (m_bIsCrusher) + m_pVehiclePickedUp->bCollisionProof = true; + DMAudio.PlayOneShot(m_nAudioEntity, SOUND_CRANE_PICKUP, 0.0f); + } + } + } } - if (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 || - m_pVehiclePickedUp->GetPosition().x > m_fPickupX2 || - m_pVehiclePickedUp->GetPosition().y > m_fPickupY1 || - m_pVehiclePickedUp->GetPosition().y > m_fPickupY2 || - m_pVehiclePickedUp->pDriver || - Abs(m_pVehiclePickedUp->GetMoveSpeed().x) > 0.01f || - Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > 0.01f || - Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > 0.01f || - FindPlayerPed()->GetPedState() == PED_ENTER_CAR && - FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) { + else + m_nCraneState = IDLE; + break; + case LIFTING_TARGET: + RotateCarriedCarProperly(); + if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), 0.3f)) + m_nCraneState = ROTATING_TARGET; + if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) { m_pVehiclePickedUp = nil; - m_bCraneState = IDLE; + m_nCraneState = IDLE; + } + break; + case GOING_TOWARDS_TARGET_ONLY_HEIGHT: + RotateCarriedCarProperly(); + if (GoTowardsHeightTarget(GetHeightToPickupHeight(), CRANE_SLOWDOWN_MULTIPLIER)) + m_nCraneState = LIFTING_TARGET; + TimerForCamInterpolation = CTimer::GetTimeInMilliseconds(); + if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) { + m_pVehiclePickedUp = nil; + m_nCraneState = IDLE; + } + break; + case ROTATING_TARGET: + { + bool bRotateFinished = RotateCarriedCarProperly(); + bool bMovementFinished = GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, m_fDropoffHeight, 0.3f); + if (bMovementFinished && bRotateFinished) { + float fDistanceFromPlayer = m_pVehiclePickedUp ? ((CVector2D)FindPlayerCoors() - (CVector2D)m_pVehiclePickedUp->GetPosition()).Magnitude() : 0.0f; + if (fDistanceFromPlayer > DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE || !m_bWasMilitaryCrane) { + m_nCraneState = DROPPING_TARGET; + if (m_pVehiclePickedUp) { + m_pVehiclePickedUp->bUsesCollision = true; + m_pVehiclePickedUp->m_nStaticFrames = 0; + ++m_nVehiclesCollected; + if (m_bIsMilitaryCrane) { + CCranes::RegisterCarForMilitaryCrane(m_pVehiclePickedUp->GetModelIndex()); + if (!CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()) { + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += CAR_REWARD_MILITARY_CRANE; + CGarages::TriggerMessage("GA_10", CAR_REWARD_MILITARY_CRANE, 4000, -1); + } + CWorld::Remove(m_pVehiclePickedUp); + delete m_pVehiclePickedUp; + } + } + m_pVehiclePickedUp = nil; + } + } + break; + } + case DROPPING_TARGET: + if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoffHeight(), CRANE_SLOWDOWN_MULTIPLIER)) { + m_nCraneState = IDLE; + m_nTimeForNextCheck = CTimer::GetTimeInMilliseconds() + 10000; + } + break; + default: + break; + } + CVector vecHook; + CalcHookCoordinates(&vecHook.x, &vecHook.y, &vecHook.z); + m_vecHookVelocity += ((CVector2D)vecHook - (CVector2D)m_vecHookCurPos) * CTimer::GetTimeStep() * CRANE_MOVEMENT_SPEED; + m_vecHookVelocity *= Pow(0.98f, CTimer::GetTimeStep()); + m_vecHookCurPos.x += m_vecHookVelocity.x * CTimer::GetTimeStep(); + m_vecHookCurPos.y += m_vecHookVelocity.y * CTimer::GetTimeStep(); + m_vecHookCurPos.z = vecHook.z; + switch (m_nCraneState) { + case LIFTING_TARGET: + case GOING_TOWARDS_TARGET_ONLY_HEIGHT: + case ROTATING_TARGET: + if (m_pVehiclePickedUp) { + m_pVehiclePickedUp->GetPosition() = CVector(m_vecHookCurPos.x, m_vecHookCurPos.y, m_vecHookCurPos.z - m_pVehiclePickedUp->GetColModel()->boundingBox.max.z); + m_pVehiclePickedUp->SetMoveSpeed(0.0f, 0.0f, 0.0f); + CVector up(vecHook.x - m_vecHookCurPos.x, vecHook.y - m_vecHookCurPos.y, 20.0f); + up.Normalise(); + m_pVehiclePickedUp->GetRight() = CrossProduct(m_pVehiclePickedUp->GetForward(), up); + m_pVehiclePickedUp->GetForward() = CrossProduct(up, m_pVehiclePickedUp->GetRight()); + m_pVehiclePickedUp->GetUp() = up; + } + break; + default: + break; + } + } + else { + int16 rnd = (m_pCraneEntity->m_randomSeed + (CTimer::GetTimeInMilliseconds() >> 11)) & 0xF; + // 16 options, lasting 2048 ms each + // a bit awkward: why there are 4 periods for -= and 6 for +=? is it a bug? + if (rnd < 4) { + m_fHookAngle -= OSCILLATION_SPEED * CTimer::GetTimeStep(); + if (m_fHookAngle < 0.0f) + m_fHookAngle += TWOPI; + } + else if (rnd > 5 && rnd < 12) { + m_fHookAngle += OSCILLATION_SPEED * CTimer::GetTimeStep(); + if (m_fHookAngle > TWOPI) + m_fHookAngle -= TWOPI; + } + CalcHookCoordinates(&m_vecHookCurPos.x, &m_vecHookCurPos.y, &m_vecHookCurPos.z); + m_vecHookVelocity.x = m_vecHookVelocity.y = 0.0f; + } + float fCos = Cos(m_fHookAngle); + float fSin = Sin(m_fHookAngle); + m_pCraneEntity->GetRight().x = fCos; + m_pCraneEntity->GetForward().y = fCos; + m_pCraneEntity->GetRight().y = fSin; + m_pCraneEntity->GetForward().x = -fSin; + m_pCraneEntity->GetMatrix().UpdateRW(); + m_pCraneEntity->UpdateRwFrame(); + SetHookMatrix(); +} + +bool CCrane::RotateCarriedCarProperly() +{ + if (m_fDropoffHeading <= 0.0f) + return true; + if (!m_pVehiclePickedUp) + return true; + float fAngleDelta = m_fDropoffHeading - CGeneral::GetATanOfXY(m_pVehiclePickedUp->GetForward().x, m_pVehiclePickedUp->GetForward().y); + while (fAngleDelta < -HALFPI) + fAngleDelta += PI; + while (fAngleDelta > HALFPI) + fAngleDelta -= PI; + float fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep(); + if (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied? + return true; + m_pVehiclePickedUp->GetMatrix().RotateZ(Abs(fDeltaThisFrame)); + return false; +} + +void CCrane::FindCarInSectorList(CPtrList* pList) +{ + CPtrNode* node; + for (node = pList->first; node; node = node->next) { + CVehicle* pVehicle = (CVehicle*)node->item; + if (pVehicle->m_scanCode == CWorld::GetCurrentScanCode()) + continue; + pVehicle->m_scanCode = CWorld::GetCurrentScanCode(); + if (pVehicle->GetPosition().x < m_fPickupX1 || pVehicle->GetPosition().x > m_fPickupX2 || + pVehicle->GetPosition().y < m_fPickupY1 || pVehicle->GetPosition().y > m_fPickupY2) + continue; + if (Abs(pVehicle->GetMoveSpeed().x) >= CAR_MOVING_SPEED_THRESHOLD || + Abs(pVehicle->GetMoveSpeed().y) >= CAR_MOVING_SPEED_THRESHOLD || + Abs(pVehicle->GetMoveSpeed().z) >= CAR_MOVING_SPEED_THRESHOLD) + continue; + if (!pVehicle->IsCar() || pVehicle->m_status == STATUS_WRECKED || pVehicle->m_fHealth < 250.0f) + continue; + if (!DoesCranePickUpThisCarType(pVehicle->GetModelIndex()) || + m_bIsMilitaryCrane && CCranes::DoesMilitaryCraneHaveThisOneAlready(pVehicle->GetModelIndex())) { + if (!pVehicle->bCraneMessageDone) { + pVehicle->bCraneMessageDone = true; + if (!m_bIsMilitaryCrane) + CGarages::TriggerMessage("CR_1", -1, 4000, -1); // Crane cannot lift this vehicle. + else if (DoesCranePickUpThisCarType(pVehicle->GetModelIndex())) + CGarages::TriggerMessage("GA_20", -1, 4000, -1); // We got more of these than we can shift. Sorry man, no deal. + else + CGarages::TriggerMessage("GA_19", -1, 4000, -1); // We're not interested in that model. + } + } + else { + m_pVehiclePickedUp = pVehicle; + pVehicle->RegisterReference((CEntity**)&m_pVehiclePickedUp); + m_nCraneState = GOING_TOWARDS_TARGET; + } + } +} + +bool CCrane::DoesCranePickUpThisCarType(uint32 mi) +{ + if (m_bIsCrusher) { + return mi != MI_FIRETRUCK && + mi != MI_TRASH && +#ifndef FIX_BUGS // why + mi != MI_BLISTA && +#endif + mi != MI_SECURICA && + mi != MI_BUS && + mi != MI_DODO && + mi != MI_RHINO; + } + if (m_bIsMilitaryCrane) { + return mi == MI_FIRETRUCK || + mi == MI_AMBULAN || + mi == MI_ENFORCER || + mi == MI_FBICAR || + mi == MI_RHINO || + mi == MI_BARRACKS || + mi == MI_POLICE; + } + return true; +} + +bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi) +{ + switch (mi) { + case MI_FIRETRUCK: return (CCranes::CarsCollectedMilitaryCrane & 1); + case MI_AMBULAN: return (CCranes::CarsCollectedMilitaryCrane & 2); + case MI_ENFORCER: return (CCranes::CarsCollectedMilitaryCrane & 4); + case MI_FBICAR: return (CCranes::CarsCollectedMilitaryCrane & 8); + case MI_RHINO: return (CCranes::CarsCollectedMilitaryCrane & 0x10); + case MI_BARRACKS: return (CCranes::CarsCollectedMilitaryCrane & 0x20); + case MI_POLICE: return (CCranes::CarsCollectedMilitaryCrane & 0x40); + default: break; + } + return false; +} + +void CCranes::RegisterCarForMilitaryCrane(uint32 mi) +{ + switch (mi) { + case MI_FIRETRUCK: CCranes::CarsCollectedMilitaryCrane |= 1; break; + case MI_AMBULAN: CCranes::CarsCollectedMilitaryCrane |= 2; break; + case MI_ENFORCER: CCranes::CarsCollectedMilitaryCrane |= 4; break; + case MI_FBICAR: CCranes::CarsCollectedMilitaryCrane |= 8; break; + case MI_RHINO: CCranes::CarsCollectedMilitaryCrane |= 0x10; break; + case MI_BARRACKS: CCranes::CarsCollectedMilitaryCrane |= 0x20; break; + case MI_POLICE: CCranes::CarsCollectedMilitaryCrane |= 0x40; break; + default: break; + } +} + +bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() +{ + return (CCranes::CarsCollectedMilitaryCrane & 0x7F) == 0x7F; +} + +bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier) +{ + bool bAngleMovementFinished, bOffsetMovementFinished, bHeightMovementFinished; + float fHookAngleDelta = fAngleToTarget - m_fHookAngle; + while (fHookAngleDelta > PI) + fHookAngleDelta -= TWOPI; + while (fHookAngleDelta < -PI) + fHookAngleDelta += TWOPI; + float fHookAngleChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_ANGLE_MOVEMENT_SPEED; + if (Abs(fHookAngleDelta) < fHookAngleChangeThisFrame) { + m_fHookAngle = fAngleToTarget; + bAngleMovementFinished = true; + } + else { + if (fHookAngleDelta < 0.0f) { + m_fHookAngle -= fHookAngleChangeThisFrame; + if (m_fHookAngle < 0.0f) + m_fHookAngle += TWOPI; + } + else { + m_fHookAngle += fHookAngleChangeThisFrame; + if (m_fHookAngle > TWOPI) + m_fHookAngle -= TWOPI; + } + bAngleMovementFinished = false; + } + float fHookOffsetDelta = fDistanceToTarget - m_fHookOffset; + float fHookOffsetChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_OFFSET_MOVEMENT_SPEED; + if (Abs(fHookOffsetDelta) < fHookOffsetChangeThisFrame) { + m_fHookOffset = fDistanceToTarget; + bOffsetMovementFinished = true; + } + else { + if (fHookOffsetDelta < 0.0f) + m_fHookOffset -= fHookOffsetChangeThisFrame; + else + m_fHookOffset += fHookOffsetChangeThisFrame; + bOffsetMovementFinished = false; + } + float fHookHeightDelta = fTargetHeight - m_fHookHeight; + float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED; + if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) { + m_fHookHeight = fTargetHeight; + bHeightMovementFinished = true; + } + else { + if (fHookHeightDelta < 0.0f) + m_fHookHeight -= fHookHeightChangeThisFrame; + else + m_fHookHeight += fHookHeightChangeThisFrame; + bHeightMovementFinished = false; + } + return bAngleMovementFinished && bOffsetMovementFinished && bHeightMovementFinished; +} + +bool CCrane::GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier) +{ + bool bHeightMovementFinished; + float fHookHeightDelta = fTargetHeight - m_fHookHeight; + float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED; + if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) { + m_fHookHeight = fTargetHeight; + bHeightMovementFinished = true; + } + else { + if (fHookHeightDelta < 0.0f) + m_fHookHeight -= fHookHeightChangeThisFrame; + else + m_fHookHeight += fHookHeightChangeThisFrame; + bHeightMovementFinished = false; + } + return bHeightMovementFinished; +} + +void CCrane::FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight) +{ + *pAngle = CGeneral::GetATanOfXY(X - m_pCraneEntity->GetPosition().x, Y - m_pCraneEntity->GetPosition().y); + *pDistance = ((CVector2D(X, Y) - (CVector2D)m_pCraneEntity->GetPosition())).Magnitude(); + *pHeight = Z; +} + +void CCrane::CalcHookCoordinates(float* pX, float* pY, float* pZ) +{ + *pX = Cos(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().x; + *pY = Sin(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().y; + *pZ = m_fHookHeight; +} + +void CCrane::SetHookMatrix() +{ + if (!m_pHook) + return; + m_pHook->GetPosition() = m_vecHookCurPos; + CVector up(m_vecHookInitPos.x - m_vecHookCurPos.x, m_vecHookInitPos.y - m_vecHookCurPos.y, 20.0f); + up.Normalise(); + m_pHook->GetRight() = CrossProduct(CVector(0.0f, 1.0f, 0.0f), up); + m_pHook->GetForward() = CrossProduct(up, m_pHook->GetRight()); + m_pHook->GetUp() = up; + m_pHook->SetOrientation(0.0f, 0.0f, -HALFPI); + m_pHook->GetMatrix().UpdateRW(); + m_pHook->UpdateRwFrame(); + CWorld::Remove(m_pHook); + CWorld::Add(m_pHook); +} + +bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle) +{ + for (int i = 0; i < NumCranes; i++) { + if (pVehicle == aCranes[i].m_pVehiclePickedUp) { + switch (aCranes[i].m_nCraneState) { + case CCrane::GOING_TOWARDS_TARGET_ONLY_HEIGHT: + case CCrane::LIFTING_TARGET: + case CCrane::ROTATING_TARGET: + return true; + default: break; } - } } + return false; +} + +bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle) +{ + for (int i = 0; i < NumCranes; i++) { + if (pVehicle == aCranes[i].m_pVehiclePickedUp) + return true; + } + return false; } -WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); } -WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); } -WRAPPER bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() { EAXJMP(0x544BE0); } +void CCranes::Save(uint8* buf, uint32* size) +{ + INITSAVEBUF + + *size = 2 * sizeof(uint32) + NUM_CRANES * sizeof(CCrane); + WriteSaveBuf(buf, NumCranes); + WriteSaveBuf(buf, CarsCollectedMilitaryCrane); + for (int i = 0; i < NUM_CRANES; i++) { + CCrane* pCrane = WriteSaveBuf(buf, aCranes[i]); + if (pCrane->m_pCraneEntity) + pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pCrane->m_pCraneEntity) + 1); + if (pCrane->m_pHook) + pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex((CObject*)pCrane->m_pHook) + 1); + if (pCrane->m_pVehiclePickedUp) + pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex((CVehicle*)pCrane->m_pVehiclePickedUp) + 1); + } + + VALIDATESAVEBUF(*size); +} +void CranesLoad(uint8* buf, uint32 size) +{ + INITSAVEBUF + + CCranes::NumCranes = ReadSaveBuf(buf); + CCranes::CarsCollectedMilitaryCrane = ReadSaveBuf(buf); + for (int i = 0; i < NUM_CRANES; i++) + CCranes::aCranes[i] = ReadSaveBuf(buf); + for (int i = 0; i < NUM_CRANES; i++) { + CCrane* pCrane = &CCranes::aCranes[i]; + if (pCrane->m_pCraneEntity) + pCrane->m_pCraneEntity = CPools::GetBuildingPool()->GetSlot((uint32)pCrane->m_pCraneEntity - 1); + if (pCrane->m_pHook) + pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uint32)pCrane->m_pHook - 1); + if (pCrane->m_pVehiclePickedUp) + pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uint32)pCrane->m_pVehiclePickedUp + 1); + } + for (int i = 0; i < NUM_CRANES; i++) { + CCranes::aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &CCranes::aCranes[i]); + if (CCranes::aCranes[i].m_nAudioEntity) + DMAudio.SetEntityStatus(CCranes::aCranes[i].m_nAudioEntity, 1); + } + + VALIDATESAVEBUF(size); +} -WRAPPER void CCranes::Save(uint8*, uint32*) { EAXJMP(0x545210); } -WRAPPER void CranesLoad(uint8*, uint32) { EAXJMP(0x5454d0); } +STARTPATCHES + InjectHook(0x5454D0, CranesLoad, PATCH_JUMP); // GenericLoad +ENDPATCHES \ No newline at end of file diff --git a/src/control/Cranes.h b/src/control/Cranes.h index c121378b..d9817282 100644 --- a/src/control/Cranes.h +++ b/src/control/Cranes.h @@ -6,6 +6,7 @@ class CVehicle; class CEntity; class CObject; +class CBuilding; class CCrane { @@ -14,7 +15,7 @@ public: IDLE = 0, GOING_TOWARDS_TARGET = 1, LIFTING_TARGET = 2, - GOING_TOWARDS_HEIGHT_TARGET = 3, + GOING_TOWARDS_TARGET_ONLY_HEIGHT = 3, ROTATING_TARGET = 4, DROPPING_TARGET = 5 }; @@ -23,8 +24,8 @@ public: ACTIVATED = 1, DEACTIVATED = 2 }; - CEntity *m_pObject; - CObject *m_pMagnet; + CBuilding *m_pCraneEntity; + CObject *m_pHook; int32 m_nAudioEntity; float m_fPickupX1; float m_fPickupX2; @@ -36,20 +37,19 @@ public: float m_fDropoffAngle; float m_fPickupDistance; float m_fDropoffDistance; - float m_fAngle; - float m_fDistance; - float m_fHeight; + float m_fPickupHeight; + float m_fDropoffHeight; + float m_fHookAngle; float m_fHookOffset; float m_fHookHeight; CVector m_vecHookInitPos; CVector m_vecHookCurPos; - float m_fHookVelocityX; - float m_fHookVelocityY; + CVector2D m_vecHookVelocity; CVehicle *m_pVehiclePickedUp; - uint32 m_nUpdateTimer; - CraneStatus m_bCraneStatus; - CraneState m_bCraneState; - uint8 m_bVehiclesCollected; + uint32 m_nTimeForNextCheck; + CraneStatus m_nCraneStatus; + CraneState m_nCraneState; + uint8 m_nVehiclesCollected; bool m_bIsCrusher; bool m_bIsMilitaryCrane; bool m_bWasMilitaryCrane; @@ -57,14 +57,19 @@ public: void Init(void) { memset(this, 0, sizeof(*this)); } void Update(void); - bool RotateCarriedCarProperly(); - void FindCarInSectorList(CPtrList*); - bool DoesCranePickUpThisCarType(uint32); - bool GoTowardsTarget(float, float, float, float); - bool GoTowardsHeightTarget(float, float); - void FindParametersForTarget(float, float, float, float*, float*, float*); - void CalcHookCoordinates(float*, float*, float*); - void SetHookMatrix(); + bool RotateCarriedCarProperly(void); + void FindCarInSectorList(CPtrList* pList); + bool DoesCranePickUpThisCarType(uint32 mi); + bool GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier = 1.0f); + bool GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier = 1.0f); + void FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight); + void CalcHookCoordinates(float* pX, float* pY, float* pZ); + void SetHookMatrix(void); + + float GetHeightToPickup() { return 4.0f + m_fPickupHeight + (m_bIsCrusher ? 4.5f : 0.0f); }; + float GetHeightToDropoff() { return m_bIsCrusher ? (2.0f + m_fDropoffHeight + 3.0f) : (2.0f + m_fDropoffHeight); } + float GetHeightToPickupHeight() { return m_fPickupHeight + (m_bIsCrusher ? 7.0f : 4.0f); } + float GetHeightToDropoffHeight() { return m_fDropoffHeight + (m_bIsCrusher ? 7.0f : 2.0f); } }; static_assert(sizeof(CCrane) == 128, "CCrane: error"); @@ -73,19 +78,19 @@ class CCranes { public: static void InitCranes(void); - static void AddThisOneCrane(CEntity*); - static void ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float); - static void DeActivateCrane(float, float); - static bool IsThisCarPickedUp(float, float, CVehicle*); + static void AddThisOneCrane(CEntity* pCraneEntity); + static void ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY); + static void DeActivateCrane(float fX, float fY); + static bool IsThisCarPickedUp(float fX, float fY, CVehicle* pVehicle); static void UpdateCranes(void); - static bool DoesMilitaryCraneHaveThisOneAlready(uint32); - static void RegisterCarForMilitaryCrane(uint32); - static bool HaveAllCarsBeenCollectedByMilitaryCrane(); - static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*); - static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*); - static void Save(uint8*, uint32*); + static bool DoesMilitaryCraneHaveThisOneAlready(uint32 mi); + static void RegisterCarForMilitaryCrane(uint32 mi); + static bool HaveAllCarsBeenCollectedByMilitaryCrane(void); + static bool IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle); + static bool IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle); + static void Save(uint8* buf, uint32* size); - static int32& CarsCollectedMilitaryCrane; + static uint32& CarsCollectedMilitaryCrane; static int32& NumCranes; static CCrane(&aCranes)[NUM_CRANES]; }; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 7e9fc0fa..64020602 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -126,7 +126,6 @@ uint32& CGarages::MessageEndTime = *(uint32*)0x8F597C; uint32& CGarages::NumGarages = *(uint32*)0x8F29F4; bool& CGarages::PlayerInGarage = *(bool*)0x95CD83; int32& CGarages::PoliceCarsCollected = *(int32*)0x941444; -uint32& CGarages::GarageToBeTidied = *(uint32*)0x623570; CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210; CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300; CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0; @@ -322,6 +321,9 @@ void CGarage::Update() } } } + break; + default: + break; } } if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED) @@ -408,11 +410,11 @@ void CGarage::Update() if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) { uint8 colour1, colour2; uint16 attempt; - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2); + FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2); for (attempt = 0; attempt < 10; attempt++) { if (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2) break; - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2); + FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2); } bChangedColour = (attempt < 10); FindPlayerVehicle()->m_currentColour1 = colour1; @@ -490,7 +492,7 @@ void CGarage::Update() break; } if (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) { - CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each" + CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each" - weird that the price is hardcoded in message m_eGarageState = GS_OPENEDCONTAINSCAR; DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1); break; @@ -1184,7 +1186,7 @@ bool CGarage::IsEntityEntirelyInside(CEntity * pEntity) if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 || pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2) return false; - CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); + CColModel* pColModel = pEntity->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1201,7 +1203,7 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin) pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin || pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin) return false; - CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); + CColModel* pColModel = pEntity->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1218,7 +1220,7 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin) if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin && pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin) return false; - CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); + CColModel* pColModel = pEntity->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1250,7 +1252,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity) pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 || pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2) return false; - CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); + CColModel* pColModel = pEntity->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; radius = pColModel->spheres[i].radius; @@ -1264,7 +1266,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity) bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin) { - CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(); + CColModel* pColModel = pEntity->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1285,7 +1287,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException) continue; if (!IsEntityTouching3D(pVehicle)) continue; - CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel(); + CColModel* pColModel = pVehicle->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1307,7 +1309,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException) continue; if (!IsEntityTouching3D(pPed)) continue; - CColModel* pColModel = CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetColModel(); + CColModel* pColModel = pException->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1329,7 +1331,7 @@ bool CGarage::IsAnyCarBlockingDoor() continue; if (!IsEntityTouching3D(pVehicle)) continue; - CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel(); + CColModel* pColModel = pVehicle->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -1698,8 +1700,8 @@ float CGarage::CalcSmallestDistToGarageDoorSquared(float X, float Y) void CGarage::FindDoorsEntities() { - m_pDoor1 = false; - m_pDoor2 = false; + m_pDoor1 = nil; + m_pDoor2 = nil; int xstart = max(0, CWorld::GetSectorIndexX(m_fX1)); int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2)); int ystart = max(0, CWorld::GetSectorIndexY(m_fY1)); @@ -1992,7 +1994,7 @@ void CGarage::TidyUpGarageClose() continue; bool bRemove = false; if (m_eGarageState != GS_FULLYCLOSED) { - CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel(); + CColModel* pColModel = pVehicle->GetColModel(); for (int i = 0; i < pColModel->numSpheres; i++) { CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center; float radius = pColModel->spheres[i].radius; @@ -2227,6 +2229,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight() 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; @@ -2248,6 +2251,9 @@ 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 } CStoredCar::CStoredCar(const CStoredCar & other) @@ -2271,6 +2277,7 @@ CStoredCar::CStoredCar(const CStoredCar & other) 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); @@ -2303,6 +2310,9 @@ void CGarages::Load(uint8* buf, uint32 size) else aGarages[i].UpdateDoorsHeight(); } +#ifdef FIX_GARAGE_SIZE + VALIDATESAVEBUF(size); +#endif } bool @@ -2345,7 +2355,6 @@ CGarages::IsModelIndexADoor(uint32 id) STARTPATCHES - InjectHook(0x426B20, CGarages::TriggerMessage, PATCH_JUMP); // CCrane::Update, CCrane::FindCarInSectorList InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad diff --git a/src/control/Garages.h b/src/control/Garages.h index 3f471555..a07fa719 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -192,7 +192,6 @@ class CGarages static uint32 &NumGarages; static bool &PlayerInGarage; static int32 &PoliceCarsCollected; - static uint32 &GarageToBeTidied; static CGarage(&aGarages)[NUM_GARAGES]; static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS]; static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS]; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 8a79ba1d..6409f339 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -2229,6 +2229,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) if (pos.z <= -100) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); UpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3])); + return 0; } case COMMAND_DEBUG_ON: CTheScripts::DbgFlag = true; @@ -7657,13 +7658,13 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) assert(pObject); if (ScriptParams[1]) { if (pObject->bIsStatic) { - pObject->bIsStatic = true; + pObject->bIsStatic = false; pObject->AddToMovingList(); } } else { if (!pObject->bIsStatic) { - pObject->bIsStatic = false; + pObject->bIsStatic = true; pObject->RemoveFromMovingList(); } } @@ -11037,6 +11038,7 @@ void CRunningScript::DoDeatharrestCheck() int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact]; if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) { messageId += CTheScripts::BaseBriefIdForContact[contact]; + found = true; } } if (!found) @@ -11331,6 +11333,7 @@ INITSAVEBUF break; case 4: InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1); + break; default: assert(false); } diff --git a/src/control/Script.h b/src/control/Script.h index fbcdce48..8143bd43 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -17,7 +17,7 @@ class CRunningScript; struct CScriptRectangle { - int8 m_bIsUsed; + bool m_bIsUsed; bool m_bBeforeFade; int16 m_nTextureId; CRect m_sRect; -- cgit v1.2.3 From e6e51492f064c4ab429a417862be1d0903bd4a0c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 6 Apr 2020 11:19:29 +0300 Subject: review fixes --- src/control/Cranes.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'src/control') diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp index cbfd2a35..021a5c19 100644 --- a/src/control/Cranes.cpp +++ b/src/control/Cranes.cpp @@ -30,6 +30,12 @@ #define HOOK_OFFSET_MOVEMENT_SPEED (0.1f) #define HOOK_HEIGHT_MOVEMENT_SPEED (0.06f) +#define MESSAGE_SHOW_DURATION (4000) + +#define MAX_DISTANCE (99999.9f) +#define MIN_VALID_POSITION (-10000.0f) +#define DEFAULT_OFFSET (20.0f) + uint32 TimerForCamInterpolation; uint32& CCranes::CarsCollectedMilitaryCrane = *(uint32*)0x8F6248; @@ -72,8 +78,8 @@ void CCranes::AddThisOneCrane(CEntity* pEntity) pCrane->m_fHookAngle = NumCranes; // lol wtf while (pCrane->m_fHookAngle > TWOPI) pCrane->m_fHookAngle -= TWOPI; - pCrane->m_fHookOffset = 20.0f; - pCrane->m_fHookHeight = 20.0f; + pCrane->m_fHookOffset = DEFAULT_OFFSET; + pCrane->m_fHookHeight = DEFAULT_OFFSET; pCrane->m_nTimeForNextCheck = 0; pCrane->m_nCraneState = CCrane::IDLE; pCrane->m_bWasMilitaryCrane = false; @@ -99,9 +105,9 @@ void CCranes::AddThisOneCrane(CEntity* pEntity) void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY) { - float fMinDistance = 99999.9f; + float fMinDistance = MAX_DISTANCE; float X = fPosX, Y = fPosY; - if (X <= -10000.0f || Y <= -10000.0f) { + if (X <= MIN_VALID_POSITION || Y <= MIN_VALID_POSITION) { X = fDropOffX; Y = fDropOffY; } @@ -114,7 +120,7 @@ void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, } } #ifdef FIX_BUGS // classic - if (fMinDistance == 99999.9f) + if (fMinDistance == MAX_DISTANCE) return; #endif CCrane* pCrane = &aCranes[index]; @@ -150,7 +156,7 @@ void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, void CCranes::DeActivateCrane(float X, float Y) { - float fMinDistance = 99999.9f; + float fMinDistance = MAX_DISTANCE; int index = 0; for (int i = 0; i < NumCranes; i++) { float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); @@ -160,7 +166,7 @@ void CCranes::DeActivateCrane(float X, float Y) } } #ifdef FIX_BUGS // classic - if (fMinDistance == 99999.9f) + if (fMinDistance == MAX_DISTANCE) return; #endif aCranes[index].m_nCraneStatus = CCrane::DEACTIVATED; @@ -269,7 +275,7 @@ void CCrane::Update(void) break; case LIFTING_TARGET: RotateCarriedCarProperly(); - if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), 0.3f)) + if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), CRANE_SLOWDOWN_MULTIPLIER)) m_nCraneState = ROTATING_TARGET; if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) { m_pVehiclePickedUp = nil; @@ -302,7 +308,7 @@ void CCrane::Update(void) CCranes::RegisterCarForMilitaryCrane(m_pVehiclePickedUp->GetModelIndex()); if (!CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()) { CWorld::Players[CWorld::PlayerInFocus].m_nMoney += CAR_REWARD_MILITARY_CRANE; - CGarages::TriggerMessage("GA_10", CAR_REWARD_MILITARY_CRANE, 4000, -1); + CGarages::TriggerMessage("GA_10", CAR_REWARD_MILITARY_CRANE, MESSAGE_SHOW_DURATION, -1); } CWorld::Remove(m_pVehiclePickedUp); delete m_pVehiclePickedUp; @@ -415,11 +421,11 @@ void CCrane::FindCarInSectorList(CPtrList* pList) if (!pVehicle->bCraneMessageDone) { pVehicle->bCraneMessageDone = true; if (!m_bIsMilitaryCrane) - CGarages::TriggerMessage("CR_1", -1, 4000, -1); // Crane cannot lift this vehicle. + CGarages::TriggerMessage("CR_1", -1, MESSAGE_SHOW_DURATION, -1); // Crane cannot lift this vehicle. else if (DoesCranePickUpThisCarType(pVehicle->GetModelIndex())) - CGarages::TriggerMessage("GA_20", -1, 4000, -1); // We got more of these than we can shift. Sorry man, no deal. + CGarages::TriggerMessage("GA_20", -1, MESSAGE_SHOW_DURATION, -1); // We got more of these than we can shift. Sorry man, no deal. else - CGarages::TriggerMessage("GA_19", -1, 4000, -1); // We're not interested in that model. + CGarages::TriggerMessage("GA_19", -1, MESSAGE_SHOW_DURATION, -1); // We're not interested in that model. } } else { -- cgit v1.2.3 From 4f1d6123dd939f87a1798a3ebb447106a8c1ff73 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 6 Apr 2020 19:31:08 +0300 Subject: stats fix --- src/control/Garages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 64020602..9e10af2d 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -526,7 +526,7 @@ void CGarage::Update() ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed(); if (m_eGarageType == GARAGE_BOMBSHOP3) CGarages::GivePlayerDetonator(); - CStats::KgOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB; + CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB; } switch (m_eGarageType) { case GARAGE_BOMBSHOP1: -- cgit v1.2.3 From 560fc655388ac8cc017b4127e9444fc8702ffd45 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 8 Apr 2020 09:58:08 +0300 Subject: Small camera fixes --- src/control/Replay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 2e325249..b8e2318d 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1107,7 +1107,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca CStreaming::LoadScene(ff_coord); } if (cam_mode == REPLAYCAMMODE_ASSTORED) - TheCamera.CarZoomIndicator = 5.0f; + TheCamera.CarZoomIndicator = CAM_ZOOM_CINEMATIC; } void CReplay::StoreStuffInMem(void) -- cgit v1.2.3 From 8e29a5ec884842e0c445b3fb00b359386b7dca3e Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 8 Apr 2020 14:06:27 +0300 Subject: bug fix --- src/control/Garages.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/control') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 9e10af2d..84d49bee 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1679,7 +1679,7 @@ float CGarage::CalcDistToGarageRectangleSquared(float X, float Y) else distX = 0.0f; if (Y < m_fY1) - distY = m_fY1 - X; + distY = m_fY1 - Y; else if (Y > m_fY2) distY = Y - m_fY2; else @@ -2358,4 +2358,4 @@ STARTPATCHES InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad -ENDPATCHES \ No newline at end of file +ENDPATCHES -- cgit v1.2.3 From 8ee98574ffa61abf1d14e9511056dcadd537fc8b Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 8 Apr 2020 14:16:59 +0300 Subject: fix bug --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 6b79265a..db36d766 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -7117,7 +7117,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) case COMMAND_CLOSE_GARAGE: { CollectParameters(&m_nIp, 1); - CGarages::CloseGarage(ScriptParams[1]); + CGarages::CloseGarage(ScriptParams[0]); return 0; } case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD: -- cgit v1.2.3 From 5966e627f007d7d28b9073c01db73428e0b2796d Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 8 Apr 2020 15:17:07 +0300 Subject: fix bug --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index db36d766..18572573 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -9141,7 +9141,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) assert(pVehicle); assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR); CAutomobile* pCar = (CAutomobile*)pVehicle; - pCar->bTakeLessDamage = ScriptParams[1]; + pCar->bMoreResistantToDamage = ScriptParams[1]; return 0; } case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER: -- cgit v1.2.3 From 42d5f65c5525f2c6ec2237b2e46c570751554c1a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 8 Apr 2020 23:50:45 +0300 Subject: fix bug --- src/control/Script.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/control') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 18572573..db2c93a3 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -9153,6 +9153,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) return 0; } case COMMAND_LOAD_END_OF_GAME_TUNE: + DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE); printf("Start preload end of game audio\n"); DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED); printf("End preload end of game audio\n"); -- cgit v1.2.3 From 590ff324691a8dd60c7e05170544cff8b9bcb0ab Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Thu, 9 Apr 2020 06:20:44 +0300 Subject: PS2 Cheats, restored R*names --- src/control/Replay.cpp | 6 +++--- src/control/Script.cpp | 8 ++++---- src/control/Script.h | 29 +++++++++++++++++++---------- 3 files changed, 26 insertions(+), 17 deletions(-) (limited to 'src/control') diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index b8e2318d..0da32dd2 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1129,8 +1129,8 @@ void CReplay::StoreStuffInMem(void) pEmptyReferences = CReferences::pEmptyList; pStoredCam = new uint8[sizeof(CCamera)]; memcpy(pStoredCam, &TheCamera, sizeof(CCamera)); - pRadarBlips = new uint8[sizeof(CBlip) * NUMRADARBLIPS]; - memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(CBlip)); + pRadarBlips = new uint8[sizeof(sRadarTrace) * NUMRADARBLIPS]; + memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(sRadarTrace)); PlayerWanted = *FindPlayerPed()->m_pWanted; PlayerInfo = CWorld::Players[0]; Time1 = CTimer::GetTimeInMilliseconds(); @@ -1179,7 +1179,7 @@ void CReplay::RestoreStuffFromMem(void) memcpy(&TheCamera, pStoredCam, sizeof(CCamera)); delete[] pStoredCam; pStoredCam = nil; - memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMRADARBLIPS); + memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(sRadarTrace) * NUMRADARBLIPS); delete[] pRadarBlips; pRadarBlips = nil; FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 18572573..75fd32a0 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -91,10 +91,10 @@ uint8 (&CTheScripts::ScriptSpace)[SIZE_SCRIPT_SPACE] = *(uint8(*)[SIZE_SCRIPT_SP CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08; int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200; int32(&CTheScripts::OnAMissionForContactFlag)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x8622F0; -CTextLine (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(CTextLine (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68; -CScriptRectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(CScriptRectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108; +intro_text_line (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(intro_text_line (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68; +intro_script_rectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(intro_script_rectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108; CSprite2d (&CTheScripts::ScriptSprites)[MAX_NUM_SCRIPT_SRPITES] = *(CSprite2d(*)[MAX_NUM_SCRIPT_SRPITES])*(uintptr*)0x72B090; -CScriptSphere(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(CScriptSphere(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60; +script_sphere_struct(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(script_sphere_struct(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60; tCollectiveData(&CTheScripts::CollectiveArray)[MAX_NUM_COLLECTIVES] = *(tCollectiveData(*)[MAX_NUM_COLLECTIVES])*(uintptr*)0x6FA008; tUsedObject(&CTheScripts::UsedObjectArray)[MAX_NUM_USED_OBJECTS] = *(tUsedObject(*)[MAX_NUM_USED_OBJECTS])*(uintptr*)0x6E69C8; int32(&CTheScripts::MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS] = *(int32(*)[MAX_NUM_MISSION_SCRIPTS])*(uintptr*)0x6F0558; @@ -313,7 +313,7 @@ bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id) return false; } -void CStuckCarCheckEntry::Reset() +void stuck_car_data::Reset() { m_nVehicleIndex = -1; m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f); diff --git a/src/control/Script.h b/src/control/Script.h index 8143bd43..4338bd18 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -15,22 +15,25 @@ class CRunningScript; #define KEY_LENGTH_IN_SCRIPT 8 -struct CScriptRectangle +struct intro_script_rectangle { bool m_bIsUsed; bool m_bBeforeFade; int16 m_nTextureId; CRect m_sRect; CRGBA m_sColor; + + intro_script_rectangle() { } + ~intro_script_rectangle() { } }; -static_assert(sizeof(CScriptRectangle) == 0x18, "Script.h: error"); +static_assert(sizeof(intro_script_rectangle) == 0x18, "Script.h: error"); enum { SCRIPT_TEXT_MAX_LENGTH = 500 }; -struct CTextLine +struct intro_text_line { float m_fScaleX; float m_fScaleY; @@ -50,6 +53,9 @@ struct CTextLine float m_fAtY; wchar m_Text[SCRIPT_TEXT_MAX_LENGTH]; + intro_text_line() { } + ~intro_text_line() { } + void Reset() { m_fScaleX = 0.48f; @@ -72,15 +78,17 @@ struct CTextLine } }; -static_assert(sizeof(CTextLine) == 0x414, "Script.h: error"); +static_assert(sizeof(intro_text_line) == 0x414, "Script.h: error"); -struct CScriptSphere +struct script_sphere_struct { bool m_bInUse; uint16 m_Index; uint32 m_Id; CVector m_vecCenter; float m_fRadius; + + script_sphere_struct() { } }; struct CStoredLine @@ -145,7 +153,7 @@ public: bool HasCarBeenUpsideDownForAWhile(int32); }; -struct CStuckCarCheckEntry +struct stuck_car_data { int32 m_nVehicleIndex; CVector m_vecPos; @@ -154,12 +162,13 @@ struct CStuckCarCheckEntry uint32 m_nStuckTime; bool m_bStuck; + stuck_car_data() { } inline void Reset(); }; class CStuckCarCheck { - CStuckCarCheckEntry m_sCars[MAX_STUCK_CAR_CHECKS]; + stuck_car_data m_sCars[MAX_STUCK_CAR_CHECKS]; public: void Init(); @@ -235,10 +244,10 @@ class CTheScripts static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS]; static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS]; static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS]; - static CTextLine(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES]; - static CScriptRectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES]; + 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 CScriptSphere(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES]; + 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]; -- cgit v1.2.3 From 34349c4df2683fca35be37ec626aaa8eef2ddaee Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 9 Apr 2020 20:50:24 +0200 Subject: normalized line endings to LF --- src/control/GameLogic.cpp | 572 ++++++------ src/control/GameLogic.h | 24 +- src/control/Gangs.cpp | 18 +- src/control/OnscreenTimer.h | 96 +- src/control/Pickups.cpp | 2098 +++++++++++++++++++++---------------------- src/control/Pickups.h | 248 ++--- src/control/PowerPoints.cpp | 42 +- src/control/PowerPoints.h | 50 +- src/control/Restart.cpp | 434 ++++----- 9 files changed, 1791 insertions(+), 1791 deletions(-) (limited to 'src/control') diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index 0abae7d6..8e0ea02d 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -1,294 +1,294 @@ #include "common.h" #include "patcher.h" -#include "GameLogic.h" -#include "Clock.h" -#include "Stats.h" -#include "Pickups.h" -#include "Timer.h" -#include "Streaming.h" -#include "CutsceneMgr.h" -#include "World.h" -#include "PlayerPed.h" -#include "Wanted.h" -#include "Camera.h" -#include "Messages.h" -#include "CarCtrl.h" -#include "Restart.h" -#include "Pad.h" -#include "References.h" -#include "Fire.h" -#include "Script.h" -#include "Garages.h" - -uint8 CGameLogic::ActivePlayers; // 0x95CD5E - -void -CGameLogic::InitAtStartOfGame() -{ - ActivePlayers = 1; -} - -void -CGameLogic::PassTime(uint32 time) -{ - int32 minutes, hours, days; - - minutes = time + CClock::GetMinutes(); - hours = CClock::GetHours(); - - for (; minutes >= 60; minutes -= 60) - hours++; - - if (hours > 23) { - days = CStats::DaysPassed; - for (; hours >= 24; hours -= 24) - days++; - CStats::DaysPassed = days; - } - - CClock::SetGameClock(hours, minutes); - CPickups::PassTime(time * 1000); -} - -void -CGameLogic::SortOutStreamingAndMemory(const CVector &pos) -{ - CTimer::Stop(); - CStreaming::FlushRequestList(); - CStreaming::DeleteRwObjectsAfterDeath(pos); - CStreaming::RemoveUnusedModelsInLoadedList(); - CGame::DrasticTidyUpMemory(true); - CStreaming::LoadScene(pos); - CTimer::Update(); -} - -void -CGameLogic::Update() -{ - CVector vecRestartPos; - float fRestartFloat; - - if (CCutsceneMgr::IsCutsceneProcessing()) return; - - CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus]; - switch (pPlayerInfo.m_WBState) { - case WBSTATE_PLAYING: - if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) { - pPlayerInfo.m_pPed->ClearAdrenaline(); - pPlayerInfo.KillPlayer(); - } - if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) { - pPlayerInfo.m_pPed->ClearAdrenaline(); - pPlayerInfo.ArrestPlayer(); - } - break; - case WBSTATE_WASTED: - if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { - TheCamera.SetFadeColour(200, 200, 200); - TheCamera.Fade(2.0f, FADE_OUT); - } - - if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { - pPlayerInfo.m_WBState = WBSTATE_PLAYING; - if (pPlayerInfo.m_bGetOutOfHospitalFree) { - pPlayerInfo.m_bGetOutOfHospitalFree = false; - } else { - pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000); - pPlayerInfo.m_pPed->ClearWeapons(); - } - - if (pPlayerInfo.m_pPed->bInVehicle) { - CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; - if (pVehicle != nil) { - if (pVehicle->pDriver == pPlayerInfo.m_pPed) { - pVehicle->pDriver = nil; - if (pVehicle->m_status != STATUS_WRECKED) - pVehicle->m_status = STATUS_ABANDONED; - } else - pVehicle->RemovePassenger(pPlayerInfo.m_pPed); - } - } - CEventList::Initialise(); - CMessages::ClearMessages(); - CCarCtrl::ClearInterestingVehicleList(); - CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); - CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); - CRestart::OverrideHospitalLevel = LEVEL_NONE; - CRestart::OverridePoliceStationLevel = LEVEL_NONE; - PassTime(720); - RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); - SortOutStreamingAndMemory(pPlayerInfo.GetPos()); - TheCamera.m_fCamShakeForce = 0.0f; - TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); - CPad::GetPad(0)->StopShaking(0); - CReferences::RemoveReferencesToPlayer(); - CCarCtrl::CountDownToCarsAtStart = 2; - CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; - if (CRestart::bFadeInAfterNextDeath) { - TheCamera.SetFadeColour(200, 200, 200); - TheCamera.Fade(4.0f, FADE_IN); - } else CRestart::bFadeInAfterNextDeath = true; - } - break; - case WBSTATE_BUSTED: - if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { - TheCamera.SetFadeColour(0, 0, 0); - TheCamera.Fade(2.0f, FADE_OUT); - } - if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { - pPlayerInfo.m_WBState = WBSTATE_PLAYING; - int takeMoney; - - switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) { - case 0: - case 1: - takeMoney = 100; - break; - case 2: - takeMoney = 200; - break; - case 3: - takeMoney = 400; - break; - case 4: - takeMoney = 600; - break; - case 5: - takeMoney = 900; - break; - case 6: - takeMoney = 1500; - break; - } - if (pPlayerInfo.m_bGetOutOfJailFree) { - pPlayerInfo.m_bGetOutOfJailFree = false; - } else { - pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney); - pPlayerInfo.m_pPed->ClearWeapons(); - } - - if (pPlayerInfo.m_pPed->bInVehicle) { - CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; - if (pVehicle != nil) { - if (pVehicle->pDriver == pPlayerInfo.m_pPed) { - pVehicle->pDriver = nil; - if (pVehicle->m_status != STATUS_WRECKED) - pVehicle->m_status = STATUS_ABANDONED; - } - else - pVehicle->RemovePassenger(pPlayerInfo.m_pPed); - } - } - CEventList::Initialise(); - CMessages::ClearMessages(); - CCarCtrl::ClearInterestingVehicleList(); - CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); - CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); - CRestart::OverrideHospitalLevel = LEVEL_NONE; - CRestart::OverridePoliceStationLevel = LEVEL_NONE; - PassTime(720); - RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); - pPlayerInfo.m_pPed->ClearWeapons(); - SortOutStreamingAndMemory(pPlayerInfo.GetPos()); - TheCamera.m_fCamShakeForce = 0.0f; - TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); - CPad::GetPad(0)->StopShaking(0); - CReferences::RemoveReferencesToPlayer(); - CCarCtrl::CountDownToCarsAtStart = 2; - CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; - if (CRestart::bFadeInAfterNextArrest) { - TheCamera.SetFadeColour(0, 0, 0); - TheCamera.Fade(4.0f, FADE_IN); - } else CRestart::bFadeInAfterNextArrest = true; - } - break; - case WBSTATE_FAILED_CRITICAL_MISSION: - if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) { - TheCamera.SetFadeColour(0, 0, 0); - TheCamera.Fade(2.0f, FADE_OUT); - } - if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { - pPlayerInfo.m_WBState = WBSTATE_PLAYING; - if (pPlayerInfo.m_pPed->bInVehicle) { - CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; - if (pVehicle != nil) { - if (pVehicle->pDriver == pPlayerInfo.m_pPed) { - pVehicle->pDriver = nil; - if (pVehicle->m_status != STATUS_WRECKED) - pVehicle->m_status = STATUS_ABANDONED; - } else - pVehicle->RemovePassenger(pPlayerInfo.m_pPed); - } - } - CEventList::Initialise(); - CMessages::ClearMessages(); - CCarCtrl::ClearInterestingVehicleList(); - CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); - CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); - CRestart::OverridePoliceStationLevel = LEVEL_NONE; - CRestart::OverrideHospitalLevel = LEVEL_NONE; - RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); - SortOutStreamingAndMemory(pPlayerInfo.GetPos()); - TheCamera.m_fCamShakeForce = 0.0f; - TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); - CPad::GetPad(0)->StopShaking(0); - CReferences::RemoveReferencesToPlayer(); - CCarCtrl::CountDownToCarsAtStart = 2; - CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; - TheCamera.SetFadeColour(0, 0, 0); - TheCamera.Fade(4.0f, FADE_IN); - } - break; - case 4: - return; - } -} - -void -CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle) -{ - pPlayerPed->m_fHealth = 100.0f; - pPlayerPed->m_fArmour = 0.0f; - pPlayerPed->bIsVisible = true; - pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0; - pPlayerPed->bDoBloodyFootprints = false; - pPlayerPed->ClearAdrenaline(); - pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina; - if (pPlayerPed->m_pFire) - pPlayerPed->m_pFire->Extinguish(); - pPlayerPed->bInVehicle = false; - pPlayerPed->m_pMyVehicle = nil; - pPlayerPed->m_pVehicleAnim = nil; - pPlayerPed->m_pWanted->Reset(); - pPlayerPed->RestartNonPartialAnims(); - pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false); - pPlayerPed->bRemoveFromWorld = false; - pPlayerPed->ClearWeaponTarget(); - pPlayerPed->SetInitialState(); - CCarCtrl::ClearInterestingVehicleList(); - - pos.z += 1.0f; - pPlayerPed->Teleport(pos); - pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f)); - - pPlayerPed->m_fRotationCur = DEGTORAD(angle); - pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur; - pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur); - CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed); - CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1); - pPlayerPed->RestoreHeadingRate(); - TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); - CReferences::RemoveReferencesToPlayer(); - CGarages::PlayerArrestedOrDied(); - CStats::CheckPointReachedUnsuccessfully(); - CWorld::Remove(pPlayerPed); - CWorld::Add(pPlayerPed); -} - +#include "GameLogic.h" +#include "Clock.h" +#include "Stats.h" +#include "Pickups.h" +#include "Timer.h" +#include "Streaming.h" +#include "CutsceneMgr.h" +#include "World.h" +#include "PlayerPed.h" +#include "Wanted.h" +#include "Camera.h" +#include "Messages.h" +#include "CarCtrl.h" +#include "Restart.h" +#include "Pad.h" +#include "References.h" +#include "Fire.h" +#include "Script.h" +#include "Garages.h" + +uint8 CGameLogic::ActivePlayers; // 0x95CD5E + +void +CGameLogic::InitAtStartOfGame() +{ + ActivePlayers = 1; +} + +void +CGameLogic::PassTime(uint32 time) +{ + int32 minutes, hours, days; + + minutes = time + CClock::GetMinutes(); + hours = CClock::GetHours(); + + for (; minutes >= 60; minutes -= 60) + hours++; + + if (hours > 23) { + days = CStats::DaysPassed; + for (; hours >= 24; hours -= 24) + days++; + CStats::DaysPassed = days; + } + + CClock::SetGameClock(hours, minutes); + CPickups::PassTime(time * 1000); +} + +void +CGameLogic::SortOutStreamingAndMemory(const CVector &pos) +{ + CTimer::Stop(); + CStreaming::FlushRequestList(); + CStreaming::DeleteRwObjectsAfterDeath(pos); + CStreaming::RemoveUnusedModelsInLoadedList(); + CGame::DrasticTidyUpMemory(true); + CStreaming::LoadScene(pos); + CTimer::Update(); +} + +void +CGameLogic::Update() +{ + CVector vecRestartPos; + float fRestartFloat; + + if (CCutsceneMgr::IsCutsceneProcessing()) return; + + CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus]; + switch (pPlayerInfo.m_WBState) { + case WBSTATE_PLAYING: + if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) { + pPlayerInfo.m_pPed->ClearAdrenaline(); + pPlayerInfo.KillPlayer(); + } + if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) { + pPlayerInfo.m_pPed->ClearAdrenaline(); + pPlayerInfo.ArrestPlayer(); + } + break; + case WBSTATE_WASTED: + if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { + TheCamera.SetFadeColour(200, 200, 200); + TheCamera.Fade(2.0f, FADE_OUT); + } + + if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { + pPlayerInfo.m_WBState = WBSTATE_PLAYING; + if (pPlayerInfo.m_bGetOutOfHospitalFree) { + pPlayerInfo.m_bGetOutOfHospitalFree = false; + } else { + pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000); + pPlayerInfo.m_pPed->ClearWeapons(); + } + + if (pPlayerInfo.m_pPed->bInVehicle) { + CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; + if (pVehicle != nil) { + if (pVehicle->pDriver == pPlayerInfo.m_pPed) { + pVehicle->pDriver = nil; + if (pVehicle->m_status != STATUS_WRECKED) + pVehicle->m_status = STATUS_ABANDONED; + } else + pVehicle->RemovePassenger(pPlayerInfo.m_pPed); + } + } + CEventList::Initialise(); + CMessages::ClearMessages(); + CCarCtrl::ClearInterestingVehicleList(); + CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); + CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); + CRestart::OverrideHospitalLevel = LEVEL_NONE; + CRestart::OverridePoliceStationLevel = LEVEL_NONE; + PassTime(720); + RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); + SortOutStreamingAndMemory(pPlayerInfo.GetPos()); + TheCamera.m_fCamShakeForce = 0.0f; + TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); + CPad::GetPad(0)->StopShaking(0); + CReferences::RemoveReferencesToPlayer(); + CCarCtrl::CountDownToCarsAtStart = 2; + CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; + if (CRestart::bFadeInAfterNextDeath) { + TheCamera.SetFadeColour(200, 200, 200); + TheCamera.Fade(4.0f, FADE_IN); + } else CRestart::bFadeInAfterNextDeath = true; + } + break; + case WBSTATE_BUSTED: + if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { + TheCamera.SetFadeColour(0, 0, 0); + TheCamera.Fade(2.0f, FADE_OUT); + } + if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { + pPlayerInfo.m_WBState = WBSTATE_PLAYING; + int takeMoney; + + switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) { + case 0: + case 1: + takeMoney = 100; + break; + case 2: + takeMoney = 200; + break; + case 3: + takeMoney = 400; + break; + case 4: + takeMoney = 600; + break; + case 5: + takeMoney = 900; + break; + case 6: + takeMoney = 1500; + break; + } + if (pPlayerInfo.m_bGetOutOfJailFree) { + pPlayerInfo.m_bGetOutOfJailFree = false; + } else { + pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney); + pPlayerInfo.m_pPed->ClearWeapons(); + } + + if (pPlayerInfo.m_pPed->bInVehicle) { + CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; + if (pVehicle != nil) { + if (pVehicle->pDriver == pPlayerInfo.m_pPed) { + pVehicle->pDriver = nil; + if (pVehicle->m_status != STATUS_WRECKED) + pVehicle->m_status = STATUS_ABANDONED; + } + else + pVehicle->RemovePassenger(pPlayerInfo.m_pPed); + } + } + CEventList::Initialise(); + CMessages::ClearMessages(); + CCarCtrl::ClearInterestingVehicleList(); + CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); + CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); + CRestart::OverrideHospitalLevel = LEVEL_NONE; + CRestart::OverridePoliceStationLevel = LEVEL_NONE; + PassTime(720); + RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); + pPlayerInfo.m_pPed->ClearWeapons(); + SortOutStreamingAndMemory(pPlayerInfo.GetPos()); + TheCamera.m_fCamShakeForce = 0.0f; + TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); + CPad::GetPad(0)->StopShaking(0); + CReferences::RemoveReferencesToPlayer(); + CCarCtrl::CountDownToCarsAtStart = 2; + CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; + if (CRestart::bFadeInAfterNextArrest) { + TheCamera.SetFadeColour(0, 0, 0); + TheCamera.Fade(4.0f, FADE_IN); + } else CRestart::bFadeInAfterNextArrest = true; + } + break; + case WBSTATE_FAILED_CRITICAL_MISSION: + if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) { + TheCamera.SetFadeColour(0, 0, 0); + TheCamera.Fade(2.0f, FADE_OUT); + } + if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { + pPlayerInfo.m_WBState = WBSTATE_PLAYING; + if (pPlayerInfo.m_pPed->bInVehicle) { + CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; + if (pVehicle != nil) { + if (pVehicle->pDriver == pPlayerInfo.m_pPed) { + pVehicle->pDriver = nil; + if (pVehicle->m_status != STATUS_WRECKED) + pVehicle->m_status = STATUS_ABANDONED; + } else + pVehicle->RemovePassenger(pPlayerInfo.m_pPed); + } + } + CEventList::Initialise(); + CMessages::ClearMessages(); + CCarCtrl::ClearInterestingVehicleList(); + CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); + CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); + CRestart::OverridePoliceStationLevel = LEVEL_NONE; + CRestart::OverrideHospitalLevel = LEVEL_NONE; + RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); + SortOutStreamingAndMemory(pPlayerInfo.GetPos()); + TheCamera.m_fCamShakeForce = 0.0f; + TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE); + CPad::GetPad(0)->StopShaking(0); + CReferences::RemoveReferencesToPlayer(); + CCarCtrl::CountDownToCarsAtStart = 2; + CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; + TheCamera.SetFadeColour(0, 0, 0); + TheCamera.Fade(4.0f, FADE_IN); + } + break; + case 4: + return; + } +} + +void +CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle) +{ + pPlayerPed->m_fHealth = 100.0f; + pPlayerPed->m_fArmour = 0.0f; + pPlayerPed->bIsVisible = true; + pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0; + pPlayerPed->bDoBloodyFootprints = false; + pPlayerPed->ClearAdrenaline(); + pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina; + if (pPlayerPed->m_pFire) + pPlayerPed->m_pFire->Extinguish(); + pPlayerPed->bInVehicle = false; + pPlayerPed->m_pMyVehicle = nil; + pPlayerPed->m_pVehicleAnim = nil; + pPlayerPed->m_pWanted->Reset(); + pPlayerPed->RestartNonPartialAnims(); + pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false); + pPlayerPed->bRemoveFromWorld = false; + pPlayerPed->ClearWeaponTarget(); + pPlayerPed->SetInitialState(); + CCarCtrl::ClearInterestingVehicleList(); + + pos.z += 1.0f; + pPlayerPed->Teleport(pos); + pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f)); + + pPlayerPed->m_fRotationCur = DEGTORAD(angle); + pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur; + pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur); + CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed); + CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1); + pPlayerPed->RestoreHeadingRate(); + TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); + CReferences::RemoveReferencesToPlayer(); + CGarages::PlayerArrestedOrDied(); + CStats::CheckPointReachedUnsuccessfully(); + CWorld::Remove(pPlayerPed); + CWorld::Add(pPlayerPed); +} + STARTPATCHES InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP); InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP); InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP); InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP); - InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP); + InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/control/GameLogic.h b/src/control/GameLogic.h index db626558..43e244a3 100644 --- a/src/control/GameLogic.h +++ b/src/control/GameLogic.h @@ -1,13 +1,13 @@ -#pragma once - -class CGameLogic -{ -public: - static void InitAtStartOfGame(); - static void PassTime(uint32 time); - static void SortOutStreamingAndMemory(const CVector &pos); - static void Update(); - static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle); - - static uint8 ActivePlayers; +#pragma once + +class CGameLogic +{ +public: + static void InitAtStartOfGame(); + static void PassTime(uint32 time); + static void SortOutStreamingAndMemory(const CVector &pos); + static void Update(); + static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle); + + static uint8 ActivePlayers; }; \ No newline at end of file diff --git a/src/control/Gangs.cpp b/src/control/Gangs.cpp index ac32ad98..57d9c67e 100644 --- a/src/control/Gangs.cpp +++ b/src/control/Gangs.cpp @@ -1,7 +1,7 @@ #include "common.h" #include "patcher.h" #include "ModelIndices.h" -#include "Gangs.h" +#include "Gangs.h" #include "Weapon.h" //CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78; @@ -57,20 +57,20 @@ void CGangs::SaveAllGangData(uint8 *buf, uint32 *size) { INITSAVEBUF - *size = SAVE_HEADER_SIZE + sizeof(Gang); + *size = SAVE_HEADER_SIZE + sizeof(Gang); WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE); - for (int i = 0; i < NUM_GANGS; i++) - WriteSaveBuf(buf, Gang[i]); - + for (int i = 0; i < NUM_GANGS; i++) + WriteSaveBuf(buf, Gang[i]); + VALIDATESAVEBUF(*size); } void CGangs::LoadAllGangData(uint8 *buf, uint32 size) { - Initialise(); - -INITSAVEBUF - // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE); + Initialise(); + +INITSAVEBUF + // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE); CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE); for (int i = 0; i < NUM_GANGS; i++) diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h index b1e0e622..fb139266 100644 --- a/src/control/OnscreenTimer.h +++ b/src/control/OnscreenTimer.h @@ -1,49 +1,49 @@ -#pragma once - -enum -{ - COUNTER_DISPLAY_NUMBER, - COUNTER_DISPLAY_BAR, -}; - -class COnscreenTimerEntry -{ -public: - uint32 m_nTimerOffset; - uint32 m_nCounterOffset; - char m_aTimerText[10]; - char m_aCounterText[10]; - uint16 m_nType; - char m_bCounterBuffer[42]; - char m_bTimerBuffer[42]; - bool m_bTimerProcessed; - bool m_bCounterProcessed; - - void Process(); - bool ProcessForDisplay(); - - void ProcessForDisplayClock(); - void ProcessForDisplayCounter(); -}; - -static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error"); - -class COnscreenTimer -{ -public: - COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES]; - bool m_bProcessed; - bool m_bDisabled; - - void Init(); - void Process(); - void ProcessForDisplay(); - - void ClearCounter(uint32 offset); - void ClearClock(uint32 offset); - - void AddCounter(uint32 offset, uint16 type, char* text); - void AddClock(uint32 offset, char* text); -}; - +#pragma once + +enum +{ + COUNTER_DISPLAY_NUMBER, + COUNTER_DISPLAY_BAR, +}; + +class COnscreenTimerEntry +{ +public: + uint32 m_nTimerOffset; + uint32 m_nCounterOffset; + char m_aTimerText[10]; + char m_aCounterText[10]; + uint16 m_nType; + char m_bCounterBuffer[42]; + char m_bTimerBuffer[42]; + bool m_bTimerProcessed; + bool m_bCounterProcessed; + + void Process(); + bool ProcessForDisplay(); + + void ProcessForDisplayClock(); + void ProcessForDisplayCounter(); +}; + +static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error"); + +class COnscreenTimer +{ +public: + COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES]; + bool m_bProcessed; + bool m_bDisabled; + + void Init(); + void Process(); + void ProcessForDisplay(); + + void ClearCounter(uint32 offset); + void ClearClock(uint32 offset); + + void AddCounter(uint32 offset, uint16 type, char* text); + void AddClock(uint32 offset, char* text); +}; + static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error"); \ No newline at end of file diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 3e3c2a48..774abd8c 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1,1049 +1,1049 @@ -#include "common.h" -#include "patcher.h" -#include "main.h" - -#include "Camera.h" -#include "Coronas.h" -#include "Darkel.h" -#include "Entity.h" -#include "Explosion.h" -#include "Font.h" -#include "Garages.h" -#include "General.h" -#include "ModelIndices.h" -#include "Object.h" -#include "Pad.h" -#include "Pickups.h" -#include "PlayerPed.h" -#include "Wanted.h" -#include "DMAudio.h" -#include "Fire.h" -#include "PointLights.h" -#include "Pools.h" -#ifdef FIX_BUGS -#include "Replay.h" -#endif -#include "Script.h" -#include "Shadows.h" -#include "SpecialFX.h" -#include "Sprite.h" -#include "Timer.h" -#include "WaterLevel.h" -#include "World.h" - -CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; -int16 CPickups::NumMessages;// = *(int16*)0x95CC98; -int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];// = *(int32(*)[NUMCOLLECTEDPICKUPS])*(uintptr*)0x87C538; -int16 CPickups::CollectedPickUpIndex;// = *(int16*)0x95CC8A; - -// unused -bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71; -CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8; -CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8; -uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C; - -tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES]; - -// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4) -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 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 }; - -WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); } -WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); } -WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); } -WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); } -WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); } -WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } -WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); } -WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); } -WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); } -WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); } -WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); } -WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); } -WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); } -WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); } -WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); } - - -void -CPickup::RemoveKeepType() -{ - CWorld::Remove(m_pObject); - delete m_pObject; - - m_bRemoved = true; - m_pObject = nil; -} - -void -CPickup::Remove() -{ - RemoveKeepType(); - m_eType = PICKUP_NONE; -} - -CObject * -CPickup::GiveUsAPickUpObject(int32 handle) -{ - CObject *object; - - if (handle <= 0) object = new CObject(m_eModelIndex, false); - else { - CPools::MakeSureSlotInObjectPoolIsEmpty(handle); - object = new(handle) CObject(m_eModelIndex, false); - } - - if (object == nil) return nil; - object->ObjectCreatedBy = MISSION_OBJECT; - object->GetPosition() = m_vecPos; - object->SetOrientation(0.0f, 0.0f, -HALFPI); - object->GetMatrix().UpdateRW(); - object->UpdateRwFrame(); - - object->bAffectedByGravity = false; - object->bExplosionProof = true; - object->bUsesCollision = false; - object->bIsPickup = true; - - object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0; - - switch (m_eType) - { - case PICKUP_IN_SHOP: - object->m_obj_flag2 = true; - object->bOutOfStock = false; - break; - case PICKUP_ON_STREET: - case PICKUP_ONCE: - case PICKUP_ONCE_TIMEOUT: - case PICKUP_COLLECTABLE1: - case PICKUP_MONEY: - case PICKUP_MINE_INACTIVE: - case PICKUP_MINE_ARMED: - case PICKUP_NAUTICAL_MINE_INACTIVE: - case PICKUP_NAUTICAL_MINE_ARMED: - case PICKUP_FLOATINGPACKAGE: - case PICKUP_ON_STREET_SLOW: - object->m_obj_flag2 = false; - object->bOutOfStock = false; - break; - case PICKUP_IN_SHOP_OUT_OF_STOCK: - object->m_obj_flag2 = false; - object->bOutOfStock = true; - object->bRenderScorched = true; - break; - case PICKUP_FLOATINGPACKAGE_FLOATING: - default: - break; - } - return object; -} - -bool -CPickup::CanBePickedUp(CPlayerPed *player) -{ - 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_BRIBE && player->m_pWanted->m_nWantedLevel == 0) - || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame)); - return !cannotBePickedUp; -} - -bool -CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) -{ - float waterLevel; - - if (m_bRemoved) { - if (CTimer::GetTimeInMilliseconds() > m_nTimer) { - // respawn pickup if we're far enough - float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y); - if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) { - m_pObject = GiveUsAPickUpObject(-1); - if (m_pObject) { - CWorld::Add(m_pObject); - m_bRemoved = false; - } - } - } - return false; - } - - if (!m_pObject) return false; - - if (!IsMine()) { - // let's check if we touched the pickup - bool isPickupTouched = false; - if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) { - if (vehicle != nil) { - if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) - isPickupTouched = true; - } - else { - if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) { - if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) + - (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f) - isPickupTouched = true; - } - } - } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) { - if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { - isPickupTouched = true; - } - } else if (vehicle == nil) { - if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) { - if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) + - (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f) - isPickupTouched = true; - } - } - - // if we didn't then we've got nothing to do - if (isPickupTouched && CanBePickedUp(player)) { - CPad::GetPad(0)->StartShake(120, 100); - switch (m_eType) - { - case PICKUP_IN_SHOP: - if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) { - CGarages::TriggerMessage("PU_MONY", -1, 6000, -1); - } else { - CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]; - if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { - player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]); - player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); - DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE); - } - RemoveKeepType(); - m_nTimer = CTimer::GetTimeInMilliseconds() + 5000; - return true; - } - break; - case PICKUP_ON_STREET: - case PICKUP_ON_STREET_SLOW: - if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { - if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) { - player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]); - if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) { - player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); - } - DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); - } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) { - DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); - CPickups::bPickUpcamActivated = true; - CPickups::pPlayerVehicle = FindPlayerVehicle(); - CPickups::StaticCamCoors = m_pObject->GetPosition(); - CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds(); - } - } - if (m_eType == PICKUP_ON_STREET) { - m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; - } else if (m_eType == PICKUP_ON_STREET_SLOW) { - if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex) - m_nTimer = CTimer::GetTimeInMilliseconds() + 300000; - else - m_nTimer = CTimer::GetTimeInMilliseconds() + 720000; - } - - RemoveKeepType(); - return true; - case PICKUP_ONCE: - case PICKUP_ONCE_TIMEOUT: - if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { - if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) { - player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]); - if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) - player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); - } - DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); - } - Remove(); - return true; - case PICKUP_COLLECTABLE1: - CWorld::Players[playerId].m_nCollectedPackages++; - CWorld::Players[playerId].m_nMoney += 1000; - - if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) { - printf("All collectables have been picked up\n"); - CGarages::TriggerMessage("CO_ALL", -1, 5000, -1); - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000; - } else - CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); - - Remove(); - DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0); - return true; - case PICKUP_MONEY: - CWorld::Players[playerId].m_nMoney += m_nQuantity; - sprintf(gString, "$%d", m_nQuantity); -#ifdef MONEY_MESSAGES - CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f); -#endif - Remove(); - DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); - return true; - //case PICKUP_IN_SHOP_OUT_OF_STOCK: - //case PICKUP_MINE_INACTIVE: - //case PICKUP_MINE_ARMED: - //case PICKUP_NAUTICAL_MINE_INACTIVE: - //case PICKUP_NAUTICAL_MINE_ARMED: - //case PICKUP_FLOATINGPACKAGE: - //case PICKUP_FLOATINGPACKAGE_FLOATING: - default: - break; - } - } - } else { - switch (m_eType) - { - case PICKUP_MINE_INACTIVE: - if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { - m_eType = PICKUP_MINE_ARMED; - m_nTimer = CTimer::GetTimeInMilliseconds() + 10000; - } - break; - case PICKUP_NAUTICAL_MINE_INACTIVE: - { - if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) - m_pObject->GetPosition().z = waterLevel + 0.6f; - - m_pObject->GetMatrix().UpdateRW(); - m_pObject->UpdateRwFrame(); - - bool touched = false; - for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { - CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); - if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { - touched = true; - break; // added break here - } - } - - if (!touched) { - m_eType = PICKUP_NAUTICAL_MINE_ARMED; - m_nTimer = CTimer::GetTimeInMilliseconds() + 10000; - } - break; - } - case PICKUP_NAUTICAL_MINE_ARMED: - if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) - m_pObject->GetPosition().z = waterLevel + 0.6f; - - m_pObject->GetMatrix().UpdateRW(); - m_pObject->UpdateRwFrame(); - // no break here - case PICKUP_MINE_ARMED: - { - bool explode = false; - if (CTimer::GetTimeInMilliseconds() > m_nTimer) - explode = true; - else {// added else here since vehicle lookup is useless - for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { - CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); - if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { - explode = true; - break; // added break here - } - } - } - if (explode) { - CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0); - Remove(); - } - break; - } - case PICKUP_FLOATINGPACKAGE: - m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep(); - m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep(); - - m_pObject->GetMatrix().UpdateRW(); - m_pObject->UpdateRwFrame(); - if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z) - m_eType = PICKUP_FLOATINGPACKAGE_FLOATING; - break; - case PICKUP_FLOATINGPACKAGE_FLOATING: - if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0)) - m_pObject->GetPosition().z = waterLevel; - - m_pObject->GetMatrix().UpdateRW(); - m_pObject->UpdateRwFrame(); - if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { - Remove(); - DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0); - return true; - } - break; - } - } - if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer) - Remove(); - return false; -} - -void -CPickups::Init(void) -{ - NumMessages = 0; - for (int i = 0; i < NUMPICKUPS; i++) { - aPickUps[i].m_eType = PICKUP_NONE; - aPickUps[i].m_nIndex = 1; - aPickUps[i].m_pObject = nil; - } - - for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) - aPickUpsCollected[i] = 0; - - CollectedPickUpIndex = 0; -} - -bool -CPickups::IsPickUpPickedUp(int32 pickupId) -{ - for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) { - if (pickupId == aPickUpsCollected[i]) { - aPickUpsCollected[i] = 0; - return true; - } - } - return false; -} - -void -CPickups::PassTime(uint32 time) -{ - for (int i = 0; i < NUMPICKUPS; i++) { - if (aPickUps[i].m_eType != PICKUP_NONE) { - if (aPickUps[i].m_nTimer <= time) - aPickUps[i].m_nTimer = 0; - else - aPickUps[i].m_nTimer -= time; - } - } -} - -int32 -CPickups::GetActualPickupIndex(int32 index) -{ - if (index == -1) return -1; - - // doesn't look nice - if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1; - return (uint16)index; -} - -bool -CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex) -{ - CPlayerPed *player; - - if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed; - else player = CWorld::Players[playerIndex].m_pPed; - - if (modelIndex == MI_PICKUP_ADRENALINE) { - player->m_bAdrenalineActive = true; - player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000; - player->m_fCurrentStamina = player->m_fMaxStamina; - DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0); - return true; - } else if (modelIndex == MI_PICKUP_BODYARMOUR) { - player->m_fArmour = 100.0f; - 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; - DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0); - return true; - } else if (modelIndex == MI_PICKUP_BONUS) { - DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); - return true; - } else if (modelIndex == MI_PICKUP_BRIBE) { - int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1; - if (level < 0) level = 0; - player->SetWantedLevel(level); - DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); - return true; - } else if (modelIndex == MI_PICKUP_KILLFRENZY) { - DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); - return true; - } - return false; -} - -void -CPickups::RemoveAllFloatingPickups() -{ - for (int i = 0; i < NUMPICKUPS; i++) { - if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) { - if (aPickUps[i].m_pObject) { - CWorld::Remove(aPickUps[i].m_pObject); - delete aPickUps[i].m_pObject; - aPickUps[i].m_pObject = nil; - } - } - } -} - -void -CPickups::RemovePickUp(int32 pickupIndex) -{ - int32 index = CPickups::GetActualPickupIndex(pickupIndex); - if (index == -1) return; - - if (aPickUps[index].m_pObject) { - CWorld::Remove(aPickUps[index].m_pObject); - delete aPickUps[index].m_pObject; - aPickUps[index].m_pObject = nil; - } - aPickUps[index].m_eType = PICKUP_NONE; - aPickUps[index].m_bRemoved = true; -} - -int32 -CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity) -{ - bool bFreeFound = false; - int32 slot = 0; - - if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) { - for (slot = NUMPICKUPS; slot >= 0; slot--) { - if (aPickUps[slot].m_eType == PICKUP_NONE) { - bFreeFound = true; - break; - } - } - } else { - for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { - if (aPickUps[slot].m_eType == PICKUP_NONE) { - bFreeFound = true; - break; - } - } - } - - if (!bFreeFound) - { - for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { - if (aPickUps[slot].m_eType == PICKUP_MONEY) break; - } - - if (slot >= NUMGENERALPICKUPS) - { - for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { - if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break; - } - - if (slot >= NUMGENERALPICKUPS) return -1; - } - } - - if (slot >= NUMPICKUPS) return -1; - - aPickUps[slot].m_eType = (ePickupType)type; - aPickUps[slot].m_bRemoved = false; - aPickUps[slot].m_nQuantity = quantity; - if (type == PICKUP_ONCE_TIMEOUT) - aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000; - else if (type == PICKUP_MONEY) - aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; - else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) { - aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE; - aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500; - } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) { - aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE; - aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500; - } - aPickUps[slot].m_eModelIndex = modelIndex; - aPickUps[slot].m_vecPos = pos; - aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1); - if (aPickUps[slot].m_pObject) - CWorld::Add(aPickUps[slot].m_pObject); - return GetNewUniquePickupIndex(slot); -} - -int32 -CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity) -{ - return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity); -} - -int32 -CPickups::GetNewUniquePickupIndex(int32 slot) -{ - if (aPickUps[slot].m_nIndex >= 0xFFFE) - aPickUps[slot].m_nIndex = 1; - else - aPickUps[slot].m_nIndex++; - return slot | (aPickUps[slot].m_nIndex << 16); -} - -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; - } - return 0; -} - -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; -} - -void -CPickups::AddToCollectedPickupsArray(int32 index) -{ - aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16); - if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS) - CollectedPickUpIndex = 0; -} - -void -CPickups::Update() -{ -#ifdef FIX_BUGS // RIP speedrunning (solution from SA) - if (CReplay::IsPlayingBack()) - return; -#endif -#define PICKUPS_FRAME_SPAN (6) -#ifdef FIX_BUGS - for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) { -#else // BUG: this code can only reach 318 out of 320 pickups - for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) { -#endif - if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { - AddToCollectedPickupsArray(i); - } - } -#undef PICKUPS_FRAME_SPAN - for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) { - if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { - AddToCollectedPickupsArray(i); - } - } -} - -void -CPickups::DoPickUpEffects(CEntity *entity) -{ - if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) - entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame; - - if (!entity->m_flagD80) { - float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); - float modifiedSin = 0.3f * (s + 1.0f); - - - int16 colorId; - - if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) - colorId = 11; - else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE) - colorId = 12; - else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) - colorId = 13; - else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) - colorId = 14; - else - colorId = FindColourIndexForWeaponMI(entity->GetModelIndex()); - - assert(colorId >= 0); - - CVector &pos = entity->GetPosition(); - - float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f; - CShadows::StoreStaticShadow( - (uintptr)entity, - SHADOWTYPE_ADDITIVE, - gpShadowExplosionTex, - &pos, - 2.0f, 0.0f, 0.0f, -2.0f, - 255, // this is 0 on PC which results in no shadow - aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier, - 4.0f, 1.0f, 40.0f, false, 0.0f); - - float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f; - CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true); - float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f; - CCoronas::RegisterCorona( (uintptr)entity, - aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f, - 255, - pos, - size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - - CObject *object = (CObject*)entity; - if (object->m_obj_flag2 || object->bOutOfStock || object->field_172) { - float dist = (TheCamera.GetPosition() - pos).Magnitude(); - const float MAXDIST = 12.0f; - - if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) { - RwV3d vecOut; - float fDistX, fDistY; - if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) { - aMessages[NumMessages].m_pos.x = vecOut.x; - aMessages[NumMessages].m_pos.y = vecOut.y; - aMessages[NumMessages].m_dist.x = fDistX; - aMessages[NumMessages].m_dist.y = fDistY; - aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex()); - aMessages[NumMessages].m_color.red = aWeaponReds[colorId]; - aMessages[NumMessages].m_color.green = aWeaponGreens[colorId]; - aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId]; - aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f; - aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock; - aMessages[NumMessages].m_quantity = object->field_172; - NumMessages++; - } - } - } - - entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]); - } -} - -void -CPickups::DoMineEffects(CEntity *entity) -{ - CVector &pos = entity->GetPosition(); - float dist = (TheCamera.GetPosition() - pos).Magnitude(); - const float MAXDIST = 20.0f; - - if (dist < MAXDIST) { - float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200)); - - int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f; - CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, - 2.0f, 0.0f, 0.0f, -2.0f, - 255, // this is 0 on PC which results in no shadow - red, 0, 0, - 4.0f, 1.0f, 40.0f, false, 0.0f); - CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - } - - entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400)); -} - -void -CPickups::DoMoneyEffects(CEntity *entity) -{ - CVector &pos = entity->GetPosition(); - float dist = (TheCamera.GetPosition() - pos).Magnitude(); - const float MAXDIST = 20.0f; - - if (dist < MAXDIST) { - float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400)); - - int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f; - CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, - 2.0f, 0.0f, 0.0f, -2.0f, - 255, // this is 0 on PC which results in no shadow - 0, green, 0, - 4.0f, 1.0f, 40.0f, false, 0.0f); - CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - } - - entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800)); -} - -void -CPickups::DoCollectableEffects(CEntity *entity) -{ - CVector &pos = entity->GetPosition(); - float dist = (TheCamera.GetPosition() - pos).Magnitude(); - const float MAXDIST = 14.0f; - - if (dist < MAXDIST) { - float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); - - int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f; - CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, - 2.0f, 0.0f, 0.0f, -2.0f, - 255, // this is 0 on PC which results in no shadow - color, color, color, - 4.0f, 1.0f, 40.0f, false, 0.0f); - CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - } - - entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000)); -} - -void -CPickups::RenderPickUpText() -{ - wchar *strToPrint; - for (int32 i = 0; i < NumMessages; i++) { - if (aMessages[i].m_quantity <= 39) { - switch (aMessages[i].m_quantity) // could use some enum maybe - { - case 0: - if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code? - // what is this?? - sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903); - } else { - if (aMessages[i].m_bOutOfStock) - strToPrint = TheText.Get("STOCK"); - else { - sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]); - AsciiToUnicode(gString, gUString); - strToPrint = gUString; - } - } - break; - case 1: - strToPrint = TheText.Get("SECURI"); - break; - case 2: - strToPrint = TheText.Get("MOONBM"); - break; - case 3: - strToPrint = TheText.Get("COACH"); - break; - case 4: - strToPrint = TheText.Get("FLATBED"); - break; - case 5: - strToPrint = TheText.Get("LINERUN"); - break; - case 6: - strToPrint = TheText.Get("TRASHM"); - break; - case 7: - strToPrint = TheText.Get("PATRIOT"); - break; - case 8: - strToPrint = TheText.Get("WHOOPEE"); - break; - case 9: - strToPrint = TheText.Get("BLISTA"); - break; - case 10: - strToPrint = TheText.Get("MULE"); - break; - case 11: - strToPrint = TheText.Get("YANKEE"); - break; - case 12: - strToPrint = TheText.Get("BOBCAT"); - break; - case 13: - strToPrint = TheText.Get("DODO"); - break; - case 14: - strToPrint = TheText.Get("BUS"); - break; - case 15: - strToPrint = TheText.Get("RUMPO"); - break; - case 16: - strToPrint = TheText.Get("PONY"); - break; - case 17: - strToPrint = TheText.Get("SENTINL"); - break; - case 18: - strToPrint = TheText.Get("CHEETAH"); - break; - case 19: - strToPrint = TheText.Get("BANSHEE"); - break; - case 20: - strToPrint = TheText.Get("IDAHO"); - break; - case 21: - strToPrint = TheText.Get("INFERNS"); - break; - case 22: - strToPrint = TheText.Get("TAXI"); - break; - case 23: - strToPrint = TheText.Get("KURUMA"); - break; - case 24: - strToPrint = TheText.Get("STRETCH"); - break; - case 25: - strToPrint = TheText.Get("PEREN"); - break; - case 26: - strToPrint = TheText.Get("STINGER"); - break; - case 27: - strToPrint = TheText.Get("MANANA"); - break; - case 28: - strToPrint = TheText.Get("LANDSTK"); - break; - case 29: - strToPrint = TheText.Get("STALION"); - break; - case 30: - strToPrint = TheText.Get("BFINJC"); - break; - case 31: - strToPrint = TheText.Get("CABBIE"); - break; - case 32: - strToPrint = TheText.Get("ESPERAN"); - break; - case 33: - strToPrint = TheText.Get("FIRETRK"); - break; - case 34: - strToPrint = TheText.Get("AMBULAN"); - break; - case 35: - strToPrint = TheText.Get("ENFORCR"); - break; - case 36: - strToPrint = TheText.Get("FBICAR"); - break; - case 37: - strToPrint = TheText.Get("RHINO"); - break; - case 38: - strToPrint = TheText.Get("BARRCKS"); - break; - case 39: - strToPrint = TheText.Get("POLICAR"); - break; - default: - break; - } - } - CFont::SetPropOn(); - CFont::SetBackgroundOff(); - - const float MAX_SCALE = 1.0f; - - float fScaleY = aMessages[i].m_dist.y / 100.0f; - if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE; - - float fScaleX = aMessages[i].m_dist.x / 100.0f; - if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE; - - CFont::SetScale(fScaleX, fScaleY); - CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_WIDTH); - CFont::SetJustifyOff(); - - CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha)); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_BANK); - CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint); - } - NumMessages = 0; -} - -void -CPickups::Load(uint8 *buf, uint32 size) -{ -INITSAVEBUF - - for (int32 i = 0; i < NUMPICKUPS; i++) { - aPickUps[i] = ReadSaveBuf(buf); - - if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil) - aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1); - } - - CollectedPickUpIndex = ReadSaveBuf(buf); - ReadSaveBuf(buf); - NumMessages = 0; - - for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) - aPickUpsCollected[i] = ReadSaveBuf(buf); - -VALIDATESAVEBUF(size) -} - -void -CPickups::Save(uint8 *buf, uint32 *size) -{ - *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); - -INITSAVEBUF - - for (int32 i = 0; i < NUMPICKUPS; i++) { - CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); - if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil) - buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1); - } - - WriteSaveBuf(buf, CollectedPickUpIndex); - WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages - - for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) - WriteSaveBuf(buf, aPickUpsCollected[i]); - -VALIDATESAVEBUF(*size) -} - -STARTPATCHES - InjectHook(0x430220, CPickups::Init, PATCH_JUMP); - InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP); - InjectHook(0x432440, CPickups::RenderPickUpText, PATCH_JUMP); - InjectHook(0x431C30, CPickups::DoCollectableEffects, PATCH_JUMP); - InjectHook(0x431F40, CPickups::DoMoneyEffects, PATCH_JUMP); - InjectHook(0x4321C0, CPickups::DoMineEffects, PATCH_JUMP); - InjectHook(0x431520, CPickups::DoPickUpEffects, PATCH_JUMP); - InjectHook(0x4304B0, CPickups::GenerateNewOne, PATCH_JUMP); - InjectHook(0x430660, CPickups::GenerateNewOne_WeaponType, PATCH_JUMP); - InjectHook(0x4307A0, CPickups::RemovePickUp, PATCH_JUMP); - InjectHook(0x430800, CPickups::RemoveAllFloatingPickups, PATCH_JUMP); - InjectHook(0x433D60, CPickups::AddToCollectedPickupsArray, PATCH_JUMP); - InjectHook(0x430770, CPickups::IsPickUpPickedUp, PATCH_JUMP); - InjectHook(0x430690, CPickups::ModelForWeapon, PATCH_JUMP); - InjectHook(0x4306F0, CPickups::WeaponForModel, PATCH_JUMP); - InjectHook(0x431510, CPickups::FindColourIndexForWeaponMI, PATCH_JUMP);/**/ - InjectHook(0x433DF0, CPickups::GetActualPickupIndex, PATCH_JUMP); - InjectHook(0x433DB0, CPickups::GetNewUniquePickupIndex, PATCH_JUMP); - InjectHook(0x433B60, CPickups::PassTime, PATCH_JUMP); - InjectHook(0x4339F0, CPickups::GivePlayerGoodiesWithPickUpMI, PATCH_JUMP); - InjectHook(0x433F60, CPickups::Load, PATCH_JUMP); - InjectHook(0x433E40, CPickups::Save, PATCH_JUMP); - InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP); - InjectHook(0x430860, &CPickup::Update, PATCH_JUMP); -ENDPATCHES +#include "common.h" +#include "patcher.h" +#include "main.h" + +#include "Camera.h" +#include "Coronas.h" +#include "Darkel.h" +#include "Entity.h" +#include "Explosion.h" +#include "Font.h" +#include "Garages.h" +#include "General.h" +#include "ModelIndices.h" +#include "Object.h" +#include "Pad.h" +#include "Pickups.h" +#include "PlayerPed.h" +#include "Wanted.h" +#include "DMAudio.h" +#include "Fire.h" +#include "PointLights.h" +#include "Pools.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif +#include "Script.h" +#include "Shadows.h" +#include "SpecialFX.h" +#include "Sprite.h" +#include "Timer.h" +#include "WaterLevel.h" +#include "World.h" + +CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; +int16 CPickups::NumMessages;// = *(int16*)0x95CC98; +int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];// = *(int32(*)[NUMCOLLECTEDPICKUPS])*(uintptr*)0x87C538; +int16 CPickups::CollectedPickUpIndex;// = *(int16*)0x95CC8A; + +// unused +bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71; +CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8; +CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8; +uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C; + +tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES]; + +// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4) +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 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 }; + +WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); } +WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); } +WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); } +WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); } +WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); } +WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } +WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); } +WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); } +WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); } +WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); } +WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); } +WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); } +WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); } +WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); } +WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); } + + +void +CPickup::RemoveKeepType() +{ + CWorld::Remove(m_pObject); + delete m_pObject; + + m_bRemoved = true; + m_pObject = nil; +} + +void +CPickup::Remove() +{ + RemoveKeepType(); + m_eType = PICKUP_NONE; +} + +CObject * +CPickup::GiveUsAPickUpObject(int32 handle) +{ + CObject *object; + + if (handle <= 0) object = new CObject(m_eModelIndex, false); + else { + CPools::MakeSureSlotInObjectPoolIsEmpty(handle); + object = new(handle) CObject(m_eModelIndex, false); + } + + if (object == nil) return nil; + object->ObjectCreatedBy = MISSION_OBJECT; + object->GetPosition() = m_vecPos; + object->SetOrientation(0.0f, 0.0f, -HALFPI); + object->GetMatrix().UpdateRW(); + object->UpdateRwFrame(); + + object->bAffectedByGravity = false; + object->bExplosionProof = true; + object->bUsesCollision = false; + object->bIsPickup = true; + + object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0; + + switch (m_eType) + { + case PICKUP_IN_SHOP: + object->m_obj_flag2 = true; + object->bOutOfStock = false; + break; + case PICKUP_ON_STREET: + case PICKUP_ONCE: + case PICKUP_ONCE_TIMEOUT: + case PICKUP_COLLECTABLE1: + case PICKUP_MONEY: + case PICKUP_MINE_INACTIVE: + case PICKUP_MINE_ARMED: + case PICKUP_NAUTICAL_MINE_INACTIVE: + case PICKUP_NAUTICAL_MINE_ARMED: + case PICKUP_FLOATINGPACKAGE: + case PICKUP_ON_STREET_SLOW: + object->m_obj_flag2 = false; + object->bOutOfStock = false; + break; + case PICKUP_IN_SHOP_OUT_OF_STOCK: + object->m_obj_flag2 = false; + object->bOutOfStock = true; + object->bRenderScorched = true; + break; + case PICKUP_FLOATINGPACKAGE_FLOATING: + default: + break; + } + return object; +} + +bool +CPickup::CanBePickedUp(CPlayerPed *player) +{ + 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_BRIBE && player->m_pWanted->m_nWantedLevel == 0) + || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame)); + return !cannotBePickedUp; +} + +bool +CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) +{ + float waterLevel; + + if (m_bRemoved) { + if (CTimer::GetTimeInMilliseconds() > m_nTimer) { + // respawn pickup if we're far enough + float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y); + if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) { + m_pObject = GiveUsAPickUpObject(-1); + if (m_pObject) { + CWorld::Add(m_pObject); + m_bRemoved = false; + } + } + } + return false; + } + + if (!m_pObject) return false; + + if (!IsMine()) { + // let's check if we touched the pickup + bool isPickupTouched = false; + if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) { + if (vehicle != nil) { + if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) + isPickupTouched = true; + } + else { + if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) { + if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) + + (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f) + isPickupTouched = true; + } + } + } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) { + if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { + isPickupTouched = true; + } + } else if (vehicle == nil) { + if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) { + if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) + + (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f) + isPickupTouched = true; + } + } + + // if we didn't then we've got nothing to do + if (isPickupTouched && CanBePickedUp(player)) { + CPad::GetPad(0)->StartShake(120, 100); + switch (m_eType) + { + case PICKUP_IN_SHOP: + if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) { + CGarages::TriggerMessage("PU_MONY", -1, 6000, -1); + } else { + CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]; + if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { + player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]); + player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); + DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE); + } + RemoveKeepType(); + m_nTimer = CTimer::GetTimeInMilliseconds() + 5000; + return true; + } + break; + case PICKUP_ON_STREET: + case PICKUP_ON_STREET_SLOW: + if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { + if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) { + player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]); + if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) { + player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); + } + DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); + } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) { + DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); + CPickups::bPickUpcamActivated = true; + CPickups::pPlayerVehicle = FindPlayerVehicle(); + CPickups::StaticCamCoors = m_pObject->GetPosition(); + CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds(); + } + } + if (m_eType == PICKUP_ON_STREET) { + m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; + } else if (m_eType == PICKUP_ON_STREET_SLOW) { + if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex) + m_nTimer = CTimer::GetTimeInMilliseconds() + 300000; + else + m_nTimer = CTimer::GetTimeInMilliseconds() + 720000; + } + + RemoveKeepType(); + return true; + case PICKUP_ONCE: + case PICKUP_ONCE_TIMEOUT: + if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { + if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) { + player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]); + if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) + player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); + } + DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); + } + Remove(); + return true; + case PICKUP_COLLECTABLE1: + CWorld::Players[playerId].m_nCollectedPackages++; + CWorld::Players[playerId].m_nMoney += 1000; + + if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) { + printf("All collectables have been picked up\n"); + CGarages::TriggerMessage("CO_ALL", -1, 5000, -1); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000; + } else + CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); + + Remove(); + DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0); + return true; + case PICKUP_MONEY: + CWorld::Players[playerId].m_nMoney += m_nQuantity; + sprintf(gString, "$%d", m_nQuantity); +#ifdef MONEY_MESSAGES + CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f); +#endif + Remove(); + DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); + return true; + //case PICKUP_IN_SHOP_OUT_OF_STOCK: + //case PICKUP_MINE_INACTIVE: + //case PICKUP_MINE_ARMED: + //case PICKUP_NAUTICAL_MINE_INACTIVE: + //case PICKUP_NAUTICAL_MINE_ARMED: + //case PICKUP_FLOATINGPACKAGE: + //case PICKUP_FLOATINGPACKAGE_FLOATING: + default: + break; + } + } + } else { + switch (m_eType) + { + case PICKUP_MINE_INACTIVE: + if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { + m_eType = PICKUP_MINE_ARMED; + m_nTimer = CTimer::GetTimeInMilliseconds() + 10000; + } + break; + case PICKUP_NAUTICAL_MINE_INACTIVE: + { + if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) + m_pObject->GetPosition().z = waterLevel + 0.6f; + + m_pObject->GetMatrix().UpdateRW(); + m_pObject->UpdateRwFrame(); + + bool touched = false; + for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { + CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); + if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { + touched = true; + break; // added break here + } + } + + if (!touched) { + m_eType = PICKUP_NAUTICAL_MINE_ARMED; + m_nTimer = CTimer::GetTimeInMilliseconds() + 10000; + } + break; + } + case PICKUP_NAUTICAL_MINE_ARMED: + if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) + m_pObject->GetPosition().z = waterLevel + 0.6f; + + m_pObject->GetMatrix().UpdateRW(); + m_pObject->UpdateRwFrame(); + // no break here + case PICKUP_MINE_ARMED: + { + bool explode = false; + if (CTimer::GetTimeInMilliseconds() > m_nTimer) + explode = true; + else {// added else here since vehicle lookup is useless + for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { + CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); + if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { + explode = true; + break; // added break here + } + } + } + if (explode) { + CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0); + Remove(); + } + break; + } + case PICKUP_FLOATINGPACKAGE: + m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep(); + m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep(); + + m_pObject->GetMatrix().UpdateRW(); + m_pObject->UpdateRwFrame(); + if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z) + m_eType = PICKUP_FLOATINGPACKAGE_FLOATING; + break; + case PICKUP_FLOATINGPACKAGE_FLOATING: + if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0)) + m_pObject->GetPosition().z = waterLevel; + + m_pObject->GetMatrix().UpdateRW(); + m_pObject->UpdateRwFrame(); + if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { + Remove(); + DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0); + return true; + } + break; + } + } + if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer) + Remove(); + return false; +} + +void +CPickups::Init(void) +{ + NumMessages = 0; + for (int i = 0; i < NUMPICKUPS; i++) { + aPickUps[i].m_eType = PICKUP_NONE; + aPickUps[i].m_nIndex = 1; + aPickUps[i].m_pObject = nil; + } + + for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) + aPickUpsCollected[i] = 0; + + CollectedPickUpIndex = 0; +} + +bool +CPickups::IsPickUpPickedUp(int32 pickupId) +{ + for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) { + if (pickupId == aPickUpsCollected[i]) { + aPickUpsCollected[i] = 0; + return true; + } + } + return false; +} + +void +CPickups::PassTime(uint32 time) +{ + for (int i = 0; i < NUMPICKUPS; i++) { + if (aPickUps[i].m_eType != PICKUP_NONE) { + if (aPickUps[i].m_nTimer <= time) + aPickUps[i].m_nTimer = 0; + else + aPickUps[i].m_nTimer -= time; + } + } +} + +int32 +CPickups::GetActualPickupIndex(int32 index) +{ + if (index == -1) return -1; + + // doesn't look nice + if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1; + return (uint16)index; +} + +bool +CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex) +{ + CPlayerPed *player; + + if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed; + else player = CWorld::Players[playerIndex].m_pPed; + + if (modelIndex == MI_PICKUP_ADRENALINE) { + player->m_bAdrenalineActive = true; + player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000; + player->m_fCurrentStamina = player->m_fMaxStamina; + DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0); + return true; + } else if (modelIndex == MI_PICKUP_BODYARMOUR) { + player->m_fArmour = 100.0f; + 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; + DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0); + return true; + } else if (modelIndex == MI_PICKUP_BONUS) { + DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); + return true; + } else if (modelIndex == MI_PICKUP_BRIBE) { + int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1; + if (level < 0) level = 0; + player->SetWantedLevel(level); + DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); + return true; + } else if (modelIndex == MI_PICKUP_KILLFRENZY) { + DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); + return true; + } + return false; +} + +void +CPickups::RemoveAllFloatingPickups() +{ + for (int i = 0; i < NUMPICKUPS; i++) { + if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) { + if (aPickUps[i].m_pObject) { + CWorld::Remove(aPickUps[i].m_pObject); + delete aPickUps[i].m_pObject; + aPickUps[i].m_pObject = nil; + } + } + } +} + +void +CPickups::RemovePickUp(int32 pickupIndex) +{ + int32 index = CPickups::GetActualPickupIndex(pickupIndex); + if (index == -1) return; + + if (aPickUps[index].m_pObject) { + CWorld::Remove(aPickUps[index].m_pObject); + delete aPickUps[index].m_pObject; + aPickUps[index].m_pObject = nil; + } + aPickUps[index].m_eType = PICKUP_NONE; + aPickUps[index].m_bRemoved = true; +} + +int32 +CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity) +{ + bool bFreeFound = false; + int32 slot = 0; + + if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) { + for (slot = NUMPICKUPS; slot >= 0; slot--) { + if (aPickUps[slot].m_eType == PICKUP_NONE) { + bFreeFound = true; + break; + } + } + } else { + for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { + if (aPickUps[slot].m_eType == PICKUP_NONE) { + bFreeFound = true; + break; + } + } + } + + if (!bFreeFound) + { + for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { + if (aPickUps[slot].m_eType == PICKUP_MONEY) break; + } + + if (slot >= NUMGENERALPICKUPS) + { + for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { + if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break; + } + + if (slot >= NUMGENERALPICKUPS) return -1; + } + } + + if (slot >= NUMPICKUPS) return -1; + + aPickUps[slot].m_eType = (ePickupType)type; + aPickUps[slot].m_bRemoved = false; + aPickUps[slot].m_nQuantity = quantity; + if (type == PICKUP_ONCE_TIMEOUT) + aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000; + else if (type == PICKUP_MONEY) + aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; + else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) { + aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE; + aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500; + } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) { + aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE; + aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500; + } + aPickUps[slot].m_eModelIndex = modelIndex; + aPickUps[slot].m_vecPos = pos; + aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1); + if (aPickUps[slot].m_pObject) + CWorld::Add(aPickUps[slot].m_pObject); + return GetNewUniquePickupIndex(slot); +} + +int32 +CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity) +{ + return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity); +} + +int32 +CPickups::GetNewUniquePickupIndex(int32 slot) +{ + if (aPickUps[slot].m_nIndex >= 0xFFFE) + aPickUps[slot].m_nIndex = 1; + else + aPickUps[slot].m_nIndex++; + return slot | (aPickUps[slot].m_nIndex << 16); +} + +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; + } + return 0; +} + +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; +} + +void +CPickups::AddToCollectedPickupsArray(int32 index) +{ + aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16); + if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS) + CollectedPickUpIndex = 0; +} + +void +CPickups::Update() +{ +#ifdef FIX_BUGS // RIP speedrunning (solution from SA) + if (CReplay::IsPlayingBack()) + return; +#endif +#define PICKUPS_FRAME_SPAN (6) +#ifdef FIX_BUGS + for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) { +#else // BUG: this code can only reach 318 out of 320 pickups + for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) { +#endif + if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { + AddToCollectedPickupsArray(i); + } + } +#undef PICKUPS_FRAME_SPAN + for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) { + if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { + AddToCollectedPickupsArray(i); + } + } +} + +void +CPickups::DoPickUpEffects(CEntity *entity) +{ + if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) + entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame; + + if (!entity->m_flagD80) { + float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); + float modifiedSin = 0.3f * (s + 1.0f); + + + int16 colorId; + + if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) + colorId = 11; + else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE) + colorId = 12; + else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) + colorId = 13; + else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) + colorId = 14; + else + colorId = FindColourIndexForWeaponMI(entity->GetModelIndex()); + + assert(colorId >= 0); + + CVector &pos = entity->GetPosition(); + + float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f; + CShadows::StoreStaticShadow( + (uintptr)entity, + SHADOWTYPE_ADDITIVE, + gpShadowExplosionTex, + &pos, + 2.0f, 0.0f, 0.0f, -2.0f, + 255, // this is 0 on PC which results in no shadow + aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier, + 4.0f, 1.0f, 40.0f, false, 0.0f); + + float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f; + CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true); + float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f; + CCoronas::RegisterCorona( (uintptr)entity, + aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f, + 255, + pos, + size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + + CObject *object = (CObject*)entity; + if (object->m_obj_flag2 || object->bOutOfStock || object->field_172) { + float dist = (TheCamera.GetPosition() - pos).Magnitude(); + const float MAXDIST = 12.0f; + + if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) { + RwV3d vecOut; + float fDistX, fDistY; + if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) { + aMessages[NumMessages].m_pos.x = vecOut.x; + aMessages[NumMessages].m_pos.y = vecOut.y; + aMessages[NumMessages].m_dist.x = fDistX; + aMessages[NumMessages].m_dist.y = fDistY; + aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex()); + aMessages[NumMessages].m_color.red = aWeaponReds[colorId]; + aMessages[NumMessages].m_color.green = aWeaponGreens[colorId]; + aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId]; + aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f; + aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock; + aMessages[NumMessages].m_quantity = object->field_172; + NumMessages++; + } + } + } + + entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]); + } +} + +void +CPickups::DoMineEffects(CEntity *entity) +{ + CVector &pos = entity->GetPosition(); + float dist = (TheCamera.GetPosition() - pos).Magnitude(); + const float MAXDIST = 20.0f; + + if (dist < MAXDIST) { + float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200)); + + int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f; + CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, + 2.0f, 0.0f, 0.0f, -2.0f, + 255, // this is 0 on PC which results in no shadow + red, 0, 0, + 4.0f, 1.0f, 40.0f, false, 0.0f); + CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + } + + entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400)); +} + +void +CPickups::DoMoneyEffects(CEntity *entity) +{ + CVector &pos = entity->GetPosition(); + float dist = (TheCamera.GetPosition() - pos).Magnitude(); + const float MAXDIST = 20.0f; + + if (dist < MAXDIST) { + float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400)); + + int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f; + CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, + 2.0f, 0.0f, 0.0f, -2.0f, + 255, // this is 0 on PC which results in no shadow + 0, green, 0, + 4.0f, 1.0f, 40.0f, false, 0.0f); + CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + } + + entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800)); +} + +void +CPickups::DoCollectableEffects(CEntity *entity) +{ + CVector &pos = entity->GetPosition(); + float dist = (TheCamera.GetPosition() - pos).Magnitude(); + const float MAXDIST = 14.0f; + + if (dist < MAXDIST) { + float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); + + int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f; + CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, + 2.0f, 0.0f, 0.0f, -2.0f, + 255, // this is 0 on PC which results in no shadow + color, color, color, + 4.0f, 1.0f, 40.0f, false, 0.0f); + CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + } + + entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000)); +} + +void +CPickups::RenderPickUpText() +{ + wchar *strToPrint; + for (int32 i = 0; i < NumMessages; i++) { + if (aMessages[i].m_quantity <= 39) { + switch (aMessages[i].m_quantity) // could use some enum maybe + { + case 0: + if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code? + // what is this?? + sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903); + } else { + if (aMessages[i].m_bOutOfStock) + strToPrint = TheText.Get("STOCK"); + else { + sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]); + AsciiToUnicode(gString, gUString); + strToPrint = gUString; + } + } + break; + case 1: + strToPrint = TheText.Get("SECURI"); + break; + case 2: + strToPrint = TheText.Get("MOONBM"); + break; + case 3: + strToPrint = TheText.Get("COACH"); + break; + case 4: + strToPrint = TheText.Get("FLATBED"); + break; + case 5: + strToPrint = TheText.Get("LINERUN"); + break; + case 6: + strToPrint = TheText.Get("TRASHM"); + break; + case 7: + strToPrint = TheText.Get("PATRIOT"); + break; + case 8: + strToPrint = TheText.Get("WHOOPEE"); + break; + case 9: + strToPrint = TheText.Get("BLISTA"); + break; + case 10: + strToPrint = TheText.Get("MULE"); + break; + case 11: + strToPrint = TheText.Get("YANKEE"); + break; + case 12: + strToPrint = TheText.Get("BOBCAT"); + break; + case 13: + strToPrint = TheText.Get("DODO"); + break; + case 14: + strToPrint = TheText.Get("BUS"); + break; + case 15: + strToPrint = TheText.Get("RUMPO"); + break; + case 16: + strToPrint = TheText.Get("PONY"); + break; + case 17: + strToPrint = TheText.Get("SENTINL"); + break; + case 18: + strToPrint = TheText.Get("CHEETAH"); + break; + case 19: + strToPrint = TheText.Get("BANSHEE"); + break; + case 20: + strToPrint = TheText.Get("IDAHO"); + break; + case 21: + strToPrint = TheText.Get("INFERNS"); + break; + case 22: + strToPrint = TheText.Get("TAXI"); + break; + case 23: + strToPrint = TheText.Get("KURUMA"); + break; + case 24: + strToPrint = TheText.Get("STRETCH"); + break; + case 25: + strToPrint = TheText.Get("PEREN"); + break; + case 26: + strToPrint = TheText.Get("STINGER"); + break; + case 27: + strToPrint = TheText.Get("MANANA"); + break; + case 28: + strToPrint = TheText.Get("LANDSTK"); + break; + case 29: + strToPrint = TheText.Get("STALION"); + break; + case 30: + strToPrint = TheText.Get("BFINJC"); + break; + case 31: + strToPrint = TheText.Get("CABBIE"); + break; + case 32: + strToPrint = TheText.Get("ESPERAN"); + break; + case 33: + strToPrint = TheText.Get("FIRETRK"); + break; + case 34: + strToPrint = TheText.Get("AMBULAN"); + break; + case 35: + strToPrint = TheText.Get("ENFORCR"); + break; + case 36: + strToPrint = TheText.Get("FBICAR"); + break; + case 37: + strToPrint = TheText.Get("RHINO"); + break; + case 38: + strToPrint = TheText.Get("BARRCKS"); + break; + case 39: + strToPrint = TheText.Get("POLICAR"); + break; + default: + break; + } + } + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + + const float MAX_SCALE = 1.0f; + + float fScaleY = aMessages[i].m_dist.y / 100.0f; + if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE; + + float fScaleX = aMessages[i].m_dist.x / 100.0f; + if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE; + + CFont::SetScale(fScaleX, fScaleY); + CFont::SetCentreOn(); + CFont::SetCentreSize(SCREEN_WIDTH); + CFont::SetJustifyOff(); + + CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha)); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_BANK); + CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint); + } + NumMessages = 0; +} + +void +CPickups::Load(uint8 *buf, uint32 size) +{ +INITSAVEBUF + + for (int32 i = 0; i < NUMPICKUPS; i++) { + aPickUps[i] = ReadSaveBuf(buf); + + if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil) + aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1); + } + + CollectedPickUpIndex = ReadSaveBuf(buf); + ReadSaveBuf(buf); + NumMessages = 0; + + for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) + aPickUpsCollected[i] = ReadSaveBuf(buf); + +VALIDATESAVEBUF(size) +} + +void +CPickups::Save(uint8 *buf, uint32 *size) +{ + *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); + +INITSAVEBUF + + for (int32 i = 0; i < NUMPICKUPS; i++) { + CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); + if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil) + buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1); + } + + WriteSaveBuf(buf, CollectedPickUpIndex); + WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages + + for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) + WriteSaveBuf(buf, aPickUpsCollected[i]); + +VALIDATESAVEBUF(*size) +} + +STARTPATCHES + InjectHook(0x430220, CPickups::Init, PATCH_JUMP); + InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP); + InjectHook(0x432440, CPickups::RenderPickUpText, PATCH_JUMP); + InjectHook(0x431C30, CPickups::DoCollectableEffects, PATCH_JUMP); + InjectHook(0x431F40, CPickups::DoMoneyEffects, PATCH_JUMP); + InjectHook(0x4321C0, CPickups::DoMineEffects, PATCH_JUMP); + InjectHook(0x431520, CPickups::DoPickUpEffects, PATCH_JUMP); + InjectHook(0x4304B0, CPickups::GenerateNewOne, PATCH_JUMP); + InjectHook(0x430660, CPickups::GenerateNewOne_WeaponType, PATCH_JUMP); + InjectHook(0x4307A0, CPickups::RemovePickUp, PATCH_JUMP); + InjectHook(0x430800, CPickups::RemoveAllFloatingPickups, PATCH_JUMP); + InjectHook(0x433D60, CPickups::AddToCollectedPickupsArray, PATCH_JUMP); + InjectHook(0x430770, CPickups::IsPickUpPickedUp, PATCH_JUMP); + InjectHook(0x430690, CPickups::ModelForWeapon, PATCH_JUMP); + InjectHook(0x4306F0, CPickups::WeaponForModel, PATCH_JUMP); + InjectHook(0x431510, CPickups::FindColourIndexForWeaponMI, PATCH_JUMP);/**/ + InjectHook(0x433DF0, CPickups::GetActualPickupIndex, PATCH_JUMP); + InjectHook(0x433DB0, CPickups::GetNewUniquePickupIndex, PATCH_JUMP); + InjectHook(0x433B60, CPickups::PassTime, PATCH_JUMP); + InjectHook(0x4339F0, CPickups::GivePlayerGoodiesWithPickUpMI, PATCH_JUMP); + InjectHook(0x433F60, CPickups::Load, PATCH_JUMP); + InjectHook(0x433E40, CPickups::Save, PATCH_JUMP); + InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP); + InjectHook(0x430860, &CPickup::Update, PATCH_JUMP); +ENDPATCHES diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 4bb0ddff..3e075b24 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -1,124 +1,124 @@ -#pragma once -#include "Weapon.h" - -enum ePickupType : uint8 -{ - PICKUP_NONE = 0, - PICKUP_IN_SHOP, - PICKUP_ON_STREET, - PICKUP_ONCE, - PICKUP_ONCE_TIMEOUT, - PICKUP_COLLECTABLE1, - PICKUP_IN_SHOP_OUT_OF_STOCK, - PICKUP_MONEY, - PICKUP_MINE_INACTIVE, - PICKUP_MINE_ARMED, - PICKUP_NAUTICAL_MINE_INACTIVE, - PICKUP_NAUTICAL_MINE_ARMED, - PICKUP_FLOATINGPACKAGE, - PICKUP_FLOATINGPACKAGE_FLOATING, - PICKUP_ON_STREET_SLOW, - PICKUP_NUMOFTYPES -}; - -class CEntity; -class CObject; -class CVehicle; -class CPlayerPed; - -class CPickup -{ -public: - ePickupType m_eType; - bool m_bRemoved; - uint16 m_nQuantity; - CObject *m_pObject; - uint32 m_nTimer; - int16 m_eModelIndex; - uint16 m_nIndex; - CVector m_vecPos; - - CObject *GiveUsAPickUpObject(int32 handle); - 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); - void RemoveKeepType(); - void Remove(); -}; - -static_assert(sizeof(CPickup) == 0x1C, "CPickup: error"); - -struct tPickupMessage -{ - CVector2D m_pos; - eWeaponType m_weaponType; - CVector2D m_dist; - CRGBA m_color; - uint8 m_bOutOfStock : 1; - uint8 m_quantity; -}; - -class CPickups -{ - static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS]; - static int16 CollectedPickUpIndex; - static int16 NumMessages; - static tPickupMessage aMessages[NUMPICKUPMESSAGES]; -public: - static void Init(); - static void Update(); - static void RenderPickUpText(); - static void DoCollectableEffects(CEntity *ent); - static void DoMoneyEffects(CEntity *ent); - static void DoMineEffects(CEntity *ent); - static void DoPickUpEffects(CEntity *ent); - static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity); - static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity); - static void RemovePickUp(int32 pickupIndex); - static void RemoveAllFloatingPickups(); - static void AddToCollectedPickupsArray(int32 index); - 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 void Load(uint8 *buf, uint32 size); - static void Save(uint8 *buf, uint32 *size); - - static CPickup(&aPickUps)[NUMPICKUPS]; - - // unused - static bool &bPickUpcamActivated; - static CVehicle *&pPlayerVehicle; - static CVector &StaticCamCoors; - static uint32 &StaticCamStartTime; -}; - -extern uint16 AmmoForWeapon[20]; -extern uint16 AmmoForWeapon_OnStreet[20]; -extern uint16 CostOfWeapon[20]; - -class CPacManPickups -{ -public: - static void Init(void); - static void Update(void); - static void GeneratePMPickUps(CVector, float, int16, uint8); - static void GeneratePMPickUpsForRace(int32); - static void GenerateOnePMPickUp(CVector); - static void Render(void); - static void DoCleanUpPacManStuff(void); - static void StartPacManRace(int32); - static void StartPacManRecord(void); - static uint32 QueryPowerPillsEatenInRace(void); - static void ResetPowerPillsEatenInRace(void); - static void CleanUpPacManStuff(void); - static void StartPacManScramble(CVector, float, int16); - static uint32 QueryPowerPillsCarriedByPlayer(void); - static void ResetPowerPillsCarriedByPlayer(void); - -}; +#pragma once +#include "Weapon.h" + +enum ePickupType : uint8 +{ + PICKUP_NONE = 0, + PICKUP_IN_SHOP, + PICKUP_ON_STREET, + PICKUP_ONCE, + PICKUP_ONCE_TIMEOUT, + PICKUP_COLLECTABLE1, + PICKUP_IN_SHOP_OUT_OF_STOCK, + PICKUP_MONEY, + PICKUP_MINE_INACTIVE, + PICKUP_MINE_ARMED, + PICKUP_NAUTICAL_MINE_INACTIVE, + PICKUP_NAUTICAL_MINE_ARMED, + PICKUP_FLOATINGPACKAGE, + PICKUP_FLOATINGPACKAGE_FLOATING, + PICKUP_ON_STREET_SLOW, + PICKUP_NUMOFTYPES +}; + +class CEntity; +class CObject; +class CVehicle; +class CPlayerPed; + +class CPickup +{ +public: + ePickupType m_eType; + bool m_bRemoved; + uint16 m_nQuantity; + CObject *m_pObject; + uint32 m_nTimer; + int16 m_eModelIndex; + uint16 m_nIndex; + CVector m_vecPos; + + CObject *GiveUsAPickUpObject(int32 handle); + 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); + void RemoveKeepType(); + void Remove(); +}; + +static_assert(sizeof(CPickup) == 0x1C, "CPickup: error"); + +struct tPickupMessage +{ + CVector2D m_pos; + eWeaponType m_weaponType; + CVector2D m_dist; + CRGBA m_color; + uint8 m_bOutOfStock : 1; + uint8 m_quantity; +}; + +class CPickups +{ + static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS]; + static int16 CollectedPickUpIndex; + static int16 NumMessages; + static tPickupMessage aMessages[NUMPICKUPMESSAGES]; +public: + static void Init(); + static void Update(); + static void RenderPickUpText(); + static void DoCollectableEffects(CEntity *ent); + static void DoMoneyEffects(CEntity *ent); + static void DoMineEffects(CEntity *ent); + static void DoPickUpEffects(CEntity *ent); + static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity); + static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity); + static void RemovePickUp(int32 pickupIndex); + static void RemoveAllFloatingPickups(); + static void AddToCollectedPickupsArray(int32 index); + 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 void Load(uint8 *buf, uint32 size); + static void Save(uint8 *buf, uint32 *size); + + static CPickup(&aPickUps)[NUMPICKUPS]; + + // unused + static bool &bPickUpcamActivated; + static CVehicle *&pPlayerVehicle; + static CVector &StaticCamCoors; + static uint32 &StaticCamStartTime; +}; + +extern uint16 AmmoForWeapon[20]; +extern uint16 AmmoForWeapon_OnStreet[20]; +extern uint16 CostOfWeapon[20]; + +class CPacManPickups +{ +public: + static void Init(void); + static void Update(void); + static void GeneratePMPickUps(CVector, float, int16, uint8); + static void GeneratePMPickUpsForRace(int32); + static void GenerateOnePMPickUp(CVector); + static void Render(void); + static void DoCleanUpPacManStuff(void); + static void StartPacManRace(int32); + static void StartPacManRecord(void); + static uint32 QueryPowerPillsEatenInRace(void); + static void ResetPowerPillsEatenInRace(void); + static void CleanUpPacManStuff(void); + static void StartPacManScramble(CVector, float, int16); + static uint32 QueryPowerPillsCarriedByPlayer(void); + static void ResetPowerPillsCarriedByPlayer(void); + +}; diff --git a/src/control/PowerPoints.cpp b/src/control/PowerPoints.cpp index 4bc773a9..9a74e8d9 100644 --- a/src/control/PowerPoints.cpp +++ b/src/control/PowerPoints.cpp @@ -1,22 +1,22 @@ -#include "common.h" -#include "PowerPoints.h" - -// Some cut beta feature - -void CPowerPoint::Update() -{} - -void CPowerPoints::Init() -{} - -void CPowerPoints::Update() -{} - -void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8) -{} - -void CPowerPoints::Save(uint8**, uint32*) -{} - -void CPowerPoints::Load(uint8*, uint32) +#include "common.h" +#include "PowerPoints.h" + +// Some cut beta feature + +void CPowerPoint::Update() +{} + +void CPowerPoints::Init() +{} + +void CPowerPoints::Update() +{} + +void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8) +{} + +void CPowerPoints::Save(uint8**, uint32*) +{} + +void CPowerPoints::Load(uint8*, uint32) {} \ No newline at end of file diff --git a/src/control/PowerPoints.h b/src/control/PowerPoints.h index d7478076..ee3750cd 100644 --- a/src/control/PowerPoints.h +++ b/src/control/PowerPoints.h @@ -1,26 +1,26 @@ -#pragma once - -enum -{ - POWERPOINT_NONE = 0, - POWERPOINT_HEALTH, - POWERPOINT_HIDEOUT_INDUSTRIAL, - POWERPOINT_HIDEOUT_COMMERCIAL, - POWERPOINT_HIDEOUT_SUBURBAN -}; - -class CPowerPoint -{ -public: - void Update(); -}; - -class CPowerPoints -{ -public: - static void Init(); - static void Update(); - static void GenerateNewOne(float, float, float, float, float, float, uint8); - static void Save(uint8**, uint32*); - static void Load(uint8*, uint32); +#pragma once + +enum +{ + POWERPOINT_NONE = 0, + POWERPOINT_HEALTH, + POWERPOINT_HIDEOUT_INDUSTRIAL, + POWERPOINT_HIDEOUT_COMMERCIAL, + POWERPOINT_HIDEOUT_SUBURBAN +}; + +class CPowerPoint +{ +public: + void Update(); +}; + +class CPowerPoints +{ +public: + static void Init(); + static void Update(); + static void GenerateNewOne(float, float, float, float, float, float, uint8); + static void Save(uint8**, uint32*); + static void Load(uint8*, uint32); }; \ No newline at end of file diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 8e983555..788a054a 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -21,234 +21,234 @@ CVector(&CRestart::PoliceRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_R float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20; uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44; -void -CRestart::Initialise() -{ - OverridePoliceStationLevel = LEVEL_NONE; - OverrideHospitalLevel = LEVEL_NONE; - bFadeInAfterNextArrest = true; - bFadeInAfterNextDeath = true; - OverrideHeading = 0.0f; - OverridePosition = CVector(0.0f, 0.0f, 0.0f); - bOverrideRestart = false; - NumberOfPoliceRestarts = 0; - NumberOfHospitalRestarts = 0; - - for (int i = 0; i < NUM_RESTART_POINTS; i++) { - HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); - HospitalRestartHeadings[i] = 0.0f; - PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); - PoliceRestartHeadings[i] = 0.0f; - } +void +CRestart::Initialise() +{ + OverridePoliceStationLevel = LEVEL_NONE; + OverrideHospitalLevel = LEVEL_NONE; + bFadeInAfterNextArrest = true; + bFadeInAfterNextDeath = true; + OverrideHeading = 0.0f; + OverridePosition = CVector(0.0f, 0.0f, 0.0f); + bOverrideRestart = false; + NumberOfPoliceRestarts = 0; + NumberOfHospitalRestarts = 0; + + for (int i = 0; i < NUM_RESTART_POINTS; i++) { + HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); + HospitalRestartHeadings[i] = 0.0f; + PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); + PoliceRestartHeadings[i] = 0.0f; + } +} + +void +CRestart::AddHospitalRestartPoint(const CVector &pos, float heading) +{ + HospitalRestartPoints[NumberOfHospitalRestarts] = pos; + HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading; +} + +void +CRestart::AddPoliceRestartPoint(const CVector &pos, float heading) +{ + PoliceRestartPoints[NumberOfPoliceRestarts] = pos; + PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading; +} + +void +CRestart::OverrideNextRestart(const CVector &pos, float heading) +{ + bOverrideRestart = true; + OverridePosition = pos; + OverrideHeading = heading; } -void -CRestart::AddHospitalRestartPoint(const CVector &pos, float heading) -{ - HospitalRestartPoints[NumberOfHospitalRestarts] = pos; - HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading; +void +CRestart::CancelOverrideRestart() +{ + bOverrideRestart = false; } -void -CRestart::AddPoliceRestartPoint(const CVector &pos, float heading) -{ - PoliceRestartPoints[NumberOfPoliceRestarts] = pos; - PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading; +void +CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) +{ + if (bOverrideRestart) { + *outPos = OverridePosition; + *outHeading = OverrideHeading; + CancelOverrideRestart(); + return; + } + + eLevelName curlevel = CTheZones::FindZoneForPoint(pos); + float fMinDist = 16000000.0f; + int closestPoint = NUM_RESTART_POINTS; + + // find closest point on this level + for (int i = 0; i < NumberOfHospitalRestarts; i++) { + if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) { + float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); + if (fMinDist >= dist) { + fMinDist = dist; + closestPoint = i; + } + } + } + + // if we didn't find anything, find closest point on any level + if (closestPoint == NUM_RESTART_POINTS) { + for (int i = 0; i < NumberOfHospitalRestarts; i++) { + float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); + if (fMinDist >= dist) { + fMinDist = dist; + closestPoint = i; + } + } + } + + // if we still didn't find anything, find closest path node + if (closestPoint == NUM_RESTART_POINTS) { + *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; + *outHeading = 0.0f; + printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z); + } else { + *outPos = HospitalRestartPoints[closestPoint]; + *outHeading = HospitalRestartHeadings[closestPoint]; + } } -void -CRestart::OverrideNextRestart(const CVector &pos, float heading) -{ - bOverrideRestart = true; - OverridePosition = pos; - OverrideHeading = heading; +void +CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) +{ + if (bOverrideRestart) { + *outPos = OverridePosition; + *outHeading = OverrideHeading; + CancelOverrideRestart(); + return; + } + + eLevelName curlevel = CTheZones::FindZoneForPoint(pos); + float fMinDist = 16000000.0f; + int closestPoint = NUM_RESTART_POINTS; + + // find closest point on this level + for (int i = 0; i < NumberOfPoliceRestarts; i++) { + if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) { + float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); + if (fMinDist >= dist) { + fMinDist = dist; + closestPoint = i; + } + } + } + + // if we didn't find anything, find closest point on any level + if (closestPoint == NUM_RESTART_POINTS) { + for (int i = 0; i < NumberOfPoliceRestarts; i++) { + float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); + if (fMinDist >= dist) { + fMinDist = dist; + closestPoint = i; + } + } + } + + // if we still didn't find anything, find closest path node + if (closestPoint == NUM_RESTART_POINTS) { + printf("Couldn't find a police restart zone near the player\n"); + *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; + *outHeading = 0.0f; + } else { + *outPos = PoliceRestartPoints[closestPoint]; + *outHeading = PoliceRestartHeadings[closestPoint]; + } } -void -CRestart::CancelOverrideRestart() -{ - bOverrideRestart = false; +void +CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size) +{ + Initialise(); + +INITSAVEBUF + CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE); + + for (int i = 0; i < NUM_RESTART_POINTS; i++) { + HospitalRestartPoints[i] = ReadSaveBuf(buf); + HospitalRestartHeadings[i] = ReadSaveBuf(buf); + } + + for (int i = 0; i < NUM_RESTART_POINTS; i++) { + PoliceRestartPoints[i] = ReadSaveBuf(buf); + PoliceRestartHeadings[i] = ReadSaveBuf(buf); + } + + NumberOfHospitalRestarts = ReadSaveBuf(buf); + NumberOfPoliceRestarts = ReadSaveBuf(buf); + bOverrideRestart = ReadSaveBuf(buf); + + // skip something unused + ReadSaveBuf(buf); + ReadSaveBuf(buf); + + OverridePosition = ReadSaveBuf(buf); + OverrideHeading = ReadSaveBuf(buf); + bFadeInAfterNextDeath = ReadSaveBuf(buf); + bFadeInAfterNextArrest = ReadSaveBuf(buf); + OverrideHospitalLevel = ReadSaveBuf(buf); + OverridePoliceStationLevel = ReadSaveBuf(buf); +VALIDATESAVEBUF(size); } -void -CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) -{ - if (bOverrideRestart) { - *outPos = OverridePosition; - *outHeading = OverrideHeading; - CancelOverrideRestart(); - return; - } - - eLevelName curlevel = CTheZones::FindZoneForPoint(pos); - float fMinDist = 16000000.0f; - int closestPoint = NUM_RESTART_POINTS; - - // find closest point on this level - for (int i = 0; i < NumberOfHospitalRestarts; i++) { - if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) { - float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); - if (fMinDist >= dist) { - fMinDist = dist; - closestPoint = i; - } - } - } - - // if we didn't find anything, find closest point on any level - if (closestPoint == NUM_RESTART_POINTS) { - for (int i = 0; i < NumberOfHospitalRestarts; i++) { - float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); - if (fMinDist >= dist) { - fMinDist = dist; - closestPoint = i; - } - } - } - - // if we still didn't find anything, find closest path node - if (closestPoint == NUM_RESTART_POINTS) { - *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; - *outHeading = 0.0f; - printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z); - } else { - *outPos = HospitalRestartPoints[closestPoint]; - *outHeading = HospitalRestartHeadings[closestPoint]; - } +void +CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size) +{ + *size = SAVE_HEADER_SIZE + + sizeof(HospitalRestartPoints) + + sizeof(HospitalRestartHeadings) + + sizeof(PoliceRestartPoints) + + sizeof(PoliceRestartHeadings) + + sizeof(NumberOfHospitalRestarts) + + sizeof(NumberOfPoliceRestarts) + + sizeof(bOverrideRestart) + + sizeof(uint8) + + sizeof(uint16) + + sizeof(OverridePosition) + + sizeof(OverrideHeading) + + sizeof(bFadeInAfterNextDeath) + + sizeof(bFadeInAfterNextArrest) + + sizeof(OverrideHospitalLevel) + + sizeof(OverridePoliceStationLevel); // == 292 + +INITSAVEBUF + WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE); + + for (int i = 0; i < NUM_RESTART_POINTS; i++) { + WriteSaveBuf(buf, HospitalRestartPoints[i]); + WriteSaveBuf(buf, HospitalRestartHeadings[i]); + } + + for (int i = 0; i < NUM_RESTART_POINTS; i++) { + WriteSaveBuf(buf, PoliceRestartPoints[i]); + WriteSaveBuf(buf, PoliceRestartHeadings[i]); + } + + WriteSaveBuf(buf, NumberOfHospitalRestarts); + WriteSaveBuf(buf, NumberOfPoliceRestarts); + WriteSaveBuf(buf, bOverrideRestart); + + WriteSaveBuf(buf, (uint8)0); + WriteSaveBuf(buf, (uint16)0); + + WriteSaveBuf(buf, OverridePosition); + WriteSaveBuf(buf, OverrideHeading); + WriteSaveBuf(buf, bFadeInAfterNextDeath); + WriteSaveBuf(buf, bFadeInAfterNextArrest); + WriteSaveBuf(buf, OverrideHospitalLevel); + WriteSaveBuf(buf, OverridePoliceStationLevel); +VALIDATESAVEBUF(*size); } -void -CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) -{ - if (bOverrideRestart) { - *outPos = OverridePosition; - *outHeading = OverrideHeading; - CancelOverrideRestart(); - return; - } - - eLevelName curlevel = CTheZones::FindZoneForPoint(pos); - float fMinDist = 16000000.0f; - int closestPoint = NUM_RESTART_POINTS; - - // find closest point on this level - for (int i = 0; i < NumberOfPoliceRestarts; i++) { - if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) { - float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); - if (fMinDist >= dist) { - fMinDist = dist; - closestPoint = i; - } - } - } - - // if we didn't find anything, find closest point on any level - if (closestPoint == NUM_RESTART_POINTS) { - for (int i = 0; i < NumberOfPoliceRestarts; i++) { - float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); - if (fMinDist >= dist) { - fMinDist = dist; - closestPoint = i; - } - } - } - - // if we still didn't find anything, find closest path node - if (closestPoint == NUM_RESTART_POINTS) { - printf("Couldn't find a police restart zone near the player\n"); - *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; - *outHeading = 0.0f; - } else { - *outPos = PoliceRestartPoints[closestPoint]; - *outHeading = PoliceRestartHeadings[closestPoint]; - } -} - -void -CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size) -{ - Initialise(); - -INITSAVEBUF - CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE); - - for (int i = 0; i < NUM_RESTART_POINTS; i++) { - HospitalRestartPoints[i] = ReadSaveBuf(buf); - HospitalRestartHeadings[i] = ReadSaveBuf(buf); - } - - for (int i = 0; i < NUM_RESTART_POINTS; i++) { - PoliceRestartPoints[i] = ReadSaveBuf(buf); - PoliceRestartHeadings[i] = ReadSaveBuf(buf); - } - - NumberOfHospitalRestarts = ReadSaveBuf(buf); - NumberOfPoliceRestarts = ReadSaveBuf(buf); - bOverrideRestart = ReadSaveBuf(buf); - - // skip something unused - ReadSaveBuf(buf); - ReadSaveBuf(buf); - - OverridePosition = ReadSaveBuf(buf); - OverrideHeading = ReadSaveBuf(buf); - bFadeInAfterNextDeath = ReadSaveBuf(buf); - bFadeInAfterNextArrest = ReadSaveBuf(buf); - OverrideHospitalLevel = ReadSaveBuf(buf); - OverridePoliceStationLevel = ReadSaveBuf(buf); -VALIDATESAVEBUF(size); -} - -void -CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size) -{ - *size = SAVE_HEADER_SIZE - + sizeof(HospitalRestartPoints) - + sizeof(HospitalRestartHeadings) - + sizeof(PoliceRestartPoints) - + sizeof(PoliceRestartHeadings) - + sizeof(NumberOfHospitalRestarts) - + sizeof(NumberOfPoliceRestarts) - + sizeof(bOverrideRestart) - + sizeof(uint8) - + sizeof(uint16) - + sizeof(OverridePosition) - + sizeof(OverrideHeading) - + sizeof(bFadeInAfterNextDeath) - + sizeof(bFadeInAfterNextArrest) - + sizeof(OverrideHospitalLevel) - + sizeof(OverridePoliceStationLevel); // == 292 - -INITSAVEBUF - WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE); - - for (int i = 0; i < NUM_RESTART_POINTS; i++) { - WriteSaveBuf(buf, HospitalRestartPoints[i]); - WriteSaveBuf(buf, HospitalRestartHeadings[i]); - } - - for (int i = 0; i < NUM_RESTART_POINTS; i++) { - WriteSaveBuf(buf, PoliceRestartPoints[i]); - WriteSaveBuf(buf, PoliceRestartHeadings[i]); - } - - WriteSaveBuf(buf, NumberOfHospitalRestarts); - WriteSaveBuf(buf, NumberOfPoliceRestarts); - WriteSaveBuf(buf, bOverrideRestart); - - WriteSaveBuf(buf, (uint8)0); - WriteSaveBuf(buf, (uint16)0); - - WriteSaveBuf(buf, OverridePosition); - WriteSaveBuf(buf, OverrideHeading); - WriteSaveBuf(buf, bFadeInAfterNextDeath); - WriteSaveBuf(buf, bFadeInAfterNextArrest); - WriteSaveBuf(buf, OverrideHospitalLevel); - WriteSaveBuf(buf, OverridePoliceStationLevel); -VALIDATESAVEBUF(*size); -} - - + STARTPATCHES InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP); InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP); @@ -258,5 +258,5 @@ STARTPATCHES InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP); InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP); InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP); - InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP); + InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP); ENDPATCHES \ No newline at end of file -- cgit v1.2.3 From 917fa80c18e83172040870d1a1cf613b51cf628c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 10 Apr 2020 11:03:38 +0300 Subject: record init --- src/control/Record.cpp | 178 ++++++++++++++++++++++++++++++++++++++++++++++++- src/control/Record.h | 36 +++++++++- 2 files changed, 210 insertions(+), 4 deletions(-) (limited to 'src/control') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 7c330311..7a3763be 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -2,12 +2,184 @@ #include "patcher.h" #include "Record.h" +#include "FileMgr.h" +#include "Pad.h" +#include "Pools.h" +#include "Timer.h" + uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24; +uint8*& CRecordDataForGame::pDataBuffer = *(uint8**)0x8F1B70; +uint8*& CRecordDataForGame::pDataBufferPointer = *(uint8**)0x8F1AB0; +int& CRecordDataForGame::FId = *(int*)0x885BA4; +tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0; uint8 &CRecordDataForChase::Status = *(uint8*)0x95CDCE; -WRAPPER void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4341F0); } -WRAPPER void CRecordDataForGame::Init(void) { EAXJMP(0x4340F0); } +#define MEMORY_FOR_GAME_RECORD (150000) + +void CRecordDataForGame::Init(void) +{ + RecordingState = STATE_NONE; + if (pDataBuffer) + delete[] pDataBuffer; + pDataBufferPointer = nil; + pDataBuffer = nil; +#ifndef GTA_PS2 // this stuff is not present on PS2 + FId = CFileMgr::OpenFile("playback.dat", "r"); + if (FId <= 0) { + if ((FId = CFileMgr::OpenFile("record.dat", "r")) <= 0) + RecordingState = STATE_NONE; + else { + CFileMgr::CloseFile(FId); + FId = CFileMgr::OpenFileForWriting("record.dat"); + RecordingState = STATE_RECORD; + } + } + else { + RecordingState = STATE_PLAYBACK; + } + if (RecordingState == STATE_PLAYBACK) { + pDataBufferPointer = (uint8*)malloc(MEMORY_FOR_GAME_RECORD); + pDataBuffer = pDataBufferPointer; + pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = -1; + CFileMgr::CloseFile(FId); + } +#else + RecordingState = STATE_NONE; // second time to make sure +#endif +} + +void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) +{ + switch (RecordingState) { + case STATE_RECORD: + { + pDataBufferForFrame.m_fTimeStep = CTimer::GetTimeStep(); + pDataBufferForFrame.m_nTimeInMilliseconds = CTimer::GetTimeInMilliseconds(); + pDataBufferForFrame.m_nSizeOfPads[0] = 0; + pDataBufferForFrame.m_nSizeOfPads[1] = 0; + pDataBufferForFrame.m_nChecksum = CalcGameChecksum(); + uint8* pController1 = PackCurrentPadValues(pDataBufferForFrame.m_ControllerBuffer, &CPad::GetPad(0)->OldState, &CPad::GetPad(0)->NewState); + pDataBufferForFrame.m_nSizeOfPads[0] = (pController1 - pDataBufferForFrame.m_ControllerBuffer) / 2; + uint8* pController2 = PackCurrentPadValues(pController1, &CPad::GetPad(1)->OldState, &CPad::GetPad(1)->NewState); + pDataBufferForFrame.m_nSizeOfPads[1] = (pController2 - pController1) / 2; + uint8* pEndPtr = pController2; + if ((pDataBufferForFrame.m_nSizeOfPads[0] + pDataBufferForFrame.m_nSizeOfPads[1]) & 1) + pEndPtr += 2; + CFileMgr::Write(FId, (char*)&pDataBufferForFrame, pEndPtr - (uint8*)&pDataBufferForFrame); + break; + } + case STATE_PLAYBACK: + if (pDataBufferPointer[8] == -1) + CPad::GetPad(0)->NewState.Clear(); + else { + tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer; + CTimer::SetTimeInMilliseconds(pData->m_nTimeInMilliseconds); + CTimer::SetTimeStep(pData->m_fTimeStep); + uint8 size1 = pData->m_nSizeOfPads[0]; + uint8 size2 = pData->m_nSizeOfPads[1]; + pDataBufferPointer = (uint8*)&pData->m_ControllerBuffer; + pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size1, &CPad::GetPad(0)->NewState); + pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size2, &CPad::GetPad(1)->NewState); + if ((size1 + size2) & 1) + pDataBufferPointer += 2; + if (pData->m_nChecksum != CalcGameChecksum()) + printf("Playback out of sync\n"); + } + } +} + +#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \ + do { \ + if (os->field != os->field){ \ + *buf++ = id; \ + *buf++ = ns->field; \ + } \ + } while (0); + +uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns) +{ + PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 2); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder1, 6); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder2, 7); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadUp, 8); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadDown, 9); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadLeft, 10); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadRight, 11); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, Start, 12); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, Select, 13); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, Square, 14); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, Triangle, 15); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, Cross, 16); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, Circle, 17); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShock, 18); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShock, 19); + return buf; +} +#undef PROCESS_BUTTON_STATE_STORE + +#define PROCESS_BUTTON_STATE_RESTORE(buf, state, field, id) case id: state->field = *buf++; break; + +uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state) +{ + for (uint8 i = 0; i < total; i++) { + switch (*buf++) { + PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0); + PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1); + PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 2); + PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3); + PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4); + PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5); + PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder1, 6); + PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder2, 7); + PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadUp, 8); + PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadDown, 9); + PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadLeft, 10); + PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadRight, 11); + PROCESS_BUTTON_STATE_RESTORE(buf, state, Start, 12); + PROCESS_BUTTON_STATE_RESTORE(buf, state, Select, 13); + PROCESS_BUTTON_STATE_RESTORE(buf, state, Square, 14); + PROCESS_BUTTON_STATE_RESTORE(buf, state, Triangle, 15); + PROCESS_BUTTON_STATE_RESTORE(buf, state, Cross, 16); + PROCESS_BUTTON_STATE_RESTORE(buf, state, Circle, 17); + PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShock, 18); + PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShock, 19); + } + } + return buf; +} + +#undef PROCESS_BUTTON_STATE_RESTORE + +uint16 CRecordDataForGame::CalcGameChecksum(void) +{ + uint32 checksum = 0; + int i = CPools::GetPedPool()->GetSize(); + while (i--) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + checksum ^= pPed->GetModelIndex() ^ *(uint32*)&pPed->GetPosition().z ^ *(uint32*)&pPed->GetPosition().y ^ *(uint32*)&pPed->GetPosition().x; + } + i = CPools::GetVehiclePool()->GetSize(); + while (i--) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (!pVehicle) + continue; + checksum ^= pVehicle->GetModelIndex() ^ *(uint32*)&pVehicle->GetPosition().z ^ *(uint32*)&pVehicle->GetPosition().y ^ *(uint32*)&pVehicle->GetPosition().x; + } + return checksum ^ checksum >> 16; +} + +WRAPPER void CRecordDataForChase::Init(void) +{ + EAXJMP(0x434780); +} WRAPPER void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4347F0); } WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); } @@ -16,4 +188,4 @@ WRAPPER void CRecordDataForChase::StartChaseScene(float) { EAXJMP(0x435690); } WRAPPER void CRecordDataForChase::CleanUpChaseScene() { EAXJMP(0x4357C0); } WRAPPER void CRecordDataForChase::RemoveCarFromChase(int32) { EAXJMP(0x435BC0); } WRAPPER CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32) { EAXJMP(0x435C00); } -WRAPPER void CRecordDataForChase::Init(void) { EAXJMP(0x434780); } + diff --git a/src/control/Record.h b/src/control/Record.h index e52a623e..3cb09318 100644 --- a/src/control/Record.h +++ b/src/control/Record.h @@ -1,6 +1,8 @@ #pragma once +class CAutomobile; class CVehicle; +class CControllerState; enum { RECORDSTATE_0, @@ -10,8 +12,15 @@ enum { class CRecordDataForChase { + enum { + NUM_CHASE_CARS = 20 + }; public: static uint8 &Status; + static int &PositionChanges; + static uint8 &CurrentCar; + static CAutomobile*(&pChaseCars)[NUM_CHASE_CARS]; + static uint32 &AnimStartTime; static void SaveOrRetrieveDataForThisFrame(void); static void ProcessControlCars(void); @@ -23,12 +32,37 @@ public: static void Init(void); }; +struct tGameBuffer +{ + float m_fTimeStep; + uint32 m_nTimeInMilliseconds; + uint8 m_nSizeOfPads[2]; + uint16 m_nChecksum; + uint8 m_ControllerBuffer[116]; +}; class CRecordDataForGame { + enum { + STATE_NONE = 0, + STATE_RECORD = 1, + STATE_PLAYBACK = 2, + }; + static uint16& RecordingState; + static uint8* &pDataBuffer; + static uint8* &pDataBufferPointer; + static int &FId; + static tGameBuffer &pDataBufferForFrame; + public: - static uint16 &RecordingState; + static bool IsRecording() { return RecordingState == STATE_RECORD; } + static bool IsPlayingBack() { return RecordingState == STATE_PLAYBACK; } static void SaveOrRetrieveDataForThisFrame(void); static void Init(void); + +private: + static uint16 CalcGameChecksum(void); + static uint8* PackCurrentPadValues(uint8*, CControllerState*, CControllerState*); + static uint8* UnPackCurrentPadValues(uint8*, uint8, CControllerState*); }; -- cgit v1.2.3 From 8917567508f1c98ba96579fdc0516cd07902c74d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 10 Apr 2020 11:23:35 +0300 Subject: Fixing mixed IsCutsceneProcessing and IsRunning --- src/control/CarCtrl.cpp | 2 +- src/control/CarGen.cpp | 2 +- src/control/Script.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/control') diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 3174a253..cdcfbba6 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -90,7 +90,7 @@ uint32 (&aCarsToKeepTime)[MAX_CARS_TO_KEEP] = *(uint32(*)[MAX_CARS_TO_KEEP])*(ui void CCarCtrl::GenerateRandomCars() { - if (CCutsceneMgr::IsCutsceneProcessing()) + if (CCutsceneMgr::IsRunning()) return; if (NumRandomCars < 30){ if (CountDownToCarsAtStart == 0){ diff --git a/src/control/CarGen.cpp b/src/control/CarGen.cpp index 49a96f50..721ac35a 100644 --- a/src/control/CarGen.cpp +++ b/src/control/CarGen.cpp @@ -242,7 +242,7 @@ void CCarGenerator::Load(uint8 *&buffer) void CTheCarGenerators::Process() { - if (FindPlayerTrain() || CCutsceneMgr::IsRunning()) + if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing()) return; if (++CTheCarGenerators::ProcessCounter == 4) CTheCarGenerators::ProcessCounter = 0; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index ddea0e3c..b7876172 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8442,7 +8442,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; CPad::GetPad(ScriptParams[0])->DisablePlayerControls |= PLAYERCONTROL_DISABLED_80; pPlayerInfo->MakePlayerSafe(true); - CCutsceneMgr::SetRunning(true); + CCutsceneMgr::StartCutsceneProcessing(); return 0; } case COMMAND_USE_TEXT_COMMANDS: -- cgit v1.2.3 From 314bb83b9aa2f801f11fa5445e86f0e896484138 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 10 Apr 2020 12:03:22 +0300 Subject: fixed intro crash --- src/control/Script.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/control') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index b7876172..ff89f0fc 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11373,15 +11373,15 @@ void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntit continue; CEntity* pFound = aEntities[i]; int cols; - if (CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel()->numLines <= 0) - cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(), - pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, nil, nil); + if (pEntity->GetColModel()->numLines <= 0) + cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(), + pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil); else { float lines[4]; lines[0] = lines[1] = lines[2] = lines[3] = 1.0f; - CColPoint tmp; - cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(), - pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, &tmp, lines); + CColPoint tmp[4]; + cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(), + pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines); } if (cols <= 0) continue; -- cgit v1.2.3 From a8f7bf0beca5c200bc3396312f0caaceacd27f94 Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 10 Apr 2020 16:44:08 +0500 Subject: CObject complete --- src/control/Pickups.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/control') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 774abd8c..16123c63 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -111,7 +111,7 @@ CPickup::GiveUsAPickUpObject(int32 handle) object->bUsesCollision = false; object->bIsPickup = true; - object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0; + object->m_nBonusValue = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0; switch (m_eType) { @@ -671,9 +671,9 @@ void CPickups::DoPickUpEffects(CEntity *entity) { if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) - entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame; + entity->bDoNotRender = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame; - if (!entity->m_flagD80) { + if (!entity->bDoNotRender) { float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); float modifiedSin = 0.3f * (s + 1.0f); @@ -716,7 +716,7 @@ CPickups::DoPickUpEffects(CEntity *entity) size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); CObject *object = (CObject*)entity; - if (object->m_obj_flag2 || object->bOutOfStock || object->field_172) { + if (object->m_obj_flag2 || object->bOutOfStock || object->m_nBonusValue) { float dist = (TheCamera.GetPosition() - pos).Magnitude(); const float MAXDIST = 12.0f; @@ -734,7 +734,7 @@ CPickups::DoPickUpEffects(CEntity *entity) aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId]; aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f; aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock; - aMessages[NumMessages].m_quantity = object->field_172; + aMessages[NumMessages].m_quantity = object->m_nBonusValue; NumMessages++; } } -- cgit v1.2.3 From c5d61392ead394a3d6a1e2832c7d9f0ccf951ad3 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 10 Apr 2020 18:36:39 +0200 Subject: implemented CTrafficLights --- src/control/AutoPilot.cpp | 16 +- src/control/CarCtrl.cpp | 144 +++++++++--------- src/control/PathFind.cpp | 167 ++++++++++++++++++--- src/control/PathFind.h | 12 +- src/control/TrafficLights.cpp | 334 ++++++++++++++++++++++++++++++++++++++++-- src/control/TrafficLights.h | 7 + 6 files changed, 567 insertions(+), 113 deletions(-) (limited to 'src/control') diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 70099291..b5bca21d 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed) float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo]; - float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dirX; - float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dirY; - float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dirX; - float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dirY; + float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.x; + float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.y; + float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.x; + float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.y; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->posX + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->posY - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->pos.x + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->pos.y - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->posX + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->posY - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->pos.x + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->pos.y - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index cdcfbba6..264f1f3f 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -393,25 +393,25 @@ CCarCtrl::GenerateOneRandomCar() pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f); pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f); - float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirX; - float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirY; - float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirX; - float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirY; + float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.x; + float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.y; + float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.x; + float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.y; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->posX + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->posY - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->posX + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->posY - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurrentLink->dirX * pCar->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurrentLink->dirY * pCar->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dirX * pCar->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dirY * pCar->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->dir.y * pCar->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -763,17 +763,17 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle) return; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - float currentPathLinkForwardX = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; - float currentPathLinkForwardY = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; - float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; - float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; + float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; + float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; + float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; + float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); @@ -1553,8 +1553,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; if (lanesOnNextNode >= 0){ if ((CGeneral::GetRandomNumber() & 0x600) == 0){ /* 25% chance vehicle will try to switch lane */ @@ -1574,17 +1574,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ - pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ + pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), - pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), + pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1725,10 +1725,10 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; if (lanesOnNextNode >= 0) { CVector2D dist = pNextPathNode->pos - pCurNode->pos; if (dist.MagnitudeSqr() >= SQR(7.0f)){ @@ -1755,17 +1755,17 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1814,10 +1814,10 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; if (lanesOnNextNode >= 0) { CVector2D dist = pNextPathNode->pos - pCurNode->pos; if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) { @@ -1835,17 +1835,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -2192,16 +2192,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv forward.Normalise(); CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - CVector2D currentPathLinkForward(pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection, - pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection); - float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; - float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; + CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection, + pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection); + float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; + float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; CVector2D positionOnCurrentLinkIncludingLane( - pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, - pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); + pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, + pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); CVector2D positionOnNextLinkIncludingLane( - pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); + pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane; float scalarDistanceToNextNode = distanceToNextNode.Magnitude(); CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane; @@ -2230,16 +2230,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv } pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; scalarDistanceToNextNode = CVector2D( - pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, - pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); + pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, + pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - currentPathLinkForward.x = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; - currentPathLinkForward.y = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; - nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; - nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; + currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; + currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; + nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; + nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; } - positionOnCurrentLinkIncludingLane.x = pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; - positionOnCurrentLinkIncludingLane.y = pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; + positionOnCurrentLinkIncludingLane.x = pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; + positionOnCurrentLinkIncludingLane.y = pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f; if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){ projectedPosition.x = positionOnCurrentLinkIncludingLane.x; @@ -2281,8 +2281,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv CCarAI::CarHasReasonToStop(pVehicle); speedStyleMultiplier = 0.0f; } - CVector2D trajectory(pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, - pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); + CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, + pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); trajectory -= pVehicle->GetPosition(); float speedAngleMultiplier = FindSpeedMultiplier( CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward, diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 608a209a..61cd3d4e 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -5,8 +5,13 @@ #include "Camera.h" #include "Vehicle.h" #include "World.h" +#include "Lines.h" // for debug #include "PathFind.h" +bool gbShowPedPaths; +bool gbShowCarPaths; +bool gbShowCarPathsLinks; + CPathFind &ThePaths = *(CPathFind*)0x8F6754; WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } @@ -466,20 +471,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor // IMPROVE: use a goto here // Find existing car path link for(k = 0; k < m_numCarPathLinks; k++){ - if(m_carPathLinks[k].dirX == tempnodes[j].dirX && - m_carPathLinks[k].dirY == tempnodes[j].dirY && - m_carPathLinks[k].posX == tempnodes[j].pos.x && - m_carPathLinks[k].posY == tempnodes[j].pos.y){ + if(m_carPathLinks[k].dir.x == tempnodes[j].dirX && + m_carPathLinks[k].dir.y == tempnodes[j].dirY && + m_carPathLinks[k].pos.x == tempnodes[j].pos.x && + m_carPathLinks[k].pos.y == tempnodes[j].pos.y){ m_carPathConnections[m_numConnections] = k; k = m_numCarPathLinks; } } // k is m_numCarPathLinks+1 if we found one if(k == m_numCarPathLinks){ - m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX; - m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY; - m_carPathLinks[m_numCarPathLinks].posX = tempnodes[j].pos.x; - m_carPathLinks[m_numCarPathLinks].posY = tempnodes[j].pos.y; + m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX; + m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY; + m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x; + m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y; m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; @@ -529,20 +534,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor // IMPROVE: use a goto here // Find existing car path link for(k = 0; k < m_numCarPathLinks; k++){ - if(m_carPathLinks[k].dirX == dx && - m_carPathLinks[k].dirY == dy && - m_carPathLinks[k].posX == posx && - m_carPathLinks[k].posY == posy){ + if(m_carPathLinks[k].dir.x == dx && + m_carPathLinks[k].dir.y == dy && + m_carPathLinks[k].pos.x == posx && + m_carPathLinks[k].pos.y == posy){ m_carPathConnections[m_numConnections] = k; k = m_numCarPathLinks; } } // k is m_numCarPathLinks+1 if we found one if(k == m_numCarPathLinks){ - m_carPathLinks[m_numCarPathLinks].dirX = dx; - m_carPathLinks[m_numCarPathLinks].dirY = dy; - m_carPathLinks[m_numCarPathLinks].posX = posx; - m_carPathLinks[m_numCarPathLinks].posY = posy; + m_carPathLinks[m_numCarPathLinks].dir.x = dx; + m_carPathLinks[m_numCarPathLinks].dir.y = dy; + m_carPathLinks[m_numCarPathLinks].pos.x = posx; + m_carPathLinks[m_numCarPathLinks].pos.y = posy; m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; @@ -760,8 +765,8 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena { int i; for(i = 0; i < m_numCarPathLinks; i++) - if(x1 < m_carPathLinks[i].posX && m_carPathLinks[i].posX < x2 && - y1 < m_carPathLinks[i].posY && m_carPathLinks[i].posY < y2) + if(x1 < m_carPathLinks[i].pos.x && m_carPathLinks[i].pos.x < x2 && + y1 < m_carPathLinks[i].pos.y && m_carPathLinks[i].pos.y < y2) m_carPathLinks[i].bBridgeLights = enable; } @@ -1444,6 +1449,132 @@ CPathFind::Load(uint8 *buf, uint32 size) m_pathNodes[i].bBetweenLevels = false; } +void +CPathFind::DisplayPathData(void) +{ + // Not the function from mobm_carPathLinksile but my own! + + int i, j, k; + // Draw 50 units around camera + CVector pos = TheCamera.GetPosition(); + const float maxDist = 50.0f; + + // Render car path nodes + if(gbShowCarPaths) + for(i = 0; i < m_numCarPathNodes; i++){ + if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist)) + continue; + + CVector n1 = m_pathNodes[i].pos; + n1.z += 0.3f; + + // Draw node itself + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + n1.x, n1.y, n1.z + 1.0f, + 0xFFFFFFFF, 0xFFFFFFFF); + + for(j = 0; j < m_pathNodes[i].numLinks; j++){ + k = m_connections[m_pathNodes[i].firstLink + j]; + CVector n2 = m_pathNodes[k].pos; + n2.z += 0.3f; + // Draw links to neighbours + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + n2.x, n2.y, n2.z, + 0xFFFFFFFF, 0xFFFFFFFF); + } + } + + // Render car path nodes + if(gbShowCarPathsLinks) + for(i = 0; i < m_numCarPathLinks; i++){ + CVector2D n1_2d = m_carPathLinks[i].pos; + if((n1_2d - pos).MagnitudeSqr() > SQR(maxDist)) + continue; + + int ni = m_carPathLinks[i].pathNodeIndex; + CVector pn1 = m_pathNodes[ni].pos; + pn1.z += 0.3f; + CVector n1(n1_2d.x, n1_2d.y, pn1.z); + n1.z += 0.3f; + + // Draw car node itself + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + n1.x, n1.y, n1.z + 1.0f, + 0xFFFFFFFF, 0xFFFFFFFF); + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z + 0.5f, + n1.x+m_carPathLinks[i].dir.x, n1.y+m_carPathLinks[i].dir.y, n1.z + 0.5f, + 0xFFFFFFFF, 0xFFFFFFFF); + + // Draw connection to car path node + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + pn1.x, pn1.y, pn1.z, + 0xFF0000FF, 0xFFFFFFFF); + + // traffic light type + uint32 col = 0xFF; + if((m_carPathLinks[i].trafficLightType&0x7F) == 1) + col += 0xFF000000; + if((m_carPathLinks[i].trafficLightType&0x7F) == 2) + col += 0x00FF0000; + if(m_carPathLinks[i].trafficLightType & 0x80) + col += 0x0000FF00; + CLines::RenderLineWithClipping(n1.x+0.2f, n1.y, n1.z, + n1.x+0.2f, n1.y, n1.z + 1.0f, + col, col); + + for(j = 0; j < m_pathNodes[ni].numLinks; j++){ + k = m_carPathConnections[m_pathNodes[ni].firstLink + j]; + CVector2D n2_2d = m_carPathLinks[k].pos; + int nk = m_carPathLinks[k].pathNodeIndex; + CVector pn2 = m_pathNodes[nk].pos; + pn2.z += 0.3f; + CVector n2(n2_2d.x, n2_2d.y, pn2.z); + n2.z += 0.3f; + + // Draw links to neighbours + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + n2.x, n2.y, n2.z, + 0xFF00FFFF, 0xFF00FFFF); + } + } + + // Render ped path nodes + if(gbShowPedPaths) + for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ + if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist)) + continue; + + CVector n1 = m_pathNodes[i].pos; + n1.z += 0.3f; + + // Draw node itself + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + n1.x, n1.y, n1.z + 1.0f, + 0xFFFFFFFF, 0xFFFFFFFF); + + for(j = 0; j < m_pathNodes[i].numLinks; j++){ + k = m_connections[m_pathNodes[i].firstLink + j]; + CVector n2 = m_pathNodes[k].pos; + n2.z += 0.3f; + // Draw links to neighbours + CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, + n2.x, n2.y, n2.z, + 0xFFFFFFFF, 0xFFFFFFFF); + + // Draw connection flags + CVector mid = (n1+n2)/2.0f; + uint32 col = 0xFF; + if(m_connectionFlags[m_pathNodes[i].firstLink + j].bCrossesRoad) + col += 0x00FF0000; + if(m_connectionFlags[m_pathNodes[i].firstLink + j].bTrafficLight) + col += 0xFF000000; + CLines::RenderLineWithClipping(mid.x, mid.y, mid.z, + mid.x, mid.y, mid.z + 1.0f, + col, col); + } + } +} + STARTPATCHES InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP); InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP); diff --git a/src/control/PathFind.h b/src/control/PathFind.h index c51cb7c7..81467cdf 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -84,10 +84,8 @@ union CConnectionFlags struct CCarPathLink { - float posX; - float posY; - float dirX; - float dirY; + CVector2D pos; + CVector2D dir; int16 pathNodeIndex; int8 numLeftLanes; int8 numRightLanes; @@ -208,7 +206,13 @@ public: bool TestCoorsCloseness(CVector target, uint8 type, CVector start); void Save(uint8 *buf, uint32 *size); void Load(uint8 *buf, uint32 size); + + void DisplayPathData(void); }; static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); extern CPathFind &ThePaths; + +extern bool gbShowPedPaths; +extern bool gbShowCarPaths; +extern bool gbShowCarPathsLinks; diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 2cd09a03..e4416965 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -1,23 +1,335 @@ #include "common.h" #include "patcher.h" -#include "TrafficLights.h" +#include "General.h" +#include "Camera.h" +#include "World.h" +#include "PathFind.h" #include "Timer.h" +#include "Clock.h" +#include "Weather.h" +#include "Timecycle.h" +#include "Pointlights.h" +#include "Shadows.h" +#include "Coronas.h" +#include "SpecialFX.h" #include "Vehicle.h" +#include "TrafficLights.h" + +// TODO: figure out the meaning of this +enum { SOME_FLAG = 0x80 }; + +void +CTrafficLights::DisplayActualLight(CEntity *ent) +{ + if(ent->GetUp().z < 0.96f || ent->bRenderDamaged) + return; + + int phase; + if(FindTrafficLightType(ent) == 1) + phase = LightForCars1(); + else + phase = LightForCars2(); + + int i; + CBaseModelInfo *mi = CModelInfo::GetModelInfo(ent->GetModelIndex()); + float x = mi->Get2dEffect(0)->pos.x; + float yMin = mi->Get2dEffect(0)->pos.y; + float yMax = mi->Get2dEffect(0)->pos.y; + float zMin = mi->Get2dEffect(0)->pos.z; + float zMax = mi->Get2dEffect(0)->pos.z; + for(i = 1; i < 6; i++){ + assert(mi->Get2dEffect(i)); + yMin = min(yMin, mi->Get2dEffect(i)->pos.y); + yMax = min(yMax, mi->Get2dEffect(i)->pos.y); + zMin = min(zMin, mi->Get2dEffect(i)->pos.z); + zMax = min(zMax, mi->Get2dEffect(i)->pos.z); + } + + CVector pos1, pos2; + uint8 r, g; + int id; + switch(phase){ + case CAR_LIGHTS_GREEN: + r = 0; + g = 255; + pos1 = ent->GetMatrix() * CVector(x, yMax, zMin); + pos2 = ent->GetMatrix() * CVector(x, yMin, zMin); + id = 0; + break; + case CAR_LIGHTS_YELLOW: + r = 255; + g = 128; + pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin+zMax)/2.0f); + pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin+zMax)/2.0f); + id = 1; + break; + case CAR_LIGHTS_RED: + default: + r = 255; + g = 0; + pos1 = ent->GetMatrix() * CVector(x, yMax, zMax); + pos2 = ent->GetMatrix() * CVector(x, yMin, zMax); + id = 2; + break; + } + + if(CClock::GetHours() > 19 || CClock::GetHours() < 6 || CWeather::Foggyness > 0.05f) + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f, + r/255.0f, g/255.0f, 0/255.0f, CPointLights::FOG_NORMAL, true); + + CShadows::StoreStaticShadow((uintptr)ent, + SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1, + 8.0f, 0.0f, 0.0f, -8.0f, 128, + r*CTimeCycle::GetLightOnGroundBrightness()/8.0f, + g*CTimeCycle::GetLightOnGroundBrightness()/8.0f, + 0*CTimeCycle::GetLightOnGroundBrightness()/8.0f, + 12.0f, 1.0f, 40.0f, false, 0.0f); + + if(DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f) + CCoronas::RegisterCorona((uintptr)ent + id, + r*CTimeCycle::GetSpriteBrightness()*0.7f, + g*CTimeCycle::GetSpriteBrightness()*0.7f, + 0*CTimeCycle::GetSpriteBrightness()*0.7f, + 255, + pos1, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f, + CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::RegisterCorona((uintptr)ent + id + 3, + r*CTimeCycle::GetSpriteBrightness()*0.7f, + g*CTimeCycle::GetSpriteBrightness()*0.7f, + 0*CTimeCycle::GetSpriteBrightness()*0.7f, + 255, + pos2, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f, + CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + + 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; + static const float left = 1.256f; + static const float right = 0.706f; + phase = CTrafficLights::LightForPeds(); + if(phase == PED_LIGHTS_DONT_WALK){ + CVector p0(2.7f, right, top); + CVector p1(2.7f, left, top); + CVector p2(2.7f, right, mid); + CVector p3(2.7f, left, mid); + CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3, + 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, + SHINYTEXT_WALK, 255, 0, 0, 60.0f); + }else if(phase == PED_LIGHTS_WALK || CTimer::GetTimeInMilliseconds() & 0x100){ + CVector p0(2.7f, right, mid); + CVector p1(2.7f, left, mid); + CVector p2(2.7f, right, bot); + CVector p3(2.7f, left, bot); + CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3, + 1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, + SHINYTEXT_WALK, 255, 255, 255, 60.0f); + } +} + +void +CTrafficLights::ScanForLightsOnMap(void) +{ + int x, y; + int i, j, l; + CPtrNode *node; + + for(x = 0; x < NUMSECTORS_X; x++) + for(y = 0; y < NUMSECTORS_Y; y++){ + 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) + continue; + + // Check cars + for(i = 0; i < ThePaths.m_numCarPathLinks; i++){ + CVector2D dist = ThePaths.m_carPathLinks[i].pos - light->GetPosition(); + float dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light + float dotX = DotProduct2D(dist, light->GetRight()); // towards base of light + // it has to be on the correct side of the node and also not very far away + if(dotX < 0.0f && dotX > -15.0f && dotY < 3.0f){ + float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].pos.z - + light->GetPosition().z; + if(dz < 15.0f){ + ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light); + // Find two neighbour nodes of this one + int n1 = -1; + int n2 = -1; + for(j = 0; j < ThePaths.m_numPathNodes; j++) + for(l = 0; l < ThePaths.m_pathNodes[j].numLinks; l++) + if(ThePaths.m_carPathConnections[ThePaths.m_pathNodes[j].firstLink + l] == i){ + if(n1 == -1) + n1 = j; + else + n2 = j; + } + // What's going on here? + if(ThePaths.m_pathNodes[n1].numLinks <= ThePaths.m_pathNodes[n2].numLinks) + n1 = n2; + if(ThePaths.m_carPathLinks[i].pathNodeIndex != n1) + ThePaths.m_carPathLinks[i].trafficLightType |= SOME_FLAG; + } + } + } + + // Check peds + for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){ + float dist1, dist2; + dist1 = Abs(ThePaths.m_pathNodes[i].pos.x - light->GetPosition().x) + + Abs(ThePaths.m_pathNodes[i].pos.y - light->GetPosition().y); + if(dist1 < 50.0f){ + for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){ + j = ThePaths.m_pathNodes[i].firstLink + l; + if(ThePaths.m_connectionFlags[j].bCrossesRoad){ + dist2 = Abs(ThePaths.m_pathNodes[j].pos.x - light->GetPosition().x) + + Abs(ThePaths.m_pathNodes[j].pos.y - light->GetPosition().y); + if(dist1 < 15.0f || dist2 < 15.0f) + ThePaths.m_connectionFlags[j].bTrafficLight = true; + } + } + } + } + } + } +} + +bool +CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) +{ + int node, type; -WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); } -WRAPPER void CTrafficLights::ScanForLightsOnMap(void) { EAXJMP(0x454F40); } -WRAPPER bool CTrafficLights::ShouldCarStopForLight(CVehicle*, bool) { EAXJMP(0x455350); } -WRAPPER bool CTrafficLights::ShouldCarStopForBridge(CVehicle*) { EAXJMP(0x456460); } + node = vehicle->AutoPilot.m_nNextPathNodeInfo; + type = ThePaths.m_carPathLinks[node].trafficLightType; + if(type){ + if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) && + (!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode)) + if(alwaysStop || + (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || + (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, + ThePaths.m_carPathLinks[node].dir); + if(vehicle->AutoPilot.m_nNextDirection == -1){ + if(dist > 0.0f && dist < 8.0f) + return true; + }else{ + if(dist < 0.0f && dist > -8.0f) + return true; + } + } + } + + node = vehicle->AutoPilot.m_nCurrentPathNodeInfo; + type = ThePaths.m_carPathLinks[node].trafficLightType; + if(type){ + if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) && + (!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode)) + if(alwaysStop || + (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || + (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, + ThePaths.m_carPathLinks[node].dir); + if(vehicle->AutoPilot.m_nCurrentDirection == -1){ + if(dist > 0.0f && dist < 8.0f) + return true; + }else{ + if(dist < 0.0f && dist > -8.0f) + return true; + } + } + } + + if(vehicle->m_status == STATUS_PHYSICS){ + node = vehicle->AutoPilot.m_nPreviousPathNodeInfo; + type = ThePaths.m_carPathLinks[node].trafficLightType; + if(type){ + if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) && + (!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode)) + if(alwaysStop || + (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || + (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, + ThePaths.m_carPathLinks[node].dir); + if(vehicle->AutoPilot.m_nPreviousDirection == -1){ + if(dist > 0.0f && dist < 6.0f) + return true; + }else{ + if(dist < 0.0f && dist > -6.0f) + return true; + } + } + } + } + + return false; +} + +bool +CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle) +{ + return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights && + !ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights; +} + +int +CTrafficLights::FindTrafficLightType(CEntity *light) +{ + float orientation = RADTODEG(CGeneral::GetATanOfXY(light->GetForward().x, light->GetForward().y)); + if((orientation > 60.0f && orientation < 60.0f + 90.0f) || + (orientation > 240.0f && orientation < 240.0f + 90.0f)) + return 1; + return 2; +} uint8 CTrafficLights::LightForPeds(void) { - uint32 period = CTimer::GetTimeInMilliseconds() & 0x3FFF; // Equals to % 16384 + uint32 period = CTimer::GetTimeInMilliseconds() % 16384; - if (period >= 15384) - return PED_LIGHTS_WALK_BLINK; - else if (period >= 12000) + if(period < 12000) + return PED_LIGHTS_DONT_WALK; + else if(period < 16384 - 1000) return PED_LIGHTS_WALK; else - return PED_LIGHTS_DONT_WALK; -} \ No newline at end of file + return PED_LIGHTS_WALK_BLINK; +} + +uint8 +CTrafficLights::LightForCars1(void) +{ + uint32 period = CTimer::GetTimeInMilliseconds() % 16384; + + if(period < 5000) + return CAR_LIGHTS_GREEN; + else if(period < 5000 + 1000) + return CAR_LIGHTS_YELLOW; + else + return CAR_LIGHTS_RED; +} + +uint8 +CTrafficLights::LightForCars2(void) +{ + uint32 period = CTimer::GetTimeInMilliseconds() % 16384; + + if(period < 6000) + return CAR_LIGHTS_RED; + else if(period < 12000 - 1000) + return CAR_LIGHTS_GREEN; + else if(period < 12000) + return CAR_LIGHTS_YELLOW; + else + return CAR_LIGHTS_RED; +} + +STARTPATCHES + InjectHook(0x455760, &CTrafficLights::LightForCars1, PATCH_JUMP); + InjectHook(0x455790, &CTrafficLights::LightForCars2, PATCH_JUMP); + InjectHook(0x4557D0, &CTrafficLights::LightForPeds, PATCH_JUMP); +ENDPATCHES diff --git a/src/control/TrafficLights.h b/src/control/TrafficLights.h index 06505ed6..f3df6cd5 100644 --- a/src/control/TrafficLights.h +++ b/src/control/TrafficLights.h @@ -7,6 +7,10 @@ enum { PED_LIGHTS_WALK, PED_LIGHTS_WALK_BLINK, PED_LIGHTS_DONT_WALK, + + CAR_LIGHTS_GREEN = 0, + CAR_LIGHTS_YELLOW, + CAR_LIGHTS_RED }; class CTrafficLights @@ -14,7 +18,10 @@ class CTrafficLights public: static void DisplayActualLight(CEntity *ent); static void ScanForLightsOnMap(void); + static int FindTrafficLightType(CEntity *light); static uint8 LightForPeds(void); + static uint8 LightForCars1(void); + static uint8 LightForCars2(void); static bool ShouldCarStopForLight(CVehicle*, bool); static bool ShouldCarStopForBridge(CVehicle*); }; -- cgit v1.2.3 From 92b6d775d67d01aab0706564b2cae3714bcf05b0 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 11 Apr 2020 02:03:42 +0300 Subject: Record --- src/control/Record.cpp | 355 +++++++++++++++++++++++++++++++++++++++++++++++-- src/control/Record.h | 54 ++++++-- 2 files changed, 390 insertions(+), 19 deletions(-) (limited to 'src/control') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 7a3763be..19fd8969 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -5,7 +5,10 @@ #include "FileMgr.h" #include "Pad.h" #include "Pools.h" +#include "Streaming.h" #include "Timer.h" +#include "VehicleModelInfo.h" +#include "World.h" uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24; uint8*& CRecordDataForGame::pDataBuffer = *(uint8**)0x8F1B70; @@ -13,8 +16,6 @@ uint8*& CRecordDataForGame::pDataBufferPointer = *(uint8**)0x8F1AB0; int& CRecordDataForGame::FId = *(int*)0x885BA4; tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0; -uint8 &CRecordDataForChase::Status = *(uint8*)0x95CDCE; - #define MEMORY_FOR_GAME_RECORD (150000) void CRecordDataForGame::Init(void) @@ -176,16 +177,348 @@ uint16 CRecordDataForGame::CalcGameChecksum(void) return checksum ^ checksum >> 16; } -WRAPPER void CRecordDataForChase::Init(void) +uint8& CRecordDataForChase::Status = *(uint8*)0x95CDCE; +int& CRecordDataForChase::PositionChanges = *(int*)0x8F59C8; +uint8& CRecordDataForChase::CurrentCar = *(uint8*)0x95CDC9; +CAutomobile* (&CRecordDataForChase::pChaseCars)[NUM_CHASE_CARS] = *(CAutomobile * (*)[NUM_CHASE_CARS])*(uintptr*)0x6F46A8; +uint32& CRecordDataForChase::AnimStartTime = *(uint32*)0x8F1AEC; +float& CRecordDataForChase::AnimTime = *(float*)0x880F88; +CCarStateEachFrame* (&CRecordDataForChase::pBaseMemForCar)[NUM_CHASE_CARS] = *(CCarStateEachFrame * (*)[NUM_CHASE_CARS])*(uintptr*)0x70EA18; +float& CRecordDataForChase::TimeMultiplier = *(float*)0x8E2A94; +int& CRecordDataForChase::FId2 = *(int*)0x8E2C18; + +#define CHASE_SCENE_LENGTH_IN_SECONDS (80) +#define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame +#define CHASE_SCENE_FRAMES_IN_RECORDING (CHASE_SCENE_LENGTH_IN_SECONDS * CHASE_SCENE_FRAMES_PER_SECOND) +#define CHASE_SCENE_LENGTH_IN_FRAMES (CHASE_SCENE_FRAMES_IN_RECORDING * 2) + +void CRecordDataForChase::Init(void) +{ + Status = STATE_NONE; + PositionChanges = 0; + CurrentCar = 0; + for (int i = 0; i < NUM_CHASE_CARS; i++) + pChaseCars[i] = nil; + AnimStartTime = 0; +} + +void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) +{ + switch (Status) { + case STATE_NONE: + return; + case STATE_RECORD: + { + if ((CTimer::GetFrameCounter() & 1) == 0) + StoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2]); + if (CTimer::GetFrameCounter() < CHASE_SCENE_LENGTH_IN_FRAMES * 2) + return; + CFileMgr::SetDir("data\\paths"); + sprintf(gString, "chase%d.dat", CurrentCar); + int fid = CFileMgr::OpenFileForWriting(gString); + uint32 fs = CHASE_SCENE_LENGTH_IN_FRAMES * sizeof(CCarStateEachFrame); + printf("FileSize:%d\n", fs); + CFileMgr::Write(fid, (char*)pBaseMemForCar[CurrentCar], fs); + CFileMgr::CloseFile(fid); + CFileMgr::SetDir(""); + sprintf(gString, "car%d.max", CurrentCar); + int fid2 = CFileMgr::OpenFileForWriting(gString); + for (int i = 0; i < CHASE_SCENE_FRAMES_IN_RECORDING; i++) { + // WTF? Was it ever used? +#ifdef FIX_BUGS + CCarStateEachFrame* pState = pBaseMemForCar[CurrentCar]; +#else + CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar]; +#endif + CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / (UINT8_MAX / 2); + CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / (UINT8_MAX / 2); + CVector up = CrossProduct(right, forward); + sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z); + CFileMgr::Write(fid2, gString, strlen(gString) - 1); + sprintf(gString, "%f %f %f\n", right.x, right.y, right.z); + CFileMgr::Write(fid2, gString, strlen(gString) - 1); + sprintf(gString, "%f %f %f\n", forward.x, forward.y, forward.z); + CFileMgr::Write(fid2, gString, strlen(gString) - 1); + sprintf(gString, "%f %f %f\n", up.x, up.y, up.z); + CFileMgr::Write(fid2, gString, strlen(gString) - 1); + } + CFileMgr::CloseFile(fid2); + } + case STATE_PLAYBACK: + case STATE_PLAYBACK_BEFORE_RECORDING: + case STATE_PLAYBACK_INIT: + break; + } +} + +struct tCoors { + CVector pos; + float angle; +}; + +// I guess developer was filling this with actual data before running the game +tCoors NewCoorsForRecordedCars[7]; + +void CRecordDataForChase::SaveOrRetrieveCarPositions(void) +{ + switch (Status) { + case STATE_NONE: + return; + case STATE_RECORD: + case STATE_PLAYBACK_BEFORE_RECORDING: + for (int i = 0; i < NUM_CHASE_CARS; i++) { + if (i != CurrentCar && CTimer::GetFrameCounter()) { + RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CTimer::GetFrameCounter() / 2], false); + pChaseCars[i]->GetMatrix().UpdateRW(); + pChaseCars[i]->UpdateRwFrame(); + } + } + if (Status == STATE_PLAYBACK_BEFORE_RECORDING && CTimer::GetFrameCounter()) { + RestoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2], false); + pChaseCars[CurrentCar]->GetMatrix().UpdateRW(); + pChaseCars[CurrentCar]->UpdateRwFrame(); + } + if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) { + if (!CPad::GetPad(0)->GetRightShockJustDown()) { + pChaseCars[CurrentCar]->GetPosition() = NewCoorsForRecordedCars[PositionChanges].pos; + pChaseCars[CurrentCar]->SetMoveSpeed(0.0f, 0.0f, 0.0f); + pChaseCars[CurrentCar]->GetMatrix().SetRotateZOnly(DEGTORAD(NewCoorsForRecordedCars[PositionChanges].angle)); + ++PositionChanges; + } + if (Status == STATE_PLAYBACK_BEFORE_RECORDING) { + Status = STATE_RECORD; + pChaseCars[CurrentCar]->m_status = STATUS_PLAYER; + } + } + break; + case STATE_PLAYBACK_INIT: + Status = STATE_PLAYBACK; + break; + case STATE_PLAYBACK: + { + TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds(); + float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier); + for (int i = 0; i < NUM_CHASE_CARS; i++) { + if (!pBaseMemForCar[i]) + continue; + if (!pChaseCars[i]) + continue; + if (EndOfFrameTime < CHASE_SCENE_FRAMES_IN_RECORDING - 1) { + int FlooredEOFTime = EndOfFrameTime; + RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][FlooredEOFTime], false); + CMatrix tmp; + float dp = EndOfFrameTime - FlooredEOFTime; + RestoreInfoForMatrix(tmp, &pBaseMemForCar[i][FlooredEOFTime + 1]); + pChaseCars[i]->GetRight() += (tmp.GetRight() - pChaseCars[i]->GetRight()) * dp; + pChaseCars[i]->GetForward() += (tmp.GetForward() - pChaseCars[i]->GetForward()) * dp; + pChaseCars[i]->GetUp() += (tmp.GetUp() - pChaseCars[i]->GetUp()) * dp; + pChaseCars[i]->GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * dp; + } + else{ + RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CHASE_SCENE_FRAMES_IN_RECORDING - 1], true); + if (i == 0) + pChaseCars[i]->GetPosition().z += 0.2f; + } + pChaseCars[i]->GetMatrix().UpdateRW(); + pChaseCars[i]->UpdateRwFrame(); + pChaseCars[i]->RemoveAndAdd(); + } + break; + } + } +} + +void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState) +{ + pState->rightX = UINT8_MAX / 2 * pCar->GetRight().x; + pState->rightY = UINT8_MAX / 2 * pCar->GetRight().y; + pState->rightZ = UINT8_MAX / 2 * pCar->GetRight().z; + pState->forwardX = UINT8_MAX / 2 * pCar->GetForward().x; + pState->forwardY = UINT8_MAX / 2 * pCar->GetForward().y; + pState->forwardZ = UINT8_MAX / 2 * pCar->GetForward().z; + pState->pos = pCar->GetPosition(); + pState->velX = 1.0f * (UINT16_MAX / 2) * pCar->GetMoveSpeed().x; + pState->velY = 1.0f * (UINT16_MAX / 2) * pCar->GetMoveSpeed().y; + pState->velZ = 1.0f * (UINT16_MAX / 2) * pCar->GetMoveSpeed().z; + pState->wheel = 20 * pCar->m_fSteerAngle; + pState->gas = 100 * pCar->m_fGasPedal; + pState->brake = 100 * pCar->m_fBrakePedal; + pState->handbrake = pCar->bIsHandbrakeOn; +} + +void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState) { - EAXJMP(0x434780); + matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / (UINT8_MAX / 2); + matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / (UINT8_MAX / 2); + matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward()); + matrix.GetPosition() = pState->pos; } -WRAPPER void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4347F0); } -WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); } -WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); } -WRAPPER void CRecordDataForChase::StartChaseScene(float) { EAXJMP(0x435690); } -WRAPPER void CRecordDataForChase::CleanUpChaseScene() { EAXJMP(0x4357C0); } -WRAPPER void CRecordDataForChase::RemoveCarFromChase(int32) { EAXJMP(0x435BC0); } -WRAPPER CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32) { EAXJMP(0x435C00); } +void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop) +{ + CVector oldPos = pCar->GetPosition(); + RestoreInfoForMatrix(pCar->GetMatrix(), pState); + pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) * 1.0f / (UINT16_MAX / 2)); + pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f); + pCar->m_fSteerAngle = pState->wheel / 20.0f; + pCar->m_fGasPedal = pState->gas / 100.0f; + pCar->m_fBrakePedal = pState->brake / 100.0f; + pCar->bIsHandbrakeOn = pState->handbrake; + if ((oldPos - pCar->GetPosition()).Magnitude() > 15.0f) { + if (pCar == pChaseCars[14]) { + pCar->m_currentColour1 = 58; + pCar->m_currentColour2 = 1; + } + else + pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2); + } + pCar->m_fHealth = min(pCar->m_fHealth, 500.0f); + if (stop) { + pCar->m_fGasPedal = 0.0f; + pCar->m_fBrakePedal = 0.0f; + pCar->SetMoveSpeed(0.0f, 0.0f, 0.0f); + pCar->bIsHandbrakeOn = false; + } +} + +void CRecordDataForChase::ProcessControlCars(void) +{ + if (Status != STATE_PLAYBACK) + return; + for (int i = 0; i < NUM_CHASE_CARS; i++) { + if (pChaseCars[i]) + pChaseCars[i]->ProcessControl(); + } +} + +#if (defined(GTA_PS2) || defined(FIX_BUGS)) +bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad) +{ + // may be wrong + if (Status == STATE_NONE || Status == STATE_PLAYBACK) + return false; + return pad != 0; +} +#endif + +void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2) +{ + CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY); + CStreaming::LoadAllRequestedModels(false); + if (!CStreaming::HasModelLoaded(mi)) + return; + CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE); + pCar->GetPosition() = pos; + pCar->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER; + pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle)); + pCar->pDriver = nil; + pCar->m_currentColour1 = colour1; + pCar->m_currentColour2 = colour2; + CWorld::Add(pCar); + *ppCar = pCar; +} + +void RemoveUnusedCollision(void) +{ + static const char* dontDeleteArray[] = { + "rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22", + "road_broadway02", "road_broadway01", "com_21way5", "com_21way50", + "cm1waycrosscom", "com_21way20", "com_21way10", "road_broadway04", + "com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22" + }; + for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++) + CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_NONE; + CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE); + for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++) + CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL; +} + +void CRecordDataForChase::StartChaseScene(float startTime) +{ + char filename[28]; + SetUpCarsForChaseScene(); + Status = STATE_PLAYBACK; + AnimTime = startTime; + AnimStartTime = CTimer::GetTimeInMilliseconds(); + RemoveUnusedCollision(); + CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); + CGame::TidyUpMemory(true, true); + CStreaming::ImGonnaUseStreamingMemory(); + CFileMgr::SetDir("data\\paths"); + for (int i = 0; i < NUM_CHASE_CARS; i++) { + if (!pChaseCars[i]) { + pBaseMemForCar[i] = nil; + continue; + } + sprintf(filename, "chase%d.dat", i); + FId2 = CFileMgr::OpenFile(filename, "rb"); + if (FId2 <= 0) { + pBaseMemForCar[i] = nil; + continue; + } + pBaseMemForCar[i] = new CCarStateEachFrame[CHASE_SCENE_FRAMES_IN_RECORDING]; + for (int j = 0; j < CHASE_SCENE_FRAMES_IN_RECORDING; j++) { + CFileMgr::Read(FId2, (char*)&pBaseMemForCar[i][j], sizeof(CCarStateEachFrame)); + CFileMgr::Seek(FId2, sizeof(CCarStateEachFrame), 1); + } + CFileMgr::CloseFile(FId2); + } + CFileMgr::SetDir(""); + CStreaming::IHaveUsedStreamingMemory(); + TimeMultiplier = 0.0f; +} + +void CRecordDataForChase::CleanUpChaseScene(void) +{ + if (Status != STATE_PLAYBACK_INIT && Status != STATE_PLAYBACK) + return; + Status = STATE_NONE; + CleanUpCarsForChaseScene(); + for (int i = 0; i < NUM_CHASE_CARS; i++) { + if (pBaseMemForCar[i]) { + delete[] pBaseMemForCar[i]; + pBaseMemForCar[i] = nil; + } + } +} + +void CRecordDataForChase::SetUpCarsForChaseScene(void) +{ + GiveUsACar(MI_POLICE, CVector(273.54221f, -1167.1907f, 24.880601f), 63.0f, &pChaseCars[0], 2, 1); + GiveUsACar(MI_ENFORCER, CVector(231.1783f, -1388.8322f, 25.978201f), 90.0f, &pChaseCars[1], 2, 1); + GiveUsACar(MI_TAXI, CVector(184.3156f, -1473.251f, 25.978201f), 0.0f, &pChaseCars[4], 6, 6); + GiveUsACar(MI_CHEETAH, CVector(173.8868f, -1377.6514f, 25.978201f), 0.0f, &pChaseCars[6], 4, 5); + GiveUsACar(MI_STINGER, CVector(102.5946f, -943.93628f, 25.9781f), 270.0f, &pChaseCars[7], 53, 53); + GiveUsACar(MI_CHEETAH, CVector(-177.7157f, -862.18652f, 25.978201f), 155.0f, &pChaseCars[10], 41, 1); + GiveUsACar(MI_STINGER, CVector(-170.56979f, -889.02362f, 25.978201f), 154.0f, &pChaseCars[11], 10, 10); + GiveUsACar(MI_KURUMA, CVector(402.60809f, -917.49628f, 37.381001f), 90.0f, &pChaseCars[14], 34, 1); + GiveUsACar(MI_TAXI, CVector(-33.496201f, -938.4563f, 25.9781f), 266.0f, &pChaseCars[16], 6, 6); + GiveUsACar(MI_KURUMA, CVector(49.363098f, -987.60498f, 25.9781f), 0.0f, &pChaseCars[18], 51, 1); + GiveUsACar(MI_TAXI, CVector(179.0049f, -1154.6686f, 25.9781f), 0.0f, &pChaseCars[19], 6, 76); + GiveUsACar(MI_RUMPO, CVector(-28.9762f, -1031.3367f, 25.990601f), 242.0f, &pChaseCars[2], 1, 75); + GiveUsACar(MI_PATRIOT, CVector(114.1564f, -796.69379f, 24.978201f), 180.0f, &pChaseCars[3], 0, 0); +} + +void CRecordDataForChase::CleanUpCarsForChaseScene(void) +{ + for (int i = 0; i < NUM_CHASE_CARS; i++) + RemoveCarFromChase(i); +} + +void CRecordDataForChase::RemoveCarFromChase(int32 i) +{ + if (!pChaseCars[i]) + return; + CWorld::Remove(pChaseCars[i]); + delete pChaseCars[i]; + pChaseCars[i] = nil; +} + +CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i) +{ + CVehicle* pVehicle = pChaseCars[i]; + pChaseCars[i] = nil; + pVehicle->m_status = STATUS_PHYSICS; + return pVehicle; +} diff --git a/src/control/Record.h b/src/control/Record.h index 3cb09318..4abeb68a 100644 --- a/src/control/Record.h +++ b/src/control/Record.h @@ -4,32 +4,70 @@ class CAutomobile; class CVehicle; class CControllerState; -enum { - RECORDSTATE_0, - RECORDSTATE_1, - RECORDSTATE_2, +class CCarStateEachFrame +{ +public: + int16 velX; + int16 velY; + int16 velZ; + int8 rightX; + int8 rightY; + int8 rightZ; + int8 forwardX; + int8 forwardY; + int8 forwardZ; + int8 wheel; + uint8 gas; + uint8 brake; + bool handbrake; + CVector pos; }; +extern char* gString; + class CRecordDataForChase { enum { NUM_CHASE_CARS = 20 }; -public: + enum { + STATE_NONE = 0, + STATE_RECORD = 1, + STATE_PLAYBACK_INIT = 2, + STATE_PLAYBACK = 3, + STATE_PLAYBACK_BEFORE_RECORDING = 4 + }; static uint8 &Status; static int &PositionChanges; static uint8 &CurrentCar; static CAutomobile*(&pChaseCars)[NUM_CHASE_CARS]; + static float &AnimTime; static uint32 &AnimStartTime; + static CCarStateEachFrame* (&pBaseMemForCar)[NUM_CHASE_CARS]; + static float &TimeMultiplier; + static int &FId2; +public: + + static bool IsRecording(void) { return Status == STATE_RECORD; } + static void Init(void); static void SaveOrRetrieveDataForThisFrame(void); - static void ProcessControlCars(void); static void SaveOrRetrieveCarPositions(void); + static void StoreInfoForCar(CAutomobile*, CCarStateEachFrame*); + static void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*); + static void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool); + static void ProcessControlCars(void); +#if (defined(GTA_PS2) || defined(FIX_BUGS)) + static bool ShouldThisPadBeLeftAlone(uint8 pad); +#endif + static void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8); static void StartChaseScene(float); - static void CleanUpChaseScene(); + static void CleanUpChaseScene(void); + static void SetUpCarsForChaseScene(void); + static void CleanUpCarsForChaseScene(void); static void RemoveCarFromChase(int32); static CVehicle* TurnChaseCarIntoScriptCar(int32); - static void Init(void); + }; struct tGameBuffer -- cgit v1.2.3 From bc90f958da4682a4b951cd77cbfd1aa3c12e2fad Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 11 Apr 2020 02:27:50 +0300 Subject: fix constants --- src/control/Record.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/control') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 19fd8969..e858bc1d 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -230,8 +230,8 @@ void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) #else CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar]; #endif - CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / (UINT8_MAX / 2); - CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / (UINT8_MAX / 2); + CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX; + CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX; CVector up = CrossProduct(right, forward); sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z); CFileMgr::Write(fid2, gString, strlen(gString) - 1); @@ -330,16 +330,16 @@ void CRecordDataForChase::SaveOrRetrieveCarPositions(void) void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState) { - pState->rightX = UINT8_MAX / 2 * pCar->GetRight().x; - pState->rightY = UINT8_MAX / 2 * pCar->GetRight().y; - pState->rightZ = UINT8_MAX / 2 * pCar->GetRight().z; - pState->forwardX = UINT8_MAX / 2 * pCar->GetForward().x; - pState->forwardY = UINT8_MAX / 2 * pCar->GetForward().y; - pState->forwardZ = UINT8_MAX / 2 * pCar->GetForward().z; + pState->rightX = INT8_MAX * pCar->GetRight().x; + pState->rightY = INT8_MAX * pCar->GetRight().y; + pState->rightZ = INT8_MAX * pCar->GetRight().z; + pState->forwardX = INT8_MAX * pCar->GetForward().x; + pState->forwardY = INT8_MAX * pCar->GetForward().y; + pState->forwardZ = INT8_MAX * pCar->GetForward().z; pState->pos = pCar->GetPosition(); - pState->velX = 1.0f * (UINT16_MAX / 2) * pCar->GetMoveSpeed().x; - pState->velY = 1.0f * (UINT16_MAX / 2) * pCar->GetMoveSpeed().y; - pState->velZ = 1.0f * (UINT16_MAX / 2) * pCar->GetMoveSpeed().z; + pState->velX = 0.5f * INT16_MAX * pCar->GetMoveSpeed().x; + pState->velY = 0.5f * INT16_MAX * pCar->GetMoveSpeed().y; + pState->velZ = 0.5f * INT16_MAX * pCar->GetMoveSpeed().z; pState->wheel = 20 * pCar->m_fSteerAngle; pState->gas = 100 * pCar->m_fGasPedal; pState->brake = 100 * pCar->m_fBrakePedal; @@ -348,8 +348,8 @@ void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState) { - matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / (UINT8_MAX / 2); - matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / (UINT8_MAX / 2); + matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX; + matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX; matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward()); matrix.GetPosition() = pState->pos; } @@ -358,7 +358,7 @@ void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFram { CVector oldPos = pCar->GetPosition(); RestoreInfoForMatrix(pCar->GetMatrix(), pState); - pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) * 1.0f / (UINT16_MAX / 2)); + pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) / INT16_MAX / 0.5f); pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f); pCar->m_fSteerAngle = pState->wheel / 20.0f; pCar->m_fGasPedal = pState->gas / 100.0f; -- cgit v1.2.3 From 1c0c0a046842c0b937a07e5a957950faf54611af Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 11 Apr 2020 13:20:41 +0300 Subject: fixed malloc/new --- src/control/Record.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index e858bc1d..aead1720 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -40,7 +40,7 @@ void CRecordDataForGame::Init(void) RecordingState = STATE_PLAYBACK; } if (RecordingState == STATE_PLAYBACK) { - pDataBufferPointer = (uint8*)malloc(MEMORY_FOR_GAME_RECORD); + pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD]; pDataBuffer = pDataBufferPointer; pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = -1; CFileMgr::CloseFile(FId); -- cgit v1.2.3 From 0d19036a4278a23db5af75c26a74b8d0e7d61454 Mon Sep 17 00:00:00 2001 From: saml1er Date: Sat, 11 Apr 2020 21:45:49 +0500 Subject: CRoadBlocks complete --- src/control/RoadBlocks.cpp | 226 +++++++++++++++++++++++++++++++++++++++++---- src/control/RoadBlocks.h | 2 +- 2 files changed, 210 insertions(+), 18 deletions(-) (limited to 'src/control') diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index e39fe481..6adcba6b 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -2,36 +2,228 @@ #include "patcher.h" #include "RoadBlocks.h" #include "PathFind.h" +#include "ModelIndices.h" +#include "Streaming.h" +#include "World.h" +#include "PedPlacement.h" +#include "Automobile.h" +#include "CopPed.h" +#include "VisibilityPlugins.h" +#include "PlayerPed.h" +#include "Wanted.h" +#include "Camera.h" +#include "CarCtrl.h" +#include "General.h" int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34; int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8; bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810; -WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); } -WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); } - void CRoadBlocks::Init(void) { - NumRoadBlocks = 0; - for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { - if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { - if (NumRoadBlocks < 600) { - InOrOut[NumRoadBlocks] = true; - RoadBlockObjects[NumRoadBlocks] = objId; - NumRoadBlocks++; - } else { + NumRoadBlocks = 0; + for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { + if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { + if (NumRoadBlocks < 600) { + InOrOut[NumRoadBlocks] = true; + RoadBlockObjects[NumRoadBlocks] = objId; + NumRoadBlocks++; + } else { #ifndef MASTER - printf("Not enough room for the potential roadblocks\n"); + printf("Not enough room for the potential roadblocks\n"); #endif - // FIX: Don't iterate loop after NUMROADBLOCKS - return; - } - } - } + // FIX: Don't iterate loop after NUMROADBLOCKS + return; + } + } + } + +} + +void +CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode) +{ + 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} }; + CEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle(); + if (!pEntityToAttack) + pEntityToAttack = (CEntity*)FindPlayerPed(); + CColModel* pPoliceColModel = CModelInfo::GetModelInfo(MI_POLICE)->GetColModel(); + float fRadius = pVehicle->GetBoundRadius() / pPoliceColModel->boundingSphere.radius; + for (int32 i = 0; i < 2; i++) { + const int32 roadBlockIndex = i + 2 * roadBlockType; + CVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]); + int32 modelInfoId = 0; + eCopType copType = COP_STREET; + switch (pVehicle->GetModelIndex()) + { + case MI_FBICAR: + modelInfoId = MI_FBI; + copType = COP_FBI; + break; + case MI_MOONBEAM: + case MI_ESPERANT: + case MI_TAXI: + case MI_KURUMA: + case MI_BOBCAT: + case MI_MRWHOOP: + case MI_BFINJECT: + case MI_CORPSE: + case MI_POLICE: + case MI_SECURICA: + case MI_BANSHEE: + case MI_PREDATOR: + case MI_BUS: + case MI_RHINO: + copType = COP_STREET; + modelInfoId = MI_COP; + break; + case MI_ENFORCER: + modelInfoId = MI_SWAT; + copType = COP_SWAT; + break; + case MI_BARRACKS: + modelInfoId = MI_ARMY; + copType = COP_ARMY; + break; + } + if (!CStreaming::HasModelLoaded(modelInfoId)) + copType = COP_STREET; + CCopPed* pCopPed = new CCopPed(copType); + if (copType == COP_STREET) + pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45); + CPedPlacement::FindZCoorForPed(&posForZ); + pCopPed->m_matrix.GetPosition() = posForZ; + CVector vecSavedPos = pCopPed->m_matrix.GetPosition(); + pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI); + pCopPed->m_matrix.GetPosition() += vecSavedPos; + pCopPed->m_bIsDisabledCop = true; + pCopPed->SetIdle(); + pCopPed->bKindaStayInSamePlace = true; + pCopPed->bNotAllowedToDuck = false; + pCopPed->m_wRoadblockNode = roadBlockNode; + pCopPed->bCrouchWhenShooting = roadBlockType != 2; + if (pEntityToAttack) { + pCopPed->m_pPointGunAt = pEntityToAttack; + pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt); + pCopPed->SetAttack(pEntityToAttack); + } + pCopPed->m_pMyVehicle = pVehicle; + pVehicle->RegisterReference((CEntity**)&pCopPed->m_pMyVehicle); + pCopPed->bCullExtraFarAway = true; + CVisibilityPlugins::SetClumpAlpha(pCopPed->GetClump(), 0); + CWorld::Add(pCopPed); + } +} +void +CRoadBlocks::GenerateRoadBlocks(void) +{ + CMatrix offsetMatrix; + unsigned int frame = CTimer::GetFrameCounter() & 0xF; + int16 nRoadblockNode = (int16)(600 * frame) / 16; + const int16 maxRoadBlocks = (int16)(600 * (frame + 1)) / 16; + int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks; + if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks) + numRoadBlocks = maxRoadBlocks; + for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) { + CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]]; + CVector2D direction = FindPlayerCoors() - mapObject->GetPosition(); + if ((direction.x <= -80.0f || direction.x < 80.0f) || (direction.y <= -80.0f || direction.y < 80.0f)) { + CRoadBlocks::InOrOut[nRoadblockNode] = false; + continue; + } + if (direction.Magnitude() < 80.0f) { + CRoadBlocks::InOrOut[nRoadblockNode] = false; + continue; + } + else if (!CRoadBlocks::InOrOut[nRoadblockNode]) { + CRoadBlocks::InOrOut[nRoadblockNode] = true; + } + else { + continue; + } + if (!FindPlayerVehicle()) + continue; + CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; + if ((CGeneral::GetRandomNumber() & 0x7F) >= pPlayerWanted->m_RoadblockDensity) + continue; + float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; + int32 vehicleId = MI_POLICE; + if (pPlayerWanted->AreArmyRequired()) + vehicleId = MI_BARRACKS; + else if (pPlayerWanted->AreFbiRequired()) + vehicleId = MI_FBICAR; + else if (pPlayerWanted->AreSwatRequired()) + vehicleId = MI_ENFORCER; + if (!CStreaming::HasModelLoaded(vehicleId)) + vehicleId = MI_POLICE; + CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); + float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; + int16 radius = (int16)(fMapObjectRadius / fModelRadius); + if (radius >= 6) + continue; + CVector2D directionToCamera = TheCamera.m_matrix.GetPosition() - mapObject->m_matrix.GetPosition(); + float fDotProduct = DotProduct2D(directionToCamera, mapObject->m_matrix.GetUp()); + if (radius <= 0) + continue; + float fOffset = 0.5f * fModelRadius * (float)(radius - 1); + for (int16 modelId = vehicleId; modelId < nRoadblockNode ; modelId++) { + uint8 nRoadblockType = fDotProduct >= 0.0f; + if (CGeneral::GetRandomNumber() & 1) { + offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); + } + else { + nRoadblockType = fDotProduct < 0.0f; + offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); + } + if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) + offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); + else + offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); + CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix; + float fModelRadius = CModelInfo::GetModelInfo(modelId)->GetColModel()->boundingSphere.radius - 0.25f; + int16 colliding = 0; + CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); + if (colliding) + continue; + CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); + pVehicle->m_status = STATUS_ABANDONED; + // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? + vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; + pVehicle->m_matrix = vehicleMatrix; + pVehicle->PlaceOnRoadProperly(); + pVehicle->bIsStatic = false; + pVehicle->m_matrix.UpdateRW(); + pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CCarCtrl::JoinCarWithRoadSystem(pVehicle); + pVehicle->bIsLocked = false; + pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; + pVehicle->AutoPilot.m_nCurrentLane = 0; + pVehicle->AutoPilot.m_nNextLane = 0; + pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f; + pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f; + pVehicle->bExtendedRange = true; + if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) + pVehicle->m_bSirenOrAlarm = true; + if (pVehicle->m_matrix.GetForward().z <= 0.94f) { + delete pVehicle; + } + else { + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); + CWorld::Add(pVehicle); + pVehicle->bCreateRoadBlockPeds = true; + pVehicle->m_nRoadblockType = nRoadblockType; + pVehicle->m_nRoadblockNode = nRoadblockNode; + } + } + } } STARTPATCHES InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP); + InjectHook(0x4376A0, &CRoadBlocks::GenerateRoadBlockCopsForCar, PATCH_JUMP); + InjectHook(0x436FA0, &CRoadBlocks::GenerateRoadBlocks, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h index 3f5868e7..16e3a362 100644 --- a/src/control/RoadBlocks.h +++ b/src/control/RoadBlocks.h @@ -11,6 +11,6 @@ public: static bool (&InOrOut)[NUMROADBLOCKS]; static void Init(void); - static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16); + static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode); static void GenerateRoadBlocks(void); }; -- cgit v1.2.3 From 3c999a1eb85e2b36cace2d4158f4777811174731 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 11 Apr 2020 19:33:39 +0200 Subject: fixed traffic light position --- src/control/TrafficLights.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/control') diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index e4416965..ab9cd92d 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -40,9 +40,9 @@ CTrafficLights::DisplayActualLight(CEntity *ent) for(i = 1; i < 6; i++){ assert(mi->Get2dEffect(i)); yMin = min(yMin, mi->Get2dEffect(i)->pos.y); - yMax = min(yMax, mi->Get2dEffect(i)->pos.y); + yMax = max(yMax, mi->Get2dEffect(i)->pos.y); zMin = min(zMin, mi->Get2dEffect(i)->pos.z); - zMax = min(zMax, mi->Get2dEffect(i)->pos.z); + zMax = max(zMax, mi->Get2dEffect(i)->pos.z); } CVector pos1, pos2; -- cgit v1.2.3 From 60898f39f2527bcef0a2617a8e6081f361c11708 Mon Sep 17 00:00:00 2001 From: saml1er Date: Sun, 12 Apr 2020 02:08:16 +0500 Subject: Improve CRoadBlocks code --- src/control/RoadBlocks.cpp | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) (limited to 'src/control') diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 6adcba6b..5f98b942 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -44,7 +44,7 @@ CRoadBlocks::Init(void) void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode) { - CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f}, + 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} }; CEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle(); if (!pEntityToAttack) @@ -54,7 +54,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType for (int32 i = 0; i < 2; i++) { const int32 roadBlockIndex = i + 2 * roadBlockType; CVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]); - int32 modelInfoId = 0; + int32 modelInfoId = MI_COP; eCopType copType = COP_STREET; switch (pVehicle->GetModelIndex()) { @@ -62,23 +62,6 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType modelInfoId = MI_FBI; copType = COP_FBI; break; - case MI_MOONBEAM: - case MI_ESPERANT: - case MI_TAXI: - case MI_KURUMA: - case MI_BOBCAT: - case MI_MRWHOOP: - case MI_BFINJECT: - case MI_CORPSE: - case MI_POLICE: - case MI_SECURICA: - case MI_BANSHEE: - case MI_PREDATOR: - case MI_BUS: - case MI_RHINO: - copType = COP_STREET; - modelInfoId = MI_COP; - break; case MI_ENFORCER: modelInfoId = MI_SWAT; copType = COP_SWAT; @@ -121,7 +104,7 @@ void CRoadBlocks::GenerateRoadBlocks(void) { CMatrix offsetMatrix; - unsigned int frame = CTimer::GetFrameCounter() & 0xF; + uint32 frame = CTimer::GetFrameCounter() & 0xF; int16 nRoadblockNode = (int16)(600 * frame) / 16; const int16 maxRoadBlocks = (int16)(600 * (frame + 1)) / 16; int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks; @@ -137,11 +120,9 @@ CRoadBlocks::GenerateRoadBlocks(void) if (direction.Magnitude() < 80.0f) { CRoadBlocks::InOrOut[nRoadblockNode] = false; continue; - } - else if (!CRoadBlocks::InOrOut[nRoadblockNode]) { + } else if (!CRoadBlocks::InOrOut[nRoadblockNode]) { CRoadBlocks::InOrOut[nRoadblockNode] = true; - } - else { + } else { continue; } if (!FindPlayerVehicle()) @@ -173,8 +154,7 @@ CRoadBlocks::GenerateRoadBlocks(void) uint8 nRoadblockType = fDotProduct >= 0.0f; if (CGeneral::GetRandomNumber() & 1) { offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); - } - else { + } else { nRoadblockType = fDotProduct < 0.0f; offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); } @@ -208,15 +188,14 @@ CRoadBlocks::GenerateRoadBlocks(void) pVehicle->bExtendedRange = true; if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) pVehicle->m_bSirenOrAlarm = true; - if (pVehicle->m_matrix.GetForward().z <= 0.94f) { - delete pVehicle; - } - else { + if (pVehicle->m_matrix.GetForward().z > 0.94f) { CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); CWorld::Add(pVehicle); pVehicle->bCreateRoadBlockPeds = true; pVehicle->m_nRoadblockType = nRoadblockType; pVehicle->m_nRoadblockNode = nRoadblockNode; + } else { + delete pVehicle; } } } -- cgit v1.2.3 From 9593a2c000c8fed4a83e26995acdba27074d5f5a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 12 Apr 2020 11:36:51 +0300 Subject: fixed cranes bug --- src/control/Cranes.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp index 021a5c19..33385dae 100644 --- a/src/control/Cranes.cpp +++ b/src/control/Cranes.cpp @@ -410,6 +410,8 @@ void CCrane::FindCarInSectorList(CPtrList* pList) if (pVehicle->GetPosition().x < m_fPickupX1 || pVehicle->GetPosition().x > m_fPickupX2 || pVehicle->GetPosition().y < m_fPickupY1 || pVehicle->GetPosition().y > m_fPickupY2) continue; + if (pVehicle->pDriver) + continue; if (Abs(pVehicle->GetMoveSpeed().x) >= CAR_MOVING_SPEED_THRESHOLD || Abs(pVehicle->GetMoveSpeed().y) >= CAR_MOVING_SPEED_THRESHOLD || Abs(pVehicle->GetMoveSpeed().z) >= CAR_MOVING_SPEED_THRESHOLD) @@ -674,4 +676,4 @@ void CranesLoad(uint8* buf, uint32 size) STARTPATCHES InjectHook(0x5454D0, CranesLoad, PATCH_JUMP); // GenericLoad -ENDPATCHES \ No newline at end of file +ENDPATCHES -- cgit v1.2.3 From 28fb1bdde762bac46d784cba0602dcfb6a98b27f Mon Sep 17 00:00:00 2001 From: saml1er Date: Mon, 13 Apr 2020 05:52:18 +0500 Subject: Fix CRoadBlocks::GenerateRoadBlocks bugs --- src/control/RoadBlocks.cpp | 151 +++++++++++++++++++++------------------------ 1 file changed, 72 insertions(+), 79 deletions(-) (limited to 'src/control') diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 5f98b942..90564e93 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -113,89 +113,82 @@ CRoadBlocks::GenerateRoadBlocks(void) for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) { CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]]; CVector2D direction = FindPlayerCoors() - mapObject->GetPosition(); - if ((direction.x <= -80.0f || direction.x < 80.0f) || (direction.y <= -80.0f || direction.y < 80.0f)) { + if (!((direction.x > -80.0f && direction.x < 80.0f) && (direction.y > -80.0f && direction.y < 80.0f))) { CRoadBlocks::InOrOut[nRoadblockNode] = false; - continue; } - if (direction.Magnitude() < 80.0f) { + else if (direction.Magnitude() >= 80.0f) { CRoadBlocks::InOrOut[nRoadblockNode] = false; - continue; - } else if (!CRoadBlocks::InOrOut[nRoadblockNode]) { - CRoadBlocks::InOrOut[nRoadblockNode] = true; - } else { - continue; } - if (!FindPlayerVehicle()) - continue; - CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; - if ((CGeneral::GetRandomNumber() & 0x7F) >= pPlayerWanted->m_RoadblockDensity) - continue; - float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; - int32 vehicleId = MI_POLICE; - if (pPlayerWanted->AreArmyRequired()) - vehicleId = MI_BARRACKS; - else if (pPlayerWanted->AreFbiRequired()) - vehicleId = MI_FBICAR; - else if (pPlayerWanted->AreSwatRequired()) - vehicleId = MI_ENFORCER; - if (!CStreaming::HasModelLoaded(vehicleId)) - vehicleId = MI_POLICE; - CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); - float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; - int16 radius = (int16)(fMapObjectRadius / fModelRadius); - if (radius >= 6) - continue; - CVector2D directionToCamera = TheCamera.m_matrix.GetPosition() - mapObject->m_matrix.GetPosition(); - float fDotProduct = DotProduct2D(directionToCamera, mapObject->m_matrix.GetUp()); - if (radius <= 0) - continue; - float fOffset = 0.5f * fModelRadius * (float)(radius - 1); - for (int16 modelId = vehicleId; modelId < nRoadblockNode ; modelId++) { - uint8 nRoadblockType = fDotProduct >= 0.0f; - if (CGeneral::GetRandomNumber() & 1) { - offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); - } else { - nRoadblockType = fDotProduct < 0.0f; - offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); - } - if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) - offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); - else - offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); - CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix; - float fModelRadius = CModelInfo::GetModelInfo(modelId)->GetColModel()->boundingSphere.radius - 0.25f; - int16 colliding = 0; - CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); - if (colliding) - continue; - CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); - pVehicle->m_status = STATUS_ABANDONED; - // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? - vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; - pVehicle->m_matrix = vehicleMatrix; - pVehicle->PlaceOnRoadProperly(); - pVehicle->bIsStatic = false; - pVehicle->m_matrix.UpdateRW(); - pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - CCarCtrl::JoinCarWithRoadSystem(pVehicle); - pVehicle->bIsLocked = false; - pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; - pVehicle->AutoPilot.m_nCurrentLane = 0; - pVehicle->AutoPilot.m_nNextLane = 0; - pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f; - pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f; - pVehicle->bExtendedRange = true; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) - pVehicle->m_bSirenOrAlarm = true; - if (pVehicle->m_matrix.GetForward().z > 0.94f) { - CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); - CWorld::Add(pVehicle); - pVehicle->bCreateRoadBlockPeds = true; - pVehicle->m_nRoadblockType = nRoadblockType; - pVehicle->m_nRoadblockNode = nRoadblockNode; - } else { - delete pVehicle; + else if (!CRoadBlocks::InOrOut[nRoadblockNode]) { + CRoadBlocks::InOrOut[nRoadblockNode] = true; + if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) { + CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; + float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; + int32 vehicleId = MI_POLICE; + if (pPlayerWanted->AreArmyRequired()) + vehicleId = MI_BARRACKS; + else if (pPlayerWanted->AreFbiRequired()) + vehicleId = MI_FBICAR; + else if (pPlayerWanted->AreSwatRequired()) + vehicleId = MI_ENFORCER; + if (!CStreaming::HasModelLoaded(vehicleId)) + vehicleId = MI_POLICE; + CColModel* pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); + float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; + int16 radius = (int16)(fMapObjectRadius / fModelRadius); + if (radius > 0 && radius < 6) { + CVector2D directionToCamera = TheCamera.m_matrix.GetPosition() - mapObject->m_matrix.GetPosition(); + float fDotProduct = DotProduct2D(directionToCamera, mapObject->m_matrix.GetUp()); + float fOffset = 0.5f * fModelRadius * (float)(radius - 1); + for (int16 i = 0; i < radius; i++) { + uint8 nRoadblockType = fDotProduct < 0.0f; + if (CGeneral::GetRandomNumber() & 1) { + offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); + } else { + nRoadblockType = !nRoadblockType; + offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); + } + if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) + offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); + else + offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); + CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix; + float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f; + int16 colliding = 0; + CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); + if (!colliding) { + CAutomobile* pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); + pVehicle->m_status = STATUS_ABANDONED; + // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? + vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; + pVehicle->m_matrix = vehicleMatrix; + pVehicle->PlaceOnRoadProperly(); + pVehicle->bIsStatic = false; + pVehicle->m_matrix.UpdateRW(); + pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CCarCtrl::JoinCarWithRoadSystem(pVehicle); + pVehicle->bIsLocked = false; + pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; + pVehicle->AutoPilot.m_nCurrentLane = 0; + pVehicle->AutoPilot.m_nNextLane = 0; + pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f; + pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f; + pVehicle->bExtendedRange = true; + if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) + pVehicle->m_bSirenOrAlarm = true; + if (pVehicle->m_matrix.GetForward().z > 0.94f) { + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); + CWorld::Add(pVehicle); + pVehicle->bCreateRoadBlockPeds = true; + pVehicle->m_nRoadblockType = nRoadblockType; + pVehicle->m_nRoadblockNode = nRoadblockNode; + } else { + delete pVehicle; + } + } + } + } } } } -- cgit v1.2.3 From 741c9405d0107daf28fefef3c882ba58a791e7d3 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 12 Apr 2020 23:50:34 +0300 Subject: CPacManPickups --- src/control/Pickups.cpp | 458 +++++++++++++++++++++++++++++++++++++++++++++--- src/control/Pickups.h | 25 ++- 2 files changed, 454 insertions(+), 29 deletions(-) (limited to 'src/control') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 16123c63..4b98bcbc 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -54,23 +54,6 @@ uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 25 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 }; -WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); } -WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); } -WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); } -WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); } -WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); } -WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } -WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); } -WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); } -WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); } -WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); } -WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); } -WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); } -WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); } -WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); } -WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); } - - void CPickup::RemoveKeepType() { @@ -289,13 +272,6 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) Remove(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); return true; - //case PICKUP_IN_SHOP_OUT_OF_STOCK: - //case PICKUP_MINE_INACTIVE: - //case PICKUP_MINE_ARMED: - //case PICKUP_NAUTICAL_MINE_INACTIVE: - //case PICKUP_NAUTICAL_MINE_ARMED: - //case PICKUP_FLOATINGPACKAGE: - //case PICKUP_FLOATINGPACKAGE_FLOATING: default: break; } @@ -530,14 +506,12 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan } } - if (!bFreeFound) - { + if (!bFreeFound) { for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { if (aPickUps[slot].m_eType == PICKUP_MONEY) break; } - if (slot >= NUMGENERALPICKUPS) - { + if (slot >= NUMGENERALPICKUPS) { for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break; } @@ -1021,6 +995,417 @@ INITSAVEBUF VALIDATESAVEBUF(*size) } +void +CPacManPickup::Update() +{ + if (FindPlayerVehicle() == nil) return; + + CVehicle *veh = FindPlayerVehicle(); + + if (DistanceSqr2D(FindPlayerVehicle()->GetPosition(), m_vecPosn.x, m_vecPosn.y) < 100.0f && veh->IsSphereTouchingVehicle(m_vecPosn.x, m_vecPosn.y, m_vecPosn.z, 1.5f)) { + switch (m_eType) + { + case PACMAN_SCRAMBLE: + { + veh->m_nPacManPickupsCarried++; + veh->m_vecMoveSpeed *= 0.65f; + float massMult = (veh->m_fMass + 250.0f) / veh->m_fMass; + veh->m_fMass *= massMult; + veh->m_fTurnMass *= massMult; + veh->fForceMultiplier *= massMult; + FindPlayerPed()->m_pWanted->m_nChaos += 10; + FindPlayerPed()->m_pWanted->UpdateWantedLevel(); + DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0); + } + case PACMAN_RACE: + CPacManPickups::PillsEatenInRace++; + DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PILL, 0); + break; + default: + break; + } + m_eType = PACMAN_NONE; + if (m_pObject != nil) { + CWorld::Remove(m_pObject); + delete m_pObject; + m_pObject = nil; + } + } +} + +int32 CollectGameState; +int16 ThingsToCollect; + +CPacManPickup CPacManPickups::aPMPickUps[NUMPACMANPICKUPS]; +CVector CPacManPickups::LastPickUpCoors; +int32 CPacManPickups::PillsEatenInRace; +bool CPacManPickups::bPMActive; + +void +CPacManPickups::Init() +{ + for (int i = 0; i < NUMPACMANPICKUPS; i++) + aPMPickUps[i].m_eType = PACMAN_NONE; + bPMActive = false; +} + +void +CPacManPickups::Update() +{ + if (FindPlayerVehicle()) { + float dist = Distance(FindPlayerCoors(), CVector(1072.0f, -948.0f, 14.5f)); + switch (CollectGameState) { + case 1: + if (dist < 10.0f) { + ThingsToCollect -= FindPlayerVehicle()->m_nPacManPickupsCarried; + FindPlayerVehicle()->m_nPacManPickupsCarried = 0; + FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->fForceMultiplier; + FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->fForceMultiplier; + FindPlayerVehicle()->fForceMultiplier = 1.0f; + } + if (ThingsToCollect <= 0) { + CollectGameState = 2; + ClearPMPickUps(); + } + break; + case 2: + if (dist > 11.0f) + CollectGameState = 0; + break; + case 20: + if (Distance(FindPlayerCoors(), LastPickUpCoors) > 30.0f) { + LastPickUpCoors = FindPlayerCoors(); + printf("%f, %f, %f,\n", LastPickUpCoors.x, LastPickUpCoors.y, LastPickUpCoors.z); + } + break; + default: + break; + } + } + if (bPMActive) { +#define PACMANPICKUPS_FRAME_SPAN (4) + for (uint32 i = (CTimer::GetFrameCounter() % PACMANPICKUPS_FRAME_SPAN) * (NUMPACMANPICKUPS / PACMANPICKUPS_FRAME_SPAN); i < ((CTimer::GetFrameCounter() % PACMANPICKUPS_FRAME_SPAN) + 1) * (NUMPACMANPICKUPS / PACMANPICKUPS_FRAME_SPAN); i++) { + if (aPMPickUps[i].m_eType != PACMAN_NONE) + aPMPickUps[i].Update(); + } +#undef PACMANPICKUPS_FRAME_SPAN + } +} + +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->GetPosition() = 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 +static const CVector aRacePoints1[] = { + CVector(913.62219f, -155.13692f, 4.9699469f), + CVector(913.92401f, -124.12943f, 4.9692569f), + CVector(913.27899f, -93.524231f, 7.4325991f), + CVector(912.60852f, -63.15905f, 7.4533591f), + CVector(934.22144f, -42.049122f, 7.4511471f), + CVector(958.88092f, -23.863735f, 7.4652338f), + CVector(978.50812f, -0.78458798f, 5.13515f), + CVector(1009.4175f, -2.1041219f, 2.4461579f), + CVector(1040.6313f, -2.0793829f, 2.293175f), + CVector(1070.7863f, -2.084095f, 2.2789791f), + CVector(1100.5773f, -8.468729f, 5.3248072f), + CVector(1119.9341f, -31.738031f, 7.1913071f), + CVector(1122.1664f, -62.762737f, 7.4703908f), + CVector(1122.814f, -93.650566f, 8.5577497f), + CVector(1125.8253f, -124.26616f, 9.9803305f), + CVector(1153.8727f, -135.47169f, 14.150617f), + CVector(1184.0831f, -135.82845f, 14.973998f), + CVector(1192.0432f, -164.57816f, 19.18627f), + CVector(1192.7761f, -194.28871f, 24.799675f), + CVector(1215.1527f, -215.0714f, 25.74975f), + CVector(1245.79f, -215.39304f, 28.70726f), + CVector(1276.2477f, -216.39485f, 33.71236f), + CVector(1306.5535f, -216.71007f, 39.711472f), + CVector(1335.0244f, -224.59329f, 46.474979f), + CVector(1355.4879f, -246.27664f, 49.934841f), + CVector(1362.6003f, -276.47064f, 49.96265f), + CVector(1363.027f, -307.30847f, 49.969173f), + CVector(1365.343f, -338.08609f, 49.967789f), + CVector(1367.5957f, -368.01105f, 50.092304f), + CVector(1368.2749f, -398.38049f, 50.061268f), + CVector(1366.9034f, -429.98483f, 50.057545f), + CVector(1356.8534f, -459.09259f, 50.035545f), + CVector(1335.5819f, -481.13544f, 47.217903f), + CVector(1306.7552f, -491.07443f, 40.202629f), + CVector(1275.5978f, -491.33194f, 33.969223f), + CVector(1244.702f, -491.46451f, 29.111021f), + CVector(1213.2222f, -491.8754f, 25.771168f), + CVector(1182.7729f, -492.19995f, 24.749964f), + CVector(1152.6874f, -491.42221f, 21.70038f), + CVector(1121.5352f, -491.94604f, 20.075182f), + CVector(1090.7056f, -492.63751f, 17.585758f), + CVector(1059.6008f, -491.65762f, 14.848632f), + CVector(1029.113f, -489.66031f, 14.918498f), + CVector(998.20679f, -486.78107f, 14.945688f), + CVector(968.00555f, -484.91266f, 15.001229f), + CVector(937.74939f, -492.09015f, 14.958629f), + CVector(927.17352f, -520.97736f, 14.972308f), + CVector(929.29749f, -552.08643f, 14.978855f), + CVector(950.69525f, -574.47778f, 14.972788f), + CVector(974.02826f, -593.56024f, 14.966445f), + CVector(989.04779f, -620.12854f, 14.951016f), + CVector(1014.1639f, -637.3905f, 14.966736f), + CVector(1017.5961f, -667.3736f, 14.956415f), + CVector(1041.9735f, -685.94391f, 15.003841f), + CVector(1043.3064f, -716.11298f, 14.974236f), + CVector(1043.5337f, -746.63855f, 14.96919f), + CVector(1044.142f, -776.93823f, 14.965424f), + CVector(1044.2657f, -807.29395f, 14.97171f), + CVector(1017.0797f, -820.1076f, 14.975431f), + CVector(986.23865f, -820.37103f, 14.972883f), + CVector(956.10065f, -820.23291f, 14.981133f), + CVector(925.86914f, -820.19049f, 14.976553f), + CVector(897.69702f, -831.08734f, 14.962709f), + CVector(868.06586f, -835.99237f, 14.970685f), + CVector(836.93054f, -836.84387f, 14.965049f), + CVector(811.63586f, -853.7915f, 15.067576f), + CVector(811.46344f, -884.27368f, 12.247812f), + CVector(811.60651f, -914.70959f, 9.2393751f), + CVector(811.10425f, -945.16272f, 5.817255f), + CVector(816.54584f, -975.64587f, 4.998558f), + CVector(828.2951f, -1003.3685f, 5.0471172f), + CVector(852.28839f, -1021.5963f, 4.9371028f), + CVector(882.50067f, -1025.4459f, 5.14077f), + CVector(912.84821f, -1026.7874f, 8.3415451f), + CVector(943.68274f, -1026.6914f, 11.341879f), + CVector(974.4129f, -1027.3682f, 14.410345f), + CVector(1004.1079f, -1036.0778f, 14.92961f), + CVector(1030.1144f, -1051.1224f, 14.850387f), + CVector(1058.7585f, -1060.342f, 14.821624f), + CVector(1087.7797f, -1068.3263f, 14.800561f), + CVector(1099.8807f, -1095.656f, 11.877907f), + CVector(1130.0005f, -1101.994f, 11.853914f), + CVector(1160.3809f, -1101.6355f, 11.854824f), + CVector(1191.8524f, -1102.1577f, 11.853843f), + CVector(1223.3307f, -1102.7448f, 11.852233f), + CVector(1253.564f, -1098.1045f, 11.853944f), + CVector(1262.0203f, -1069.1785f, 14.8147f), + CVector(1290.9998f, -1059.1882f, 14.816016f), + CVector(1316.246f, -1041.0635f, 14.81109f), + CVector(1331.7539f, -1013.835f, 14.81207f), + CVector(1334.0579f, -983.55402f, 14.827253f), + CVector(1323.2429f, -954.23083f, 14.954678f), + CVector(1302.7495f, -932.21216f, 14.962917f), + CVector(1317.418f, -905.89325f, 14.967506f), + CVector(1337.9503f, -883.5025f, 14.969675f), + CVector(1352.6929f, -855.96954f, 14.967854f), + CVector(1357.2388f, -826.26971f, 14.97295f), + CVector(1384.8668f, -812.47693f, 12.907736f), + CVector(1410.8983f, -795.39056f, 12.052228f), + CVector(1433.901f, -775.55811f, 11.96265f), + CVector(1443.8615f, -746.92511f, 11.976114f), + CVector(1457.7015f, -720.00903f, 11.971177f), + CVector(1481.5685f, -701.30237f, 11.977908f), + CVector(1511.4004f, -696.83295f, 11.972709f), + CVector(1542.1796f, -695.61676f, 11.970441f), + CVector(1570.3301f, -684.6239f, 11.969202f), + CVector(0.0f, 0.0f, 0.0f), +}; + +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->GetPosition() = 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 +CPacManPickups::GenerateOnePMPickUp(CVector pos) +{ + bPMActive = true; + aPMPickUps[0].m_eType = PACMAN_RACE; + aPMPickUps[0].m_vecPosn = pos; +} + +void +CPacManPickups::Render() +{ + if (!bPMActive) return; + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[6])); + + RwV3d pos; + float w, h; + + for (int i = 0; i < NUMPACMANPICKUPS; i++) { + switch (aPMPickUps[i].m_eType) + { + case PACMAN_SCRAMBLE: + case PACMAN_RACE: + if (CSprite::CalcScreenCoors(aPMPickUps[i].m_vecPosn, &pos, &w, &h, true) && pos.z < 100.0f) { + if (aPMPickUps[i].m_pObject != nil) { + aPMPickUps[i].m_pObject->GetMatrix().SetRotateZOnly((CTimer::GetTimeInMilliseconds() % 1024) * TWOPI / 1024.0f); + aPMPickUps[i].m_pObject->GetMatrix().UpdateRW(); + aPMPickUps[i].m_pObject->UpdateRwFrame(); + } + float fsin = Sin((CTimer::GetTimeInMilliseconds() % 1024) * 6.28f / 1024.0f); // yes, it is 6.28f when it was TWOPI just now... + CSprite::RenderOneXLUSprite(pos.x, pos.y, pos.z, 0.8f * w * fsin, 0.8f * h, 100, 50, 5, 255, 1.0f / pos.z, 255); + } + break; + default: + break; + } + } + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE); +} + +void +CPacManPickups::ClearPMPickUps() +{ + bPMActive = false; + + for (int i = 0; i < NUMPACMANPICKUPS; i++) { + if (aPMPickUps[i].m_pObject != nil) { + CWorld::Remove(aPMPickUps[i].m_pObject); + delete aPMPickUps[i].m_pObject; + aPMPickUps[i].m_pObject = nil; + } + aPMPickUps[i].m_eType = PACMAN_NONE; + } +} + +void +CPacManPickups::StartPacManRace(int32 race) +{ + GeneratePMPickUpsForRace(race); + PillsEatenInRace = 0; +} + +void +CPacManPickups::StartPacManRecord() +{ + CollectGameState = 20; + LastPickUpCoors = FindPlayerCoors(); +} + +uint32 +CPacManPickups::QueryPowerPillsEatenInRace() +{ + return PillsEatenInRace; +} + +void +CPacManPickups::ResetPowerPillsEatenInRace() +{ + PillsEatenInRace = 0; +} + +void +CPacManPickups::CleanUpPacManStuff() +{ + ClearPMPickUps(); +} + +void +CPacManPickups::StartPacManScramble(CVector pos, float scrambleMult, int16 count) +{ + GeneratePMPickUps(pos, scrambleMult, count, PACMAN_SCRAMBLE); +} + +uint32 +CPacManPickups::QueryPowerPillsCarriedByPlayer() +{ + if (FindPlayerVehicle()) + return FindPlayerVehicle()->m_nPacManPickupsCarried; + return 0; +} + +void +CPacManPickups::ResetPowerPillsCarriedByPlayer() +{ + if (FindPlayerVehicle() != nil) { + FindPlayerVehicle()->m_nPacManPickupsCarried = 0; + FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->fForceMultiplier; + FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->fForceMultiplier; + FindPlayerVehicle()->fForceMultiplier = 1.0f; + } +} + STARTPATCHES InjectHook(0x430220, CPickups::Init, PATCH_JUMP); InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP); @@ -1046,4 +1431,21 @@ STARTPATCHES InjectHook(0x433E40, CPickups::Save, PATCH_JUMP); InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP); InjectHook(0x430860, &CPickup::Update, PATCH_JUMP); + InjectHook(0x4331B0, &CPacManPickup::Update, PATCH_JUMP); + InjectHook(0x432760, CPacManPickups::Init, PATCH_JUMP); + InjectHook(0x432800, CPacManPickups::Update, PATCH_JUMP); + InjectHook(0x432AE0, CPacManPickups::GeneratePMPickUps, PATCH_JUMP); + InjectHook(0x432D50, CPacManPickups::GeneratePMPickUpsForRace, PATCH_JUMP); + InjectHook(0x432F20, CPacManPickups::GenerateOnePMPickUp, PATCH_JUMP); + InjectHook(0x432F60, CPacManPickups::Render, PATCH_JUMP); + InjectHook(0x433150, CPacManPickups::ClearPMPickUps, PATCH_JUMP); + InjectHook(0x433340, CPacManPickups::StartPacManRace, PATCH_JUMP); + InjectHook(0x433360, CPacManPickups::StartPacManRecord, PATCH_JUMP); + InjectHook(0x4333A0, CPacManPickups::QueryPowerPillsEatenInRace, PATCH_JUMP); + InjectHook(0x4333B0, CPacManPickups::ResetPowerPillsEatenInRace, PATCH_JUMP); + InjectHook(0x4333C0, CPacManPickups::CleanUpPacManStuff, PATCH_JUMP); + InjectHook(0x4333D0, CPacManPickups::StartPacManScramble, PATCH_JUMP); + InjectHook(0x4333F0, CPacManPickups::QueryPowerPillsCarriedByPlayer, PATCH_JUMP); + InjectHook(0x433410, CPacManPickups::ResetPowerPillsCarriedByPlayer, PATCH_JUMP); + ENDPATCHES diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 3e075b24..b5b4f396 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -102,8 +102,31 @@ extern uint16 AmmoForWeapon[20]; extern uint16 AmmoForWeapon_OnStreet[20]; extern uint16 CostOfWeapon[20]; +enum ePacmanPickupType +{ + PACMAN_NONE, + PACMAN_SCRAMBLE, + PACMAN_RACE, +}; + +class CPacManPickup +{ +public: + CVector m_vecPosn; + CObject *m_pObject; + uint8 m_eType; + + void Update(); +}; + class CPacManPickups { + friend CPacManPickup; + + static CPacManPickup aPMPickUps[NUMPACMANPICKUPS]; + static CVector LastPickUpCoors; + static int PillsEatenInRace; + static bool bPMActive; public: static void Init(void); static void Update(void); @@ -111,11 +134,11 @@ public: static void GeneratePMPickUpsForRace(int32); static void GenerateOnePMPickUp(CVector); static void Render(void); - static void DoCleanUpPacManStuff(void); static void StartPacManRace(int32); static void StartPacManRecord(void); static uint32 QueryPowerPillsEatenInRace(void); static void ResetPowerPillsEatenInRace(void); + static void ClearPMPickUps(void); static void CleanUpPacManStuff(void); static void StartPacManScramble(CVector, float, int16); static uint32 QueryPowerPillsCarriedByPlayer(void); -- cgit v1.2.3 From 68f8a6a9edb0197738f2ae99e42571b28181b2c9 Mon Sep 17 00:00:00 2001 From: saml1er Date: Mon, 13 Apr 2020 15:21:39 +0500 Subject: more CRoadBlocks::GenerateRoadBlocks improvements --- src/control/RoadBlocks.cpp | 148 +++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 73 deletions(-) (limited to 'src/control') diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 90564e93..65f039ae 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -112,84 +112,86 @@ CRoadBlocks::GenerateRoadBlocks(void) numRoadBlocks = maxRoadBlocks; for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) { CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]]; - CVector2D direction = FindPlayerCoors() - mapObject->GetPosition(); - if (!((direction.x > -80.0f && direction.x < 80.0f) && (direction.y > -80.0f && direction.y < 80.0f))) { - CRoadBlocks::InOrOut[nRoadblockNode] = false; - } - else if (direction.Magnitude() >= 80.0f) { - CRoadBlocks::InOrOut[nRoadblockNode] = false; - } - else if (!CRoadBlocks::InOrOut[nRoadblockNode]) { - CRoadBlocks::InOrOut[nRoadblockNode] = true; - if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) { - CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; - float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; - int32 vehicleId = MI_POLICE; - if (pPlayerWanted->AreArmyRequired()) - vehicleId = MI_BARRACKS; - else if (pPlayerWanted->AreFbiRequired()) - vehicleId = MI_FBICAR; - else if (pPlayerWanted->AreSwatRequired()) - vehicleId = MI_ENFORCER; - if (!CStreaming::HasModelLoaded(vehicleId)) - vehicleId = MI_POLICE; - CColModel* pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); - float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; - int16 radius = (int16)(fMapObjectRadius / fModelRadius); - if (radius > 0 && radius < 6) { - CVector2D directionToCamera = TheCamera.m_matrix.GetPosition() - mapObject->m_matrix.GetPosition(); - float fDotProduct = DotProduct2D(directionToCamera, mapObject->m_matrix.GetUp()); - float fOffset = 0.5f * fModelRadius * (float)(radius - 1); - for (int16 i = 0; i < radius; i++) { - uint8 nRoadblockType = fDotProduct < 0.0f; - if (CGeneral::GetRandomNumber() & 1) { - offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); - } else { - nRoadblockType = !nRoadblockType; - offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); - } - if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) - offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); - else - offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); - CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix; - float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f; - int16 colliding = 0; - CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); - if (!colliding) { - CAutomobile* pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); - pVehicle->m_status = STATUS_ABANDONED; - // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? - vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; - pVehicle->m_matrix = vehicleMatrix; - pVehicle->PlaceOnRoadProperly(); - pVehicle->bIsStatic = false; - pVehicle->m_matrix.UpdateRW(); - pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - CCarCtrl::JoinCarWithRoadSystem(pVehicle); - pVehicle->bIsLocked = false; - pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; - pVehicle->AutoPilot.m_nCurrentLane = 0; - pVehicle->AutoPilot.m_nNextLane = 0; - pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f; - pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f; - pVehicle->bExtendedRange = true; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) - pVehicle->m_bSirenOrAlarm = true; - if (pVehicle->m_matrix.GetForward().z > 0.94f) { - CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); - CWorld::Add(pVehicle); - pVehicle->bCreateRoadBlockPeds = true; - pVehicle->m_nRoadblockType = nRoadblockType; - pVehicle->m_nRoadblockNode = nRoadblockNode; - } else { - delete pVehicle; + CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition(); + if (vecDistance.x > -80.0f && vecDistance.x < 80.0f && + vecDistance.y > -80.0f && vecDistance.y < 80.0f && + vecDistance.Magnitude() < 80.0f) { + if (!CRoadBlocks::InOrOut[nRoadblockNode]) { + CRoadBlocks::InOrOut[nRoadblockNode] = true; + if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) { + CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; + float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; + int32 vehicleId = MI_POLICE; + if (pPlayerWanted->AreArmyRequired()) + vehicleId = MI_BARRACKS; + else if (pPlayerWanted->AreFbiRequired()) + vehicleId = MI_FBICAR; + else if (pPlayerWanted->AreSwatRequired()) + vehicleId = MI_ENFORCER; + if (!CStreaming::HasModelLoaded(vehicleId)) + vehicleId = MI_POLICE; + CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); + float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; + int16 radius = (int16)(fMapObjectRadius / fModelRadius); + if (radius > 0 && radius < 6) { + CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->m_matrix.GetPosition(); + float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->m_matrix.GetUp()); + float fOffset = 0.5f * fModelRadius * (float)(radius - 1); + for (int16 i = 0; i < radius; i++) { + uint8 nRoadblockType = fDotProduct < 0.0f; + if (CGeneral::GetRandomNumber() & 1) { + offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); + } + else { + nRoadblockType = !nRoadblockType; + offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); + } + if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) + offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); + else + offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); + CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix; + float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f; + int16 colliding = 0; + CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); + if (!colliding) { + CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); + pVehicle->m_status = STATUS_ABANDONED; + // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? + vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; + pVehicle->m_matrix = vehicleMatrix; + pVehicle->PlaceOnRoadProperly(); + pVehicle->bIsStatic = false; + pVehicle->m_matrix.UpdateRW(); + pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CCarCtrl::JoinCarWithRoadSystem(pVehicle); + pVehicle->bIsLocked = false; + pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; + pVehicle->AutoPilot.m_nCurrentLane = 0; + pVehicle->AutoPilot.m_nNextLane = 0; + pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f; + pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f; + pVehicle->bExtendedRange = true; + if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) + pVehicle->m_bSirenOrAlarm = true; + if (pVehicle->m_matrix.GetForward().z > 0.94f) { + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); + CWorld::Add(pVehicle); + pVehicle->bCreateRoadBlockPeds = true; + pVehicle->m_nRoadblockType = nRoadblockType; + pVehicle->m_nRoadblockNode = nRoadblockNode; + } + else { + delete pVehicle; + } } } } } } + } else { + CRoadBlocks::InOrOut[nRoadblockNode] = false; } } } -- cgit v1.2.3 From d8be75ac46cf9e0e1056e94973cdf1c328bbf52e Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 13 Apr 2020 15:21:26 +0300 Subject: Fix compilation error --- src/control/Pickups.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/control') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 4b98bcbc..80e89ee8 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1012,7 +1012,7 @@ CPacManPickup::Update() float massMult = (veh->m_fMass + 250.0f) / veh->m_fMass; veh->m_fMass *= massMult; veh->m_fTurnMass *= massMult; - veh->fForceMultiplier *= massMult; + veh->m_fForceMultiplier *= massMult; FindPlayerPed()->m_pWanted->m_nChaos += 10; FindPlayerPed()->m_pWanted->UpdateWantedLevel(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0); @@ -1059,9 +1059,9 @@ CPacManPickups::Update() if (dist < 10.0f) { ThingsToCollect -= FindPlayerVehicle()->m_nPacManPickupsCarried; FindPlayerVehicle()->m_nPacManPickupsCarried = 0; - FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->fForceMultiplier; - FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->fForceMultiplier; - FindPlayerVehicle()->fForceMultiplier = 1.0f; + FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->m_fForceMultiplier; + FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->m_fForceMultiplier; + FindPlayerVehicle()->m_fForceMultiplier = 1.0f; } if (ThingsToCollect <= 0) { CollectGameState = 2; @@ -1400,9 +1400,9 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer() { if (FindPlayerVehicle() != nil) { FindPlayerVehicle()->m_nPacManPickupsCarried = 0; - FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->fForceMultiplier; - FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->fForceMultiplier; - FindPlayerVehicle()->fForceMultiplier = 1.0f; + FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->m_fForceMultiplier; + FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->m_fForceMultiplier; + FindPlayerVehicle()->m_fForceMultiplier = 1.0f; } } -- cgit v1.2.3 From 12d36d871016643aae518117efd78a4ffbd3a88c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 13 Apr 2020 22:12:41 +0300 Subject: fixed record --- src/control/Record.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/control') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index aead1720..f41bead4 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -42,7 +42,7 @@ void CRecordDataForGame::Init(void) if (RecordingState == STATE_PLAYBACK) { pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD]; pDataBuffer = pDataBufferPointer; - pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = -1; + pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1; CFileMgr::CloseFile(FId); } #else @@ -71,7 +71,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) break; } case STATE_PLAYBACK: - if (pDataBufferPointer[8] == -1) + if (pDataBufferPointer[8] == (uint8)-1) CPad::GetPad(0)->NewState.Clear(); else { tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer; @@ -92,7 +92,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) #define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \ do { \ - if (os->field != os->field){ \ + if (os->field != ns->field){ \ *buf++ = id; \ *buf++ = ns->field; \ } \ -- cgit v1.2.3 From c21529467adcdf98d369bb461e100b44333b0b81 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 13 Apr 2020 22:16:51 +0300 Subject: fixed record --- src/control/Record.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/control') diff --git a/src/control/Record.cpp b/src/control/Record.cpp index f41bead4..ca4128e3 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -21,8 +21,7 @@ tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0; void CRecordDataForGame::Init(void) { RecordingState = STATE_NONE; - if (pDataBuffer) - delete[] pDataBuffer; + delete[] pDataBuffer; pDataBufferPointer = nil; pDataBuffer = nil; #ifndef GTA_PS2 // this stuff is not present on PS2 @@ -102,7 +101,7 @@ uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os { PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0); PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1); - PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 2); + PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2); PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3); PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4); PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5); @@ -132,7 +131,7 @@ uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CCont switch (*buf++) { PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0); PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1); - PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 2); + PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2); PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3); PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4); PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5); -- cgit v1.2.3 From 304b574eba47a4bce472ceabf5f0af27fc461d20 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 13 Apr 2020 22:25:24 +0300 Subject: added missing break --- src/control/Pickups.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/control') diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 80e89ee8..eb561670 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1016,6 +1016,7 @@ CPacManPickup::Update() FindPlayerPed()->m_pWanted->m_nChaos += 10; FindPlayerPed()->m_pWanted->UpdateWantedLevel(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0); + break; } case PACMAN_RACE: CPacManPickups::PillsEatenInRace++; -- cgit v1.2.3 From 906133d3be4f3bb5c6c0b234f1cd642b5d1daaee Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 13 Apr 2020 22:43:41 +0300 Subject: fix garages --- src/control/Garages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 84d49bee..d971d453 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -2108,7 +2108,7 @@ void CGarages::CloseHideOutGaragesBeforeSave() aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE) continue; if (aGarages[i].m_eGarageState != GS_FULLYCLOSED && - aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor()) { + (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) { aGarages[i].m_eGarageState = GS_FULLYCLOSED; switch (aGarages[i].m_eGarageType) { case GARAGE_HIDEOUT_ONE: -- cgit v1.2.3 From 60eb60de4e0d3a9b2b52d40617205efe134199b7 Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 02:13:00 +0500 Subject: Use NUMROADBLOCKS enum member in CRoadBlocks --- src/control/RoadBlocks.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/control') diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 65f039ae..9548bc0a 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -25,7 +25,7 @@ CRoadBlocks::Init(void) NumRoadBlocks = 0; for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { - if (NumRoadBlocks < 600) { + if (NumRoadBlocks < NUMROADBLOCKS) { InOrOut[NumRoadBlocks] = true; RoadBlockObjects[NumRoadBlocks] = objId; NumRoadBlocks++; @@ -105,8 +105,8 @@ CRoadBlocks::GenerateRoadBlocks(void) { CMatrix offsetMatrix; uint32 frame = CTimer::GetFrameCounter() & 0xF; - int16 nRoadblockNode = (int16)(600 * frame) / 16; - const int16 maxRoadBlocks = (int16)(600 * (frame + 1)) / 16; + int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16; + const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16; int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks; if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks) numRoadBlocks = maxRoadBlocks; -- cgit v1.2.3 From a19fa8764f63b4521873bbee8d2549c23d4be70a Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 14 Apr 2020 13:08:03 +0300 Subject: CarGen, Cranes, Gangs: cleanup, fixes, r* visioned placement --- src/control/CarGen.cpp | 312 ----------------------- src/control/CarGen.h | 56 ---- src/control/Cranes.cpp | 679 ------------------------------------------------- src/control/Cranes.h | 98 ------- src/control/Gangs.cpp | 89 ------- src/control/Gangs.h | 44 ---- 6 files changed, 1278 deletions(-) delete mode 100644 src/control/CarGen.cpp delete mode 100644 src/control/CarGen.h delete mode 100644 src/control/Cranes.cpp delete mode 100644 src/control/Cranes.h delete mode 100644 src/control/Gangs.cpp delete mode 100644 src/control/Gangs.h (limited to 'src/control') diff --git a/src/control/CarGen.cpp b/src/control/CarGen.cpp deleted file mode 100644 index 721ac35a..00000000 --- a/src/control/CarGen.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#include "common.h" -#include "patcher.h" -#include "CarGen.h" - -#include "Automobile.h" -#include "Boat.h" -#include "Camera.h" -#include "CarCtrl.h" -#include "CutsceneMgr.h" -#include "General.h" -#include "Pools.h" -#include "Streaming.h" -#include "Timer.h" -#include "Vehicle.h" -#include "World.h" - -uint8 &CTheCarGenerators::ProcessCounter = *(uint8*)0x95CDAF; -uint32 &CTheCarGenerators::NumOfCarGenerators = *(uint32*)0x8E2C1C; -CCarGenerator (&CTheCarGenerators::CarGeneratorArray)[NUM_CARGENS] = *(CCarGenerator(*)[NUM_CARGENS])*(uintptr*)0x87CB18; -uint8 &CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = *(uint8*)0x95CDC6; -uint32 &CTheCarGenerators::CurrentActiveCount = *(uint32*)0x8F2C5C; - -void CCarGenerator::SwitchOff() -{ - m_nUsesRemaining = 0; - --CTheCarGenerators::CurrentActiveCount; -} - -void CCarGenerator::SwitchOn() -{ - m_nUsesRemaining = -1; - m_nTimer = CalcNextGen(); - ++CTheCarGenerators::CurrentActiveCount; -} - -uint32 CCarGenerator::CalcNextGen() -{ - return CTimer::GetTimeInMilliseconds() + 4; -} - -void CCarGenerator::DoInternalProcessing() -{ - if (CheckForBlockage()) { - m_nTimer += 4; - if (m_nUsesRemaining == 0) - --CTheCarGenerators::CurrentActiveCount; - return; - } - if (CCarCtrl::NumParkedCars >= 10) - return; - CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY); - if (!CStreaming::HasModelLoaded(m_nModelIndex)) - return; - if (CModelInfo::IsBoatModel(m_nModelIndex)){ - CBoat* pBoat = new CBoat(m_nModelIndex, PARKED_VEHICLE); - pBoat->bIsStatic = false; - pBoat->bEngineOn = false; - CVector pos = m_vecPos; - if (pos.z <= -100.0f) - pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pos.z += pBoat->GetDistanceFromCentreOfMassToBaseOfModel(); - pBoat->GetPosition() = pos; - pBoat->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); - pBoat->m_status = STATUS_ABANDONED; - pBoat->m_nDoorLock = CARLOCK_UNLOCKED; - CWorld::Add(pBoat); - if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm) - pBoat->m_nAlarmState = -1; - if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock) - pBoat->m_nDoorLock = CARLOCK_LOCKED; - if (m_nColor1 != -1 && m_nColor2){ - pBoat->m_currentColour1 = m_nColor1; - pBoat->m_currentColour2 = m_nColor2; - } - m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat); - }else{ - bool groundFound = false; - CVector pos = m_vecPos; - if (pos.z > -100.0f){ - pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound); - }else{ - CColPoint cp; - CEntity* pEntity; - groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f, - cp, pEntity, true, false, false, false, false, false, nil); - if (groundFound) - pos.z = cp.point.z; - } - if (!groundFound) { - debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y); - }else{ - CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE); - pCar->bIsStatic = false; - pCar->bEngineOn = false; - pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel(); - pCar->GetPosition() = pos; - pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); - pCar->m_status = STATUS_ABANDONED; - pCar->bLightsOn = false; - pCar->m_nDoorLock = CARLOCK_UNLOCKED; - CWorld::Add(pCar); - if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm) - pCar->m_nAlarmState = -1; - if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock) - pCar->m_nDoorLock = CARLOCK_LOCKED; - if (m_nColor1 != -1 && m_nColor2) { - pCar->m_currentColour1 = m_nColor1; - pCar->m_currentColour2 = m_nColor2; - } - m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pCar); - } - } - if (m_nUsesRemaining < -1) /* I don't think this is a correct comparasion */ - --m_nUsesRemaining; - m_nTimer = CalcNextGen(); - if (m_nUsesRemaining == 0) - --CTheCarGenerators::CurrentActiveCount; -} - -void CCarGenerator::Process() -{ - if (m_nVehicleHandle == -1 && - (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) && - m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayer()) - DoInternalProcessing(); - if (m_nVehicleHandle == -1) - return; - CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_nVehicleHandle); - if (!pVehicle){ - m_nVehicleHandle = -1; - return; - } - if (pVehicle->m_status != STATUS_PLAYER) - return; - m_nTimer += 60000; - m_nVehicleHandle = -1; - m_bIsBlocking = true; - pVehicle->bExtendedRange = false; -} - -void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay) -{ - CMatrix m1, m2, m3; /* Unused but present on stack, so I'll leave them. */ - m_vecPos = CVector(x, y, z); - m_fAngle = angle; - m_nModelIndex = mi; - m_nColor1 = color1; - m_nColor2 = color2; - m_bForceSpawn = force; - m_nAlarm = alarm; - m_nDoorlock = lock; - m_nMinDelay = min_delay; - m_nMaxDelay = max_delay; - m_nVehicleHandle = -1; - m_nTimer = CTimer::GetTimeInMilliseconds() + 1; - m_nUsesRemaining = 0; - m_bIsBlocking = false; - m_vecInf = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.min; - m_vecSup = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.max; - m_fSize = max(m_vecInf.Magnitude(), m_vecSup.Magnitude()); -} - -bool CCarGenerator::CheckForBlockage() -{ - int16 entities; - CWorld::FindObjectsKindaColliding(CVector(m_vecPos), m_fSize, 1, &entities, 2, nil, false, true, true, false, false); - return entities > 0; -} - -bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer() -{ - CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos; - float distance = direction.Magnitude(); - float farclip = 120.0f * TheCamera.GenerationDistMultiplier; - float nearclip = farclip - 20.0f; - if (distance >= farclip){ - if (m_bIsBlocking) - m_bIsBlocking = false; - return false; - } - if (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter) - return true; - if (m_bIsBlocking) - return false; - if (distance < nearclip) - return false; - return DotProduct2D(direction, FindPlayerSpeed()) <= 0; -} - -void CCarGenerator::Save(uint8 *&buffer) -{ - WriteSaveBuf(buffer, m_nModelIndex); - WriteSaveBuf(buffer, m_vecPos); - WriteSaveBuf(buffer, m_fAngle); - WriteSaveBuf(buffer, m_nColor1); - WriteSaveBuf(buffer, m_nColor2); - WriteSaveBuf(buffer, m_bForceSpawn); - WriteSaveBuf(buffer, m_nAlarm); - WriteSaveBuf(buffer, m_nDoorlock); - WriteSaveBuf(buffer, (uint8)0); - WriteSaveBuf(buffer, m_nMinDelay); - WriteSaveBuf(buffer, m_nMaxDelay); - WriteSaveBuf(buffer, m_nTimer); - WriteSaveBuf(buffer, m_nVehicleHandle); - WriteSaveBuf(buffer, m_nUsesRemaining); - WriteSaveBuf(buffer, m_bIsBlocking); - WriteSaveBuf(buffer, (uint8)0); - WriteSaveBuf(buffer, m_vecInf); - WriteSaveBuf(buffer, m_vecSup); - WriteSaveBuf(buffer, m_fSize); - - // or - //WriteSaveBuf(buffer, *this); - -} - -void CCarGenerator::Load(uint8 *&buffer) -{ - m_nModelIndex = ReadSaveBuf(buffer); - m_vecPos = ReadSaveBuf(buffer); - m_fAngle = ReadSaveBuf(buffer); - m_nColor1 = ReadSaveBuf(buffer); - m_nColor2 = ReadSaveBuf(buffer); - m_bForceSpawn = ReadSaveBuf(buffer); - m_nAlarm = ReadSaveBuf(buffer); - m_nDoorlock = ReadSaveBuf(buffer); - ReadSaveBuf(buffer); - m_nMinDelay = ReadSaveBuf(buffer); - m_nMaxDelay = ReadSaveBuf(buffer); - m_nTimer = ReadSaveBuf(buffer); - m_nVehicleHandle = ReadSaveBuf(buffer); - m_nUsesRemaining = ReadSaveBuf(buffer); - m_bIsBlocking = ReadSaveBuf(buffer); - ReadSaveBuf(buffer); - m_vecInf = ReadSaveBuf(buffer); - m_vecSup = ReadSaveBuf(buffer); - m_fSize = ReadSaveBuf(buffer); - - // or - //*this = ReadSaveBuf(buffer); -} - -void CTheCarGenerators::Process() -{ - if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing()) - return; - if (++CTheCarGenerators::ProcessCounter == 4) - CTheCarGenerators::ProcessCounter = 0; - for (uint32 i = ProcessCounter; i < NumOfCarGenerators; i += 4) - CTheCarGenerators::CarGeneratorArray[i].Process(); - if (GenerateEvenIfPlayerIsCloseCounter) - GenerateEvenIfPlayerIsCloseCounter--; -} - -int32 CTheCarGenerators::CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay) -{ - CarGeneratorArray[NumOfCarGenerators].Setup(x, y, z, angle, mi, color1, color2, force, alarm, lock, min_delay, max_delay); - return NumOfCarGenerators++; -} - -void CTheCarGenerators::Init() -{ - GenerateEvenIfPlayerIsCloseCounter = 0; - NumOfCarGenerators = 0; - ProcessCounter = 0; - CurrentActiveCount = 0; -} - -void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size) -{ - *size = 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE; -INITSAVEBUF - WriteSaveHeader(buffer, 'C','G','N','\0', *size - SAVE_HEADER_SIZE); - - WriteSaveBuf(buffer, 12); /* what is this? */ - WriteSaveBuf(buffer, NumOfCarGenerators); - WriteSaveBuf(buffer, CurrentActiveCount); - WriteSaveBuf(buffer, ProcessCounter); - WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter); - WriteSaveBuf(buffer, (int16)0); - WriteSaveBuf(buffer, sizeof(CarGeneratorArray)); - for (int i = 0; i < NUM_CARGENS; i++){ - CarGeneratorArray[i].Save(buffer); - } -VALIDATESAVEBUF(*size) -} - -void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size) -{ - Init(); -INITSAVEBUF - assert(size == 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE); - CheckSaveHeader(buffer, 'C','G','N','\0', size - SAVE_HEADER_SIZE); - ReadSaveBuf(buffer); - NumOfCarGenerators = ReadSaveBuf(buffer); - CurrentActiveCount = ReadSaveBuf(buffer); - ProcessCounter = ReadSaveBuf(buffer); - GenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf(buffer); - ReadSaveBuf(buffer); - assert(ReadSaveBuf(buffer) == sizeof(CarGeneratorArray)); - for (int i = 0; i < NUM_CARGENS; i++) { - CarGeneratorArray[i].Load(buffer); - } -VALIDATESAVEBUF(size) -} - -STARTPATCHES -InjectHook(0x543020, CTheCarGenerators::Init, PATCH_JUMP); -InjectHook(0x542F40, CTheCarGenerators::Process, PATCH_JUMP); -InjectHook(0x543050, CTheCarGenerators::SaveAllCarGenerators, PATCH_JUMP); -InjectHook(0x5431E0, CTheCarGenerators::LoadAllCarGenerators, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/CarGen.h b/src/control/CarGen.h deleted file mode 100644 index 75acdd56..00000000 --- a/src/control/CarGen.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "common.h" -#include "config.h" - -enum { - CARGEN_MAXACTUALLIMIT = 100 -}; - -class CCarGenerator -{ - int32 m_nModelIndex; - CVector m_vecPos; - float m_fAngle; - int16 m_nColor1; - int16 m_nColor2; - uint8 m_bForceSpawn; - uint8 m_nAlarm; - uint8 m_nDoorlock; - int16 m_nMinDelay; - int16 m_nMaxDelay; - uint32 m_nTimer; - int32 m_nVehicleHandle; - uint16 m_nUsesRemaining; - bool m_bIsBlocking; - CVector m_vecInf; - CVector m_vecSup; - float m_fSize; -public: - void SwitchOff(); - void SwitchOn(); - uint32 CalcNextGen(); - void DoInternalProcessing(); - void Process(); - void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay); - bool CheckForBlockage(); - bool CheckIfWithinRangeOfAnyPlayer(); - void Save(uint8*&); - void Load(uint8*&); - void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; } -}; - -class CTheCarGenerators -{ -public: - static uint8 &ProcessCounter; - static uint32 &NumOfCarGenerators; - static CCarGenerator (&CarGeneratorArray)[NUM_CARGENS]; - static uint8 &GenerateEvenIfPlayerIsCloseCounter; - static uint32 &CurrentActiveCount; - - static void Process(); - static int32 CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay); - static void Init(); - static void SaveAllCarGenerators(uint8 *, uint32 *); - static void LoadAllCarGenerators(uint8 *, uint32); -}; diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp deleted file mode 100644 index 33385dae..00000000 --- a/src/control/Cranes.cpp +++ /dev/null @@ -1,679 +0,0 @@ -#include "common.h" -#include "patcher.h" -#include "Cranes.h" - -#include "Camera.h" -#include "DMAudio.h" -#include "Garages.h" -#include "General.h" -#include "Entity.h" -#include "ModelIndices.h" -#include "Replay.h" -#include "Object.h" -#include "World.h" - -#define MAX_DISTANCE_TO_FIND_CRANE (10.0f) -#define CRANE_UPDATE_RADIUS (300.0f) -#define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f) -#define CRUSHER_Z (-0.951f) -#define MILITARY_Z (10.7862f) -#define DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE (5.0f) -#define DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT (0.5f) -#define CAR_REWARD_MILITARY_CRANE (1500) -#define CAR_MOVING_SPEED_THRESHOLD (0.01f) -#define CRANE_SLOWDOWN_MULTIPLIER (0.3f) - -#define OSCILLATION_SPEED (0.002f) -#define CAR_ROTATION_SPEED (0.0035f) -#define CRANE_MOVEMENT_SPEED (0.001f) -#define HOOK_ANGLE_MOVEMENT_SPEED (0.004f) -#define HOOK_OFFSET_MOVEMENT_SPEED (0.1f) -#define HOOK_HEIGHT_MOVEMENT_SPEED (0.06f) - -#define MESSAGE_SHOW_DURATION (4000) - -#define MAX_DISTANCE (99999.9f) -#define MIN_VALID_POSITION (-10000.0f) -#define DEFAULT_OFFSET (20.0f) - -uint32 TimerForCamInterpolation; - -uint32& CCranes::CarsCollectedMilitaryCrane = *(uint32*)0x8F6248; -int32& CCranes::NumCranes = *(int32*)0x8E28AC; -CCrane(&CCranes::aCranes)[NUM_CRANES] = *(CCrane(*)[NUM_CRANES])*(uintptr*)0x6FA4E0; - -void CCranes::InitCranes(void) -{ - CarsCollectedMilitaryCrane = 0; - NumCranes = 0; - for (int i = 0; i < NUMSECTORS_X; i++) { - for (int j = 0; j < NUMSECTORS_Y; j++) { - for (CPtrNode* pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (MODELID_CRANE_1 == pEntity->GetModelIndex() || - MODELID_CRANE_2 == pEntity->GetModelIndex() || - MODELID_CRANE_3 == pEntity->GetModelIndex()) - AddThisOneCrane(pEntity); - } - } - } - for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (MODELID_CRANE_1 == pEntity->GetModelIndex() || - MODELID_CRANE_2 == pEntity->GetModelIndex() || - MODELID_CRANE_3 == pEntity->GetModelIndex()) - AddThisOneCrane(pEntity); - } -} - -void CCranes::AddThisOneCrane(CEntity* pEntity) -{ - pEntity->GetMatrix().ResetOrientation(); - if (NumCranes >= NUM_CRANES) - return; - CCrane* pCrane = &aCranes[NumCranes]; - pCrane->Init(); - pCrane->m_pCraneEntity = (CBuilding*)pEntity; - pCrane->m_nCraneStatus = CCrane::NONE; - pCrane->m_fHookAngle = NumCranes; // lol wtf - while (pCrane->m_fHookAngle > TWOPI) - pCrane->m_fHookAngle -= TWOPI; - pCrane->m_fHookOffset = DEFAULT_OFFSET; - pCrane->m_fHookHeight = DEFAULT_OFFSET; - pCrane->m_nTimeForNextCheck = 0; - pCrane->m_nCraneState = CCrane::IDLE; - pCrane->m_bWasMilitaryCrane = false; - pCrane->m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[NumCranes]); - if (pCrane->m_nAudioEntity >= 0) - DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1); - pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex()); - // Is this used to avoid military crane? - if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) { - CObject* pHook = new CObject(MI_MAGNET, false); - pHook->ObjectCreatedBy = MISSION_OBJECT; - pHook->bUsesCollision = false; - pHook->bExplosionProof = true; - pHook->bAffectedByGravity = false; - pCrane->m_pHook = pHook; - pCrane->CalcHookCoordinates(&pCrane->m_vecHookCurPos.x, &pCrane->m_vecHookCurPos.y, &pCrane->m_vecHookCurPos.z); - pCrane->SetHookMatrix(); - } - else - pCrane->m_pHook = nil; - NumCranes++; -} - -void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY) -{ - float fMinDistance = MAX_DISTANCE; - float X = fPosX, Y = fPosY; - if (X <= MIN_VALID_POSITION || Y <= MIN_VALID_POSITION) { - X = fDropOffX; - Y = fDropOffY; - } - int index = 0; - for (int i = 0; i < NumCranes; i++) { - float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); - if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) { - fMinDistance = distance; - index = i; - } - } -#ifdef FIX_BUGS // classic - if (fMinDistance == MAX_DISTANCE) - return; -#endif - CCrane* pCrane = &aCranes[index]; - pCrane->m_fPickupX1 = fInfX; - pCrane->m_fPickupX2 = fSupX; - pCrane->m_fPickupY1 = fInfY; - pCrane->m_fPickupY2 = fSupY; - pCrane->m_vecDropoffTarget.x = fDropOffX; - pCrane->m_vecDropoffTarget.y = fDropOffY; - pCrane->m_vecDropoffTarget.z = fDropOffZ; - pCrane->m_nCraneStatus = CCrane::ACTIVATED; - pCrane->m_pVehiclePickedUp = nil; - pCrane->m_nVehiclesCollected = 0; - pCrane->m_fDropoffHeading = fHeading; - pCrane->m_bIsCrusher = bIsCrusher; - pCrane->m_bIsMilitaryCrane = bIsMilitary; - bool military = true; - if (!bIsMilitary && !pCrane->m_bWasMilitaryCrane) - military = false; - pCrane->m_bWasMilitaryCrane = military; - pCrane->m_nTimeForNextCheck = 0; - pCrane->m_nCraneState = CCrane::IDLE; - float Z; - if (bIsCrusher) - Z = CRUSHER_Z; - else if (bIsMilitary) - Z = MILITARY_Z; - else - Z = CWorld::FindGroundZForCoord((fInfX + fSupX) / 2, (fInfY + fSupY) / 2); - pCrane->FindParametersForTarget((fInfX + fSupX) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fPickupHeight); - pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDropoffHeight); -} - -void CCranes::DeActivateCrane(float X, float Y) -{ - float fMinDistance = MAX_DISTANCE; - int index = 0; - for (int i = 0; i < NumCranes; i++) { - float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); - if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) { - fMinDistance = distance; - index = i; - } - } -#ifdef FIX_BUGS // classic - if (fMinDistance == MAX_DISTANCE) - return; -#endif - aCranes[index].m_nCraneStatus = CCrane::DEACTIVATED; - aCranes[index].m_nCraneState = CCrane::IDLE; -} - -bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle) -{ - int index = 0; - bool result = false; - for (int i = 0; i < NumCranes; i++) { - float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude(); - if (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) { - if (aCranes[i].m_nCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_nCraneStatus == CCrane::ROTATING_TARGET) - result = true; - } - } - return true; -} - -void CCranes::UpdateCranes(void) -{ - for (int i = 0; i < NumCranes; i++) { - if (aCranes[i].m_bIsTop || aCranes[i].m_bIsCrusher || - (TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().x && - TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().x && - TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().y && - TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().y)) - aCranes[i].Update(); - } -} - -void CCrane::Update(void) -{ - if (CReplay::IsPlayingBack()) - return; - if (((m_nCraneStatus == ACTIVATED || m_nCraneStatus == DEACTIVATED) && - Abs(TheCamera.GetGameCamPosition().x - m_pCraneEntity->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS && - Abs(TheCamera.GetGameCamPosition().y - m_pCraneEntity->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) || - m_nCraneState != IDLE) { - switch (m_nCraneState) { - case IDLE: - if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, GetHeightToPickup()) && - CTimer::GetTimeInMilliseconds() > m_nTimeForNextCheck) { - CWorld::AdvanceCurrentScanCode(); -#ifdef FIX_BUGS - int xstart = max(0, CWorld::GetSectorIndexX(m_fPickupX1)); - int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2)); - int ystart = max(0, CWorld::GetSectorIndexY(m_fPickupY1)); - int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2)); -#else - int xstart = CWorld::GetSectorIndexX(m_fPickupX1); - int xend = CWorld::GetSectorIndexX(m_fPickupX2); - int ystart = CWorld::GetSectorIndexY(m_fPickupY1); - int yend = CWorld::GetSectorIndexY(m_fPickupY1); -#endif - assert(xstart <= xend); - assert(ystart <= yend); - for (int i = xstart; i <= xend; i++) { - for (int j = ystart; j <= yend; j++) { - FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES]); - FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES_OVERLAP]); - } - } - } - break; - case GOING_TOWARDS_TARGET: - if (m_pVehiclePickedUp){ - if (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 || - m_pVehiclePickedUp->GetPosition().x > m_fPickupX2 || - m_pVehiclePickedUp->GetPosition().y < m_fPickupY1 || - m_pVehiclePickedUp->GetPosition().y > m_fPickupY2 || - m_pVehiclePickedUp->pDriver || - 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) { - m_pVehiclePickedUp = nil; - m_nCraneState = IDLE; - } - else { - float fAngle, fOffset, fHeight; - FindParametersForTarget( - m_pVehiclePickedUp->GetPosition().x, - m_pVehiclePickedUp->GetPosition().y, - m_pVehiclePickedUp->GetPosition().z + m_pVehiclePickedUp->GetColModel()->boundingBox.max.z, - &fAngle, &fOffset, &fHeight); - if (GoTowardsTarget(fAngle, fOffset, fHeight)) { - CVector distance = m_pVehiclePickedUp->GetPosition() - m_vecHookCurPos; - distance.z += m_pVehiclePickedUp->GetColModel()->boundingBox.max.z; - if (distance.MagnitudeSqr() < SQR(DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT)) { - m_nCraneState = GOING_TOWARDS_TARGET_ONLY_HEIGHT; - m_vecHookVelocity *= 0.4f; - m_pVehiclePickedUp->bLightsOn = false; - m_pVehiclePickedUp->bUsesCollision = false; - if (m_bIsCrusher) - m_pVehiclePickedUp->bCollisionProof = true; - DMAudio.PlayOneShot(m_nAudioEntity, SOUND_CRANE_PICKUP, 0.0f); - } - } - } - } - else - m_nCraneState = IDLE; - break; - case LIFTING_TARGET: - RotateCarriedCarProperly(); - if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), CRANE_SLOWDOWN_MULTIPLIER)) - m_nCraneState = ROTATING_TARGET; - if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) { - m_pVehiclePickedUp = nil; - m_nCraneState = IDLE; - } - break; - case GOING_TOWARDS_TARGET_ONLY_HEIGHT: - RotateCarriedCarProperly(); - if (GoTowardsHeightTarget(GetHeightToPickupHeight(), CRANE_SLOWDOWN_MULTIPLIER)) - m_nCraneState = LIFTING_TARGET; - TimerForCamInterpolation = CTimer::GetTimeInMilliseconds(); - if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) { - m_pVehiclePickedUp = nil; - m_nCraneState = IDLE; - } - break; - case ROTATING_TARGET: - { - bool bRotateFinished = RotateCarriedCarProperly(); - bool bMovementFinished = GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, m_fDropoffHeight, 0.3f); - if (bMovementFinished && bRotateFinished) { - float fDistanceFromPlayer = m_pVehiclePickedUp ? ((CVector2D)FindPlayerCoors() - (CVector2D)m_pVehiclePickedUp->GetPosition()).Magnitude() : 0.0f; - if (fDistanceFromPlayer > DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE || !m_bWasMilitaryCrane) { - m_nCraneState = DROPPING_TARGET; - if (m_pVehiclePickedUp) { - m_pVehiclePickedUp->bUsesCollision = true; - m_pVehiclePickedUp->m_nStaticFrames = 0; - ++m_nVehiclesCollected; - if (m_bIsMilitaryCrane) { - CCranes::RegisterCarForMilitaryCrane(m_pVehiclePickedUp->GetModelIndex()); - if (!CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()) { - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += CAR_REWARD_MILITARY_CRANE; - CGarages::TriggerMessage("GA_10", CAR_REWARD_MILITARY_CRANE, MESSAGE_SHOW_DURATION, -1); - } - CWorld::Remove(m_pVehiclePickedUp); - delete m_pVehiclePickedUp; - } - } - m_pVehiclePickedUp = nil; - } - } - break; - } - case DROPPING_TARGET: - if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoffHeight(), CRANE_SLOWDOWN_MULTIPLIER)) { - m_nCraneState = IDLE; - m_nTimeForNextCheck = CTimer::GetTimeInMilliseconds() + 10000; - } - break; - default: - break; - } - CVector vecHook; - CalcHookCoordinates(&vecHook.x, &vecHook.y, &vecHook.z); - m_vecHookVelocity += ((CVector2D)vecHook - (CVector2D)m_vecHookCurPos) * CTimer::GetTimeStep() * CRANE_MOVEMENT_SPEED; - m_vecHookVelocity *= Pow(0.98f, CTimer::GetTimeStep()); - m_vecHookCurPos.x += m_vecHookVelocity.x * CTimer::GetTimeStep(); - m_vecHookCurPos.y += m_vecHookVelocity.y * CTimer::GetTimeStep(); - m_vecHookCurPos.z = vecHook.z; - switch (m_nCraneState) { - case LIFTING_TARGET: - case GOING_TOWARDS_TARGET_ONLY_HEIGHT: - case ROTATING_TARGET: - if (m_pVehiclePickedUp) { - m_pVehiclePickedUp->GetPosition() = CVector(m_vecHookCurPos.x, m_vecHookCurPos.y, m_vecHookCurPos.z - m_pVehiclePickedUp->GetColModel()->boundingBox.max.z); - m_pVehiclePickedUp->SetMoveSpeed(0.0f, 0.0f, 0.0f); - CVector up(vecHook.x - m_vecHookCurPos.x, vecHook.y - m_vecHookCurPos.y, 20.0f); - up.Normalise(); - m_pVehiclePickedUp->GetRight() = CrossProduct(m_pVehiclePickedUp->GetForward(), up); - m_pVehiclePickedUp->GetForward() = CrossProduct(up, m_pVehiclePickedUp->GetRight()); - m_pVehiclePickedUp->GetUp() = up; - } - break; - default: - break; - } - } - else { - int16 rnd = (m_pCraneEntity->m_randomSeed + (CTimer::GetTimeInMilliseconds() >> 11)) & 0xF; - // 16 options, lasting 2048 ms each - // a bit awkward: why there are 4 periods for -= and 6 for +=? is it a bug? - if (rnd < 4) { - m_fHookAngle -= OSCILLATION_SPEED * CTimer::GetTimeStep(); - if (m_fHookAngle < 0.0f) - m_fHookAngle += TWOPI; - } - else if (rnd > 5 && rnd < 12) { - m_fHookAngle += OSCILLATION_SPEED * CTimer::GetTimeStep(); - if (m_fHookAngle > TWOPI) - m_fHookAngle -= TWOPI; - } - CalcHookCoordinates(&m_vecHookCurPos.x, &m_vecHookCurPos.y, &m_vecHookCurPos.z); - m_vecHookVelocity.x = m_vecHookVelocity.y = 0.0f; - } - float fCos = Cos(m_fHookAngle); - float fSin = Sin(m_fHookAngle); - m_pCraneEntity->GetRight().x = fCos; - m_pCraneEntity->GetForward().y = fCos; - m_pCraneEntity->GetRight().y = fSin; - m_pCraneEntity->GetForward().x = -fSin; - m_pCraneEntity->GetMatrix().UpdateRW(); - m_pCraneEntity->UpdateRwFrame(); - SetHookMatrix(); -} - -bool CCrane::RotateCarriedCarProperly() -{ - if (m_fDropoffHeading <= 0.0f) - return true; - if (!m_pVehiclePickedUp) - return true; - float fAngleDelta = m_fDropoffHeading - CGeneral::GetATanOfXY(m_pVehiclePickedUp->GetForward().x, m_pVehiclePickedUp->GetForward().y); - while (fAngleDelta < -HALFPI) - fAngleDelta += PI; - while (fAngleDelta > HALFPI) - fAngleDelta -= PI; - float fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep(); - if (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied? - return true; - m_pVehiclePickedUp->GetMatrix().RotateZ(Abs(fDeltaThisFrame)); - return false; -} - -void CCrane::FindCarInSectorList(CPtrList* pList) -{ - CPtrNode* node; - for (node = pList->first; node; node = node->next) { - CVehicle* pVehicle = (CVehicle*)node->item; - if (pVehicle->m_scanCode == CWorld::GetCurrentScanCode()) - continue; - pVehicle->m_scanCode = CWorld::GetCurrentScanCode(); - if (pVehicle->GetPosition().x < m_fPickupX1 || pVehicle->GetPosition().x > m_fPickupX2 || - pVehicle->GetPosition().y < m_fPickupY1 || pVehicle->GetPosition().y > m_fPickupY2) - continue; - if (pVehicle->pDriver) - continue; - if (Abs(pVehicle->GetMoveSpeed().x) >= CAR_MOVING_SPEED_THRESHOLD || - Abs(pVehicle->GetMoveSpeed().y) >= CAR_MOVING_SPEED_THRESHOLD || - Abs(pVehicle->GetMoveSpeed().z) >= CAR_MOVING_SPEED_THRESHOLD) - continue; - if (!pVehicle->IsCar() || pVehicle->m_status == STATUS_WRECKED || pVehicle->m_fHealth < 250.0f) - continue; - if (!DoesCranePickUpThisCarType(pVehicle->GetModelIndex()) || - m_bIsMilitaryCrane && CCranes::DoesMilitaryCraneHaveThisOneAlready(pVehicle->GetModelIndex())) { - if (!pVehicle->bCraneMessageDone) { - pVehicle->bCraneMessageDone = true; - if (!m_bIsMilitaryCrane) - CGarages::TriggerMessage("CR_1", -1, MESSAGE_SHOW_DURATION, -1); // Crane cannot lift this vehicle. - else if (DoesCranePickUpThisCarType(pVehicle->GetModelIndex())) - CGarages::TriggerMessage("GA_20", -1, MESSAGE_SHOW_DURATION, -1); // We got more of these than we can shift. Sorry man, no deal. - else - CGarages::TriggerMessage("GA_19", -1, MESSAGE_SHOW_DURATION, -1); // We're not interested in that model. - } - } - else { - m_pVehiclePickedUp = pVehicle; - pVehicle->RegisterReference((CEntity**)&m_pVehiclePickedUp); - m_nCraneState = GOING_TOWARDS_TARGET; - } - } -} - -bool CCrane::DoesCranePickUpThisCarType(uint32 mi) -{ - if (m_bIsCrusher) { - return mi != MI_FIRETRUCK && - mi != MI_TRASH && -#ifndef FIX_BUGS // why - mi != MI_BLISTA && -#endif - mi != MI_SECURICA && - mi != MI_BUS && - mi != MI_DODO && - mi != MI_RHINO; - } - if (m_bIsMilitaryCrane) { - return mi == MI_FIRETRUCK || - mi == MI_AMBULAN || - mi == MI_ENFORCER || - mi == MI_FBICAR || - mi == MI_RHINO || - mi == MI_BARRACKS || - mi == MI_POLICE; - } - return true; -} - -bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi) -{ - switch (mi) { - case MI_FIRETRUCK: return (CCranes::CarsCollectedMilitaryCrane & 1); - case MI_AMBULAN: return (CCranes::CarsCollectedMilitaryCrane & 2); - case MI_ENFORCER: return (CCranes::CarsCollectedMilitaryCrane & 4); - case MI_FBICAR: return (CCranes::CarsCollectedMilitaryCrane & 8); - case MI_RHINO: return (CCranes::CarsCollectedMilitaryCrane & 0x10); - case MI_BARRACKS: return (CCranes::CarsCollectedMilitaryCrane & 0x20); - case MI_POLICE: return (CCranes::CarsCollectedMilitaryCrane & 0x40); - default: break; - } - return false; -} - -void CCranes::RegisterCarForMilitaryCrane(uint32 mi) -{ - switch (mi) { - case MI_FIRETRUCK: CCranes::CarsCollectedMilitaryCrane |= 1; break; - case MI_AMBULAN: CCranes::CarsCollectedMilitaryCrane |= 2; break; - case MI_ENFORCER: CCranes::CarsCollectedMilitaryCrane |= 4; break; - case MI_FBICAR: CCranes::CarsCollectedMilitaryCrane |= 8; break; - case MI_RHINO: CCranes::CarsCollectedMilitaryCrane |= 0x10; break; - case MI_BARRACKS: CCranes::CarsCollectedMilitaryCrane |= 0x20; break; - case MI_POLICE: CCranes::CarsCollectedMilitaryCrane |= 0x40; break; - default: break; - } -} - -bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() -{ - return (CCranes::CarsCollectedMilitaryCrane & 0x7F) == 0x7F; -} - -bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier) -{ - bool bAngleMovementFinished, bOffsetMovementFinished, bHeightMovementFinished; - float fHookAngleDelta = fAngleToTarget - m_fHookAngle; - while (fHookAngleDelta > PI) - fHookAngleDelta -= TWOPI; - while (fHookAngleDelta < -PI) - fHookAngleDelta += TWOPI; - float fHookAngleChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_ANGLE_MOVEMENT_SPEED; - if (Abs(fHookAngleDelta) < fHookAngleChangeThisFrame) { - m_fHookAngle = fAngleToTarget; - bAngleMovementFinished = true; - } - else { - if (fHookAngleDelta < 0.0f) { - m_fHookAngle -= fHookAngleChangeThisFrame; - if (m_fHookAngle < 0.0f) - m_fHookAngle += TWOPI; - } - else { - m_fHookAngle += fHookAngleChangeThisFrame; - if (m_fHookAngle > TWOPI) - m_fHookAngle -= TWOPI; - } - bAngleMovementFinished = false; - } - float fHookOffsetDelta = fDistanceToTarget - m_fHookOffset; - float fHookOffsetChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_OFFSET_MOVEMENT_SPEED; - if (Abs(fHookOffsetDelta) < fHookOffsetChangeThisFrame) { - m_fHookOffset = fDistanceToTarget; - bOffsetMovementFinished = true; - } - else { - if (fHookOffsetDelta < 0.0f) - m_fHookOffset -= fHookOffsetChangeThisFrame; - else - m_fHookOffset += fHookOffsetChangeThisFrame; - bOffsetMovementFinished = false; - } - float fHookHeightDelta = fTargetHeight - m_fHookHeight; - float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED; - if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) { - m_fHookHeight = fTargetHeight; - bHeightMovementFinished = true; - } - else { - if (fHookHeightDelta < 0.0f) - m_fHookHeight -= fHookHeightChangeThisFrame; - else - m_fHookHeight += fHookHeightChangeThisFrame; - bHeightMovementFinished = false; - } - return bAngleMovementFinished && bOffsetMovementFinished && bHeightMovementFinished; -} - -bool CCrane::GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier) -{ - bool bHeightMovementFinished; - float fHookHeightDelta = fTargetHeight - m_fHookHeight; - float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED; - if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) { - m_fHookHeight = fTargetHeight; - bHeightMovementFinished = true; - } - else { - if (fHookHeightDelta < 0.0f) - m_fHookHeight -= fHookHeightChangeThisFrame; - else - m_fHookHeight += fHookHeightChangeThisFrame; - bHeightMovementFinished = false; - } - return bHeightMovementFinished; -} - -void CCrane::FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight) -{ - *pAngle = CGeneral::GetATanOfXY(X - m_pCraneEntity->GetPosition().x, Y - m_pCraneEntity->GetPosition().y); - *pDistance = ((CVector2D(X, Y) - (CVector2D)m_pCraneEntity->GetPosition())).Magnitude(); - *pHeight = Z; -} - -void CCrane::CalcHookCoordinates(float* pX, float* pY, float* pZ) -{ - *pX = Cos(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().x; - *pY = Sin(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().y; - *pZ = m_fHookHeight; -} - -void CCrane::SetHookMatrix() -{ - if (!m_pHook) - return; - m_pHook->GetPosition() = m_vecHookCurPos; - CVector up(m_vecHookInitPos.x - m_vecHookCurPos.x, m_vecHookInitPos.y - m_vecHookCurPos.y, 20.0f); - up.Normalise(); - m_pHook->GetRight() = CrossProduct(CVector(0.0f, 1.0f, 0.0f), up); - m_pHook->GetForward() = CrossProduct(up, m_pHook->GetRight()); - m_pHook->GetUp() = up; - m_pHook->SetOrientation(0.0f, 0.0f, -HALFPI); - m_pHook->GetMatrix().UpdateRW(); - m_pHook->UpdateRwFrame(); - CWorld::Remove(m_pHook); - CWorld::Add(m_pHook); -} - -bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle) -{ - for (int i = 0; i < NumCranes; i++) { - if (pVehicle == aCranes[i].m_pVehiclePickedUp) { - switch (aCranes[i].m_nCraneState) { - case CCrane::GOING_TOWARDS_TARGET_ONLY_HEIGHT: - case CCrane::LIFTING_TARGET: - case CCrane::ROTATING_TARGET: - return true; - default: - break; - } - } - } - return false; -} - -bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle) -{ - for (int i = 0; i < NumCranes; i++) { - if (pVehicle == aCranes[i].m_pVehiclePickedUp) - return true; - } - return false; -} - -void CCranes::Save(uint8* buf, uint32* size) -{ - INITSAVEBUF - - *size = 2 * sizeof(uint32) + NUM_CRANES * sizeof(CCrane); - WriteSaveBuf(buf, NumCranes); - WriteSaveBuf(buf, CarsCollectedMilitaryCrane); - for (int i = 0; i < NUM_CRANES; i++) { - CCrane* pCrane = WriteSaveBuf(buf, aCranes[i]); - if (pCrane->m_pCraneEntity) - pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pCrane->m_pCraneEntity) + 1); - if (pCrane->m_pHook) - pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex((CObject*)pCrane->m_pHook) + 1); - if (pCrane->m_pVehiclePickedUp) - pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex((CVehicle*)pCrane->m_pVehiclePickedUp) + 1); - } - - VALIDATESAVEBUF(*size); -} - -void CranesLoad(uint8* buf, uint32 size) -{ - INITSAVEBUF - - CCranes::NumCranes = ReadSaveBuf(buf); - CCranes::CarsCollectedMilitaryCrane = ReadSaveBuf(buf); - for (int i = 0; i < NUM_CRANES; i++) - CCranes::aCranes[i] = ReadSaveBuf(buf); - for (int i = 0; i < NUM_CRANES; i++) { - CCrane* pCrane = &CCranes::aCranes[i]; - if (pCrane->m_pCraneEntity) - pCrane->m_pCraneEntity = CPools::GetBuildingPool()->GetSlot((uint32)pCrane->m_pCraneEntity - 1); - if (pCrane->m_pHook) - pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uint32)pCrane->m_pHook - 1); - if (pCrane->m_pVehiclePickedUp) - pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uint32)pCrane->m_pVehiclePickedUp + 1); - } - for (int i = 0; i < NUM_CRANES; i++) { - CCranes::aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &CCranes::aCranes[i]); - if (CCranes::aCranes[i].m_nAudioEntity) - DMAudio.SetEntityStatus(CCranes::aCranes[i].m_nAudioEntity, 1); - } - - VALIDATESAVEBUF(size); -} - -STARTPATCHES - InjectHook(0x5454D0, CranesLoad, PATCH_JUMP); // GenericLoad -ENDPATCHES diff --git a/src/control/Cranes.h b/src/control/Cranes.h deleted file mode 100644 index d9817282..00000000 --- a/src/control/Cranes.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include "common.h" - -#include "World.h" - -class CVehicle; -class CEntity; -class CObject; -class CBuilding; - -class CCrane -{ -public: - enum CraneState : uint8 { - IDLE = 0, - GOING_TOWARDS_TARGET = 1, - LIFTING_TARGET = 2, - GOING_TOWARDS_TARGET_ONLY_HEIGHT = 3, - ROTATING_TARGET = 4, - DROPPING_TARGET = 5 - }; - enum CraneStatus : uint8 { - NONE = 0, - ACTIVATED = 1, - DEACTIVATED = 2 - }; - CBuilding *m_pCraneEntity; - CObject *m_pHook; - int32 m_nAudioEntity; - float m_fPickupX1; - float m_fPickupX2; - float m_fPickupY1; - float m_fPickupY2; - CVector m_vecDropoffTarget; - float m_fDropoffHeading; - float m_fPickupAngle; - float m_fDropoffAngle; - float m_fPickupDistance; - float m_fDropoffDistance; - float m_fPickupHeight; - float m_fDropoffHeight; - float m_fHookAngle; - float m_fHookOffset; - float m_fHookHeight; - CVector m_vecHookInitPos; - CVector m_vecHookCurPos; - CVector2D m_vecHookVelocity; - CVehicle *m_pVehiclePickedUp; - uint32 m_nTimeForNextCheck; - CraneStatus m_nCraneStatus; - CraneState m_nCraneState; - uint8 m_nVehiclesCollected; - bool m_bIsCrusher; - bool m_bIsMilitaryCrane; - bool m_bWasMilitaryCrane; - bool m_bIsTop; - - void Init(void) { memset(this, 0, sizeof(*this)); } - void Update(void); - bool RotateCarriedCarProperly(void); - void FindCarInSectorList(CPtrList* pList); - bool DoesCranePickUpThisCarType(uint32 mi); - bool GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier = 1.0f); - bool GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier = 1.0f); - void FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight); - void CalcHookCoordinates(float* pX, float* pY, float* pZ); - void SetHookMatrix(void); - - float GetHeightToPickup() { return 4.0f + m_fPickupHeight + (m_bIsCrusher ? 4.5f : 0.0f); }; - float GetHeightToDropoff() { return m_bIsCrusher ? (2.0f + m_fDropoffHeight + 3.0f) : (2.0f + m_fDropoffHeight); } - float GetHeightToPickupHeight() { return m_fPickupHeight + (m_bIsCrusher ? 7.0f : 4.0f); } - float GetHeightToDropoffHeight() { return m_fDropoffHeight + (m_bIsCrusher ? 7.0f : 2.0f); } -}; - -static_assert(sizeof(CCrane) == 128, "CCrane: error"); - -class CCranes -{ -public: - static void InitCranes(void); - static void AddThisOneCrane(CEntity* pCraneEntity); - static void ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY); - static void DeActivateCrane(float fX, float fY); - static bool IsThisCarPickedUp(float fX, float fY, CVehicle* pVehicle); - static void UpdateCranes(void); - static bool DoesMilitaryCraneHaveThisOneAlready(uint32 mi); - static void RegisterCarForMilitaryCrane(uint32 mi); - static bool HaveAllCarsBeenCollectedByMilitaryCrane(void); - static bool IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle); - static bool IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle); - static void Save(uint8* buf, uint32* size); - - static uint32& CarsCollectedMilitaryCrane; - static int32& NumCranes; - static CCrane(&aCranes)[NUM_CRANES]; -}; - -void CranesLoad(uint8*, uint32); // is this really outside CCranes? diff --git a/src/control/Gangs.cpp b/src/control/Gangs.cpp deleted file mode 100644 index 57d9c67e..00000000 --- a/src/control/Gangs.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "common.h" -#include "patcher.h" -#include "ModelIndices.h" -#include "Gangs.h" -#include "Weapon.h" - -//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78; -CGangInfo CGangs::Gang[NUM_GANGS]; - -CGangInfo::CGangInfo() : - m_nVehicleMI(MI_BUS), - m_nPedModelOverride(-1), - m_Weapon1(WEAPONTYPE_UNARMED), - m_Weapon2(WEAPONTYPE_UNARMED) -{} - -void CGangs::Initialise(void) -{ - Gang[GANG_MAFIA].m_nVehicleMI = MI_MAFIA; - Gang[GANG_TRIAD].m_nVehicleMI = MI_BELLYUP; - Gang[GANG_DIABLOS].m_nVehicleMI = MI_DIABLOS; - Gang[GANG_YAKUZA].m_nVehicleMI = MI_YAKUZA; - Gang[GANG_YARDIE].m_nVehicleMI = MI_YARDIE; - Gang[GANG_COLUMB].m_nVehicleMI = MI_COLUMB; - Gang[GANG_HOODS].m_nVehicleMI = MI_HOODS; - Gang[GANG_7].m_nVehicleMI = -1; - Gang[GANG_8].m_nVehicleMI = -1; -#ifdef FIX_BUGS - for (int i = 0; i < NUM_GANGS; i++) - Gang[i].m_nPedModelOverride = -1; -#endif -} - -void CGangs::SetGangVehicleModel(int16 gang, int32 model) -{ - GetGangInfo(gang)->m_nVehicleMI = model; -} - -void CGangs::SetGangWeapons(int16 gang, int32 weapon1, int32 weapon2) -{ - CGangInfo *gi = GetGangInfo(gang); - gi->m_Weapon1 = weapon1; - gi->m_Weapon2 = weapon2; -} - -void CGangs::SetGangPedModelOverride(int16 gang, int8 ovrd) -{ - GetGangInfo(gang)->m_nPedModelOverride = ovrd; -} - -int8 CGangs::GetGangPedModelOverride(int16 gang) -{ - return GetGangInfo(gang)->m_nPedModelOverride; -} - -void CGangs::SaveAllGangData(uint8 *buf, uint32 *size) -{ -INITSAVEBUF - - *size = SAVE_HEADER_SIZE + sizeof(Gang); - WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE); - for (int i = 0; i < NUM_GANGS; i++) - WriteSaveBuf(buf, Gang[i]); - -VALIDATESAVEBUF(*size); -} - -void CGangs::LoadAllGangData(uint8 *buf, uint32 size) -{ - Initialise(); - -INITSAVEBUF - // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE); - CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE); - - for (int i = 0; i < NUM_GANGS; i++) - Gang[i] = ReadSaveBuf(buf); -VALIDATESAVEBUF(size); -} - -STARTPATCHES - InjectHook(0x4C3FB0, CGangs::Initialise, PATCH_JUMP); - InjectHook(0x4C4010, CGangs::SetGangVehicleModel, PATCH_JUMP); - InjectHook(0x4C4030, CGangs::SetGangWeapons, PATCH_JUMP); - InjectHook(0x4C4050, CGangs::SetGangPedModelOverride, PATCH_JUMP); - InjectHook(0x4C4070, CGangs::GetGangPedModelOverride, PATCH_JUMP); - InjectHook(0x4C4080, CGangs::SaveAllGangData, PATCH_JUMP); - InjectHook(0x4C4100, CGangs::LoadAllGangData, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/Gangs.h b/src/control/Gangs.h deleted file mode 100644 index dd7a7f93..00000000 --- a/src/control/Gangs.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -struct CGangInfo -{ - int32 m_nVehicleMI; - int8 m_nPedModelOverride; - int32 m_Weapon1; - int32 m_Weapon2; - - CGangInfo(); -}; - -static_assert(sizeof(CGangInfo) == 0x10, "CGangInfo: error"); - -enum { - GANG_MAFIA = 0, - GANG_TRIAD, - GANG_DIABLOS, - GANG_YAKUZA, - GANG_YARDIE, - GANG_COLUMB, - GANG_HOODS, - GANG_7, - GANG_8, - NUM_GANGS -}; - -class CGangs -{ -public: - static void Initialise(void); - static void SetGangVehicleModel(int16, int32); - static void SetGangWeapons(int16, int32, int32); - static void SetGangPedModelOverride(int16, int8); - static int8 GetGangPedModelOverride(int16); - static void SaveAllGangData(uint8 *, uint32 *); - static void LoadAllGangData(uint8 *, uint32); - - static int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; } - static CGangInfo *GetGangInfo(int16 gang) { return &Gang[gang]; } - -private: - static CGangInfo Gang[NUM_GANGS]; -}; -- cgit v1.2.3