Merge branch 'miami' into lcs

# Conflicts:
#	README.md
#	gamefiles/TEXT/american.gxt
#	gamefiles/TEXT/french.gxt
#	gamefiles/TEXT/german.gxt
#	gamefiles/TEXT/italian.gxt
#	gamefiles/TEXT/spanish.gxt
#	src/audio/AudioManager.h
#	src/control/Garages.cpp
#	src/control/Garages.h
#	src/control/Script5.cpp
#	src/core/config.h
#	utils/gxt/american.txt
#	utils/gxt/spanish.txt
This commit is contained in:
Sergeanur 2021-07-12 04:13:22 +03:00
commit 55d30a11ec
35 changed files with 1351 additions and 449 deletions

View file

@ -96,8 +96,8 @@ public:
m_nCommentsInBank[i] = 0; m_nCommentsInBank[i] = 0;
m_nActiveBank = 0; m_nActiveBank = 0;
} }
void Add(tPedComment *com); // done void Add(tPedComment *com);
void Process(); // done void Process();
}; };
VALIDATE_SIZE(cPedComments, 0x490); VALIDATE_SIZE(cPedComments, 0x490);
@ -251,34 +251,34 @@ public:
~cAudioManager(); ~cAudioManager();
// getters // getters
uint32 GetFrameCounter() const { return m_FrameCounter; } // done uint32 GetFrameCounter() const { return m_FrameCounter; }
float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; } // done float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; }
int32 GetRandomNumber(int32 idx) const { return m_anRandomTable[idx]; } int32 GetRandomNumber(int32 idx) const { return m_anRandomTable[idx]; }
int32 GetRandomNumberInRange(int32 idx, int32 low, int32 high) const { return (m_anRandomTable[idx] % (high - low + 1)) + low; } int32 GetRandomNumberInRange(int32 idx, int32 low, int32 high) const { return (m_anRandomTable[idx] % (high - low + 1)) + low; }
bool8 IsMissionAudioSamplePlaying(uint8 slot) const; // { return m_sMissionAudio.m_nPlayStatus == 1; } bool8 IsMissionAudioSamplePlaying(uint8 slot) const; // { return m_sMissionAudio.m_nPlayStatus == 1; }
bool8 ShouldDuckMissionAudio(uint8 slot) const; bool8 ShouldDuckMissionAudio(uint8 slot) const;
// "Should" be in alphabetic order, except "getXTalkSfx" // "Should" be in alphabetic order, except "getXTalkSfx"
void AddDetailsToRequestedOrderList(uint8 sample); // done (inlined in vc) void AddDetailsToRequestedOrderList(uint8 sample); // inlined in vc
void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping); // done void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping);
void AddReflectionsToRequestedQueue(); // done void AddReflectionsToRequestedQueue();
void AddReleasingSounds(); // done void AddReleasingSounds();
void AddSampleToRequestedQueue(); // done void AddSampleToRequestedQueue();
void AgeCrimes(); // done (inlined in vc) void AgeCrimes(); // inlined in vc
void CalculateDistance(bool8 &condition, float dist); // done void CalculateDistance(bool8 &condition, float dist);
bool8 CheckForAnAudioFileOnCD() const; // done bool8 CheckForAnAudioFileOnCD() const;
void ClearActiveSamples(); // done void ClearActiveSamples();
void ClearMissionAudio(uint8 slot); // done (inlined in vc) void ClearMissionAudio(uint8 slot); // inlined in vc
void ClearRequestedQueue(); // done (inlined in vc) void ClearRequestedQueue(); // inlined in vc
uint32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const; // done uint32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const;
int32 ComputePan(float, CVector *); // done int32 ComputePan(float, CVector *);
uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; // done uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const;
int32 CreateEntity(eAudioType type, void *entity); // done int32 CreateEntity(eAudioType type, void *entity);
void DestroyAllGameCreatedEntities(); // done void DestroyAllGameCreatedEntities();
void DestroyEntity(int32 id); // done (inlined in vc) void DestroyEntity(int32 id); // inlined in vc
void DoPoliceRadioCrackle(); // done void DoPoliceRadioCrackle();
// functions returning talk sfx, // functions returning talk sfx,
// order from GetPedCommentSfx // order from GetPedCommentSfx
@ -382,170 +382,170 @@ public:
uint32 GetGenericFemaleTalkSfx(CPed *ped, int16 sound); // todo names (inlined in vc) uint32 GetGenericFemaleTalkSfx(CPed *ped, int16 sound); // todo names (inlined in vc)
// end of functions returning talk sfx // end of functions returning talk sfx
void GenerateIntegerRandomNumberTable(); // done void GenerateIntegerRandomNumberTable();
char *Get3DProviderName(uint8 id) const; // done char *Get3DProviderName(uint8 id) const;
char GetCDAudioDriveLetter() const; // done char GetCDAudioDriveLetter() const;
int8 GetCurrent3DProviderIndex() const; // done int8 GetCurrent3DProviderIndex() const;
int8 AutoDetect3DProviders() const; // done int8 AutoDetect3DProviders() const;
float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used
float GetCollisionOneShotRatio(int32 a, float b) const; // done float GetCollisionOneShotRatio(int32 a, float b) const;
float GetCollisionRatio(float a, float b, float c, float d) const; // done (inlined in vc) float GetCollisionRatio(float a, float b, float c, float d) const; // inlined in vc
float GetDistanceSquared(const CVector &v) const; // done (inlined in vc) float GetDistanceSquared(const CVector &v) const; // inlined in vc
int32 GetJumboTaxiFreq() const; // done (inlined in vc) int32 GetJumboTaxiFreq() const; // inlined in vc
uint8 GetMissionAudioLoadingStatus(uint8 slot) const; // done uint8 GetMissionAudioLoadingStatus(uint8 slot) const;
int8 GetMissionScriptPoliceAudioPlayingStatus() const; // done int8 GetMissionScriptPoliceAudioPlayingStatus() const;
uint8 GetNum3DProvidersAvailable() const; // done uint8 GetNum3DProvidersAvailable() const;
uint32 GetPedCommentSfx(CPed *ped, int32 sound); // done uint32 GetPedCommentSfx(CPed *ped, int32 sound);
void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const; // done void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const;
float GetVehicleDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, float gasPedalAudio, cTransmission *transmission, float GetVehicleDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, float gasPedalAudio, cTransmission *transmission,
float velocityChange); // done float velocityChange);
float GetVehicleNonDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, cTransmission *transmission, float velocityChange); // done float GetVehicleNonDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, cTransmission *transmission, float velocityChange);
bool8 HasAirBrakes(int32 model) const; // done bool8 HasAirBrakes(int32 model) const;
void Initialise(); // done void Initialise();
void InitialisePoliceRadio(); // done void InitialisePoliceRadio();
void InitialisePoliceRadioZones(); // done void InitialisePoliceRadioZones();
void InterrogateAudioEntities(); // done (inlined) void InterrogateAudioEntities(); // inlined
bool8 IsAudioInitialised() const; // done bool8 IsAudioInitialised() const;
bool8 IsMissionAudioSampleFinished(uint8 slot); // done bool8 IsMissionAudioSampleFinished(uint8 slot);
bool8 IsMP3RadioChannelAvailable() const; // done bool8 IsMP3RadioChannelAvailable() const;
bool8 MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; //done bool8 MissionScriptAudioUsesPoliceChannel(int32 soundMission) const;
void PlayLoadedMissionAudio(uint8 slot); // done void PlayLoadedMissionAudio(uint8 slot);
void PlayOneShot(int32 index, uint16 sound, float vol); // done void PlayOneShot(int32 index, uint16 sound, float vol);
void PlaySuspectLastSeen(float x, float y, float z); // done void PlaySuspectLastSeen(float x, float y, float z);
void PlayerJustGotInCar() const; // done void PlayerJustGotInCar() const;
void PlayerJustLeftCar() const; // done void PlayerJustLeftCar() const;
void PostInitialiseGameSpecificSetup(); // done void PostInitialiseGameSpecificSetup();
void PostTerminateGameSpecificShutdown(); // done void PostTerminateGameSpecificShutdown();
void PreInitialiseGameSpecificSetup() const; // done void PreInitialiseGameSpecificSetup() const;
void PreloadMissionAudio(uint8 slot, Const char *name); // done void PreloadMissionAudio(uint8 slot, Const char *name);
void PreTerminateGameSpecificShutdown(); // done void PreTerminateGameSpecificShutdown();
/// processX - main logic of adding new sounds /// processX - main logic of adding new sounds
void ProcessActiveQueues(); // done void ProcessActiveQueues();
bool8 ProcessAirBrakes(cVehicleParams& params); // done bool8 ProcessAirBrakes(cVehicleParams& params);
bool8 ProcessBoatEngine(cVehicleParams& params); bool8 ProcessBoatEngine(cVehicleParams& params);
bool8 ProcessBoatMovingOverWater(cVehicleParams& params); //done bool8 ProcessBoatMovingOverWater(cVehicleParams& params);
#ifdef GTA_BRIDGE #ifdef GTA_BRIDGE
void ProcessBridge(); // done(bcs not exists in VC) void ProcessBridge();
void ProcessBridgeMotor(); // done(bcs not exists in VC) void ProcessBridgeMotor();
void ProcessBridgeOneShots(); // done(bcs not exists in VC) void ProcessBridgeOneShots();
void ProcessBridgeWarning(); // done(bcs not exists in VC) void ProcessBridgeWarning();
#endif #endif
bool8 ProcessCarBombTick(cVehicleParams& params); // done bool8 ProcessCarBombTick(cVehicleParams& params);
void ProcessCarHeli(cVehicleParams& params); // done void ProcessCarHeli(cVehicleParams& params);
void ProcessCesna(cVehicleParams& params); // done void ProcessCesna(cVehicleParams& params);
//void ProcessCrane(); // done(bcs not exists in VC) //void ProcessCrane();
bool8 ProcessEngineDamage(cVehicleParams& params); // done bool8 ProcessEngineDamage(cVehicleParams& params);
void ProcessEntity(int32 sound); // done void ProcessEntity(int32 sound);
void ProcessExplosions(int32 explosion); // done void ProcessExplosions(int32 explosion);
void ProcessFireHydrant(); // done void ProcessFireHydrant();
void ProcessFires(int32 entity); // done void ProcessFires(int32 entity);
void ProcessFrontEnd(); // done void ProcessFrontEnd();
void ProcessGarages(); // done void ProcessGarages();
void ProcessJumbo(cVehicleParams& params); // done void ProcessJumbo(cVehicleParams& params);
void ProcessJumboAccel(CPlane *plane); // done void ProcessJumboAccel(CPlane *plane);
void ProcessJumboDecel(CPlane *plane); // done void ProcessJumboDecel(CPlane *plane);
void ProcessJumboFlying(); // done void ProcessJumboFlying();
void ProcessJumboLanding(CPlane *plane); // done void ProcessJumboLanding(CPlane *plane);
void ProcessJumboTakeOff(CPlane *plane); // done void ProcessJumboTakeOff(CPlane *plane);
void ProcessJumboTaxi(); // done void ProcessJumboTaxi();
void ProcessLoopingScriptObject(uint8 sound); // done void ProcessLoopingScriptObject(uint8 sound);
void ProcessMissionAudio(); // done void ProcessMissionAudio();
void ProcessMissionAudioSlot(uint8 slot); // done void ProcessMissionAudioSlot(uint8 slot);
void ProcessModelHeliVehicle(cVehicleParams& params); // done void ProcessModelHeliVehicle(cVehicleParams& params);
void ProcessModelVehicle(cVehicleParams& params); // done void ProcessModelVehicle(cVehicleParams& params);
void ProcessOneShotScriptObject(uint8 sound); // void ProcessOneShotScriptObject(uint8 sound);
void ProcessPed(CPhysical *ped); // done void ProcessPed(CPhysical *ped);
void ProcessPedOneShots(cPedParams &params); // void ProcessPedOneShots(cPedParams &params);
void ProcessPhysical(int32 id); // done void ProcessPhysical(int32 id);
void ProcessPlane(cVehicleParams& params); // done void ProcessPlane(cVehicleParams& params);
void ProcessPlayerMood(); // done void ProcessPlayerMood();
void ProcessPlayersVehicleEngine(cVehicleParams& params, CVehicle* veh); // done void ProcessPlayersVehicleEngine(cVehicleParams& params, CVehicle* veh);
void ProcessProjectiles(); // done void ProcessProjectiles();
void ProcessRainOnVehicle(cVehicleParams& params); // done void ProcessRainOnVehicle(cVehicleParams& params);
void ProcessReverb() const; // done void ProcessReverb() const;
bool8 ProcessReverseGear(cVehicleParams& params); // done bool8 ProcessReverseGear(cVehicleParams& params);
void ProcessScriptObject(int32 id); // done void ProcessScriptObject(int32 id);
void ProcessSpecial(); // done void ProcessSpecial();
#ifdef GTA_TRAIN #ifdef GTA_TRAIN
bool8 ProcessTrainNoise(cVehicleParams &params); //done(bcs not exists in VC) bool8 ProcessTrainNoise(cVehicleParams &params);
#endif #endif
void ProcessVehicle(CVehicle *vehicle); // done void ProcessVehicle(CVehicle *vehicle);
bool8 ProcessVehicleDoors(cVehicleParams &params); // done bool8 ProcessVehicleDoors(cVehicleParams &params);
void ProcessVehicleEngine(cVehicleParams &params); // done void ProcessVehicleEngine(cVehicleParams &params);
void ProcessVehicleFlatTyre(cVehicleParams &params); // done void ProcessVehicleFlatTyre(cVehicleParams &params);
bool8 ProcessVehicleHorn(cVehicleParams &params); // done bool8 ProcessVehicleHorn(cVehicleParams &params);
void ProcessVehicleOneShots(cVehicleParams &params); // done void ProcessVehicleOneShots(cVehicleParams &params);
bool8 ProcessVehicleReverseWarning(cVehicleParams &params); // done bool8 ProcessVehicleReverseWarning(cVehicleParams &params);
bool8 ProcessVehicleRoadNoise(cVehicleParams &params); // done bool8 ProcessVehicleRoadNoise(cVehicleParams &params);
bool8 ProcessVehicleSirenOrAlarm(cVehicleParams &params); // done bool8 ProcessVehicleSirenOrAlarm(cVehicleParams &params);
bool8 ProcessVehicleSkidding(cVehicleParams &params); // done bool8 ProcessVehicleSkidding(cVehicleParams &params);
void ProcessWaterCannon(int32); // done void ProcessWaterCannon(int32);
void ProcessWeather(int32 id); // done void ProcessWeather(int32 id);
bool8 ProcessWetRoadNoise(cVehicleParams& params); // done bool8 ProcessWetRoadNoise(cVehicleParams& params);
void ProcessEscalators(); // done void ProcessEscalators();
void ProcessExtraSounds(); // done void ProcessExtraSounds();
int32 RandomDisplacement(uint32 seed) const; // done int32 RandomDisplacement(uint32 seed) const;
void ReacquireDigitalHandle() const; // done void ReacquireDigitalHandle() const;
void ReleaseDigitalHandle() const; // done void ReleaseDigitalHandle() const;
void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2); // done void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2);
void ReportCrime(eCrimeType crime, const CVector &pos); // done void ReportCrime(eCrimeType crime, const CVector &pos);
void ResetAudioLogicTimers(uint32 timer); // done void ResetAudioLogicTimers(uint32 timer);
void ResetPoliceRadio(); // done void ResetPoliceRadio();
void ResetTimers(uint32 time); // done void ResetTimers(uint32 time);
void Service(); // done void Service();
void ServiceCollisions(); // done void ServiceCollisions();
void ServicePoliceRadio(); // done void ServicePoliceRadio();
void ServicePoliceRadioChannel(uint8 wantedLevel); // done void ServicePoliceRadioChannel(uint8 wantedLevel);
void ServiceSoundEffects(); // done void ServiceSoundEffects();
int8 SetCurrent3DProvider(uint8 which); // done int8 SetCurrent3DProvider(uint8 which);
void SetDynamicAcousticModelingStatus(bool8 status); // done void SetDynamicAcousticModelingStatus(bool8 status);
void SetEffectsFadeVol(uint8 volume) const; // done void SetEffectsFadeVol(uint8 volume) const;
void SetEffectsMasterVolume(uint8 volume) const; // done void SetEffectsMasterVolume(uint8 volume) const;
void SetMP3BoostVolume(uint8 volume) const; // done void SetMP3BoostVolume(uint8 volume) const;
void SetEntityStatus(int32 id, bool8 status); // done void SetEntityStatus(int32 id, bool8 status);
uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); // done uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision);
void SetMissionAudioLocation(uint8 slot, float x, float y, float z); // done void SetMissionAudioLocation(uint8 slot, float x, float y, float z);
void SetMissionScriptPoliceAudio(int32 sfx) const; // inlined and optimized void SetMissionScriptPoliceAudio(int32 sfx) const; // inlined and optimized
void SetMonoMode(bool8 mono); // done void SetMonoMode(bool8 mono);
void SetMusicFadeVol(uint8 volume) const; // done void SetMusicFadeVol(uint8 volume) const;
void SetMusicMasterVolume(uint8 volume) const; // done void SetMusicMasterVolume(uint8 volume) const;
void SetSpeakerConfig(int32 conf) const; // done void SetSpeakerConfig(int32 conf) const;
void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter); // done void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter);
void SetUpOneShotCollisionSound(const cAudioCollision &col); // done void SetUpOneShotCollisionSound(const cAudioCollision &col);
bool8 SetupCrimeReport(); // done bool8 SetupCrimeReport();
bool8 SetupJumboEngineSound(uint8 vol, uint32 freq); // done bool8 SetupJumboEngineSound(uint8 vol, uint32 freq);
bool8 SetupJumboFlySound(uint8 emittingVol); // done bool8 SetupJumboFlySound(uint8 emittingVol);
bool8 SetupJumboRumbleSound(uint8 emittingVol); // done bool8 SetupJumboRumbleSound(uint8 emittingVol);
bool8 SetupJumboTaxiSound(uint8 vol); // done bool8 SetupJumboTaxiSound(uint8 vol);
bool8 SetupJumboWhineSound(uint8 emittingVol, uint32 freq); // done bool8 SetupJumboWhineSound(uint8 emittingVol, uint32 freq);
void SetupPedComments(cPedParams &params, uint16 sound); // done void SetupPedComments(cPedParams &params, uint16 sound);
void SetupSuspectLastSeenReport(); void SetupSuspectLastSeenReport();
void Terminate(); // done void Terminate();
void TranslateEntity(Const CVector *v1, CVector *v2) const; // done void TranslateEntity(Const CVector *v1, CVector *v2) const;
void UpdateGasPedalAudio(CVehicle *veh, int vehType); // done void UpdateGasPedalAudio(CVehicle *veh, int vehType);
void UpdateReflections(); // done void UpdateReflections();
bool8 UsesReverseWarning(int32 model) const; // done bool8 UsesReverseWarning(int32 model) const;
bool8 UsesSiren(cVehicleParams &params) const; // done bool8 UsesSiren(cVehicleParams &params) const;
bool8 UsesSirenSwitching(cVehicleParams &params) const; // done bool8 UsesSirenSwitching(cVehicleParams &params) const;
CVehicle *FindVehicleOfPlayer(); // done CVehicle *FindVehicleOfPlayer();
void SetPedTalkingStatus(CPed *ped, bool8 status); // done void SetPedTalkingStatus(CPed *ped, bool8 status);
void SetPlayersMood(uint8 mood, uint32 time); // done void SetPlayersMood(uint8 mood, uint32 time);
float Sqrt(float v) const { return v <= 0.0f ? 0.0f : ::Sqrt(v); } float Sqrt(float v) const { return v <= 0.0f ? 0.0f : ::Sqrt(v); }
#ifdef GTA_PC #ifdef GTA_PC
// only used in pc // only used in pc
void AdjustSamplesVolume(); // done (inlined) void AdjustSamplesVolume(); // inlined
uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); // done (inlined) uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); // inlined
#endif #endif
}; };

