#include "common.h" #include "GameLogic.h" #include "Clock.h" #include "Stats.h" #include "Pickups.h" #include "Timer.h" #include "Streaming.h" #include "CutsceneMgr.h" #include "World.h" #include "PlayerPed.h" #include "Wanted.h" #include "Camera.h" #include "Messages.h" #include "CarCtrl.h" #include "Restart.h" #include "Pad.h" #include "References.h" #include "Fire.h" #include "Script.h" #include "Garages.h" #include "Population.h" #include "General.h" #include "DMAudio.h" #include "Radar.h" #include "Pools.h" #include "Hud.h" #include "Particle.h" #include "ColStore.h" #include "Automobile.h" #include "MBlur.h" #include "screendroplets.h" #include "SaveBuf.h" uint8 CGameLogic::ActivePlayers; uint8 CGameLogic::ShortCutState; CAutomobile* CGameLogic::pShortCutTaxi; uint32 CGameLogic::NumAfterDeathStartPoints; CVector CGameLogic::ShortCutStart; float CGameLogic::ShortCutStartOrientation; CVector CGameLogic::ShortCutDestination; float CGameLogic::ShortCutDestinationOrientation; uint32 CGameLogic::ShortCutTimer; CVector CGameLogic::AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS]; float CGameLogic::AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS]; CVector CGameLogic::ShortCutDropOffForMission; float CGameLogic::ShortCutDropOffOrientationForMission; bool CGameLogic::MissionDropOffReadyToBeUsed; #define SHORTCUT_TAXI_COST (9) #define TOTAL_BUSTED_AUDIO (28) void CGameLogic::InitAtStartOfGame() { ActivePlayers = 1; ShortCutState = SHORTCUT_NONE; pShortCutTaxi = nil; NumAfterDeathStartPoints = 0; } void CGameLogic::PassTime(uint32 time) { int32 minutes, hours, days; minutes = time + CClock::GetMinutes(); hours = CClock::GetHours(); for (; minutes >= 60; minutes -= 60) hours++; if (hours > 23) { days = CStats::DaysPassed; for (; hours >= 24; hours -= 24) days++; CStats::DaysPassed = days; } CClock::SetGameClock(hours, minutes); CPickups::PassTime(time * 1000); } void CGameLogic::SortOutStreamingAndMemory(const CVector &pos) { CTimer::Stop(); CStreaming::FlushRequestList(); CStreaming::DeleteRwObjectsAfterDeath(pos); CStreaming::RemoveUnusedModelsInLoadedList(); CGame::DrasticTidyUpMemory(true); CWorld::Players[CWorld::PlayerInFocus].m_pPed->Undress("player"); CStreaming::LoadSceneCollision(pos); CStreaming::LoadScene(pos); CWorld::Players[CWorld::PlayerInFocus].m_pPed->Dress(); CTimer::Update(); } void CGameLogic::Update() { CVector vecRestartPos; float fRestartFloat; if (CCutsceneMgr::IsCutsceneProcessing()) return; UpdateShortCut(); CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus]; switch (pPlayerInfo.m_WBState) { case WBSTATE_PLAYING: if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) { pPlayerInfo.m_pPed->ClearAdrenaline(); pPlayerInfo.KillPlayer(); } if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) { pPlayerInfo.m_pPed->ClearAdrenaline(); pPlayerInfo.ArrestPlayer(); } break; case WBSTATE_WASTED: #ifdef MISSION_REPLAY if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > AddExtraDeathDelay() + 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= AddExtraDeathDelay() + 0x800)) { #else if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { #endif TheCamera.SetFadeColour(200, 200, 200); TheCamera.Fade(2.0f, FADE_OUT); } #ifdef MISSION_REPLAY if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) { #else if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { #endif pPlayerInfo.m_WBState = WBSTATE_PLAYING; if (pPlayerInfo.m_bGetOutOfHospitalFree) { pPlayerInfo.m_bGetOutOfHospitalFree = false; } else { pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 100); pPlayerInfo.m_pPed->ClearWeapons(); } if (pPlayerInfo.m_pPed->bInVehicle) { CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; if (pVehicle != nil) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) { pVehicle->pDriver = nil; if (pVehicle->GetStatus() != STATUS_WRECKED) pVehicle->SetStatus(STATUS_ABANDONED); } else pVehicle->RemovePassenger(pPlayerInfo.m_pPed); } } CEventList::Initialise(); #ifdef SCREEN_DROPLETS ScreenDroplets::Initialise(); #endif CMessages::ClearMessages(); CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true); CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); CRestart::OverrideHospitalLevel = LEVEL_GENERIC; CRestart::OverridePoliceStationLevel = LEVEL_GENERIC; PassTime(720); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); AfterDeathArrestSetUpShortCutTaxi(); SortOutStreamingAndMemory(pPlayerInfo.GetPos()); TheCamera.m_fCamShakeForce = 0.0f; TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE); CPad::GetPad(0)->StopShaking(0); CReferences::RemoveReferencesToPlayer(); CPopulation::m_CountDownToPedsAtStart = 10; CCarCtrl::CountDownToCarsAtStart = 10; CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; if (CRestart::bFadeInAfterNextDeath) { TheCamera.SetFadeColour(200, 200, 200); TheCamera.Fade(4.0f, FADE_IN); } else CRestart::bFadeInAfterNextDeath = true; } break; case WBSTATE_BUSTED: #ifdef MISSION_REPLAY if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > AddExtraDeathDelay() + 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= AddExtraDeathDelay() + 0x800)) { #else if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { #endif TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(2.0f, FADE_OUT); } if (!CTheScripts::IsPlayerOnAMission() && pPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_NONE) { if (CGeneral::GetRandomNumberInRange(0, 4) == 0) pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE; else { pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_LOADING; char name[12]; sprintf(name, pPlayerInfo.m_nCurrentBustedAudio >= 10 ? "bust_%d" : "bust_0%d", pPlayerInfo.m_nCurrentBustedAudio); DMAudio.ClearMissionAudio(0); DMAudio.PreloadMissionAudio(0, name); pPlayerInfo.m_nCurrentBustedAudio = pPlayerInfo.m_nCurrentBustedAudio % TOTAL_BUSTED_AUDIO + 1; } } if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 4000 && pPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_LOADING && DMAudio.GetMissionAudioLoadingStatus(0) == 1) { DMAudio.PlayLoadedMissionAudio(0); pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE; } #ifdef MISSION_REPLAY if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) { #else if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { #endif #ifdef FIX_BUGS pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_NONE; #endif pPlayerInfo.m_WBState = WBSTATE_PLAYING; int takeMoney; switch (pPlayerInfo.m_pPed->m_pWanted->GetWantedLevel()) { case 0: case 1: takeMoney = 100; break; case 2: takeMoney = 200; break; case 3: takeMoney = 400; break; case 4: takeMoney = 600; break; case 5: takeMoney = 900; break; case 6: takeMoney = 1500; break; } if (pPlayerInfo.m_bGetOutOfJailFree) { pPlayerInfo.m_bGetOutOfJailFree = false; } else { pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - takeMoney); pPlayerInfo.m_pPed->ClearWeapons(); } if (pPlayerInfo.m_pPed->bInVehicle) { CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; if (pVehicle != nil) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) { pVehicle->pDriver = nil; if (pVehicle->GetStatus() != STATUS_WRECKED) pVehicle->SetStatus(STATUS_ABANDONED); } else pVehicle->RemovePassenger(pPlayerInfo.m_pPed); } } CEventList::Initialise(); #ifdef SCREEN_DROPLETS ScreenDroplets::Initialise(); #endif CMessages::ClearMessages(); CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true); CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); CRestart::OverrideHospitalLevel = LEVEL_GENERIC; CRestart::OverridePoliceStationLevel = LEVEL_GENERIC; PassTime(720); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); AfterDeathArrestSetUpShortCutTaxi(); pPlayerInfo.m_pPed->ClearWeapons(); SortOutStreamingAndMemory(pPlayerInfo.GetPos()); TheCamera.m_fCamShakeForce = 0.0f; TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE); CPad::GetPad(0)->StopShaking(0); CReferences::RemoveReferencesToPlayer(); CPopulation::m_CountDownToPedsAtStart = 10; CCarCtrl::CountDownToCarsAtStart = 10; CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; if (CRestart::bFadeInAfterNextArrest) { TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(4.0f, FADE_IN); } else CRestart::bFadeInAfterNextArrest = true; } break; case WBSTATE_FAILED_CRITICAL_MISSION: #ifdef MISSION_REPLAY if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > AddExtraDeathDelay() + 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= AddExtraDeathDelay() + 0x800)) { #else if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) { #endif TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(2.0f, FADE_OUT); } #ifdef MISSION_REPLAY if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) { #else if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) { #endif pPlayerInfo.m_WBState = WBSTATE_PLAYING; if (pPlayerInfo.m_pPed->bInVehicle) { CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle; if (pVehicle != nil) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) { pVehicle->pDriver = nil; if (pVehicle->GetStatus() != STATUS_WRECKED) pVehicle->SetStatus(STATUS_ABANDONED); } else pVehicle->RemovePassenger(pPlayerInfo.m_pPed); } } CEventList::Initialise(); #ifdef SCREEN_DROPLETS ScreenDroplets::Initialise(); #endif CMessages::ClearMessages(); CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true); CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); CRestart::OverridePoliceStationLevel = LEVEL_GENERIC; CRestart::OverrideHospitalLevel = LEVEL_GENERIC; RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); SortOutStreamingAndMemory(pPlayerInfo.GetPos()); TheCamera.m_fCamShakeForce = 0.0f; TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE); CPad::GetPad(0)->StopShaking(0); CReferences::RemoveReferencesToPlayer(); CPopulation::m_CountDownToPedsAtStart = 10; CCarCtrl::CountDownToCarsAtStart = 10; CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED; TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(4.0f, FADE_IN); } break; case 4: return; } } void CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle) { ClearShortCut(); CPlayerInfo* pPlayerInfo = pPlayerPed->GetPlayerInfoForThisPlayerPed(); pPlayerPed->m_fHealth = pPlayerInfo->m_nMaxHealth; pPlayerPed->m_fArmour = 0.0f; pPlayerPed->bIsVisible = true; pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0; pPlayerPed->bDoBloodyFootprints = false; pPlayerPed->m_nDrunkenness = 0; pPlayerPed->m_nFadeDrunkenness = 0; CMBlur::ClearDrunkBlur(); pPlayerPed->m_nDrunkCountdown = 0; pPlayerPed->ClearAdrenaline(); pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina; if (pPlayerPed->m_pFire) pPlayerPed->m_pFire->Extinguish(); pPlayerPed->bInVehicle = false; pPlayerPed->m_pMyVehicle = nil; pPlayerPed->m_pVehicleAnim = nil; pPlayerPed->m_pWanted->Reset(); pPlayerPed->bCancelEnteringCar = false; pPlayerPed->RestartNonPartialAnims(); pPlayerInfo->MakePlayerSafe(false); pPlayerPed->bRemoveFromWorld = false; pPlayerPed->ClearWeaponTarget(); pPlayerPed->SetInitialState(); CCarCtrl::ClearInterestingVehicleList(); pPlayerPed->Teleport(pos + CVector(0.0f, 0.0f, 1.0f)); pPlayerPed->SetMoveSpeed(0.0f, 0.0f, 0.0f); pPlayerPed->m_fRotationCur = DEGTORAD(angle); pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur; pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur); CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed); CWorld::ClearExcitingStuffFromArea(pos, 4000.0f, true); pPlayerPed->RestoreHeadingRate(); CGame::currArea = AREA_MAIN_MAP; CStreaming::RemoveBuildingsNotInArea(0); TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString(); TheCamera.Restore(); CReferences::RemoveReferencesToPlayer(); CGarages::PlayerArrestedOrDied(); CStats::CheckPointReachedUnsuccessfully(); CWorld::Remove(pPlayerPed); CWorld::Add(pPlayerPed); CHud::ResetWastedText(); CStreaming::StreamZoneModels(pos); clearWaterDrop = true; } void CGameLogic::ClearShortCut() { if (pShortCutTaxi) { if (pShortCutTaxi->VehicleCreatedBy == MISSION_VEHICLE) { pShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE; --CCarCtrl::NumMissionCars; ++CCarCtrl::NumRandomCars; } CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi)); pShortCutTaxi = nil; } CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI); } void CGameLogic::SetUpShortCut(CVector vStartPos, float fStartAngle, CVector vEndPos, float fEndAngle) { ClearShortCut(); ShortCutState = SHORTCUT_INIT; ShortCutStart = vStartPos; ShortCutStartOrientation = fStartAngle; ShortCutDestination = vEndPos; ShortCutDestinationOrientation = fEndAngle; CStreaming::RequestModel(MI_KAUFMAN, 0); } void CGameLogic::AbandonShortCutIfTaxiHasBeenMessedWith() { if (!pShortCutTaxi) return; if (pShortCutTaxi->pDriver == nil || pShortCutTaxi->pDriver->DyingOrDead() || pShortCutTaxi->pDriver->GetPedState() == PED_DRAG_FROM_CAR || pShortCutTaxi->pDriver->GetPedState() == PED_ON_FIRE || pShortCutTaxi->pDriver->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE || pShortCutTaxi->m_fHealth < 250.0f || pShortCutTaxi->bRenderScorched) ClearShortCut(); } void CGameLogic::AbandonShortCutIfPlayerMilesAway() { if (!pShortCutTaxi) return; if ((FindPlayerCoors() - pShortCutTaxi->GetPosition()).Magnitude() > 120.0f) ClearShortCut(); } void CGameLogic::UpdateShortCut() { switch (ShortCutState) { case SHORTCUT_INIT: if (!CStreaming::HasModelLoaded(MI_KAUFMAN)) { CStreaming::RequestModel(MI_KAUFMAN, 0); return; } pShortCutTaxi = new CAutomobile(MI_KAUFMAN, RANDOM_VEHICLE); if (!pShortCutTaxi) return; pShortCutTaxi->SetPosition(ShortCutStart); pShortCutTaxi->SetHeading(DEGTORAD(ShortCutStartOrientation)); pShortCutTaxi->PlaceOnRoadProperly(); pShortCutTaxi->SetStatus(STATUS_PHYSICS); pShortCutTaxi->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER; pShortCutTaxi->AutoPilot.m_nCruiseSpeed = 0; pShortCutTaxi->SetUpDriver(); pShortCutTaxi->VehicleCreatedBy = MISSION_VEHICLE; ++CCarCtrl::NumMissionCars; --CCarCtrl::NumRandomCars; CTheScripts::ClearSpaceForMissionEntity(ShortCutStart, pShortCutTaxi); CWorld::Add(pShortCutTaxi); CRadar::SetEntityBlip(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi), 0, BLIP_DISPLAY_MARKER_ONLY); ShortCutState = SHORTCUT_IDLE; break; case SHORTCUT_IDLE: if (FindPlayerPed()->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && FindPlayerPed()->m_carInObjective == pShortCutTaxi) { CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI); FindPlayerPed()->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pShortCutTaxi); ShortCutState = SHORTCUT_GETTING_IN; } AbandonShortCutIfTaxiHasBeenMessedWith(); AbandonShortCutIfPlayerMilesAway(); break; case SHORTCUT_GETTING_IN: if (pShortCutTaxi->pPassengers[0] == FindPlayerPed() || pShortCutTaxi->pPassengers[1] == FindPlayerPed() || pShortCutTaxi->pPassengers[2] == FindPlayerPed()) { pShortCutTaxi->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; pShortCutTaxi->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2500; TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(2.5f, FADE_OUT); ShortCutState = SHORTCUT_TRANSITION; ShortCutTimer = CTimer::GetTimeInMilliseconds() + 3000; CMessages::AddBigMessage(TheText.Get("TAXI"), 4500, 1); } AbandonShortCutIfTaxiHasBeenMessedWith(); break; case SHORTCUT_TRANSITION: if (CTimer::GetTimeInMilliseconds() > ShortCutTimer) { CTimer::Suspend(); CColStore::RequestCollision(ShortCutDestination); CStreaming::LoadSceneCollision(ShortCutDestination); CStreaming::LoadScene(ShortCutDestination); CTheScripts::ClearSpaceForMissionEntity(ShortCutDestination, pShortCutTaxi); pShortCutTaxi->Teleport(ShortCutDestination); pShortCutTaxi->SetHeading(DEGTORAD(ShortCutDestinationOrientation)); pShortCutTaxi->PlaceOnRoadProperly(); pShortCutTaxi->SetMoveSpeed(pShortCutTaxi->GetForward() * 0.4f); ShortCutTimer = CTimer::GetTimeInMilliseconds() + 1500; TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(1.0f, FADE_IN); ShortCutState = SHORTCUT_ARRIVING; CTimer::Resume(); } break; case SHORTCUT_ARRIVING: if (CTimer::GetTimeInMilliseconds() > ShortCutTimer) { CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - SHORTCUT_TAXI_COST); FindPlayerPed()->SetObjective(OBJECTIVE_LEAVE_CAR, pShortCutTaxi); FindPlayerPed()->m_carInObjective = pShortCutTaxi; ShortCutState = SHORTCUT_GETTING_OUT; } AbandonShortCutIfTaxiHasBeenMessedWith(); break; case SHORTCUT_GETTING_OUT: if (pShortCutTaxi->pPassengers[0] != FindPlayerPed() && pShortCutTaxi->pPassengers[1] != FindPlayerPed() && pShortCutTaxi->pPassengers[2] != FindPlayerPed()) { CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI); pShortCutTaxi->AutoPilot.m_nCarMission = MISSION_CRUISE; pShortCutTaxi->AutoPilot.m_nCruiseSpeed = 18; CCarCtrl::JoinCarWithRoadSystem(pShortCutTaxi); pShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE; ++CCarCtrl::NumRandomCars; --CCarCtrl::NumMissionCars; CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi)); ShortCutState = SHORTCUT_NONE; pShortCutTaxi = nil; } AbandonShortCutIfTaxiHasBeenMessedWith(); break; } } void CGameLogic::AddShortCutPointAfterDeath(CVector point, float angle) { if (NumAfterDeathStartPoints >= NUM_SHORTCUT_START_POINTS) return; AfterDeathStartPoints[NumAfterDeathStartPoints] = point; AfterDeathStartPointOrientation[NumAfterDeathStartPoints] = angle; NumAfterDeathStartPoints++; } void CGameLogic::AddShortCutDropOffPointForMission(CVector point, float angle) { ShortCutDropOffForMission = point; ShortCutDropOffOrientationForMission = angle; MissionDropOffReadyToBeUsed = true; } void CGameLogic::RemoveShortCutDropOffPointForMission() { MissionDropOffReadyToBeUsed = false; } void CGameLogic::AfterDeathArrestSetUpShortCutTaxi() { if (!MissionDropOffReadyToBeUsed) return; int nClosestPoint = -1; float fDistanceToPoint = 999999.9f; for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) { float dist = (AfterDeathStartPoints[i] - FindPlayerCoors()).Magnitude(); if (dist < fDistanceToPoint) { fDistanceToPoint = dist; nClosestPoint = i; } } if (fDistanceToPoint < 100.0f) SetUpShortCut(AfterDeathStartPoints[nClosestPoint], AfterDeathStartPointOrientation[nClosestPoint], ShortCutDropOffForMission, ShortCutDropOffOrientationForMission); MissionDropOffReadyToBeUsed = false; } void CGameLogic::Save(uint8* buf, uint32* size) { INITSAVEBUF WriteSaveBuf(buf, NumAfterDeathStartPoints); *size += sizeof(NumAfterDeathStartPoints); for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) { WriteSaveBuf(buf, AfterDeathStartPoints[i].x); *size += sizeof(AfterDeathStartPoints[i].x); WriteSaveBuf(buf, AfterDeathStartPoints[i].y); *size += sizeof(AfterDeathStartPoints[i].y); WriteSaveBuf(buf, AfterDeathStartPoints[i].z); *size += sizeof(AfterDeathStartPoints[i].z); WriteSaveBuf(buf, AfterDeathStartPointOrientation[i]); *size += sizeof(AfterDeathStartPointOrientation[i]); } VALIDATESAVEBUF(*size) } void CGameLogic::Load(uint8* buf, uint32 size) { INITSAVEBUF ReadSaveBuf(&NumAfterDeathStartPoints, buf); for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) { ReadSaveBuf(&AfterDeathStartPoints[i].x, buf); ReadSaveBuf(&AfterDeathStartPoints[i].y, buf); ReadSaveBuf(&AfterDeathStartPoints[i].z, buf); ReadSaveBuf(&AfterDeathStartPointOrientation[i], buf); } VALIDATESAVEBUF(size) }