#include "common.h" #include "Restart.h" #include "Zones.h" #include "PathFind.h" uint8 CRestart::OverrideHospitalLevel; uint8 CRestart::OverridePoliceStationLevel; bool CRestart::bFadeInAfterNextArrest; bool CRestart::bFadeInAfterNextDeath; bool CRestart::bOverrideRestart; CVector CRestart::OverridePosition; float CRestart::OverrideHeading; CVector CRestart::HospitalRestartPoints[NUM_RESTART_POINTS]; float CRestart::HospitalRestartHeadings[NUM_RESTART_POINTS]; uint16 CRestart::NumberOfHospitalRestarts; CVector CRestart::PoliceRestartPoints[NUM_RESTART_POINTS]; float CRestart::PoliceRestartHeadings[NUM_RESTART_POINTS]; uint16 CRestart::NumberOfPoliceRestarts; void CRestart::Initialise() { OverridePoliceStationLevel = LEVEL_GENERIC; OverrideHospitalLevel = LEVEL_GENERIC; bFadeInAfterNextArrest = true; bFadeInAfterNextDeath = true; OverrideHeading = 0.0f; OverridePosition = CVector(0.0f, 0.0f, 0.0f); bOverrideRestart = false; NumberOfPoliceRestarts = 0; NumberOfHospitalRestarts = 0; for (int i = 0; i < NUM_RESTART_POINTS; i++) { HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); HospitalRestartHeadings[i] = 0.0f; PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f); PoliceRestartHeadings[i] = 0.0f; } } void CRestart::AddHospitalRestartPoint(const CVector &pos, float heading) { HospitalRestartPoints[NumberOfHospitalRestarts] = pos; HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading; } void CRestart::AddPoliceRestartPoint(const CVector &pos, float heading) { PoliceRestartPoints[NumberOfPoliceRestarts] = pos; PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading; } void CRestart::OverrideNextRestart(const CVector &pos, float heading) { bOverrideRestart = true; OverridePosition = pos; OverrideHeading = heading; } void CRestart::CancelOverrideRestart() { bOverrideRestart = false; } void CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) { if (bOverrideRestart) { *outPos = OverridePosition; *outHeading = OverrideHeading; CancelOverrideRestart(); return; } eLevelName curlevel = CTheZones::FindZoneForPoint(pos); float fMinDist = SQR(4000.0f); int closestPoint = NUM_RESTART_POINTS; // find closest point on this level for (int i = 0; i < NumberOfHospitalRestarts; i++) { if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_GENERIC ? OverrideHospitalLevel : curlevel)) { float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); if (fMinDist >= dist) { fMinDist = dist; closestPoint = i; } } } // if we didn't find anything, find closest point on any level if (closestPoint == NUM_RESTART_POINTS) { for (int i = 0; i < NumberOfHospitalRestarts; i++) { float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); if (fMinDist >= dist) { fMinDist = dist; closestPoint = i; } } } // if we still didn't find anything, find closest path node if (closestPoint == NUM_RESTART_POINTS) { *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition(); *outHeading = 0.0f; printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z); } else { *outPos = HospitalRestartPoints[closestPoint]; *outHeading = HospitalRestartHeadings[closestPoint]; } } void CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading) { if (bOverrideRestart) { *outPos = OverridePosition; *outHeading = OverrideHeading; CancelOverrideRestart(); return; } eLevelName curlevel = CTheZones::FindZoneForPoint(pos); float fMinDist = SQR(4000.0f); int closestPoint = NUM_RESTART_POINTS; // find closest point on this level for (int i = 0; i < NumberOfPoliceRestarts; i++) { if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_GENERIC ? OverridePoliceStationLevel : curlevel)) { float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); if (fMinDist >= dist) { fMinDist = dist; closestPoint = i; } } } // if we didn't find anything, find closest point on any level if (closestPoint == NUM_RESTART_POINTS) { for (int i = 0; i < NumberOfPoliceRestarts; i++) { float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); if (fMinDist >= dist) { fMinDist = dist; closestPoint = i; } } } // if we still didn't find anything, find closest path node if (closestPoint == NUM_RESTART_POINTS) { printf("Couldn't find a police restart zone near the player\n"); *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition(); *outHeading = 0.0f; } else { *outPos = PoliceRestartPoints[closestPoint]; *outHeading = PoliceRestartHeadings[closestPoint]; } } void CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size) { Initialise(); INITSAVEBUF CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE); for (int i = 0; i < NUM_RESTART_POINTS; i++) { HospitalRestartPoints[i] = ReadSaveBuf(buf); HospitalRestartHeadings[i] = ReadSaveBuf(buf); } for (int i = 0; i < NUM_RESTART_POINTS; i++) { PoliceRestartPoints[i] = ReadSaveBuf(buf); PoliceRestartHeadings[i] = ReadSaveBuf(buf); } NumberOfHospitalRestarts = ReadSaveBuf(buf); NumberOfPoliceRestarts = ReadSaveBuf(buf); bOverrideRestart = ReadSaveBuf(buf); // skip something unused ReadSaveBuf(buf); ReadSaveBuf(buf); OverridePosition = ReadSaveBuf(buf); OverrideHeading = ReadSaveBuf(buf); bFadeInAfterNextDeath = ReadSaveBuf(buf); bFadeInAfterNextArrest = ReadSaveBuf(buf); OverrideHospitalLevel = ReadSaveBuf(buf); OverridePoliceStationLevel = ReadSaveBuf(buf); VALIDATESAVEBUF(size); } void CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size) { *size = SAVE_HEADER_SIZE + sizeof(HospitalRestartPoints) + sizeof(HospitalRestartHeadings) + sizeof(PoliceRestartPoints) + sizeof(PoliceRestartHeadings) + sizeof(NumberOfHospitalRestarts) + sizeof(NumberOfPoliceRestarts) + sizeof(bOverrideRestart) + sizeof(uint8) + sizeof(uint16) + sizeof(OverridePosition) + sizeof(OverrideHeading) + sizeof(bFadeInAfterNextDeath) + sizeof(bFadeInAfterNextArrest) + sizeof(OverrideHospitalLevel) + sizeof(OverridePoliceStationLevel); // == 292 INITSAVEBUF WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE); for (int i = 0; i < NUM_RESTART_POINTS; i++) { WriteSaveBuf(buf, HospitalRestartPoints[i]); WriteSaveBuf(buf, HospitalRestartHeadings[i]); } for (int i = 0; i < NUM_RESTART_POINTS; i++) { WriteSaveBuf(buf, PoliceRestartPoints[i]); WriteSaveBuf(buf, PoliceRestartHeadings[i]); } WriteSaveBuf(buf, NumberOfHospitalRestarts); WriteSaveBuf(buf, NumberOfPoliceRestarts); WriteSaveBuf(buf, bOverrideRestart); WriteSaveBuf(buf, (uint8)0); WriteSaveBuf(buf, (uint16)0); WriteSaveBuf(buf, OverridePosition); WriteSaveBuf(buf, OverrideHeading); WriteSaveBuf(buf, bFadeInAfterNextDeath); WriteSaveBuf(buf, bFadeInAfterNextArrest); WriteSaveBuf(buf, OverrideHospitalLevel); WriteSaveBuf(buf, OverridePoliceStationLevel); VALIDATESAVEBUF(*size); }