View file

@ -1648,7 +1648,7 @@ void CStream::SetPlay(bool state)
{ {
ALint sourceState = AL_STOPPED; ALint sourceState = AL_STOPPED;
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState); alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
if (sourceState != AL_STOPPED ) if (sourceState != AL_STOPPED)
alSourceStop(m_pAlSources[0]); alSourceStop(m_pAlSources[0]);
sourceState = AL_STOPPED; sourceState = AL_STOPPED;

View file

@ -50,45 +50,45 @@ void CAutoPilot::RemoveOnePathNode()
#ifdef COMPATIBLE_SAVES #ifdef COMPATIBLE_SAVES
void CAutoPilot::Save(uint8*& buf) void CAutoPilot::Save(uint8*& buf)
{ {
WriteSaveBuf<int32>(buf, m_nCurrentRouteNode); WriteSaveBuf(buf, m_nCurrentRouteNode);
WriteSaveBuf<int32>(buf, m_nNextRouteNode); WriteSaveBuf(buf, m_nNextRouteNode);
WriteSaveBuf<int32>(buf, m_nPrevRouteNode); WriteSaveBuf(buf, m_nPrevRouteNode);
WriteSaveBuf<int32>(buf, m_nTimeEnteredCurve); WriteSaveBuf(buf, m_nTimeEnteredCurve);
WriteSaveBuf<int32>(buf, m_nTimeToSpendOnCurrentCurve); WriteSaveBuf(buf, m_nTimeToSpendOnCurrentCurve);
WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo); WriteSaveBuf(buf, m_nCurrentPathNodeInfo);
WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo); WriteSaveBuf(buf, m_nNextPathNodeInfo);
WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo); WriteSaveBuf(buf, m_nPreviousPathNodeInfo);
WriteSaveBuf<uint32>(buf, m_nAntiReverseTimer); WriteSaveBuf(buf, m_nAntiReverseTimer);
WriteSaveBuf<uint32>(buf, m_nTimeToStartMission); WriteSaveBuf(buf, m_nTimeToStartMission);
WriteSaveBuf<int8>(buf, m_nPreviousDirection); WriteSaveBuf(buf, m_nPreviousDirection);
WriteSaveBuf<int8>(buf, m_nCurrentDirection); WriteSaveBuf(buf, m_nCurrentDirection);
WriteSaveBuf<int8>(buf, m_nNextDirection); WriteSaveBuf(buf, m_nNextDirection);
WriteSaveBuf<int8>(buf, m_nCurrentLane); WriteSaveBuf(buf, m_nCurrentLane);
WriteSaveBuf<int8>(buf, m_nNextLane); WriteSaveBuf(buf, m_nNextLane);
WriteSaveBuf<uint8>(buf, m_nDrivingStyle); WriteSaveBuf(buf, m_nDrivingStyle);
WriteSaveBuf<uint8>(buf, m_nCarMission); WriteSaveBuf(buf, m_nCarMission);
WriteSaveBuf<uint8>(buf, m_nTempAction); WriteSaveBuf(buf, m_nTempAction);
WriteSaveBuf<uint32>(buf, m_nTimeTempAction); WriteSaveBuf(buf, m_nTimeTempAction);
WriteSaveBuf<float>(buf, m_fMaxTrafficSpeed); WriteSaveBuf(buf, m_fMaxTrafficSpeed);
WriteSaveBuf<uint8>(buf, m_nCruiseSpeed); WriteSaveBuf(buf, m_nCruiseSpeed);
WriteSaveBuf<uint8>(buf, m_nCruiseSpeedMultiplierType); WriteSaveBuf(buf, m_nCruiseSpeedMultiplierType);
SkipSaveBuf(buf, 2); ZeroSaveBuf(buf, 2);
WriteSaveBuf<float>(buf, m_fCruiseSpeedMultiplier); WriteSaveBuf(buf, m_fCruiseSpeedMultiplier);
uint8 flags = 0; uint8 flags = 0;
if (m_bSlowedDownBecauseOfCars) flags |= BIT(0); if (m_bSlowedDownBecauseOfCars) flags |= BIT(0);
if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1); if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1);
if (m_bStayInCurrentLevel) flags |= BIT(2); if (m_bStayInCurrentLevel) flags |= BIT(2);
if (m_bStayInFastLane) flags |= BIT(3); if (m_bStayInFastLane) flags |= BIT(3);
if (m_bIgnorePathfinding) flags |= BIT(4); if (m_bIgnorePathfinding) flags |= BIT(4);
WriteSaveBuf<uint8>(buf, flags); WriteSaveBuf(buf, flags);
WriteSaveBuf<uint8>(buf, m_nSwitchDistance); WriteSaveBuf(buf, m_nSwitchDistance);
SkipSaveBuf(buf, 2); ZeroSaveBuf(buf, 2);
WriteSaveBuf<float>(buf, m_vecDestinationCoors.x); WriteSaveBuf(buf, m_vecDestinationCoors.x);
WriteSaveBuf<float>(buf, m_vecDestinationCoors.y); WriteSaveBuf(buf, m_vecDestinationCoors.y);
WriteSaveBuf<float>(buf, m_vecDestinationCoors.z); WriteSaveBuf(buf, m_vecDestinationCoors.z);
SkipSaveBuf(buf, 32); ZeroSaveBuf(buf, 32);
WriteSaveBuf<int16>(buf, m_nPathFindNodesCount); WriteSaveBuf(buf, m_nPathFindNodesCount);
SkipSaveBuf(buf, 6); ZeroSaveBuf(buf, 6);
} }
void CAutoPilot::Load(uint8*& buf) void CAutoPilot::Load(uint8*& buf)

View file

