#pragma once
#include "audio_enums.h"
#include "Camera.h"
#include "config.h"
#include "Lists.h"
class CVehicle;
enum eGarageState
{
GS_FULLYCLOSED,
GS_OPENED,
GS_CLOSING,
GS_OPENING,
GS_OPENEDCONTAINSCAR,
GS_CLOSEDCONTAINSCAR,
GS_AFTERDROPOFF,
GS_WAITINGFORCAR
};
enum eGarageType
{
GARAGE_NONE,
GARAGE_MISSION,
GARAGE_BOMBSHOP1,
GARAGE_BOMBSHOP2,
GARAGE_BOMBSHOP3,
GARAGE_RESPRAY,
GARAGE_COLLECTORSITEMS,
GARAGE_COLLECTSPECIFICCARS,
GARAGE_COLLECTCARS_1,
GARAGE_COLLECTCARS_2,
GARAGE_COLLECTCARS_3,
GARAGE_FORCARTOCOMEOUTOF,
GARAGE_CRATE_GARAGE,
GARAGE_CRUSHER,
GARAGE_MISSION_KEEPCAR,
GARAGE_FOR_SCRIPT_TO_OPEN,
GARAGE_HIDEOUT_ONE,
GARAGE_HIDEOUT_TWO,
GARAGE_HIDEOUT_THREE,
GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE,
GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR,
GARAGE_MISSION_KEEPCAR_REMAINCLOSED,
GARAGE_COLLECTCARS_4,
GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR,
GARAGE_HIDEOUT_FOUR,
GARAGE_HIDEOUT_FIVE,
GARAGE_HIDEOUT_SIX,
GARAGE_HIDEOUT_SEVEN,
GARAGE_HIDEOUT_EIGHT,
GARAGE_HIDEOUT_NINE,
GARAGE_HIDEOUT_TEN,
GARAGE_HIDEOUT_ELEVEN,
GARAGE_HIDEOUT_TWELVE
};
enum
{
TOTAL_COLLECTCARS_GARAGES = 4,
TOTAL_HIDEOUT_GARAGES = 12,
TOTAL_COLLECTCARS_CARS = 16
};
class CStoredCar
{
enum {
FLAG_BULLETPROOF = 0x1,
FLAG_FIREPROOF = 0x2,
FLAG_EXPLOSIONPROOF = 0x4,
FLAG_COLLISIONPROOF = 0x8,
FLAG_MELEEPROOF = 0x10,
FLAG_TIRES_INVULNERABLE = 0x20,
FLAG_STRONG = 0x40,
FLAG_HEAVY = 0x80,
FLAG_PERMANENT_COLOUR = 0x100,
FLAG_BOMB = 0x200,
FLAG_NOT_DAMAGED_UPSIDEDOWN = 0x400,
FLAG_REWARD_VEHICLE = 0x8000
};
int32 m_nModelIndex;
float m_fPosX;
float m_fPosY;
float m_fPosZ;
float m_fForwardX;
float m_fForwardY;
float m_fForwardZ;
float m_fTractionMultiplier;
int32 m_nFlags;
int8 m_nPrimaryColor;
int8 m_nSecondaryColor;
int8 m_nRadioStation;
int8 m_nVariationA;
int8 m_nVariationB;
int8 m_nCarBombType;
public:
void Init() { m_nModelIndex = 0; }
void Clear() { m_nModelIndex = 0; }
bool HasCar() { return m_nModelIndex != 0; }
void StoreCar(CVehicle*);
CVehicle* RestoreCar();
};
VALIDATE_SIZE(CStoredCar, 0x28);
#define SWITCH_GARAGE_DISTANCE_CLOSE 40.0f
class CGarage
{
public:
uint8 m_eGarageType;
uint8 m_eGarageState;
uint8 m_nMaxStoredCars;
bool field_2; // unused
bool m_bClosingWithoutTargetCar;
bool m_bDeactivated;
bool m_bResprayHappened;
int m_nTargetModelIndex;
CEntity *m_pDoor1;
CEntity *m_pDoor2;
uint8 m_bDoor1PoolIndex;
uint8 m_bDoor2PoolIndex;
bool m_bDoor1IsDummy;
bool m_bDoor2IsDummy;
bool m_bRecreateDoorOnNextRefresh;
bool m_bRotatedDoor;
bool m_bCameraFollowsPlayer;
CVector2D m_vecCorner1;
float m_fInfZ;
CVector2D m_vDir1;
CVector2D m_vDir2;
float m_fSupZ;
CVector m_vecSSGaragePos;
float m_fSSGarageAngle;
float m_fDir1Len;
float m_fDir2Len;
float m_fInfX;
float m_fSupX;
float m_fInfY;
float m_fSupY;
uint32 m_nTimeCrusherCraneActivated;
CVehicle* m_pSSTargetCar;
float m_fDoorPos;
float m_fDoorHeight;
float m_fDoor1X;
float m_fDoor1Y;
float m_fDoor2X;
float m_fDoor2Y;
float m_fDoor1Z;
float m_fDoor2Z;
uint32 m_nTimeToStartAction;
uint8 m_bCollectedCarsState;
CVehicle *m_pTarget;
CStoredCar m_sStoredCar; // not needed
bool m_bInitialized;
#ifdef GTA_NETWORK
void* m_pSSVehicle; // some multiplayer vehicle structure, +104 == GetVehiclePointer
#endif
bool m_bSSGarageAcceptedVehicle;
bool m_bLocked;
bool m_nSSGarageState;
bool m_bSSGarageStateChanging;
void OpenThisGarage();
void CloseThisGarage();
bool IsOpen() { return m_eGarageState == GS_OPENED || m_eGarageState == GS_OPENEDCONTAINSCAR; }
bool IsClosed() { return m_eGarageState == GS_FULLYCLOSED; }
bool IsUsed() { return m_eGarageType != GARAGE_NONE; }
void Update();
float GetGarageCenterX() { return (m_fInfX + m_fSupX) / 2; }
float GetGarageCenterY() { return (m_fInfY + m_fSupY) / 2; }
bool IsFar()
{
#ifdef FIX_BUGS
return Abs(TheCamera.GetPosition().x - GetGarageCenterX()) > SWITCH_GARAGE_DISTANCE_CLOSE ||
Abs(TheCamera.GetPosition().y - GetGarageCenterY()) > SWITCH_GARAGE_DISTANCE_CLOSE;
#else
return Abs(TheCamera.GetPosition().x - m_fInfX) > SWITCH_GARAGE_DISTANCE_CLOSE ||
Abs(TheCamera.GetPosition().y - m_fInfY) > SWITCH_GARAGE_DISTANCE_CLOSE;
#endif
}
void TidyUpGarageClose();
void TidyUpGarage();
void RefreshDoorPointers(bool);
void UpdateCrusherAngle();
void UpdateDoorsHeight();
bool IsEntityEntirelyInside3D(CEntity*, float);
bool IsEntityEntirelyOutside(CEntity*, float);
float CalcDistToGarageRectangleSquared(float, float);
float CalcSmallestDistToGarageDoorSquared(float, float);
bool IsAnyOtherCarTouchingGarage(CVehicle* pException);
bool IsStaticPlayerCarEntirelyInside();
bool IsPlayerOutsideGarage();
bool IsAnyCarBlockingDoor();
void CenterCarInGarage(CVehicle*);
bool DoesCraigNeedThisCar(int32);
bool MarkThisCarAsCollectedForCraig(int32);
bool HasCraigCollectedThisCar(int32);
bool IsGarageEmpty();
void UpdateCrusherShake(float, float);
int32 CountCarsWithCenterPointWithinGarage(CEntity* pException);
void RemoveCarsBlockingDoorNotInside();
void StoreAndRemoveCarsForThisHideout(CStoredCar*, int32);
bool RestoreCarsForThisHideout(CStoredCar*);
bool IsEntityTouching3D(CEntity*);
bool EntityHasASphereWayOutsideGarage(CEntity*, float);
bool IsAnyOtherPedTouchingGarage(CPed* pException);
void BuildRotatedDoorMatrix(CEntity*, float);
void FindDoorsEntities();
void FindDoorsEntitiesSectorList(CPtrList&, bool);
void PlayerArrestedOrDied();
bool Does60SecondsNeedThisCarAtAll(int mi);
bool Does60SecondsNeedThisCar(int mi);
void MarkThisCarAsCollectedFor60Seconds(int mi);
bool IsPlayerEntirelyInsideGarage();
bool IsPointInsideGarage(CVector);
bool IsPointInsideGarage(CVector, float);
void ThrowCarsNearDoorOutOfGarage(CVehicle*);
int32 FindMaxNumStoredCarsForGarage() { return Min(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }
};
class CGarages
{
enum {
MESSAGE_LENGTH = 8,
};
public:
static int32 BankVansCollected;
static bool BombsAreFree;
static bool RespraysAreFree;
static int32 CarsCollected;
static int32 CarTypesCollected[TOTAL_COLLECTCARS_GARAGES];
static int32 CrushedCarId;
static uint32 LastTimeHelpMessage;
static int32 MessageNumberInString;
static char MessageIDString[MESSAGE_LENGTH];
static int32 MessageNumberInString2;
static uint32 MessageStartTime;
static uint32 MessageEndTime;
static uint32 NumGarages;
static bool PlayerInGarage;
static int32 PoliceCarsCollected;
static CGarage aGarages[NUM_GARAGES];
static CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];
static bool bCamShouldBeOutisde;
static uint8 CrusherRewardMultiplier;
static void Init(void);
#ifndef PS2
static void Shutdown(void);
#endif
static void Update(void);
static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, uint8 type, int32 targetId);
static void ChangeGarageType(int16, uint8, int32);
static void PrintMessages(void);
static void TriggerMessage(const char* text, int16, uint16 time, int16);
static void SetTargetCarForMissonGarage(int16, CVehicle*);
static bool HasCarBeenDroppedOffYet(int16);
static void DeActivateGarage(int16);
static void ActivateGarage(int16);
static int32 QueryCarsCollected(int16);
static bool HasImportExportGarageCollectedThisCar(int16, int8);
static bool IsGarageOpen(int16);
static bool IsGarageClosed(int16);
static bool HasThisCarBeenCollected(int16, uint8);
static void OpenGarage(int16 garage) { aGarages[garage].OpenThisGarage(); }
static void CloseGarage(int16 garage) { aGarages[garage].CloseThisGarage(); }
static bool HasResprayHappened(int16);
static void SetGarageDoorToRotate(int16);
static void SetLeaveCameraForThisGarage(int16);
static bool IsThisCarWithinGarageArea(int16, CEntity*);
static bool HasCarBeenCrushed(int32);
static bool IsPointInAGarageCameraZone(CVector);
static bool CameraShouldBeOutside(void);
static void GivePlayerDetonator(void);
static void PlayerArrestedOrDied(void);
static bool IsPointWithinHideOutGarage(Const CVector&);
static bool IsPointWithinAnyGarage(Const CVector&);
static void SetAllDoorsBackToOriginalHeight(void);
static void Save(uint8* buf, uint32* size);
static void Load(uint8* buf, uint32 size);
static bool IsModelIndexADoor(uint32 id);
static void SetFreeBombs(bool bValue) { BombsAreFree = bValue; }
static void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }
static void StopCarFromBlowingUp(CAutomobile*);
static void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }
static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void);
static int32 CountCarsInHideoutGarage(uint8);
static int32 GetBombTypeForGarageType(uint8 type) { return type - GARAGE_BOMBSHOP1 + 1; }
static int32 GetCarsCollectedIndexForGarageType(uint8 type, uint32& total)
{
switch (type) {
case GARAGE_COLLECTCARS_1: total = TOTAL_COLLECTCARS_CARS; return 0;
case GARAGE_COLLECTCARS_2: total = 0; return 1;
case GARAGE_COLLECTCARS_3: total = 0; return 2;
case GARAGE_COLLECTCARS_4: total = 0; return 3;
default: assert(0);
}
return 0;
}
static int32 FindSafeHouseIndexForGarageType(uint8 type)
{
switch (type) {
case GARAGE_HIDEOUT_ONE: return 0;
case GARAGE_HIDEOUT_TWO: return 1;
case GARAGE_HIDEOUT_THREE: return 2;
case GARAGE_HIDEOUT_FOUR: return 3;
case GARAGE_HIDEOUT_FIVE: return 4;
case GARAGE_HIDEOUT_SIX: return 5;
case GARAGE_HIDEOUT_SEVEN: return 6;
case GARAGE_HIDEOUT_EIGHT: return 7;
case GARAGE_HIDEOUT_NINE: return 8;
case GARAGE_HIDEOUT_TEN: return 9;
case GARAGE_HIDEOUT_ELEVEN: return 10;
case GARAGE_HIDEOUT_TWELVE: return 11;
}
return -1;
}
static bool IsThisGarageTypeSafehouse(uint8 type) { return FindSafeHouseIndexForGarageType(type) >= 0; }
static bool InitDoorGubbins(uint32, uint8);
static void SetupAnyGaragesForThisIsland(void);
static void LockGarage(int16, bool);
static int16 AddCrateGarage(CVector, float);
#ifdef GTA_NETWORK
static void RemoveAllCrateGarages();
static bool HasSSGarageAcceptedVehicle(int16 garage);
static void SetVehicleForSSGarage(bool state, int16 garage, void* pVehicle); // void* -> ?
#endif
};