@ -29,13 +29,6 @@
#include "VarConsole.h" #include "VarConsole.h"
#include "SaveBuf.h" #include "SaveBuf.h"
#define CRUSHER_GARAGE_X1 (1135.5f)
#define CRUSHER_GARAGE_Y1 (57.0f)
#define CRUSHER_GARAGE_Z1 (-1.0f)
#define CRUSHER_GARAGE_X2 (1149.5f)
#define CRUSHER_GARAGE_Y2 (63.7f)
#define CRUSHER_GARAGE_Z2 (3.5f)
#define ROTATED_DOOR_OPEN_SPEED (0.015f) #define ROTATED_DOOR_OPEN_SPEED (0.015f)
#define ROTATED_DOOR_CLOSE_SPEED (0.02f) #define ROTATED_DOOR_CLOSE_SPEED (0.02f)
#define DEFAULT_DOOR_OPEN_SPEED (0.035f) #define DEFAULT_DOOR_OPEN_SPEED (0.035f)
@ -2640,8 +2633,53 @@ void CGarages::Save(uint8 * buf, uint32 * size)
WriteSaveBuf(buf, aCarsInSafeHouses[j][i]); WriteSaveBuf(buf, aCarsInSafeHouses[j][i]);
} }
} }
for (int i = 0; i < NUM_GARAGES; i++) for (int i = 0; i < NUM_GARAGES; i++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, aGarages[i].m_eGarageType);
WriteSaveBuf(buf, aGarages[i].m_eGarageState);
WriteSaveBuf(buf, aGarages[i].m_nMaxStoredCars);
WriteSaveBuf(buf, aGarages[i].field_2);
WriteSaveBuf(buf, aGarages[i].m_bClosingWithoutTargetCar);
WriteSaveBuf(buf, aGarages[i].m_bDeactivated);
WriteSaveBuf(buf, aGarages[i].m_bResprayHappened);
ZeroSaveBuf(buf, 1);
WriteSaveBuf(buf, aGarages[i].m_nTargetModelIndex);
ZeroSaveBuf(buf, 4 + 4);
WriteSaveBuf(buf, aGarages[i].m_bDoor1PoolIndex);
WriteSaveBuf(buf, aGarages[i].m_bDoor2PoolIndex);
WriteSaveBuf(buf, aGarages[i].m_bDoor1IsDummy);
WriteSaveBuf(buf, aGarages[i].m_bDoor2IsDummy);
WriteSaveBuf(buf, aGarages[i].m_bRecreateDoorOnNextRefresh);
WriteSaveBuf(buf, aGarages[i].m_bRotatedDoor);
WriteSaveBuf(buf, aGarages[i].m_bCameraFollowsPlayer);
ZeroSaveBuf(buf, 1);
WriteSaveBuf(buf, aGarages[i].m_vecCorner1);
WriteSaveBuf(buf, aGarages[i].m_fInfZ);
WriteSaveBuf(buf, aGarages[i].m_vDir1);
WriteSaveBuf(buf, aGarages[i].m_vDir2);
WriteSaveBuf(buf, aGarages[i].m_fSupZ);
WriteSaveBuf(buf, aGarages[i].m_fDir1Len);
WriteSaveBuf(buf, aGarages[i].m_fDir2Len);
WriteSaveBuf(buf, aGarages[i].m_fInfX);
WriteSaveBuf(buf, aGarages[i].m_fSupX);
WriteSaveBuf(buf, aGarages[i].m_fInfY);
WriteSaveBuf(buf, aGarages[i].m_fSupY);
WriteSaveBuf(buf, aGarages[i].m_fDoorPos);
WriteSaveBuf(buf, aGarages[i].m_fDoorHeight);
WriteSaveBuf(buf, aGarages[i].m_fDoor1X);
WriteSaveBuf(buf, aGarages[i].m_fDoor1Y);
WriteSaveBuf(buf, aGarages[i].m_fDoor2X);
WriteSaveBuf(buf, aGarages[i].m_fDoor2Y);
WriteSaveBuf(buf, aGarages[i].m_fDoor1Z);
WriteSaveBuf(buf, aGarages[i].m_fDoor2Z);
WriteSaveBuf(buf, aGarages[i].m_nTimeToStartAction);
WriteSaveBuf(buf, aGarages[i].m_bCollectedCarsState);
ZeroSaveBuf(buf, 3 + 4);
ZeroSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar));
#else
WriteSaveBuf(buf, aGarages[i]); WriteSaveBuf(buf, aGarages[i]);
#endif
}
//VALIDATESAVEBUF(*size); //VALIDATESAVEBUF(*size);
} }
@ -2669,7 +2707,51 @@ void CGarages::Load(uint8* buf, uint32 size)
} }
} }
for (int i = 0; i < NUM_GARAGES; i++) { for (int i = 0; i < NUM_GARAGES; i++) {
#ifdef COMPATIBLE_SAVES
ReadSaveBuf(&aGarages[i].m_eGarageType, buf);
ReadSaveBuf(&aGarages[i].m_eGarageState, buf);
ReadSaveBuf(&aGarages[i].m_nMaxStoredCars, buf);
ReadSaveBuf(&aGarages[i].field_2, buf);
ReadSaveBuf(&aGarages[i].m_bClosingWithoutTargetCar, buf);
ReadSaveBuf(&aGarages[i].m_bDeactivated, buf);
ReadSaveBuf(&aGarages[i].m_bResprayHappened, buf);
SkipSaveBuf(buf, 1);
ReadSaveBuf(&aGarages[i].m_nTargetModelIndex, buf);
SkipSaveBuf(buf, 4 + 4);
ReadSaveBuf(&aGarages[i].m_bDoor1PoolIndex, buf);
ReadSaveBuf(&aGarages[i].m_bDoor2PoolIndex, buf);
ReadSaveBuf(&aGarages[i].m_bDoor1IsDummy, buf);
ReadSaveBuf(&aGarages[i].m_bDoor2IsDummy, buf);
ReadSaveBuf(&aGarages[i].m_bRecreateDoorOnNextRefresh, buf);
ReadSaveBuf(&aGarages[i].m_bRotatedDoor, buf);
ReadSaveBuf(&aGarages[i].m_bCameraFollowsPlayer, buf);
SkipSaveBuf(buf, 1);
ReadSaveBuf(&aGarages[i].m_vecCorner1, buf);
ReadSaveBuf(&aGarages[i].m_fInfZ, buf);
ReadSaveBuf(&aGarages[i].m_vDir1, buf);
ReadSaveBuf(&aGarages[i].m_vDir2, buf);
ReadSaveBuf(&aGarages[i].m_fSupZ, buf);
ReadSaveBuf(&aGarages[i].m_fDir1Len, buf);
ReadSaveBuf(&aGarages[i].m_fDir2Len, buf);
ReadSaveBuf(&aGarages[i].m_fInfX, buf);
ReadSaveBuf(&aGarages[i].m_fSupX, buf);
ReadSaveBuf(&aGarages[i].m_fInfY, buf);
ReadSaveBuf(&aGarages[i].m_fSupY, buf);
ReadSaveBuf(&aGarages[i].m_fDoorPos, buf);
ReadSaveBuf(&aGarages[i].m_fDoorHeight, buf);
ReadSaveBuf(&aGarages[i].m_fDoor1X, buf);
ReadSaveBuf(&aGarages[i].m_fDoor1Y, buf);
ReadSaveBuf(&aGarages[i].m_fDoor2X, buf);
ReadSaveBuf(&aGarages[i].m_fDoor2Y, buf);
ReadSaveBuf(&aGarages[i].m_fDoor1Z, buf);
ReadSaveBuf(&aGarages[i].m_fDoor2Z, buf);
ReadSaveBuf(&aGarages[i].m_nTimeToStartAction, buf);
ReadSaveBuf(&aGarages[i].m_bCollectedCarsState, buf);
SkipSaveBuf(buf, 3 + 4);
SkipSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar));
#else
ReadSaveBuf(&aGarages[i], buf); ReadSaveBuf(&aGarages[i], buf);
#endif
aGarages[i].m_pDoor1 = nil; aGarages[i].m_pDoor1 = nil;
aGarages[i].m_pDoor2 = nil; aGarages[i].m_pDoor2 = nil;
aGarages[i].m_pTarget = nil; aGarages[i].m_pTarget = nil;

View file

@ -115,7 +115,7 @@ public:
bool m_bClosingWithoutTargetCar; bool m_bClosingWithoutTargetCar;
bool m_bDeactivated; bool m_bDeactivated;
bool m_bResprayHappened; bool m_bResprayHappened;
int m_nTargetModelIndex; int32 m_nTargetModelIndex;
CEntity *m_pDoor1; CEntity *m_pDoor1;
CEntity *m_pDoor2; CEntity *m_pDoor2;
uint8 m_bDoor1PoolIndex; uint8 m_bDoor1PoolIndex;

View file

@ -18,6 +18,12 @@
#include "Replay.h" #include "Replay.h"
#endif #endif
#ifdef COMPATIBLE_SAVES
#define PHONEINFO_SAVE_SIZE 0xA30
#else
#define PHONEINFO_SAVE_SIZE sizeof(CPhoneInfo)
#endif
CPhoneInfo gPhoneInfo; CPhoneInfo gPhoneInfo;
bool CPhoneInfo::bDisplayingPhoneMessage; // is phone picked up bool CPhoneInfo::bDisplayingPhoneMessage; // is phone picked up
@ -201,11 +207,24 @@ INITSAVEBUF
ReadSaveBuf(&m_nMax, buf); ReadSaveBuf(&m_nMax, buf);
ReadSaveBuf(&m_nScriptPhonesMax, buf); ReadSaveBuf(&m_nScriptPhonesMax, buf);
for (int i = 0; i < NUMPHONES; i++) { for (int i = 0; i < NUMPHONES; i++) {
#ifdef COMPATIBLE_SAVES
ReadSaveBuf(&m_aPhones[i].m_vecPos, buf);
SkipSaveBuf(buf, 6 * 4);
ReadSaveBuf(&m_aPhones[i].m_repeatedMessagePickupStart, buf);
int32 tmp;
ReadSaveBuf(&tmp, buf);
// It's saved as building pool index in save file, convert it to true entity
m_aPhones[i].m_pEntity = tmp != 0 ? CPools::GetBuildingPool()->GetSlot(tmp - 1) : nil;
ReadSaveBuf(&m_aPhones[i].m_nState, buf);
ReadSaveBuf(&m_aPhones[i].m_visibleToCam, buf);
SkipSaveBuf(buf, 3);
#else
ReadSaveBuf(&m_aPhones[i], buf); ReadSaveBuf(&m_aPhones[i], buf);
// It's saved as building pool index in save file, convert it to true entity // It's saved as building pool index in save file, convert it to true entity
if (m_aPhones[i].m_pEntity) { if (m_aPhones[i].m_pEntity) {
m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1); m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1);
} }
#endif
} }
VALIDATESAVEBUF(size) VALIDATESAVEBUF(size)
} }
@ -299,17 +318,29 @@ CPhoneInfo::Initialise(void)
void void
CPhoneInfo::Save(uint8 *buf, uint32 *size) CPhoneInfo::Save(uint8 *buf, uint32 *size)
{ {
*size = sizeof(CPhoneInfo); *size = PHONEINFO_SAVE_SIZE;
INITSAVEBUF INITSAVEBUF
WriteSaveBuf(buf, m_nMax); WriteSaveBuf(buf, m_nMax);
WriteSaveBuf(buf, m_nScriptPhonesMax); WriteSaveBuf(buf, m_nScriptPhonesMax);
for(int phoneId = 0; phoneId < NUMPHONES; phoneId++) { for(int phoneId = 0; phoneId < NUMPHONES; phoneId++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, m_aPhones[phoneId].m_vecPos);
ZeroSaveBuf(buf, 6 * 4);
WriteSaveBuf(buf, m_aPhones[phoneId].m_repeatedMessagePickupStart);
// Convert entity pointer to building pool index while saving
int32 tmp = m_aPhones[phoneId].m_pEntity ? CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)m_aPhones[phoneId].m_pEntity) + 1 : 0;
WriteSaveBuf(buf, tmp);
WriteSaveBuf(buf, m_aPhones[phoneId].m_nState);
WriteSaveBuf(buf, m_aPhones[phoneId].m_visibleToCam);
ZeroSaveBuf(buf, 3);
#else
CPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]); CPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]);
// Convert entity pointer to building pool index while saving // Convert entity pointer to building pool index while saving
if (phone->m_pEntity) { if (phone->m_pEntity) {
phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1); phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1);
} }
#endif
} }
VALIDATESAVEBUF(*size) VALIDATESAVEBUF(*size)
} }

View file

@ -35,6 +35,12 @@
#include "Streaming.h" #include "Streaming.h"
#include "SaveBuf.h" #include "SaveBuf.h"
#ifdef COMPATIBLE_SAVES
#define PICKUPS_SAVE_SIZE 0x4440
#else
#define PICKUPS_SAVE_SIZE sizeof(aPickUps)
#endif
CPickup CPickups::aPickUps[NUMPICKUPS]; CPickup CPickups::aPickUps[NUMPICKUPS];
int16 CPickups::NumMessages; int16 CPickups::NumMessages;
int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS]; int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];
@ -1442,6 +1448,31 @@ CPickups::Load(uint8 *buf, uint32 size)
INITSAVEBUF INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) { for (int32 i = 0; i < NUMPICKUPS; i++) {
#ifdef COMPATIBLE_SAVES
ReadSaveBuf(&aPickUps[i].m_vecPos, buf);
ReadSaveBuf(&aPickUps[i].m_fRevenue, buf);
int32 tmp_pObject;
ReadSaveBuf(&tmp_pObject, buf);
int32 tmp_pExtraObject;
ReadSaveBuf(&tmp_pExtraObject, buf);
ReadSaveBuf(&aPickUps[i].m_nQuantity, buf);
ReadSaveBuf(&aPickUps[i].m_nTimer, buf);
ReadSaveBuf(&aPickUps[i].m_nMoneySpeed, buf);
ReadSaveBuf(&aPickUps[i].m_eModelIndex, buf);
ReadSaveBuf(&aPickUps[i].m_nIndex, buf);
memcpy(aPickUps[i].m_sTextKey, buf, sizeof(aPickUps[i].m_sTextKey));
SkipSaveBuf(buf, sizeof(aPickUps[i].m_sTextKey));
ReadSaveBuf(&aPickUps[i].m_eType, buf);
ReadSaveBuf(&aPickUps[i].m_bRemoved, buf);
uint8 flags;
ReadSaveBuf(&flags, buf);
aPickUps[i].m_bWasAmmoCollected = !!(flags & BIT(0));
aPickUps[i].m_bWasControlMessageShown = !!(flags & BIT(1));
SkipSaveBuf(buf, 3);
aPickUps[i].m_pObject = aPickUps[i].m_eType != PICKUP_NONE && tmp_pObject != 0 ? CPools::GetObjectPool()->GetSlot(tmp_pObject - 1) : nil;
aPickUps[i].m_pExtraObject = aPickUps[i].m_eType != PICKUP_NONE && tmp_pExtraObject != 0 ? CPools::GetObjectPool()->GetSlot(tmp_pExtraObject - 1) : nil;
#else
ReadSaveBuf(&aPickUps[i], buf); ReadSaveBuf(&aPickUps[i], buf);
if (aPickUps[i].m_eType != PICKUP_NONE) { if (aPickUps[i].m_eType != PICKUP_NONE) {
@ -1450,7 +1481,7 @@ INITSAVEBUF
if (aPickUps[i].m_pExtraObject != nil) if (aPickUps[i].m_pExtraObject != nil)
aPickUps[i].m_pExtraObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pExtraObject - 1); aPickUps[i].m_pExtraObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pExtraObject - 1);
} }
#endif
} }
ReadSaveBuf(&CollectedPickUpIndex, buf); ReadSaveBuf(&CollectedPickUpIndex, buf);
@ -1466,12 +1497,34 @@ VALIDATESAVEBUF(size)
void void
CPickups::Save(uint8 *buf, uint32 *size) CPickups::Save(uint8 *buf, uint32 *size)
{ {
*size = sizeof(aPickUps); *size = PICKUPS_SAVE_SIZE;
*size += sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); *size += sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
INITSAVEBUF INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) { for (int32 i = 0; i < NUMPICKUPS; i++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, aPickUps[i].m_vecPos);
WriteSaveBuf(buf, aPickUps[i].m_fRevenue);
int32 tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pObject) + 1 : 0;
WriteSaveBuf(buf, tmp);
tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pExtraObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pExtraObject) + 1 : 0;
WriteSaveBuf(buf, tmp);
WriteSaveBuf(buf, aPickUps[i].m_nQuantity);
WriteSaveBuf(buf, aPickUps[i].m_nTimer);
WriteSaveBuf(buf, aPickUps[i].m_nMoneySpeed);
WriteSaveBuf(buf, aPickUps[i].m_eModelIndex);
WriteSaveBuf(buf, aPickUps[i].m_nIndex);
memcpy(buf, aPickUps[i].m_sTextKey, sizeof(aPickUps[i].m_sTextKey));
SkipSaveBuf(buf, sizeof(aPickUps[i].m_sTextKey));
WriteSaveBuf(buf, aPickUps[i].m_eType);
WriteSaveBuf(buf, aPickUps[i].m_bRemoved);
uint8 flags = 0;
if (aPickUps[i].m_bWasAmmoCollected) flags |= BIT(0);
if (aPickUps[i].m_bWasControlMessageShown) flags |= BIT(1);
WriteSaveBuf(buf, flags);
ZeroSaveBuf(buf, 3);
#else
CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
if (buf_pickup->m_eType != PICKUP_NONE) { if (buf_pickup->m_eType != PICKUP_NONE) {
if (buf_pickup->m_pObject != nil) if (buf_pickup->m_pObject != nil)
@ -1479,6 +1532,7 @@ INITSAVEBUF
if (buf_pickup->m_pExtraObject != nil) if (buf_pickup->m_pExtraObject != nil)
buf_pickup->m_pExtraObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pExtraObject) + 1); buf_pickup->m_pExtraObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pExtraObject) + 1);
} }
#endif
} }
WriteSaveBuf(buf, CollectedPickUpIndex); WriteSaveBuf(buf, CollectedPickUpIndex);

View file

@ -2314,35 +2314,35 @@ VALIDATESAVEBUF(size)
void CRunningScript::Save(uint8*& buf) void CRunningScript::Save(uint8*& buf)
{ {
#ifdef COMPATIBLE_SAVES #ifdef COMPATIBLE_SAVES
SkipSaveBuf(buf, 8); ZeroSaveBuf(buf, 8);
WriteSaveBuf<int32>(buf, m_nId); WriteSaveBuf<int32>(buf, m_nId);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
WriteSaveBuf<char>(buf, m_abScriptName[i]); WriteSaveBuf(buf, m_abScriptName[i]);
WriteSaveBuf<uint32>(buf, m_nIp); WriteSaveBuf(buf, m_nIp);
#ifdef CHECK_STRUCT_SIZES #ifdef CHECK_STRUCT_SIZES
static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6");
#endif #endif
for (int i = 0; i < MAX_STACK_DEPTH; i++) for (int i = 0; i < MAX_STACK_DEPTH; i++)
WriteSaveBuf<uint32>(buf, m_anStack[i]); WriteSaveBuf(buf, m_anStack[i]);
WriteSaveBuf<uint16>(buf, m_nStackPointer); WriteSaveBuf(buf, m_nStackPointer);
SkipSaveBuf(buf, 2); ZeroSaveBuf(buf, 2);
#ifdef CHECK_STRUCT_SIZES #ifdef CHECK_STRUCT_SIZES
static_assert(NUM_LOCAL_VARS + 8 + NUM_TIMERS == 106, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 106"); static_assert(NUM_LOCAL_VARS + 8 + NUM_TIMERS == 106, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 106");
#endif #endif
for (int i = 0; i < NUM_LOCAL_VARS + 8 + NUM_TIMERS; i++) for (int i = 0; i < NUM_LOCAL_VARS + 8 + NUM_TIMERS; i++)
WriteSaveBuf<int32>(buf, m_anLocalVariables[i]); WriteSaveBuf(buf, m_anLocalVariables[i]);
WriteSaveBuf<int32>(buf, m_nLocalsPointer); WriteSaveBuf(buf, m_nLocalsPointer);
WriteSaveBuf<bool>(buf, m_bIsActive); WriteSaveBuf(buf, m_bIsActive);
WriteSaveBuf<bool>(buf, m_bCondResult); WriteSaveBuf(buf, m_bCondResult);
WriteSaveBuf<bool>(buf, m_bIsMissionScript); WriteSaveBuf(buf, m_bIsMissionScript);
WriteSaveBuf<bool>(buf, m_bSkipWakeTime); WriteSaveBuf(buf, m_bSkipWakeTime);
WriteSaveBuf<uint32>(buf, m_nWakeTime); WriteSaveBuf(buf, m_nWakeTime);
WriteSaveBuf<uint16>(buf, m_nAndOrState); WriteSaveBuf(buf, m_nAndOrState);
WriteSaveBuf<bool>(buf, m_bNotFlag); WriteSaveBuf(buf, m_bNotFlag);
WriteSaveBuf<bool>(buf, m_bDeatharrestEnabled); WriteSaveBuf(buf, m_bDeatharrestEnabled);
WriteSaveBuf<bool>(buf, m_bDeatharrestExecuted); WriteSaveBuf(buf, m_bDeatharrestExecuted);
WriteSaveBuf<bool>(buf, m_bMissionFlag); WriteSaveBuf(buf, m_bMissionFlag);
SkipSaveBuf(buf, 2); ZeroSaveBuf(buf, 2);
#else #else
WriteSaveBuf(buf, *this); WriteSaveBuf(buf, *this);
#endif #endif

View file

@ -33,4 +33,4 @@ public:
bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2); bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2);
}; };
VALIDATE_SIZE(CPlaceable, 0x4C); VALIDATE_SIZE(CPlaceable, 0x48);

View file

@ -310,9 +310,9 @@ INITSAVEBUF
#else #else
if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
#endif #endif
WriteSaveBuf<uint32>(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->m_vehType);
WriteSaveBuf<int16>(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, pVehicle->GetModelIndex());
WriteSaveBuf<int32>(buf, GetVehicleRef(pVehicle)); WriteSaveBuf(buf, GetVehicleRef(pVehicle));
pVehicle->Save(buf); pVehicle->Save(buf);
} }
#else #else
@ -321,7 +321,7 @@ INITSAVEBUF
#else #else
if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
#endif #endif
WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->m_vehType);
WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, pVehicle->GetModelIndex());
WriteSaveBuf(buf, GetVehicleRef(pVehicle)); WriteSaveBuf(buf, GetVehicleRef(pVehicle));
memcpy(buf, pVehicle, sizeof(CAutomobile)); memcpy(buf, pVehicle, sizeof(CAutomobile));
@ -332,7 +332,7 @@ INITSAVEBUF
#else #else
if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
#endif #endif
WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->m_vehType);
WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, pVehicle->GetModelIndex());
WriteSaveBuf(buf, GetVehicleRef(pVehicle)); WriteSaveBuf(buf, GetVehicleRef(pVehicle));
memcpy(buf, pVehicle, sizeof(CBoat)); memcpy(buf, pVehicle, sizeof(CBoat));
@ -343,7 +343,7 @@ INITSAVEBUF
#else #else
if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
#endif #endif
WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->m_vehType);
WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, pVehicle->GetModelIndex());
WriteSaveBuf(buf, GetVehicleRef(pVehicle)); WriteSaveBuf(buf, GetVehicleRef(pVehicle));
memcpy(buf, pVehicle, sizeof(CBike)); memcpy(buf, pVehicle, sizeof(CBike));

View file

@ -1229,7 +1229,11 @@ CStats::ConstructStatLine(int rowIdx)
FASTEST_TIME(20, "STFT_21"); FASTEST_TIME(20, "STFT_21");
if (FastestTimes[21]) if (FastestTimes[21])
#ifdef FIX_BUGS
STAT_LINE_1(float, "STFT_22", Floor(FastestTimes[21] / 10) / 100, 1);
#else
STAT_LINE_1(float, "STFT_22", FastestTimes[21] / 1000, 1); STAT_LINE_1(float, "STFT_22", FastestTimes[21] / 1000, 1);
#endif
if (TopShootingRangeScore > 0.0f) if (TopShootingRangeScore > 0.0f)
STAT_LINE_1(int, "TOP_SHO", TopShootingRangeScore, 0); STAT_LINE_1(int, "TOP_SHO", TopShootingRangeScore, 0);

View file

@ -1,7 +1,9 @@
#pragma once #pragma once
// disables (most) stuff that wasn't in original gta-vc.exe - check section at the bottom of this file // disables (most) stuff that wasn't in original gta-vc.exe
//#define VANILLA_DEFINES #ifdef __MWERKS__
#define VANILLA_DEFINES
#endif
enum Config { enum Config {
NUMPLAYERS = 1, NUMPLAYERS = 1,
@ -154,8 +156,36 @@ enum Config {
//#define GTA_PS2 //#define GTA_PS2
//#define GTA_XBOX //#define GTA_XBOX
// This enables things from the PS2 version on PC #define GTA_TRAIN
#define GTA_PS2_STUFF #define GTA_BRIDGE
// Version defines
#define GTAVC_PS2 400
#define GTAVC_PC_10 410
#define GTAVC_PC_11 411
#define GTAVC_PC_JAP 412
// TODO? maybe something for xbox or android?
#define GTA_VERSION GTAVC_PC_11
// TODO(MIAMI): someone ought to find and check out uses of these defines:
//#define GTA3_STEAM_PATCH
//#define GTAVC_JP_PATCH
#if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH
//# define USE_CUSTOM_ALLOCATOR
# define VU_COLLISION
# define PS2_MENU
#elif defined GTA_PC
# define PC_PLAYER_CONTROLS // mouse player/cam mode
//# define GTA_REPLAY
# define GTA_SCENE_EDIT
# define PC_MENU
# define PC_WATER
#elif defined GTA_XBOX
#endif
// This is enabled for all released games. // This is enabled for all released games.
// any debug stuff that isn't left in any game is not in FINAL // any debug stuff that isn't left in any game is not in FINAL
@ -174,22 +204,24 @@ enum Config {
#define FINAL #define FINAL
#endif #endif
// Version defines // these are placed here to work with VANILLA_DEFINES for compatibility
#define GTAVC_PS2 400 #define NO_CDCHECK // skip audio CD check
#define GTAVC_PC_10 410 #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch)
#define GTAVC_PC_11 411
#define GTAVC_PC_JAP 412
// TODO? maybe something for xbox or android?
#define GTA_VERSION GTAVC_PC_11
// TODO(MIAMI): someone ought to find and check out uses of these defines: #ifdef VANILLA_DEFINES
//#define GTA3_STEAM_PATCH #define FINAL
//#define GTAVC_JP_PATCH #define MASTER
//#define USE_MY_DOCUMENTS
#define THIS_IS_STUPID
#define DONT_FIX_REPLAY_BUGS
#define USE_TXD_CDIMAGE // generate and load textures from txd.img
//#define USE_TEXTURE_POOL // not possible because R* used custom RW33
#else
// This enables things from the PS2 version on PC
#define GTA_PS2_STUFF
// quality of life fixes that should also be in FINAL // quality of life fixes that should also be in FINAL
#define NASTY_GAME // nasty game for all languages #define NASTY_GAME // nasty game for all languages
#define NO_CDCHECK
// those infamous texts // those infamous texts
#define DRAW_GAME_VERSION_TEXT #define DRAW_GAME_VERSION_TEXT
@ -204,24 +236,10 @@ enum Config {
//#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices //#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices
//#define ANIM_COMPRESSION // only keep most recently used anims uncompressed //#define ANIM_COMPRESSION // only keep most recently used anims uncompressed
#define GTA_TRAIN #if defined GTA_PC && defined GTA_PS2_STUFF
#define GTA_BRIDGE
#if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH
//# define USE_CUSTOM_ALLOCATOR
# define VU_COLLISION
#elif defined GTA_PC
# ifdef GTA_PS2_STUFF
# define USE_PS2_RAND # define USE_PS2_RAND
# define RANDOMSPLASH // use random splash as on PS2 # define RANDOMSPLASH // use random splash as on PS2
# define PS2_MATFX # define PS2_MATFX
# endif
# define PC_PLAYER_CONTROLS // mouse player/cam mode
//# define GTA_REPLAY
# define GTA_SCENE_EDIT
#elif defined GTA_XBOX
#endif #endif
#ifdef VU_COLLISION #ifdef VU_COLLISION
@ -249,7 +267,8 @@ enum Config {
#define FIX_BUGS // fixes bugs that we've came across during reversing. You can undefine this only on release builds. #define FIX_BUGS // fixes bugs that we've came across during reversing. You can undefine this only on release builds.
//#define MORE_LANGUAGES // Add more translations to the game //#define MORE_LANGUAGES // Add more translations to the game
#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible, and keeps saves compatible between platforms
#define FIX_INCOMPATIBLE_SAVES // try to fix incompatible saves, requires COMPATIBLE_SAVES
#define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS #define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS
#define NO_MOVIES // add option to disable intro videos #define NO_MOVIES // add option to disable intro videos
@ -260,7 +279,7 @@ enum Config {
#define ASCII_STRCMP // use faster ascii str comparisons #define ASCII_STRCMP // use faster ascii str comparisons
#if !defined _WIN32 || defined __MWERKS__ || defined __MINGW32__ || defined VANILLA_DEFINES #if !defined _WIN32 || defined __MINGW32__
#undef ASCII_STRCMP #undef ASCII_STRCMP
#endif #endif
@ -295,7 +314,7 @@ enum Config {
#endif #endif
// Water & Particle // Water & Particle
// #define PC_WATER #undef PC_WATER
#define WATER_CHEATS #define WATER_CHEATS
//#define PSP_WATERCANNON //#define PSP_WATERCANNON
@ -432,97 +451,4 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#undef PS2_AUDIO_CHANNELS #undef PS2_AUDIO_CHANNELS
#endif #endif
// ------- #endif // VANILLA_DEFINES
#if defined __MWERKS__ || defined VANILLA_DEFINES
#define FINAL
#undef CHATTYSPLASH
#undef TIMEBARS
#define MASTER
#undef VALIDATE_SAVE_SIZE
#undef NO_MOVIES
#undef DEBUGMENU
#undef DRAW_GAME_VERSION_TEXT
//#undef NASTY_GAME
//#undef NO_CDCHECK
#undef GTA_PS2_STUFF
#undef USE_PS2_RAND
#undef RANDOMSPLASH
#undef PS2_MATFX
#undef FIX_BUGS
#define THIS_IS_STUPID
#undef MORE_LANGUAGES
#undef COMPATIBLE_SAVES
#undef LOAD_INI_SETTINGS
#undef ASPECT_RATIO_SCALE
#undef PROPER_SCALING
//#undef DEFAULT_NATIVE_RESOLUTION
#undef PS2_ALPHA_TEST
#undef IMPROVED_VIDEOMODE
#undef DISABLE_LOADING_SCREEN
#undef DISABLE_VSYNC_ON_TEXTURE_CONVERSION
#undef EXTENDED_COLOURFILTER
#undef EXTENDED_PIPELINES
#undef SCREEN_DROPLETS
#undef NEW_RENDERER
#undef FIX_SPRITES
#define PC_WATER
#undef WATER_CHEATS
#undef USE_CUTSCENE_SHADOW_FOR_PED
#undef DISABLE_CUTSCENE_SHADOWS
#undef XINPUT
#undef DETECT_PAD_INPUT_SWITCH
#undef KANGAROO_CHEAT
#undef RESTORE_ALLCARSHELI_CHEAT
#undef BETTER_ALLCARSAREDODO_CHEAT
#undef WALLCLIMB_CHEAT
#undef REGISTER_START_BUTTON
#undef BIND_VEHICLE_FIREWEAPON
#undef BUTTON_ICONS
#undef FIX_RADAR
#undef RADIO_OFF_TEXT
#undef MAP_ENHANCEMENTS
#undef GAMEPAD_MENU
#undef MUCH_SHORTER_OUTRO_SCREEN
#undef CUSTOM_FRONTEND_OPTIONS
#undef GRAPHICS_MENU_OPTIONS
#undef NO_ISLAND_LOADING
#undef CUTSCENE_BORDERS_SWITCH
#undef MULTISAMPLING
#undef INVERT_LOOK_FOR_PAD
#undef USE_DEBUG_SCRIPT_LOADER
#undef USE_MEASUREMENTS_IN_METERS
#undef USE_PRECISE_MEASUREMENT_CONVERTION
#undef SUPPORT_JAPANESE_SCRIPT
#undef MISSION_REPLAY
#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT
#define DONT_FIX_REPLAY_BUGS
#undef EXPLODING_AIRTRAIN
#undef CPLANE_ROTORS
#undef CAMERA_PICKUP
#undef CANCELLABLE_CAR_ENTER
#undef IMPROVED_CAMERA
#undef FREE_CAM
#undef BIG_IMG
#undef PS2_AUDIO_CHANNELS
#undef MULTITHREADED_AUDIO
#undef RADIO_SCROLL_TO_PREV_STATION
#endif

View file

@ -901,7 +901,7 @@ CEntity::SaveEntityFlags(uint8*& buf)
if (bStreamingDontDelete) tmp |= BIT(30); if (bStreamingDontDelete) tmp |= BIT(30);
if (bRemoveFromWorld) tmp |= BIT(31); if (bRemoveFromWorld) tmp |= BIT(31);
WriteSaveBuf<uint32>(buf, tmp); WriteSaveBuf(buf, tmp);
tmp = 0; tmp = 0;
@ -922,7 +922,7 @@ CEntity::SaveEntityFlags(uint8*& buf)
if (bUnderwater) tmp |= BIT(13); if (bUnderwater) tmp |= BIT(13);
if (bHasPreRenderEffects) tmp |= BIT(14); if (bHasPreRenderEffects) tmp |= BIT(14);
WriteSaveBuf<uint32>(buf, tmp); WriteSaveBuf(buf, tmp);
} }
void void

View file

@ -529,6 +529,10 @@ CPhysical::ApplySpringDampening(float damping, float dampingLimit, CVector &spri
{ {
float speedA = DotProduct(speed, springDir); float speedA = DotProduct(speed, springDir);
float speedB = DotProduct(GetSpeed(point), springDir); float speedB = DotProduct(GetSpeed(point), springDir);
#ifdef FIX_BUGS
if (speedB == 0.0f)
return true;
#endif
float step = Min(CTimer::GetTimeStep(), 3.0f); float step = Min(CTimer::GetTimeStep(), 3.0f);
damping *= step; damping *= step;
if(bIsHeavy) if(bIsHeavy)

View file

@ -10,6 +10,12 @@
#include "DMAudio.h" #include "DMAudio.h"
#include "screendroplets.h" #include "screendroplets.h"
#ifdef COMPATIBLE_SAVES
#define PARTICLE_OBJECT_SIZEOF 0x84
#else
#define PARTICLE_OBJECT_SIZEOF sizeof(CParticleObject)
#endif
CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS]; CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS];
@ -1062,6 +1068,48 @@ CParticleObject::UpdateFar(void)
} }
} }
#ifdef COMPATIBLE_SAVES
static inline void
SaveOneParticle(CParticleObject *p, uint8 *&buffer)
{
#define SkipBuf(buf, num) buf += num
#define ZeroBuf(buf, num) memset(buf, 0, num); SkipBuf(buf, num)
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipBuf(buf, sizeof(data))
// CPlaceable
{
CopyToBuf(buffer, p->GetMatrix().f);
ZeroBuf(buffer, 4);
CopyToBuf(buffer, p->GetMatrix().m_hasRwMatrix);
ZeroBuf(buffer, 3);
}
// CParticleObject
{
ZeroBuf(buffer, 4);
ZeroBuf(buffer, 4);
ZeroBuf(buffer, 4);
CopyToBuf(buffer, p->m_nRemoveTimer);
CopyToBuf(buffer, p->m_Type);
CopyToBuf(buffer, p->m_ParticleType);
CopyToBuf(buffer, p->m_nNumEffectCycles);
CopyToBuf(buffer, p->m_nSkipFrames);
CopyToBuf(buffer, p->m_nFrameCounter);
CopyToBuf(buffer, p->m_nState);
ZeroBuf(buffer, 2);
CopyToBuf(buffer, p->m_vecTarget);
CopyToBuf(buffer, p->m_fRandVal);
CopyToBuf(buffer, p->m_fSize);
CopyToBuf(buffer, p->m_Color);
CopyToBuf(buffer, p->m_bRemove);
CopyToBuf(buffer, p->m_nCreationChance);
ZeroBuf(buffer, 2);
}
#undef SkipBuf
#undef ZeroBuf
#undef CopyToBuf
}
#endif
bool bool
CParticleObject::SaveParticle(uint8 *buffer, uint32 *length) CParticleObject::SaveParticle(uint8 *buffer, uint32 *length)
{ {
@ -1079,27 +1127,35 @@ CParticleObject::SaveParticle(uint8 *buffer, uint32 *length)
*(int32 *)buffer = numObjects; *(int32 *)buffer = numObjects;
buffer += sizeof(int32); buffer += sizeof(int32);
int32 objectsLength = sizeof(CParticleObject) * (numObjects + 1); int32 objectsLength = PARTICLE_OBJECT_SIZEOF * (numObjects + 1);
int32 dataLength = objectsLength + sizeof(int32); int32 dataLength = objectsLength + sizeof(int32);
for ( CParticleObject *p = pCloseListHead; p != nil; p = p->m_pNext ) for ( CParticleObject *p = pCloseListHead; p != nil; p = p->m_pNext )
{ {
#if 0 // todo better #ifdef COMPATIBLE_SAVES
SaveOneParticle(p, buffer);
#else
#ifdef THIS_IS_STUPID
*(CParticleObject*)buffer = *p; *(CParticleObject*)buffer = *p;
#else #else
memcpy(buffer, p, sizeof(CParticleObject)); memcpy(buffer, p, sizeof(CParticleObject));
#endif #endif
buffer += sizeof(CParticleObject); buffer += sizeof(CParticleObject);
#endif
} }
for ( CParticleObject *p = pFarListHead; p != nil; p = p->m_pNext ) for ( CParticleObject *p = pFarListHead; p != nil; p = p->m_pNext )
{ {
#if 0 // todo better #ifdef COMPATIBLE_SAVES
SaveOneParticle(p, buffer);
#else
#ifdef THIS_IS_STUPID
*(CParticleObject*)buffer = *p; *(CParticleObject*)buffer = *p;
#else #else
memcpy(buffer, p, sizeof(CParticleObject)); memcpy(buffer, p, sizeof(CParticleObject));
#endif #endif
buffer += sizeof(CParticleObject); buffer += sizeof(CParticleObject);
#endif
} }
*length = dataLength; *length = dataLength;
@ -1117,7 +1173,7 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length)
int32 numObjects = *(int32 *)buffer; int32 numObjects = *(int32 *)buffer;
buffer += sizeof(int32); buffer += sizeof(int32);
if ( length != sizeof(CParticleObject) * (numObjects + 1) + sizeof(int32) ) if ( length != PARTICLE_OBJECT_SIZEOF * (numObjects + 1) + sizeof(int32) )
return false; return false;
if ( numObjects == 0 ) if ( numObjects == 0 )
@ -1128,14 +1184,17 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length)
while ( i < numObjects ) while ( i < numObjects )
{ {
CParticleObject *dst = pUnusedListHead; CParticleObject *dst = pUnusedListHead;
#ifndef COMPATIBLE_SAVES
CParticleObject *src = (CParticleObject *)buffer; CParticleObject *src = (CParticleObject *)buffer;
buffer += sizeof(CParticleObject); buffer += sizeof(CParticleObject);
#endif
if ( dst == nil ) if ( dst == nil )
return false; return false;
MoveToList(&pUnusedListHead, &pCloseListHead, dst); MoveToList(&pUnusedListHead, &pCloseListHead, dst);
#ifndef COMPATIBLE_SAVES
dst->m_nState = POBJECTSTATE_UPDATE_CLOSE; dst->m_nState = POBJECTSTATE_UPDATE_CLOSE;
dst->m_Type = src->m_Type; dst->m_Type = src->m_Type;
dst->m_ParticleType = src->m_ParticleType; dst->m_ParticleType = src->m_ParticleType;
@ -1151,6 +1210,46 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length)
dst->m_nNumEffectCycles = src->m_nNumEffectCycles; dst->m_nNumEffectCycles = src->m_nNumEffectCycles;
dst->m_nSkipFrames = src->m_nSkipFrames; dst->m_nSkipFrames = src->m_nSkipFrames;
dst->m_nCreationChance = src->m_nCreationChance; dst->m_nCreationChance = src->m_nCreationChance;
#else
dst->m_nState = POBJECTSTATE_UPDATE_CLOSE;
dst->m_pParticle = NULL;
#define SkipBuf(buf, num) buf += num
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipBuf(buf, sizeof(data))
// CPlaceable
{
CMatrix matrix;
CopyFromBuf(buffer, matrix.f);
SkipBuf(buffer, 4);
CopyFromBuf(buffer, matrix.m_hasRwMatrix);
SkipBuf(buffer, 3);
dst->SetPosition(matrix.GetPosition());
}
// CParticleObject
{
SkipBuf(buffer, 4);
SkipBuf(buffer, 4);
SkipBuf(buffer, 4);
CopyFromBuf(buffer, dst->m_nRemoveTimer);
CopyFromBuf(buffer, dst->m_Type);
CopyFromBuf(buffer, dst->m_ParticleType);
CopyFromBuf(buffer, dst->m_nNumEffectCycles);
CopyFromBuf(buffer, dst->m_nSkipFrames);
CopyFromBuf(buffer, dst->m_nFrameCounter);
SkipBuf(buffer, 2);
SkipBuf(buffer, 2);
CopyFromBuf(buffer, dst->m_vecTarget);
CopyFromBuf(buffer, dst->m_fRandVal);
CopyFromBuf(buffer, dst->m_fSize);
CopyFromBuf(buffer, dst->m_Color);
CopyFromBuf(buffer, dst->m_bRemove);
CopyFromBuf(buffer, dst->m_nCreationChance);
SkipBuf(buffer, 2);
}
#undef CopyFromBuf
#undef SkipBuf
#endif
i++; i++;
} }

View file

@ -10136,19 +10136,19 @@ CPed::UnloadNonStandardPedAnim(eWaitState waitState)
void void
CPed::Save(uint8*& buf) CPed::Save(uint8*& buf)
{ {
SkipSaveBuf(buf, 52); ZeroSaveBuf(buf, 52);
CopyToBuf(buf, GetPosition().x); CopyToBuf(buf, GetPosition().x);
CopyToBuf(buf, GetPosition().y); CopyToBuf(buf, GetPosition().y);
CopyToBuf(buf, GetPosition().z); CopyToBuf(buf, GetPosition().z);
SkipSaveBuf(buf, 288); ZeroSaveBuf(buf, 288);
CopyToBuf(buf, CharCreatedBy); CopyToBuf(buf, CharCreatedBy);
SkipSaveBuf(buf, 499); ZeroSaveBuf(buf, 499);
CopyToBuf(buf, m_fHealth); CopyToBuf(buf, m_fHealth);
CopyToBuf(buf, m_fArmour); CopyToBuf(buf, m_fArmour);
SkipSaveBuf(buf, 172); ZeroSaveBuf(buf, 172);
for (int i = 0; i < 10; i++) // has to be hardcoded for (int i = 0; i < 10; i++) // has to be hardcoded
m_weapons[i].Save(buf); m_weapons[i].Save(buf);
SkipSaveBuf(buf, 252); ZeroSaveBuf(buf, 252);
} }
void void

View file

@ -2189,14 +2189,14 @@ void
CPlayerPed::Save(uint8*& buf) CPlayerPed::Save(uint8*& buf)
{ {
CPed::Save(buf); CPed::Save(buf);
SkipSaveBuf(buf, 16); ZeroSaveBuf(buf, 16);
CopyToBuf(buf, m_fMaxStamina); CopyToBuf(buf, m_fMaxStamina);
SkipSaveBuf(buf, 28); ZeroSaveBuf(buf, 28);
CopyToBuf(buf, m_nTargettableObjects[0]); CopyToBuf(buf, m_nTargettableObjects[0]);
CopyToBuf(buf, m_nTargettableObjects[1]); CopyToBuf(buf, m_nTargettableObjects[1]);
CopyToBuf(buf, m_nTargettableObjects[2]); CopyToBuf(buf, m_nTargettableObjects[2]);
CopyToBuf(buf, m_nTargettableObjects[3]); CopyToBuf(buf, m_nTargettableObjects[3]);
SkipSaveBuf(buf, 164); ZeroSaveBuf(buf, 164);
} }
void void

View file

@ -25,6 +25,12 @@
#include "Coronas.h" #include "Coronas.h"
#include "SaveBuf.h" #include "SaveBuf.h"
#ifdef COMPATIBLE_SAVES
#define SCRIPTPATHS_SAVE_SIZE 0x9C
#else
#define SCRIPTPATHS_SAVE_SIZE sizeof(aArray)
#endif
CPlaneTrail CPlaneTrails::aArray[6]; CPlaneTrail CPlaneTrails::aArray[6];
RwImVertexIndex TrailIndices[32] = { RwImVertexIndex TrailIndices[32] = {
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
@ -1269,14 +1275,34 @@ INITSAVEBUF
aArray[i].Clear(); aArray[i].Clear();
for (int32 i = 0; i < 3; i++) { for (int32 i = 0; i < 3; i++) {
#ifdef COMPATIBLE_SAVES
ReadSaveBuf(&aArray[i].m_numNodes, buf);
SkipSaveBuf(buf, 4);
ReadSaveBuf(&aArray[i].m_fTotalLength, buf);
ReadSaveBuf(&aArray[i].m_fSpeed, buf);
ReadSaveBuf(&aArray[i].m_fPosition, buf);
ReadSaveBuf(&aArray[i].m_fObjectLength, buf);
ReadSaveBuf(&aArray[i].m_state, buf);
#else
ReadSaveBuf(&aArray[i], buf); ReadSaveBuf(&aArray[i], buf);
#endif
for (int32 j = 0; j < 6; j++) { for (int32 j = 0; j < 6; j++) {
#ifdef COMPATIBLE_SAVES
aArray[i].m_pObjects[j] = nil;
int32 tmp;
ReadSaveBuf(&tmp, buf);
if (tmp != 0) {
aArray[i].m_pObjects[j] = CPools::GetObjectPool()->GetSlot(tmp - 1);
aArray[i].m_pObjects[j]->m_phy_flagA08 = false;
}
#else
CScriptPath *pPath = &aArray[i]; CScriptPath *pPath = &aArray[i];
if (pPath->m_pObjects[j] != nil) { if (pPath->m_pObjects[j] != nil) {
pPath->m_pObjects[j] = CPools::GetObjectPool()->GetSlot((uintptr)pPath->m_pObjects[j] - 1); pPath->m_pObjects[j] = CPools::GetObjectPool()->GetSlot((uintptr)pPath->m_pObjects[j] - 1);
pPath->m_pObjects[j]->m_phy_flagA08 = false; pPath->m_pObjects[j]->m_phy_flagA08 = false;
} }
#endif
} }
aArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes]; aArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes];
@ -1288,14 +1314,28 @@ VALIDATESAVEBUF(size)
} }
void CScriptPaths::Save(uint8 *buf, uint32 *size) { void CScriptPaths::Save(uint8 *buf, uint32 *size) {
*size = sizeof(aArray); *size = SCRIPTPATHS_SAVE_SIZE;
INITSAVEBUF INITSAVEBUF
for (int32 i = 0; i < 3; i++) { for (int32 i = 0; i < 3; i++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, aArray[i].m_numNodes);
ZeroSaveBuf(buf, 4);
WriteSaveBuf(buf, aArray[i].m_fTotalLength);
WriteSaveBuf(buf, aArray[i].m_fSpeed);
WriteSaveBuf(buf, aArray[i].m_fPosition);
WriteSaveBuf(buf, aArray[i].m_fObjectLength);
WriteSaveBuf(buf, aArray[i].m_state);
#else
CScriptPath *pPath = WriteSaveBuf(buf, aArray[i]); CScriptPath *pPath = WriteSaveBuf(buf, aArray[i]);
#endif
for (int32 j = 0; j < 6; j++) { for (int32 j = 0; j < 6; j++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, aArray[i].m_pObjects[j] != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aArray[i].m_pObjects[j]) + 1 : 0);
#else
if (pPath->m_pObjects[j] != nil) if (pPath->m_pObjects[j] != nil)
pPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pPath->m_pObjects[j]) + 1); pPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pPath->m_pObjects[j]) + 1);
#endif
} }
for (int32 j = 0; j < aArray[i].m_numNodes; j++) { for (int32 j = 0; j < aArray[i].m_numNodes; j++) {

View file

@ -643,6 +643,525 @@ align4bytes(int32 size)
return (size + 3) & 0xFFFFFFFC; return (size + 3) & 0xFFFFFFFC;
} }
#ifdef FIX_INCOMPATIBLE_SAVES
#define LoadSaveDataBlockNoCheck(buf, file, size) \
do { \
CFileMgr::Read(file, (const char *)&size, sizeof(size)); \
size = align4bytes(size); \
CFileMgr::Read(file, (const char *)work_buff, size); \
buf = work_buff; \
} while(0)
#define WriteSavaDataBlockNoFunc(buf, file, size) \
do { \
if (!PcSaveHelper.PcClassSaveRoutine(file, buf, size)) \
goto fail; \
totalSize += size; \
} while(0)
#define FixSaveDataBlock(fix_func, file, size) \
do { \
ReadDataFromBufferPointer(buf, size); \
memset(work_buff2, 0, sizeof(work_buff2)); \
buf2 = work_buff2; \
reserved = 0; \
MakeSpaceForSizeInBufferPointer(presize, buf2, postsize); \
fix_func(save_type, buf, buf2, &size); \
CopySizeAndPreparePointer(presize, buf2, postsize, reserved, size); \
if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff2, buf2 - work_buff2)) \
goto fail; \
totalSize += buf2 - work_buff2; \
} while(0)
#define ReadDataFromBufferPointerWithSize(buf, to, size) memcpy(&to, buf, size); buf += align4bytes(size)
#define ReadBuf(buf, to) memcpy(&to, buf, sizeof(to)); buf += sizeof(to)
#define WriteBuf(buf, from) memcpy(buf, &from, sizeof(from)); buf += sizeof(from)
#define CopyBuf(from, to, size) memcpy(to, from, size); to += (size); from += (size)
#define CopyPtr(from, to) memcpy(to, from, 4); to += 4; from += 8
#define SkipBuf(buf, size) buf += (size)
#define SkipBoth(from, to, size) to += (size); from += (size)
#define SkipPtr(from, to) to += 4; from += 8
// unfortunately we need a 2nd buffer of the same size to store the fixed output ...
static uint8 work_buff2[sizeof(work_buff)];
enum
{
SAVE_TYPE_NONE = 0,
SAVE_TYPE_32_BIT = 1,
SAVE_TYPE_64_BIT = 2,
SAVE_TYPE_MSVC = 4,
SAVE_TYPE_GCC = 8,
};
uint8
GetSaveType(char *savename)
{
uint8 save_type = SAVE_TYPE_NONE;
int file = CFileMgr::OpenFile(savename, "rb");
uint32 size;
CFileMgr::Read(file, (const char *)&size, sizeof(size));
uint8 *buf = work_buff;
CFileMgr::Read(file, (const char *)work_buff, size); // simple vars + scripts
LoadSaveDataBlockNoCheck(buf, file, size); // ped pool
LoadSaveDataBlockNoCheck(buf, file, size); // garages
ReadDataFromBufferPointer(buf, size);
// store for later after we know how much data we need to skip
ReadDataFromBufferPointerWithSize(buf, work_buff2, size);
LoadSaveDataBlockNoCheck(buf, file, size); // game logic
LoadSaveDataBlockNoCheck(buf, file, size); // vehicle pool
LoadSaveDataBlockNoCheck(buf, file, size); // object pool
LoadSaveDataBlockNoCheck(buf, file, size); // paths
LoadSaveDataBlockNoCheck(buf, file, size); // cranes
CFileMgr::CloseFile(file);
ReadDataFromBufferPointer(buf, size);
if (size == 1000)
save_type |= SAVE_TYPE_32_BIT;
else if (size == 1160)
save_type |= SAVE_TYPE_64_BIT;
else
assert(0); // this should never happen
buf = work_buff2;
buf += 1964; // skip everything before the first garage
buf += save_type & SAVE_TYPE_32_BIT ? 28 : 40; // skip first garage up to m_vecCorner1
CVector2D vecCorner1;
float fInfZ, fSupZ;
ReadBuf(buf, vecCorner1);
ReadBuf(buf, fInfZ);
SkipBuf(buf, sizeof(CVector2D));
SkipBuf(buf, sizeof(CVector2D));
ReadBuf(buf, fSupZ);
// SET_GARAGE -914.129028 -1263.540039 10.706000 -907.137024 -1246.625977 -906.299988 -1266.900024 14.421000
if (vecCorner1.x == -914.129028f && vecCorner1.y == -1263.540039f &&
fInfZ == 10.706000f && fSupZ == 14.421000f)
save_type |= SAVE_TYPE_MSVC;
else
save_type |= SAVE_TYPE_GCC;
return save_type;
}
static void
FixGarages(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
{
// hardcoded: 7876
// x86 msvc: 7340
// x86 gcc: 7020
// amd64 msvc: 7852
// amd64 gcc: 7660
uint8 *buf_start = buf;
uint8 *buf2_start = buf2;
uint32 read;
uint32 written = 7340;
if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_GCC)
read = 7020;
else if (save_type & SAVE_TYPE_64_BIT && save_type & SAVE_TYPE_GCC)
read = 7660;
else
read = 7852;
uint32 ptrsize = save_type & SAVE_TYPE_32_BIT ? 4 : 8;
CopyBuf(buf, buf2, 4 * 6);
CopyBuf(buf, buf2, 4 * TOTAL_COLLECTCARS_GARAGES);
CopyBuf(buf, buf2, 4);
if (save_type & SAVE_TYPE_GCC)
{
for (int32 i = 0; i < NUM_GARAGE_STORED_CARS; i++)
{
for (int32 j = 0; j < TOTAL_HIDEOUT_GARAGES; j++)
{
CopyBuf(buf, buf2, 4 + sizeof(CVector) + sizeof(CVector));
uint8 nFlags8;
ReadBuf(buf, nFlags8);
int32 nFlags32 = nFlags8;
WriteBuf(buf2, nFlags32);
CopyBuf(buf, buf2, 1 * 6);
SkipBuf(buf, 1);
SkipBuf(buf2, 2);
}
}
}
else
{
CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS * TOTAL_HIDEOUT_GARAGES);
}
for (int32 i = 0; i < NUM_GARAGES; i++)
{
CopyBuf(buf, buf2, 1 * 7);
SkipBoth(buf, buf2, 1);
CopyBuf(buf, buf2, 4);
SkipBuf(buf, ptrsize - 4); // write 4 bytes padding if 8 byte pointer, if not, write 0
SkipBuf(buf, ptrsize * 2);
SkipBuf(buf2, 4 * 2);
CopyBuf(buf, buf2, 1 * 7);
SkipBoth(buf, buf2, 1);
CopyBuf(buf, buf2, sizeof(CVector2D) * 3 + 4 * 17 + 1);
SkipBoth(buf, buf2, 3);
SkipBuf(buf, ptrsize);
SkipBuf(buf2, 4);
if (save_type & SAVE_TYPE_GCC)
SkipBuf(buf, save_type & SAVE_TYPE_64_BIT ? 36 + 4 : 36); // sizeof(CStoredCar) on gcc 64/32 before fix
else
SkipBuf(buf, sizeof(CStoredCar));
SkipBuf(buf2, sizeof(CStoredCar));
}
}
static void
FixCranes(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
{
uint8 *buf_start = buf;
uint8 *buf2_start = buf2;
uint32 read = 2 * sizeof(uint32) + 0x480; // sizeof(aCranes)
uint32 written = 2 * sizeof(uint32) + 0x3E0; // see CRANES_SAVE_SIZE
CopyBuf(buf, buf2, 4 + 4);
for (int32 i = 0; i < NUM_CRANES; i++)
{
CopyPtr(buf, buf2);
CopyPtr(buf, buf2);
CopyBuf(buf, buf2, 14 * 4 + sizeof(CVector) * 3 + sizeof(CVector2D));
SkipBuf(buf, 4);
CopyPtr(buf, buf2);
CopyBuf(buf, buf2, 4 + 7 * 1);
SkipBuf(buf, 5);
SkipBuf(buf2, 1);
}
*size = 0;
assert(buf - buf_start == read);
assert(buf2 - buf2_start == written);
*size = written;
}
static void
FixPickups(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
{
uint8 *buf_start = buf;
uint8 *buf2_start = buf2;
uint32 read = 0x5400 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // sizeof(aPickUps)
uint32 written = 0x4440 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // see PICKUPS_SAVE_SIZE
for (int32 i = 0; i < NUMPICKUPS; i++)
{
CopyBuf(buf, buf2, sizeof(CVector) + 4);
CopyPtr(buf, buf2);
CopyPtr(buf, buf2);
CopyBuf(buf, buf2, 4 * 2 + 2 * 3 + 8 + 1 * 3);
SkipBuf(buf, 7);
SkipBuf(buf2, 3);
}
CopyBuf(buf, buf2, 2);
SkipBoth(buf, buf2, 2);
CopyBuf(buf, buf2, NUMCOLLECTEDPICKUPS * 4);
*size = 0;
assert(buf - buf_start == read);
assert(buf2 - buf2_start == written);
*size = written;
}
static void
FixPhoneInfo(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
{
uint8 *buf_start = buf;
uint8 *buf2_start = buf2;
uint32 read = 0x1138; // sizeof(CPhoneInfo)
uint32 written = 0xA30; // see PHONEINFO_SAVE_SIZE
CopyBuf(buf, buf2, 4 + 4);
for (int32 i = 0; i < NUMPHONES; i++)
{
CopyBuf(buf, buf2, sizeof(CVector));
SkipBuf(buf, 4);
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
CopyBuf(buf, buf2, 4);
SkipBuf(buf, 4);
CopyPtr(buf, buf2);
CopyBuf(buf, buf2, 4 + 1);
SkipBoth(buf, buf2, 3);
}
*size = 0;
assert(buf - buf_start == read);
assert(buf2 - buf2_start == written);
*size = written;
}
static void
FixParticles(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
{
uint8 *buf_start = buf;
uint8 *buf2_start = buf2;
int32 numObjects;
ReadBuf(buf, numObjects);
WriteBuf(buf2, numObjects);
uint32 read = 0x98 * (numObjects + 1) + 4; // sizeof(CParticleObject)
uint32 written = 0x84 * (numObjects + 1) + 4; // see PARTICLE_OBJECT_SIZEOF
for (int32 i = 0; i < numObjects; i++)
{
// CPlaceable
CopyBuf(buf, buf2, 4 * 4 * 4);
SkipPtr(buf, buf2);
CopyBuf(buf, buf2, 1);
SkipBuf(buf, 7);
SkipBuf(buf2, 3);
// CParticleObject
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
SkipPtr(buf, buf2);
CopyBuf(buf, buf2, 4 * 3 + 2 * 1 + 2 * 2);
SkipBoth(buf, buf2, 2);
CopyBuf(buf, buf2, sizeof(CVector) + 2 * 4 + sizeof(CRGBA) + 2 * 1);
SkipBoth(buf, buf2, 2);
}
SkipBuf(buf, 0x98); // sizeof(CParticleObject)
SkipBuf(buf2, 0x84); // see PARTICLE_OBJECT_SIZEOF
*size = 0;
assert(buf - buf_start == read);
assert(buf2 - buf2_start == written);
*size = written;
}
static void
FixScriptPaths(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
{
uint8 *buf_start = buf;
uint8 *buf2_start = buf2;
uint32 read = 0x108; // sizeof(CScriptPath) * 3
uint32 written = 0x9C; // see SCRIPTPATHS_SAVE_SIZE
for (int32 i = 0; i < 3; i++)
{
int32 numNodes;
ReadBuf(buf, numNodes);
WriteBuf(buf2, numNodes);
SkipBuf(buf, 4);
SkipPtr(buf, buf2);
CopyBuf(buf, buf2, 4 * 5);
SkipBuf(buf, 4);
for (int32 i = 0; i < 6; i++)
{
CopyPtr(buf, buf2);
}
for (int32 i = 0; i < numNodes; i++)
{
CopyBuf(buf, buf2, sizeof(CPlaneNode));
read += sizeof(CPlaneNode);
written += sizeof(CPlaneNode);
}
}
*size = 0;
assert(buf - buf_start == read);
assert(buf2 - buf2_start == written);
*size = written;
}
bool
FixSave(int32 slot, uint8 save_type)
{
if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_MSVC)
return true;
bool success = false;
uint8 *buf, *presize, *postsize, *buf2;
uint32 size;
uint32 reserved;
uint32 totalSize;
char savename[MAX_PATH];
char savename_bak[MAX_PATH];
sprintf(savename, "%s%i%s", DefaultPCSaveFileName, slot + 1, ".b");
sprintf(savename_bak, "%s%i%s.%lld.bak", DefaultPCSaveFileName, slot + 1, ".b", time(nil));
assert(caserename(savename, savename_bak) == 0);
int file_in = CFileMgr::OpenFile(savename_bak, "rb");
int file_out = CFileMgr::OpenFileForWriting(savename);
CheckSum = 0;
totalSize = 0;
CFileMgr::Read(file_in, (const char *)&size, sizeof(size));
buf = work_buff;
CFileMgr::Read(file_in, (const char *)work_buff, size); // simple vars + scripts
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // ped pool
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // garages
FixSaveDataBlock(FixGarages, file_out, size); // garages need to be fixed in either case
LoadSaveDataBlockNoCheck(buf, file_in, size); // game logic
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // vehicle pool
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // object pool
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // paths
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // cranes
if (save_type & SAVE_TYPE_64_BIT)
FixSaveDataBlock(FixCranes, file_out, size);
else
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // pickups
if (save_type & SAVE_TYPE_64_BIT)
FixSaveDataBlock(FixPickups, file_out, size);
else
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // phoneinfo
if (save_type & SAVE_TYPE_64_BIT)
FixSaveDataBlock(FixPhoneInfo, file_out, size);
else
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // restart
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // radar blips
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // zones
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // gang data
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // car generators
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // particles
if (save_type & SAVE_TYPE_64_BIT)
FixSaveDataBlock(FixParticles, file_out, size);
else
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // audio script objects
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // script paths
if (save_type & SAVE_TYPE_64_BIT)
FixSaveDataBlock(FixScriptPaths, file_out, size);
else
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // player info
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // stats
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // set pieces
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // streaming
WriteSavaDataBlockNoFunc(buf, file_out, size);
LoadSaveDataBlockNoCheck(buf, file_in, size); // ped type
WriteSavaDataBlockNoFunc(buf, file_out, size);
memset(work_buff, 0, sizeof(work_buff));
for (int i = 0; i < 4; i++) {
size = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4);
if (size > sizeof(work_buff))
size = sizeof(work_buff);
if (size > 4) {
if (!PcSaveHelper.PcClassSaveRoutine(file_out, work_buff, size))
goto fail;
totalSize += size;
}
}
if (!CFileMgr::Write(file_out, (const char *)&CheckSum, sizeof(CheckSum)))
goto fail;
success = true;
fail:;
CFileMgr::CloseFile(file_in);
CFileMgr::CloseFile(file_out);
return success;
}
#undef LoadSaveDataBlockNoCheck
#undef WriteSavaDataBlockNoFunc
#undef FixSaveDataBlock
#undef ReadDataFromBufferPointerWithSize
#undef ReadBuf
#undef WriteBuf
#undef CopyBuf
#undef CopyPtr
#undef SkipBuf
#undef SkipBoth
#undef SkipPtr
#endif
#ifdef MISSION_REPLAY #ifdef MISSION_REPLAY
void DisplaySaveResult(int unk, char* name) void DisplaySaveResult(int unk, char* name)

View file

@ -25,6 +25,11 @@ bool CheckDataNotCorrupt(int32 slot, char *name);
bool RestoreForStartLoad(); bool RestoreForStartLoad();
int align4bytes(int32 size); int align4bytes(int32 size);
#ifdef FIX_INCOMPATIBLE_SAVES
uint8 GetSaveType(char *savename);
bool FixSave(int32 slot, uint8 save_type);
#endif
extern char DefaultPCSaveFileName[260]; extern char DefaultPCSaveFileName[260];
extern char ValidSaveName[260]; extern char ValidSaveName[260];
extern char LoadFileName[256]; extern char LoadFileName[256];

View file

@ -122,6 +122,13 @@ C_PcSave::PopulateSlotInfo()
} }
if (Slots[i] == SLOT_OK) { if (Slots[i] == SLOT_OK) {
if (CheckDataNotCorrupt(i, savename)) { if (CheckDataNotCorrupt(i, savename)) {
#ifdef FIX_INCOMPATIBLE_SAVES
if (!FixSave(i, GetSaveType(savename))) {
CMessages::InsertNumberInString(TheText.Get("FEC_SLC"), i + 1, -1, -1, -1, -1, -1, SlotFileName[i]);
Slots[i] = SLOT_CORRUPTED;
continue;
}
#endif
SYSTEMTIME st; SYSTEMTIME st;
memcpy(&st, &header.SaveDateTime, sizeof(SYSTEMTIME)); memcpy(&st, &header.SaveDateTime, sizeof(SYSTEMTIME));
const char *month; const char *month;

View file

@ -33,7 +33,7 @@ public:
void PopulateSlotInfo(); void PopulateSlotInfo();
bool DeleteSlot(int32 slot); bool DeleteSlot(int32 slot);
int8 SaveSlot(int32 slot); int8 SaveSlot(int32 slot);
bool PcClassSaveRoutine(int32 a2, uint8 *data, uint32 size); bool PcClassSaveRoutine(int32 file, uint8 *data, uint32 size);
static void SetSaveDirectory(const char *path); static void SetSaveDirectory(const char *path);
}; };

View file

@ -64,6 +64,14 @@ WriteSaveBuf(uint8 *&buf, uint32 &length, const T &value)
return p; return p;
} }
#ifdef COMPATIBLE_SAVES
inline void
ZeroSaveBuf(uint8 *&buf, uint32 length)
{
memset(buf, 0, length);
SkipSaveBuf(buf, length);
}
#endif
#define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32)) #define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32))

View file

@ -155,6 +155,29 @@ FILE* _fcaseopen(char const* filename, char const* mode)
return result; return result;
} }
int _caserename(const char *old_filename, const char *new_filename)
{
int result;
char *real_old = casepath(old_filename);
char *real_new = casepath(new_filename);
// hack so we don't even try to rename it to new_filename if it already exists
if (!real_new) {
free(real_old);
return -1;
}
if (!real_old)
result = rename(old_filename, real_new);
else
result = rename(real_old, real_new);
free(real_old);
free(real_new);
return result;
}
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
// Returned string should freed manually (if exists) // Returned string should freed manually (if exists)
char* casepath(char const* path, bool checkPathFirst) char* casepath(char const* path, bool checkPathFirst)

View file

@ -33,6 +33,7 @@ char *_strdate(char *buf);
#endif #endif
extern DWORD _dwOperatingSystemVersion; extern DWORD _dwOperatingSystemVersion;
#define fcaseopen fopen #define fcaseopen fopen
#define caserename rename
#else #else
char *strupr(char *str); char *strupr(char *str);
char *strlwr(char *str); char *strlwr(char *str);
@ -55,6 +56,8 @@ extern long _dwOperatingSystemVersion;
char *casepath(char const *path, bool checkPathFirst = true); char *casepath(char const *path, bool checkPathFirst = true);
FILE *_fcaseopen(char const *filename, char const *mode); FILE *_fcaseopen(char const *filename, char const *mode);
#define fcaseopen _fcaseopen #define fcaseopen _fcaseopen
int _caserename(const char *old_filename, const char *new_filename);
#define caserename _caserename
#endif #endif
#ifdef RW_GL3 #ifdef RW_GL3

View file

@ -5725,7 +5725,7 @@ CAutomobile::Save(uint8*& buf)
{ {
CVehicle::Save(buf); CVehicle::Save(buf);
WriteSaveBuf(buf, Damage); WriteSaveBuf(buf, Damage);
SkipSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager)); ZeroSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager));
} }
void void

View file

@ -2953,7 +2953,7 @@ void
CBike::Save(uint8*& buf) CBike::Save(uint8*& buf)
{ {
CVehicle::Save(buf); CVehicle::Save(buf);
SkipSaveBuf(buf, 1260 - 672); ZeroSaveBuf(buf, 1260 - 672);
} }
void void

View file

@ -1478,7 +1478,7 @@ void
CBoat::Save(uint8*& buf) CBoat::Save(uint8*& buf)
{ {
CVehicle::Save(buf); CVehicle::Save(buf);
SkipSaveBuf(buf, 1216 - 672); ZeroSaveBuf(buf, 1216 - 672);
} }
void void

View file

@ -37,6 +37,12 @@
#define MIN_VALID_POSITION (-10000.0f) #define MIN_VALID_POSITION (-10000.0f)
#define DEFAULT_OFFSET (20.0f) #define DEFAULT_OFFSET (20.0f)
#ifdef COMPATIBLE_SAVES
#define CRANES_SAVE_SIZE 0x3E0
#else
#define CRANES_SAVE_SIZE sizeof(aCranes)
#endif
uint32 TimerForCamInterpolation; uint32 TimerForCamInterpolation;
uint32 CCranes::CarsCollectedMilitaryCrane; uint32 CCranes::CarsCollectedMilitaryCrane;
@ -624,10 +630,45 @@ void CCranes::Save(uint8* buf, uint32* size)
{ {
INITSAVEBUF INITSAVEBUF
*size = 2 * sizeof(uint32) + sizeof(aCranes); *size = 2 * sizeof(uint32) + CRANES_SAVE_SIZE;
WriteSaveBuf(buf, NumCranes); WriteSaveBuf(buf, NumCranes);
WriteSaveBuf(buf, CarsCollectedMilitaryCrane); WriteSaveBuf(buf, CarsCollectedMilitaryCrane);
for (int i = 0; i < NUM_CRANES; i++) { for (int i = 0; i < NUM_CRANES; i++) {
#ifdef COMPATIBLE_SAVES
int32 tmp = aCranes[i].m_pCraneEntity != nil ? CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pCraneEntity) + 1 : 0;
WriteSaveBuf(buf, tmp);
tmp = aCranes[i].m_pHook != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pHook) + 1 : 0;
WriteSaveBuf(buf, tmp);
WriteSaveBuf(buf, aCranes[i].m_fPickupX1);
WriteSaveBuf(buf, aCranes[i].m_fPickupX2);
WriteSaveBuf(buf, aCranes[i].m_fPickupY1);
WriteSaveBuf(buf, aCranes[i].m_fPickupY2);
WriteSaveBuf(buf, aCranes[i].m_vecDropoffTarget);
WriteSaveBuf(buf, aCranes[i].m_fDropoffHeading);
WriteSaveBuf(buf, aCranes[i].m_fPickupAngle);
WriteSaveBuf(buf, aCranes[i].m_fDropoffAngle);
WriteSaveBuf(buf, aCranes[i].m_fPickupDistance);
WriteSaveBuf(buf, aCranes[i].m_fDropoffDistance);
WriteSaveBuf(buf, aCranes[i].m_fPickupHeight);
WriteSaveBuf(buf, aCranes[i].m_fDropoffHeight);
WriteSaveBuf(buf, aCranes[i].m_fHookAngle);
WriteSaveBuf(buf, aCranes[i].m_fHookOffset);
WriteSaveBuf(buf, aCranes[i].m_fHookHeight);
WriteSaveBuf(buf, aCranes[i].m_vecHookInitPos);
WriteSaveBuf(buf, aCranes[i].m_vecHookCurPos);
WriteSaveBuf(buf, aCranes[i].m_vecHookVelocity);
tmp = aCranes[i].m_pVehiclePickedUp != nil ? CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pVehiclePickedUp) + 1 : 0;
WriteSaveBuf(buf, tmp);
WriteSaveBuf(buf, aCranes[i].m_nTimeForNextCheck);
WriteSaveBuf(buf, aCranes[i].m_nCraneStatus);
WriteSaveBuf(buf, aCranes[i].m_nCraneState);
WriteSaveBuf(buf, aCranes[i].m_nVehiclesCollected);
WriteSaveBuf(buf, aCranes[i].m_bIsCrusher);
WriteSaveBuf(buf, aCranes[i].m_bIsMilitaryCrane);
WriteSaveBuf(buf, aCranes[i].m_bWasMilitaryCrane);
WriteSaveBuf(buf, aCranes[i].m_bIsTop);
ZeroSaveBuf(buf, 1);
#else
CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]); CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]);
if (pCrane->m_pCraneEntity != nil) if (pCrane->m_pCraneEntity != nil)
pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1); pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1);
@ -635,6 +676,7 @@ void CCranes::Save(uint8* buf, uint32* size)
pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1); pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1);
if (pCrane->m_pVehiclePickedUp != nil) if (pCrane->m_pVehiclePickedUp != nil)
pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1); pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1);
#endif
} }
VALIDATESAVEBUF(*size); VALIDATESAVEBUF(*size);
@ -646,8 +688,45 @@ void CCranes::Load(uint8* buf, uint32 size)
ReadSaveBuf(&NumCranes, buf); ReadSaveBuf(&NumCranes, buf);
ReadSaveBuf(&CarsCollectedMilitaryCrane, buf); ReadSaveBuf(&CarsCollectedMilitaryCrane, buf);
for (int i = 0; i < NUM_CRANES; i++) for (int i = 0; i < NUM_CRANES; i++) {
#ifdef COMPATIBLE_SAVES
int32 tmp;
ReadSaveBuf(&tmp, buf);
aCranes[i].m_pCraneEntity = tmp != 0 ? CPools::GetBuildingPool()->GetSlot(tmp - 1) : nil;
ReadSaveBuf(&tmp, buf);
aCranes[i].m_pHook = tmp != 0 ? CPools::GetObjectPool()->GetSlot(tmp - 1) : nil;
ReadSaveBuf(&aCranes[i].m_fPickupX1, buf);
ReadSaveBuf(&aCranes[i].m_fPickupX2, buf);
ReadSaveBuf(&aCranes[i].m_fPickupY1, buf);
ReadSaveBuf(&aCranes[i].m_fPickupY2, buf);
ReadSaveBuf(&aCranes[i].m_vecDropoffTarget, buf);
ReadSaveBuf(&aCranes[i].m_fDropoffHeading, buf);
ReadSaveBuf(&aCranes[i].m_fPickupAngle, buf);
ReadSaveBuf(&aCranes[i].m_fDropoffAngle, buf);
ReadSaveBuf(&aCranes[i].m_fPickupDistance, buf);
ReadSaveBuf(&aCranes[i].m_fDropoffDistance, buf);
ReadSaveBuf(&aCranes[i].m_fPickupHeight, buf);
ReadSaveBuf(&aCranes[i].m_fDropoffHeight, buf);
ReadSaveBuf(&aCranes[i].m_fHookAngle, buf);
ReadSaveBuf(&aCranes[i].m_fHookOffset, buf);
ReadSaveBuf(&aCranes[i].m_fHookHeight, buf);
ReadSaveBuf(&aCranes[i].m_vecHookInitPos, buf);
ReadSaveBuf(&aCranes[i].m_vecHookCurPos, buf);
ReadSaveBuf(&aCranes[i].m_vecHookVelocity, buf);
ReadSaveBuf(&tmp, buf);
aCranes[i].m_pVehiclePickedUp = tmp != 0 ? CPools::GetVehiclePool()->GetSlot(tmp - 1) : nil;
ReadSaveBuf(&aCranes[i].m_nTimeForNextCheck, buf);
ReadSaveBuf(&aCranes[i].m_nCraneStatus, buf);
ReadSaveBuf(&aCranes[i].m_nCraneState, buf);
ReadSaveBuf(&aCranes[i].m_nVehiclesCollected, buf);
ReadSaveBuf(&aCranes[i].m_bIsCrusher, buf);
ReadSaveBuf(&aCranes[i].m_bIsMilitaryCrane, buf);
ReadSaveBuf(&aCranes[i].m_bWasMilitaryCrane, buf);
ReadSaveBuf(&aCranes[i].m_bIsTop, buf);
SkipSaveBuf(buf, 1);
#else
ReadSaveBuf(&aCranes[i], buf); ReadSaveBuf(&aCranes[i], buf);
}
for (int i = 0; i < NUM_CRANES; i++) { for (int i = 0; i < NUM_CRANES; i++) {
CCrane *pCrane = &aCranes[i]; CCrane *pCrane = &aCranes[i];
if (pCrane->m_pCraneEntity != nil) if (pCrane->m_pCraneEntity != nil)
@ -656,6 +735,7 @@ void CCranes::Load(uint8* buf, uint32 size)
pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uintptr)pCrane->m_pHook - 1); pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uintptr)pCrane->m_pHook - 1);
if (pCrane->m_pVehiclePickedUp != nil) if (pCrane->m_pVehiclePickedUp != nil)
pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uintptr)pCrane->m_pVehiclePickedUp - 1); pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uintptr)pCrane->m_pVehiclePickedUp - 1);
#endif
} }
VALIDATESAVEBUF(size); VALIDATESAVEBUF(size);

View file

@ -2377,42 +2377,42 @@ DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle)
void void
CVehicle::Save(uint8*& buf) CVehicle::Save(uint8*& buf)
{ {
SkipSaveBuf(buf, 4); ZeroSaveBuf(buf, 4);
WriteSaveBuf<float>(buf, GetRight().x); WriteSaveBuf(buf, GetRight().x);
WriteSaveBuf<float>(buf, GetRight().y); WriteSaveBuf(buf, GetRight().y);
WriteSaveBuf<float>(buf, GetRight().z); WriteSaveBuf(buf, GetRight().z);
SkipSaveBuf(buf, 4); ZeroSaveBuf(buf, 4);
WriteSaveBuf<float>(buf, GetForward().x); WriteSaveBuf(buf, GetForward().x);
WriteSaveBuf<float>(buf, GetForward().y); WriteSaveBuf(buf, GetForward().y);
WriteSaveBuf<float>(buf, GetForward().z); WriteSaveBuf(buf, GetForward().z);
SkipSaveBuf(buf, 4); ZeroSaveBuf(buf, 4);
WriteSaveBuf<float>(buf, GetUp().x); WriteSaveBuf(buf, GetUp().x);
WriteSaveBuf<float>(buf, GetUp().y); WriteSaveBuf(buf, GetUp().y);
WriteSaveBuf<float>(buf, GetUp().z); WriteSaveBuf(buf, GetUp().z);
SkipSaveBuf(buf, 4); ZeroSaveBuf(buf, 4);
WriteSaveBuf<float>(buf, GetPosition().x); WriteSaveBuf(buf, GetPosition().x);
WriteSaveBuf<float>(buf, GetPosition().y); WriteSaveBuf(buf, GetPosition().y);
WriteSaveBuf<float>(buf, GetPosition().z); WriteSaveBuf(buf, GetPosition().z);
SkipSaveBuf(buf, 16); ZeroSaveBuf(buf, 16);
SaveEntityFlags(buf); SaveEntityFlags(buf);
SkipSaveBuf(buf, 208); ZeroSaveBuf(buf, 208);
AutoPilot.Save(buf); AutoPilot.Save(buf);
WriteSaveBuf<int8>(buf, m_currentColour1); WriteSaveBuf(buf, m_currentColour1);
WriteSaveBuf<int8>(buf, m_currentColour2); WriteSaveBuf(buf, m_currentColour2);
SkipSaveBuf(buf, 2); ZeroSaveBuf(buf, 2);
WriteSaveBuf<int16>(buf, m_nAlarmState); WriteSaveBuf(buf, m_nAlarmState);
SkipSaveBuf(buf, 42); ZeroSaveBuf(buf, 42);
WriteSaveBuf<uint8>(buf, m_nNumMaxPassengers); WriteSaveBuf(buf, m_nNumMaxPassengers);
SkipSaveBuf(buf, 3); ZeroSaveBuf(buf, 3);
WriteSaveBuf<float>(buf, field_1D0[0]); WriteSaveBuf(buf, field_1D0[0]);
WriteSaveBuf<float>(buf, field_1D0[1]); WriteSaveBuf(buf, field_1D0[1]);
WriteSaveBuf<float>(buf, field_1D0[2]); WriteSaveBuf(buf, field_1D0[2]);
WriteSaveBuf<float>(buf, field_1D0[3]); WriteSaveBuf(buf, field_1D0[3]);
SkipSaveBuf(buf, 8); ZeroSaveBuf(buf, 8);
WriteSaveBuf<float>(buf, m_fSteerAngle); WriteSaveBuf(buf, m_fSteerAngle);
WriteSaveBuf<float>(buf, m_fGasPedal); WriteSaveBuf(buf, m_fGasPedal);
WriteSaveBuf<float>(buf, m_fBrakePedal); WriteSaveBuf(buf, m_fBrakePedal);
WriteSaveBuf<uint8>(buf, VehicleCreatedBy); WriteSaveBuf(buf, VehicleCreatedBy);
uint8 flags = 0; uint8 flags = 0;
if (bIsLawEnforcer) flags |= BIT(0); if (bIsLawEnforcer) flags |= BIT(0);
if (bIsLocked) flags |= BIT(3); if (bIsLocked) flags |= BIT(3);
@ -2420,19 +2420,19 @@ CVehicle::Save(uint8*& buf)
if (bIsHandbrakeOn) flags |= BIT(5); if (bIsHandbrakeOn) flags |= BIT(5);
if (bLightsOn) flags |= BIT(6); if (bLightsOn) flags |= BIT(6);
if (bFreebies) flags |= BIT(7); if (bFreebies) flags |= BIT(7);
WriteSaveBuf<uint8>(buf, flags); WriteSaveBuf(buf, flags);
SkipSaveBuf(buf, 10); ZeroSaveBuf(buf, 10);
WriteSaveBuf<float>(buf, m_fHealth); WriteSaveBuf(buf, m_fHealth);
WriteSaveBuf<uint8>(buf, m_nCurrentGear); WriteSaveBuf(buf, m_nCurrentGear);
SkipSaveBuf(buf, 3); ZeroSaveBuf(buf, 3);
WriteSaveBuf<float>(buf, m_fChangeGearTime); WriteSaveBuf(buf, m_fChangeGearTime);
SkipSaveBuf(buf, 12); ZeroSaveBuf(buf, 12);
WriteSaveBuf<uint32>(buf, m_nTimeOfDeath); WriteSaveBuf(buf, m_nTimeOfDeath);
SkipSaveBuf(buf, 2); ZeroSaveBuf(buf, 2);
WriteSaveBuf<int16>(buf, m_nBombTimer); WriteSaveBuf(buf, m_nBombTimer);
SkipSaveBuf(buf, 12); ZeroSaveBuf(buf, 12);
WriteSaveBuf<int8>(buf, m_nDoorLock); WriteSaveBuf(buf, m_nDoorLock);
SkipSaveBuf(buf, 111); ZeroSaveBuf(buf, 108);
} }
void void
@ -2494,9 +2494,8 @@ CVehicle::Load(uint8*& buf)
SkipSaveBuf(buf, 2); SkipSaveBuf(buf, 2);
ReadSaveBuf(&m_nBombTimer, buf); ReadSaveBuf(&m_nBombTimer, buf);
SkipSaveBuf(buf, 12); SkipSaveBuf(buf, 12);
ReadSaveBuf(&flags, buf); ReadSaveBuf(&m_nDoorLock, buf);
m_nDoorLock = (eCarLock)flags; SkipSaveBuf(buf, 108);
SkipSaveBuf(buf, 111);
} }
#endif #endif

View file

@ -279,7 +279,7 @@ public:
int8 m_comedyControlState; int8 m_comedyControlState;
CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car
float m_fSteerInput; float m_fSteerInput;
uint8 m_vehType; eVehicleType m_vehType;
static void *operator new(size_t) throw(); static void *operator new(size_t) throw();
static void *operator new(size_t sz, int slot) throw(); static void *operator new(size_t sz, int slot) throw();

View file

@ -3285,7 +3285,7 @@ CWeapon::Save(uint8*& buf)
CopyToBuf(buf, m_nAmmoTotal); CopyToBuf(buf, m_nAmmoTotal);
CopyToBuf(buf, m_nTimer); CopyToBuf(buf, m_nTimer);
CopyToBuf(buf, m_bAddRotOffset); CopyToBuf(buf, m_bAddRotOffset);
SkipSaveBuf(buf, 3); ZeroSaveBuf(buf, 3);
} }
void void

View file

@ -17107,6 +17107,12 @@ This track contains a sample of "Next Level" as performed by Showbiz & AG. Court
[CR19_20:CRED01] [CR19_20:CRED01]
~n~ ~n~Donna Young, Richie Zito ~n~ ~n~Donna Young, Richie Zito
[FEM_PED]
PED DENSITY
[FEM_CAR]
CAR DENSITY
[DUMMY] [DUMMY]
THIS LABEL NEEDS TO BE HERE !!! THIS LABEL NEEDS TO BE HERE !!!
AS THE LAST LABEL DOES NOT GET COMPILED AS THE LAST LABEL DOES NOT GET COMPILED

View file

@ -17452,6 +17452,12 @@ This track contains a sample of "Next Level" as performed by Showbiz & AG. Court
[CR19_20:CRED01] [CR19_20:CRED01]
~n~ ~n~Donna Young, Richie Zito ~n~ ~n~Donna Young, Richie Zito
[FEM_PED]
PED DENSITY
[FEM_CAR]
CAR DENSITY
[DUMMY] [DUMMY]
THIS LABEL NEEDS TO BE HERE !!! THIS LABEL NEEDS TO BE HERE !!!
AS THE LAST LABEL DOES NOT GET COMPILED AS THE LAST LABEL DOES NOT GET COMPILED

View file

@ -17455,6 +17455,12 @@ This track contains a sample of "Next Level" as performed by Showbiz & AG. Court
[CR19_20:CRED01] [CR19_20:CRED01]
~n~ ~n~Donna Young, Richie Zito ~n~ ~n~Donna Young, Richie Zito
[FEM_PED]
PED DENSITY
[FEM_CAR]
CAR DENSITY
[DUMMY] [DUMMY]
THIS LABEL NEEDS TO BE HERE !!! THIS LABEL NEEDS TO BE HERE !!!
AS THE LAST LABEL DOES NOT GET COMPILED AS THE LAST LABEL DOES NOT GET COMPILED