diff options
Diffstat (limited to 'src/core')
62 files changed, 15291 insertions, 13704 deletions
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index 946693a7..562b9c15 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -12,11 +12,13 @@ #include "General.h" #include "Camera.h" #include "Vehicle.h" +#include "Bike.h" #include "PlayerSkin.h" #include "PlayerInfo.h" #include "World.h" #include "Renderer.h" #include "AnimManager.h" +#include "AnimBlendAssocGroup.h" #include "AnimViewer.h" #include "PlayerPed.h" #include "Pools.h" @@ -45,14 +47,11 @@ CEntity *CAnimViewer::pTarget = nil; void CAnimViewer::Render(void) { if (pTarget) { -// pTarget->GetPosition() = CVector(0.0f, 0.0f, 0.0f); // Only on Mobile if (pTarget) { #ifdef FIX_BUGS -#ifdef PED_SKIN - if(pTarget->IsPed() && IsClumpSkinned(pTarget->GetClump())) + if(pTarget->IsPed()) ((CPed*)pTarget)->UpdateRpHAnim(); #endif -#endif pTarget->Render(); CRenderer::RenderOneNonRoad(pTarget); } @@ -61,13 +60,14 @@ CAnimViewer::Render(void) { void CAnimViewer::Initialise(void) { - // we need messages, messages needs hud, hud needs this + + // we need messages, messages needs hud, hud needs those + int hudSlot = CTxdStore::AddTxdSlot("hud"); + CTxdStore::LoadTxd(hudSlot, "MODELS/HUD.TXD"); CHud::m_Wants_To_Draw_Hud = false; animTxdSlot = CTxdStore::AddTxdSlot("generic"); CTxdStore::Create(animTxdSlot); - int hudSlot = CTxdStore::AddTxdSlot("hud"); - CTxdStore::LoadTxd(hudSlot, "MODELS/HUD.TXD"); int particleSlot = CTxdStore::AddTxdSlot("particle"); CTxdStore::LoadTxd(particleSlot, "MODELS/PARTICLE.TXD"); CTxdStore::SetCurrentTxd(animTxdSlot); @@ -76,7 +76,6 @@ CAnimViewer::Initialise(void) { TheCamera.Init(); TheCamera.SetRwCamera(Scene.camera); TheCamera.Cams[TheCamera.ActiveCam].Distance = 5.0f; - ThePaths.Init(); ThePaths.AllocatePathFindInfoMem(4500); CCollision::Init(); @@ -90,14 +89,16 @@ CAnimViewer::Initialise(void) { CPedStats::Initialise(); CMessages::Init(); CdStreamAddImage("MODELS\\GTA3.IMG"); + CFileLoader::LoadLevel("DATA\\DEFAULT.DAT"); CFileLoader::LoadLevel("DATA\\ANIMVIEWER.DAT"); CStreaming::Init(); + for(int i = 0; i < MODELINFOSIZE; i++) + if(CModelInfo::GetModelInfo(i)) + CModelInfo::GetModelInfo(i)->ConvertAnimFileIndex(); CStreaming::LoadInitialPeds(); CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE); CStreaming::LoadAllRequestedModels(false); CRenderer::Init(); - CRadar::Initialise(); - CRadar::LoadTextures(); CVehicleModelInfo::LoadVehicleColours(); #ifdef FIX_BUGS CVehicleModelInfo::LoadEnvironmentMaps(); @@ -105,14 +106,13 @@ CAnimViewer::Initialise(void) { CAnimManager::LoadAnimFiles(); CWorld::PlayerInFocus = 0; CWeapon::InitialiseWeapons(); - CShadows::Init(); CPed::Initialise(); CTimer::Initialise(); CClock::Initialise(60000); CTimeCycle::Initialise(); CCarCtrl::Init(); CPlayerPed *player = new CPlayerPed(); - player->SetPosition(0.0f, 0.0f, 0.0f); // This is 1000.f for all axes on Xbox, but 0.f on mobile? + player->SetPosition(1000.0f, 1000.0f, 1000.0f); CWorld::Players[0].m_pPed = player; CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; @@ -138,12 +138,27 @@ CAnimViewer::Initialise(void) { } CFileMgr::CloseFile(fd); } else { - // From xbox - CStreaming::RequestSpecialChar(0, "luigi", STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestSpecialChar(1, "joey", STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestSpecialChar(2, "tony", STREAMFLAGS_DONT_REMOVE); - CStreaming::RequestSpecialChar(3, "curly", STREAMFLAGS_DONT_REMOVE); + // TODO? maybe request some special models here so the thing doesn't crash } + + // From LCS. idk if needed + int vanBlock = CAnimManager::GetAnimationBlockIndex("van"); + int bikesBlock = CAnimManager::GetAnimationBlockIndex("bikes"); + int bikevBlock = CAnimManager::GetAnimationBlockIndex("bikev"); + int bikehBlock = CAnimManager::GetAnimationBlockIndex("bikeh"); + int bikedBlock = CAnimManager::GetAnimationBlockIndex("biked"); + CStreaming::FlushRequestList(); + CStreaming::RequestAnim(vanBlock, STREAMFLAGS_DEPENDENCY); + CStreaming::RequestAnim(bikesBlock, STREAMFLAGS_DEPENDENCY); + CStreaming::RequestAnim(bikevBlock, STREAMFLAGS_DEPENDENCY); + CStreaming::RequestAnim(bikehBlock, STREAMFLAGS_DEPENDENCY); + CStreaming::RequestAnim(bikedBlock, STREAMFLAGS_DEPENDENCY); + CStreaming::LoadAllRequestedModels(false); + CAnimManager::AddAnimBlockRef(vanBlock); + CAnimManager::AddAnimBlockRef(bikesBlock); + CAnimManager::AddAnimBlockRef(bikevBlock); + CAnimManager::AddAnimBlockRef(bikehBlock); + CAnimManager::AddAnimBlockRef(bikedBlock); } int @@ -270,6 +285,8 @@ CAnimViewer::Update(void) pTarget = new CAutomobile(modelId, RANDOM_VEHICLE); } else if (veh->m_vehicleType == VEHICLE_TYPE_BOAT) { pTarget = new CBoat(modelId, RANDOM_VEHICLE); + } else if (veh->m_vehicleType == VEHICLE_TYPE_BIKE) { + pTarget = new CBike(modelId, RANDOM_VEHICLE); } else { pTarget = new CObject(modelId, true); if (!modelInfo->GetColModel()) { @@ -300,7 +317,6 @@ CAnimViewer::Update(void) pTarget->GetMatrix().GetPosition().z = 10.0f; #else pTarget->GetMatrix().GetPosition().z = 0.0f; - #endif if (modelInfo->GetModelType() == MITYPE_PED) { @@ -349,16 +365,15 @@ CAnimViewer::Update(void) CMessages::AddMessage(gUString, 1000, 0); // Originally it was GetPad(1)->LeftShoulder2 } else if (pad->NewState.Triangle) { -#ifdef PED_SKIN - if(IsClumpSkinned(pTarget->GetClump())) - ((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump()); - else -#endif - CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->GetHitColModel(), - RpClumpGetFrame(pTarget->GetClump())); + ((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump()); AsciiToUnicode("Ped Col model will be animated as long as you hold the button", gUString); CMessages::AddMessage(gUString, 100, 0); } + + // From LCS + if (CAnimManager::GetAnimAssocGroups()[animGroup].numAssociations <= animId) + animId = 0; + } else if (modelInfo->GetModelType() == MITYPE_VEHICLE) { if (pad->GetLeftShoulder1JustDown()) { diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index ecfade74..89a48438 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -6,6 +6,7 @@ #include "Vehicle.h" #include "Automobile.h" #include "Boat.h" +#include "Bones.h" #include "Ped.h" #include "PlayerPed.h" #include "CopPed.h" @@ -14,6 +15,7 @@ #include "Pad.h" #include "Frontend.h" #include "General.h" +#include "Timecycle.h" #include "Renderer.h" #include "Shadows.h" #include "Hud.h" @@ -25,10 +27,15 @@ #include "Debug.h" #include "Camera.h" #include "DMAudio.h" +#include "Bike.h" +#include "Pickups.h" bool PrintDebugCode = false; int16 DebugCamMode; +extern float fRangePlayerRadius; +extern float fCloseNearClipLimit; + #ifdef FREE_CAM bool CCamera::bFreeCam = false; int nPreviousMode = -1; @@ -56,6 +63,8 @@ CCam::Init(void) m_pLastPedLookedAt = nil; ResetStatics = true; Beta = 0.0f; + m_fTilt = 0.0f; + m_fTiltSpeed = 0.0f; m_bFixingBeta = false; CA_MIN_DISTANCE = 0.0f; CA_MAX_DISTANCE = 0.0f; @@ -79,9 +88,11 @@ CCam::Init(void) m_fBufferedTargetOrientation = 0.0f; m_fBufferedTargetOrientationSpeed = 0.0f; m_fDimensionOfHighestNearCar = 0.0f; - m_fRoadOffSet = 0.0f; } +float PLAYERPED_LEVEL_SMOOTHING_CONST_INV = 0.6f; +float PLAYERPED_TREND_SMOOTHING_CONST_INV = 0.8f; + void CCam::Process(void) { @@ -89,6 +100,9 @@ CCam::Process(void) float TargetSpeedVar = 0.0f; float TargetOrientation = 0.0f; + static CVector SmoothedPos(0.0f, 0.0f, 10000.0f); + static CVector SmoothedSpeed(0.0f, 0.0f, 0.0f); + if(CamTargetEntity == nil) CamTargetEntity = TheCamera.pTargetEntity; @@ -125,7 +139,27 @@ CCam::Process(void) TargetSpeedVar = -Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/1.8f, 0.5f); SpeedVar = 0.895f*SpeedVar + 0.105*TargetSpeedVar; }else{ - CameraTarget = CamTargetEntity->GetPosition(); + if(CamTargetEntity == FindPlayerPed()){ + // Some fancy smoothing of player position and speed + float LevelSmoothing = 1.0f - Pow(PLAYERPED_LEVEL_SMOOTHING_CONST_INV, CTimer::GetTimeStep()); + float TrendSmoothing = 1.0f - Pow(PLAYERPED_TREND_SMOOTHING_CONST_INV, CTimer::GetTimeStep()); + + CVector NewSmoothedPos, NewSmoothedSpeed; + if((SmoothedPos - CamTargetEntity->GetPosition()).MagnitudeSqr() > SQR(3.0f) || + CTimer::GetTimeStep() < 0.2f || Using3rdPersonMouseCam()){ + // Reset values + NewSmoothedPos = CamTargetEntity->GetPosition(); + NewSmoothedSpeed = CVector(0.0f, 0.0f, 0.0f); + }else{ + NewSmoothedPos = LevelSmoothing*CamTargetEntity->GetPosition() + (1.0f-LevelSmoothing)*(SmoothedPos + SmoothedSpeed*CTimer::GetTimeStep()); + NewSmoothedSpeed = TrendSmoothing*(NewSmoothedPos-SmoothedPos)/CTimer::GetTimeStep() + (1.0f-TrendSmoothing)*SmoothedSpeed; + } + + CameraTarget = NewSmoothedPos; + SmoothedPos = NewSmoothedPos; + SmoothedSpeed = NewSmoothedSpeed; + }else + CameraTarget = CamTargetEntity->GetPosition(); if(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f) TargetOrientation = 0.0f; @@ -138,7 +172,7 @@ CCam::Process(void) switch(Mode){ case MODE_TOPDOWN: case MODE_GTACLASSIC: - Process_TopDown(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); + // Process_TopDown(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; case MODE_BEHINDCAR: Process_BehindCar(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); @@ -161,6 +195,7 @@ CCam::Process(void) Process_Debug(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; case MODE_SNIPER: + case MODE_CAMERA: Process_Sniper(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; case MODE_ROCKETLAUNCHER: @@ -169,14 +204,12 @@ CCam::Process(void) case MODE_MODELVIEW: Process_ModelView(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; - case MODE_BILL: - Process_Bill(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; +// case MODE_BILL: case MODE_SYPHON: Process_Syphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; case MODE_CIRCLE: - Process_Circle(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); +// Process_Circle(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; // case MODE_CHEESYZOOM: case MODE_WHEELCAM: @@ -199,15 +232,9 @@ CCam::Process(void) #endif Process_Cam_On_A_String(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; - case MODE_REACTION: - Process_ReactionCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; - case MODE_FOLLOW_PED_WITH_BIND: - Process_FollowPed_WithBinding(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; - case MODE_CHRIS: - Process_Chris_With_Binding_PlusRotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; +// case MODE_REACTION: +// case MODE_FOLLOW_PED_WITH_BIND: +// case MODE_CHRIS: case MODE_BEHINDBOAT: #ifdef FREE_CAM if (CCamera::bFreeCam) @@ -219,18 +246,10 @@ CCam::Process(void) case MODE_PLAYER_FALLEN_WATER: Process_Player_Fallen_Water(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; - case MODE_CAM_ON_TRAIN_ROOF: - Process_Cam_On_Train_Roof(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; - case MODE_CAM_RUNNING_SIDE_TRAIN: - Process_Cam_Running_Side_Train(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; - case MODE_BLOOD_ON_THE_TRACKS: - Process_Blood_On_The_Tracks(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; - case MODE_IM_THE_PASSENGER_WOOWOO: - Process_Im_The_Passenger_Woo_Woo(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); - break; +// case MODE_CAM_ON_TRAIN_ROOF: +// case MODE_CAM_RUNNING_SIDE_TRAIN: +// case MODE_BLOOD_ON_THE_TRACKS: +// case MODE_IM_THE_PASSENGER_WOOWOO: case MODE_SYPHON_CRIM_IN_FRONT: Process_Syphon_Crim_In_Front(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; @@ -246,7 +265,7 @@ CCam::Process(void) ProcessArrestCamTwo(); break; case MODE_M16_1STPERSON: - case MODE_HELICANNON_1STPERSON: // miami + case MODE_HELICANNON_1STPERSON: Process_M16_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; case MODE_SPECIAL_FIXED_FOR_SYPHON: @@ -255,8 +274,11 @@ CCam::Process(void) case MODE_FIGHT_CAM: Process_Fight_Cam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; + case MODE_LIGHTHOUSE: + Process_LightHouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); + break; case MODE_TOP_DOWN_PED: - Process_TopDownPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); + // Process_TopDownPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); break; case MODE_SNIPER_RUNABOUT: case MODE_ROCKETLAUNCHER_RUNABOUT: @@ -292,13 +314,19 @@ CCam::Process(void) LookingRight = false; SourceBeforeLookBehind = Source; if(&TheCamera.Cams[TheCamera.ActiveCam] == this){ - if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_1STPERSON || Mode == MODE_BEHINDBOAT) && + if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_1STPERSON || Mode == MODE_BEHINDBOAT || Mode == MODE_BEHINDCAR) && CamTargetEntity->IsVehicle()){ + bool bDisableLR = CamTargetEntity && + (((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || CamTargetEntity->GetModelIndex() == MI_RCBARON); if(CPad::GetPad(0)->GetLookBehindForCar()){ LookBehind(); if(DirectionWasLooking != LOOKING_BEHIND) TheCamera.m_bJust_Switched = true; DirectionWasLooking = LOOKING_BEHIND; + }else if(bDisableLR){ + if(DirectionWasLooking != LOOKING_FORWARD) + TheCamera.m_bJust_Switched = true; + DirectionWasLooking = LOOKING_FORWARD; }else if(CPad::GetPad(0)->GetLookLeft()){ LookLeft(); if(DirectionWasLooking != LOOKING_LEFT) @@ -327,7 +355,7 @@ CCam::Process(void) } if(Mode == MODE_SNIPER || Mode == MODE_ROCKETLAUNCHER || Mode == MODE_M16_1STPERSON || - Mode == MODE_1STPERSON || Mode == MODE_HELICANNON_1STPERSON || GetWeaponFirstPersonOn()) + Mode == MODE_1STPERSON || Mode == MODE_HELICANNON_1STPERSON || Mode == MODE_CAMERA || GetWeaponFirstPersonOn()) ClipIfPedInFrontOfPlayer(); } @@ -371,22 +399,19 @@ MakeAngleLessThan180(float &Angle) void CCam::ProcessSpecialHeightRoutines(void) { - int i = 0; + int i; bool StandingOnBoat = false; static bool PreviouslyFailedRoadHeightCheck = false; CVector CamToTarget, CamToPed; float DistOnGround, BetaAngle; CPed *Player; - int ClosestPed = 0; - bool FoundPed = false; - float ClosestPedDist, PedZDist; + float PedZDist; CColPoint colPoint; CamToTarget = TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition(); DistOnGround = CamToTarget.Magnitude2D(); BetaAngle = CGeneral::GetATanOfXY(CamToTarget.x, CamToTarget.y); m_bTheHeightFixerVehicleIsATrain = false; - ClosestPedDist = 0.0f; // CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y); Player = CWorld::Players[CWorld::PlayerInFocus].m_pPed; @@ -398,65 +423,61 @@ CCam::ProcessSpecialHeightRoutines(void) ((CVehicle*)FindPlayerPed()->m_pCurSurface)->IsBoat()) StandingOnBoat = true; + float FoundPedZ = -100.0f; + // Move up the camera if there is a ped close to it - if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM){ - // Find ped closest to camera - while(i < Player->m_numNearPeds){ - if(Player->m_nearPeds[i] && Player->m_nearPeds[i]->GetPedState() != PED_DEAD){ - CamToPed = Player->m_nearPeds[i]->GetPosition() - TheCamera.GetGameCamPosition(); - if(FoundPed){ - if(CamToPed.Magnitude2D() < ClosestPedDist){ - ClosestPed = i; - ClosestPedDist = CamToPed.Magnitude2D(); + if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM || Mode == MODE_PILLOWS_PAPS){ + // Find highest ped close to camera + for(i = 0; i < Player->m_numNearPeds; i++){ + CPed *nearPed = Player->m_nearPeds[i]; + if(nearPed && nearPed->GetPedState() != PED_DEAD){ + CamToPed = nearPed->GetPosition() - TheCamera.GetGameCamPosition(); + if(Abs(CamToPed.z) < 1.0f){ + float DistSq = CamToPed.MagnitudeSqr(); + if(DistSq < SQR(2.1f)){ + if(nearPed->GetPosition().z > FoundPedZ) + FoundPedZ = nearPed->GetPosition().z; + }else{ + float Dist = Sqrt(DistSq); + CamToPed /= Dist; + // strange calculation + CVector PlayerCamSpeed = DotProduct(Front, Player->m_vecMoveSpeed)*Front; + float SpeedDiff = DotProduct(PlayerCamSpeed - nearPed->m_vecMoveSpeed, CamToPed); + if(SpeedDiff > 0.01f && + (m_fPedBetweenCameraHeightOffset > 0.0f && (Dist-2.1f)/SpeedDiff < 75.0f || + m_fPedBetweenCameraHeightOffset <= 0.0f && (Dist-2.1f)/SpeedDiff < 75.0f * 0.1f)) + if(nearPed->GetPosition().z > FoundPedZ) + FoundPedZ = nearPed->GetPosition().z; } - }else{ - FoundPed = true; - ClosestPed = i; - ClosestPedDist = CamToPed.Magnitude2D(); } } - i++; } - if(FoundPed){ + if(FoundPedZ > -99.0f){ float Offset = 0.0f; - CPed *Ped = Player->m_nearPeds[ClosestPed]; - CamToPed = Ped->GetPosition() - TheCamera.GetGameCamPosition(); PedZDist = 0.0f; - float dist = CamToPed.Magnitude2D(); // should be same as ClosestPedDist - if(dist < 2.1f){ - // Ped is close to camera, move up - - // Z Distance between player and close ped - PedZDist = 0.0f; - if(Ped->bIsStanding) - PedZDist = Ped->GetPosition().z - Player->GetPosition().z; - // Ignore if too distant - if(PedZDist > 1.2f || PedZDist < -1.2f) - PedZDist = 0.0f; - - float DistScale = (2.1f - dist)/2.1f; - if(Mode == MODE_FOLLOWPED){ - if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) - Offset = 0.45f*DistScale + PedZDist; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) - Offset = 0.35f*DistScale + PedZDist; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) - Offset = 0.25f*DistScale + PedZDist; - if(Abs(CGeneral::GetRadianAngleBetweenPoints(CamToPed.x, CamToPed.y, CamToTarget.x, CamToTarget.y)) > HALFPI) - Offset += 0.3f; - m_fPedBetweenCameraHeightOffset = Offset + 1.3f; - PedZDist = 0.0f; - }else if(Mode == MODE_FIGHT_CAM) - m_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.5f; - }else - m_fPedBetweenCameraHeightOffset = 0.0f; + if(FoundPedZ > Player->GetPosition().z) + PedZDist = FoundPedZ - Player->GetPosition().z; + + if(Mode == MODE_FOLLOWPED){ + if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 && + ((CPed*)CamTargetEntity)->GetPedState() != PED_ENTER_CAR && + ((CPed*)CamTargetEntity)->GetPedState() != PED_CARJACK) + Offset = 0.45f + PedZDist; + // BUG: overrides this ^ case + if(TheCamera.PedZoomIndicator == CAM_ZOOM_2 || TheCamera.PedZoomIndicator == CAM_ZOOM_1) + Offset = 0.35f + PedZDist; + if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) + Offset = 0.25f + PedZDist; + m_fPedBetweenCameraHeightOffset = Offset + 1.3f; + }else if(Mode == MODE_FIGHT_CAM) + m_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.5f; + else if(Mode == MODE_PILLOWS_PAPS) + m_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.45f; }else{ - PedZDist = 0.0f; m_fPedBetweenCameraHeightOffset = 0.0f; } - }else - PedZDist = 0.0f; + } // Move camera up for vehicles in the way @@ -465,6 +486,8 @@ CCam::ProcessSpecialHeightRoutines(void) CEntity *vehicle = nil; float TestDist = DistOnGround + 1.25f; float HighestCar = 0.0f; + if(m_fDimensionOfHighestNearCar > 0.0f) + TestDist += 0.3f; CVector TestBase = CamTargetEntity->GetPosition(); CVector TestPoint; TestBase.z -= 0.15f; @@ -514,96 +537,9 @@ CCam::ProcessSpecialHeightRoutines(void) }else m_fDimensionOfHighestNearCar = 0.0f; } - - // Move up for road - if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM || - Mode == MODE_SYPHON || Mode == MODE_SYPHON_CRIM_IN_FRONT || Mode == MODE_SPECIAL_FIXED_FOR_SYPHON){ - bool Inside = false; - bool OnRoad = false; - - switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched) - case SURFACE_GRASS: - case SURFACE_GRAVEL: - case SURFACE_MUD_DRY: - case SURFACE_THICK_METAL_PLATE: - case SURFACE_RUBBER: - case SURFACE_STEEP_CLIFF: - OnRoad = true; - - if(CCullZones::PlayerNoRain()) - Inside = true; - - if((m_bCollisionChecksOn || PreviouslyFailedRoadHeightCheck || OnRoad) && - m_fCloseInPedHeightOffset < 0.0001f && !Inside){ - CVector TestPoint; - CEntity *road; - float GroundZ = 0.0f; - bool FoundGround = false; - float RoofZ = 0.0f; - bool FoundRoof = false; - static float MinHeightAboveRoad = 0.9f; - - TestPoint = CamTargetEntity->GetPosition() - DistOnGround * CVector(Cos(BetaAngle), Sin(BetaAngle), 0.0f); - m_fRoadOffSet = 0.0f; - - if(CWorld::ProcessVerticalLine(TestPoint, -1000.0f, colPoint, road, true, false, false, false, false, false, nil)){ - FoundGround = true; - GroundZ = colPoint.point.z; - } - // Move up if too close to ground - if(FoundGround){ - if(TestPoint.z - GroundZ < MinHeightAboveRoad){ - m_fRoadOffSet = GroundZ + MinHeightAboveRoad - TestPoint.z; - PreviouslyFailedRoadHeightCheck = true; - }else{ - if(m_bCollisionChecksOn) - PreviouslyFailedRoadHeightCheck = false; - else - m_fRoadOffSet = 0.0f; - } - }else{ - if(CWorld::ProcessVerticalLine(TestPoint, 1000.0f, colPoint, road, true, false, false, false, false, false, nil)){ - FoundRoof = true; - RoofZ = colPoint.point.z; - } - if(FoundRoof){ - if(TestPoint.z - RoofZ < MinHeightAboveRoad){ - m_fRoadOffSet = RoofZ + MinHeightAboveRoad - TestPoint.z; - PreviouslyFailedRoadHeightCheck = true; - }else{ - if(m_bCollisionChecksOn) - PreviouslyFailedRoadHeightCheck = false; - else - m_fRoadOffSet = 0.0f; - } - } - } - } - } - - if(PreviouslyFailedRoadHeightCheck && m_fCloseInPedHeightOffset < 0.0001f){ - if(colPoint.surfaceB != SURFACE_TARMAC && - colPoint.surfaceB != SURFACE_GRASS && - colPoint.surfaceB != SURFACE_GRAVEL && - colPoint.surfaceB != SURFACE_MUD_DRY && - colPoint.surfaceB != SURFACE_STEEP_CLIFF){ - if(m_fRoadOffSet > 1.4f) - m_fRoadOffSet = 1.4f; - }else{ - if(Mode == MODE_FOLLOWPED){ - if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) - m_fRoadOffSet += 0.2f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) - m_fRoadOffSet += 0.5f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) - m_fRoadOffSet += 0.95f; - } - } - } } if(StandingOnBoat){ - m_fRoadOffSet = 0.0f; m_fDimensionOfHighestNearCar = 1.0f; m_fPedBetweenCameraHeightOffset = 0.0f; } @@ -624,18 +560,30 @@ CCam::GetVectorsReadyForRW(void) Up = CrossProduct(right, Front); } +bool +CCam::GetBoatLook_L_R_HeightOffset(float &Offset) +{ + if(CamTargetEntity == nil) + return false; + CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex()); + tBoatHandlingData *handling = mod_HandlingManager.GetBoatPointer(mi->m_handlingId); + if(handling){ + Offset = handling->fLook_L_R_BehindCamHeight; + return true; + } + return false; // can't happen, we always get a boat pointer back +} + void CCam::LookBehind(void) { float Dist, DeltaBeta, TargetOrientation, Angle; CVector TargetCoors, TargetFwd, TestCoors; - CColPoint colPoint; - CEntity *entity; TargetCoors = CamTargetEntity->GetPosition(); Front = CamTargetEntity->GetPosition() - Source; - if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){ + if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT || Mode == MODE_BEHINDCAR) && CamTargetEntity->IsVehicle()){ LookingBehind = true; Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 15.5f; TargetFwd = CamTargetEntity->GetForward(); @@ -650,12 +598,8 @@ CCam::LookBehind(void) TargetOrientation += PI; Source.x = Dist*Cos(TargetOrientation) + TargetCoors.x; Source.y = Dist*Sin(TargetOrientation) + TargetCoors.y; - Source.z -= 1.0f; - if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){ - RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); - Source = colPoint.point; - } - Source.z += 1.0f; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); Front = CamTargetEntity->GetPosition() - Source; GetVectorsReadyForRW(); } @@ -666,55 +610,76 @@ CCam::LookBehind(void) Front.Normalise(); if(((CVehicle*)CamTargetEntity)->IsBoat()) Source.z -= 0.5f; - Source += 0.25f*Front; - Front = -Front; -#ifdef FIX_BUGS - // not sure if this is a bug... - GetVectorsReadyForRW(); -#endif + if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE){ + float FrontDist = 1.1f; + if(((CVehicle*)CamTargetEntity)->pDriver){ + CVector ExtraFwd(0.0f, 0.0f, 0.0f); + ((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(ExtraFwd, PED_HEAD); + ExtraFwd += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed*CTimer::GetTimeStep() - CamTargetEntity->GetPosition(); + FrontDist += 0.2f + Max(DotProduct(ExtraFwd, CamTargetEntity->GetForward()), 0.0f); + } + Source += FrontDist*Front; + Front = -Front; + }else if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI){ + Front = -1.0f*CamTargetEntity->GetUp(); + Up = CamTargetEntity->GetForward(); + Source += 0.25f*Front; + }else{ + Source += 0.25f*Front; + Front = -Front; + } } if(CamTargetEntity->IsPed()){ Angle = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y) + PI; Source.x = 4.5f*Cos(Angle) + TargetCoors.x; Source.y = 4.5f*Sin(Angle) + TargetCoors.y; Source.z = 1.15f + TargetCoors.z; - TestCoors = TargetCoors; - TestCoors.z = Source.z; - if(CWorld::ProcessLineOfSight(TestCoors, Source, colPoint, entity, true, true, false, true, false, true, true)){ - Source.x = colPoint.point.x; - Source.y = colPoint.point.y; - if((TargetCoors - Source).Magnitude2D() < 1.15f) - RwCameraSetNearClipPlane(Scene.camera, 0.05f); - } + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); Front = TargetCoors - Source; GetVectorsReadyForRW(); } } +float BOAT_1STPERSON_L_OFFSETX = 0.7f; +float BOAT_1STPERSON_R_OFFSETX = 0.3f; +float BOAT_1STPERSON_LR_OFFSETZ = 0.2f; + void CCam::LookLeft(void) { float Dist, TargetOrientation; CVector TargetCoors, TargetFwd; - CColPoint colPoint; - CEntity *entity; - if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){ + if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT || Mode == MODE_BEHINDCAR) && CamTargetEntity->IsVehicle()){ LookingLeft = true; TargetCoors = CamTargetEntity->GetPosition(); Front = CamTargetEntity->GetPosition() - Source; - Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 9.0f; + if(Mode == MODE_CAM_ON_A_STRING) + Dist = CA_MAX_DISTANCE; + else if(Mode == MODE_BEHINDBOAT){ + Dist = 9.0f; + float Offset = 0.0f; + if(GetBoatLook_L_R_HeightOffset(Offset) && !CCullZones::Cam1stPersonForPlayer()) + Source.z = TargetCoors.z + Offset; + }else + Dist = 9.0f; TargetFwd = CamTargetEntity->GetForward(); TargetFwd.Normalise(); TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y); Source.x = Dist*Cos(TargetOrientation - HALFPI) + TargetCoors.x; Source.y = Dist*Sin(TargetOrientation - HALFPI) + TargetCoors.y; - Source.z -= 1.0f; - if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){ - RwCameraSetNearClipPlane(Scene.camera, 0.4f); - Source = colPoint.point; - } - Source.z += 1.0f; + + CColModel *colModel = CamTargetEntity->GetColModel(); + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); + + CVector TopRight = CamTargetEntity->GetPosition() + + CamTargetEntity->GetRight()*colModel->boundingBox.max.x + + CamTargetEntity->GetUp()*colModel->boundingBox.max.z; + float Height = Min(Max(m_cvecTargetCoorsForFudgeInter.z, TopRight.z)+0.1f, OrigSource.z); + Source.z = Max(Height, Source.z); + Front = CamTargetEntity->GetPosition() - Source; Front.z += 1.1f; if(Mode == MODE_BEHINDBOAT) @@ -724,8 +689,21 @@ CCam::LookLeft(void) if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){ LookingLeft = true; RwCameraSetNearClipPlane(Scene.camera, 0.25f); - if(((CVehicle*)CamTargetEntity)->IsBoat()) - Source.z -= 0.5f; + if(((CVehicle*)CamTargetEntity)->IsBoat()){ + if(((CVehicle*)CamTargetEntity)->pDriver){ + CVector neck(0.0f, 0.0f, 0.0f); + CPed *driver = ((CVehicle*)CamTargetEntity)->pDriver; + driver->SetPedPositionInCar(); + driver->GetMatrix().UpdateRW(); + driver->UpdateRwFrame(); + driver->UpdateRpHAnim(); + driver->m_pedIK.GetComponentPosition(neck, PED_NECK); + Source = neck + + BOAT_1STPERSON_L_OFFSETX*CamTargetEntity->GetRight() + + BOAT_1STPERSON_LR_OFFSETZ*CamTargetEntity->GetUp(); + }else + Source.z -= 0.5f; + } Up = CamTargetEntity->GetUp(); Up.Normalise(); @@ -733,10 +711,8 @@ CCam::LookLeft(void) Front.Normalise(); Front = -CrossProduct(Front, Up); Front.Normalise(); -#ifdef FIX_BUGS - // not sure if this is a bug... - GetVectorsReadyForRW(); -#endif + if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) + Source -= 1.45f*Front; } } @@ -746,24 +722,36 @@ CCam::LookRight(void) float Dist, TargetOrientation; CVector TargetCoors, TargetFwd; CColPoint colPoint; - CEntity *entity; if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){ LookingRight = true; TargetCoors = CamTargetEntity->GetPosition(); Front = CamTargetEntity->GetPosition() - Source; - Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 9.0f; + if(Mode == MODE_CAM_ON_A_STRING) + Dist = CA_MAX_DISTANCE; + else if(Mode == MODE_BEHINDBOAT){ + Dist = 9.0f; + float Offset = 0.0f; + if(GetBoatLook_L_R_HeightOffset(Offset) && !CCullZones::Cam1stPersonForPlayer()) + Source.z = TargetCoors.z + Offset; + }else + Dist = 9.0f; TargetFwd = CamTargetEntity->GetForward(); TargetFwd.Normalise(); TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y); Source.x = Dist*Cos(TargetOrientation + HALFPI) + TargetCoors.x; Source.y = Dist*Sin(TargetOrientation + HALFPI) + TargetCoors.y; - Source.z -= 1.0f; - if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){ - RwCameraSetNearClipPlane(Scene.camera, 0.4f); - Source = colPoint.point; - } - Source.z += 1.0f; + + CColModel *colModel = CamTargetEntity->GetColModel(); + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); + + CVector TopLeft = CamTargetEntity->GetPosition() + + CamTargetEntity->GetRight()*colModel->boundingBox.min.x + + CamTargetEntity->GetUp()*colModel->boundingBox.max.z; + float Height = Min(Max(m_cvecTargetCoorsForFudgeInter.z, TopLeft.z)+0.1f, OrigSource.z); + Source.z = Max(Height, Source.z); + Front = CamTargetEntity->GetPosition() - Source; Front.z += 1.1f; if(Mode == MODE_BEHINDBOAT) @@ -773,8 +761,21 @@ CCam::LookRight(void) if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){ LookingRight = true; RwCameraSetNearClipPlane(Scene.camera, 0.25f); - if(((CVehicle*)CamTargetEntity)->IsBoat()) - Source.z -= 0.5f; + if(((CVehicle*)CamTargetEntity)->IsBoat()){ + if(((CVehicle*)CamTargetEntity)->pDriver){ + CVector neck(0.0f, 0.0f, 0.0f); + CPed *driver = ((CVehicle*)CamTargetEntity)->pDriver; + driver->SetPedPositionInCar(); + driver->GetMatrix().UpdateRW(); + driver->UpdateRwFrame(); + driver->UpdateRpHAnim(); + driver->m_pedIK.GetComponentPosition(neck, PED_NECK); + Source = neck + + BOAT_1STPERSON_R_OFFSETX*CamTargetEntity->GetRight() + + BOAT_1STPERSON_LR_OFFSETZ*CamTargetEntity->GetUp(); + }else + Source.z -= 0.5f; + } Up = CamTargetEntity->GetUp(); Up.Normalise(); @@ -782,10 +783,8 @@ CCam::LookRight(void) Front.Normalise(); Front = CrossProduct(Front, Up); Front.Normalise(); -#ifdef FIX_BUGS - // not sure if this is a bug... - GetVectorsReadyForRW(); -#endif + if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) + Source -= 1.45f*Front; } } @@ -861,11 +860,7 @@ CCam::KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CV bool CCam::Using3rdPersonMouseCam(void) { - return CCamera::m_bUseMouse3rdPerson && - (Mode == MODE_FOLLOWPED || - TheCamera.m_bPlayerIsInGarage && - FindPlayerPed() && FindPlayerPed()->m_nPedState != PED_DRIVING && - Mode != MODE_TOPDOWN && CamTargetEntity == FindPlayerPed()); + return CCamera::m_bUseMouse3rdPerson && Mode == MODE_FOLLOWPED; } bool @@ -877,16 +872,22 @@ CCam::GetWeaponFirstPersonOn(void) bool CCam::IsTargetInWater(const CVector &CamCoors) { - if(CamTargetEntity == nil) - return false; - if(CamTargetEntity->IsPed()){ - if(!((CPed*)CamTargetEntity)->bIsInWater) - return false; - if(!((CPed*)CamTargetEntity)->bIsStanding) - return true; - return false; + if(CamTargetEntity){ + float WaterZ = -6000.0f; + CWaterLevel::GetWaterLevel(CamTargetEntity->GetPosition(), &WaterZ, false); + if(CamTargetEntity->IsPed()){ + if(((CPed*)CamTargetEntity)->bIsDrowning || + ((CPed*)CamTargetEntity)->bIsInWater && CamTargetEntity->GetPosition().z < WaterZ) + return true; + }else{ + assert(CamTargetEntity->IsVehicle()); + if(((CVehicle*)CamTargetEntity)->bIsDrowning || + ((CVehicle*)CamTargetEntity)->bIsInWater && CamTargetEntity->GetPosition().z < WaterZ) + return true; + } } - return ((CPhysical*)CamTargetEntity)->bIsInWater; + m_vecLastAboveWaterCamPosition = Source; + return false; } void @@ -910,10 +911,10 @@ CCam::PrintMode(void) "Blood on the tracks", "Passenger", "Syphon Crim in Front", "Dead Baby", "Pillow Paps", "Look at Cars", "Arrest One", "Arrest Two", "M16", "Special fixed for Syphon", "Fight", - "Top Down Ped", + "Top Down Ped", "Lighthouse", "Sniper run about", "Rocket run about", "1st Person run about", "M16 run about", "Fight run about", - "Editor" + "Editor", "Helicannon", "Camera" }; sprintf(buf, "Cam: %s", modes[TheCamera.Cams[TheCamera.ActiveCam].Mode]); CDebug::PrintAt(buf, 2, 5); @@ -946,7 +947,7 @@ CVector CCam::DoAverageOnVector(const CVector &vec) { int i; - CVector Average(0.0f, 0.0f, 0.0f); + CVector Average = CVector(0.0f, 0.0f, 0.0f); if(ResetStatics){ m_iRunningVectorArrayPos = 0; @@ -974,41 +975,16 @@ CCam::DoAverageOnVector(const CVector &vec) return Average; } -// Rotate Beta in direction opposite of BetaOffset in 5 deg. steps. -// Return the first angle for which Beta + BetaOffset + Angle has a clear view. -// i.e. BetaOffset is a safe zone so that Beta + Angle is really clear. -// If BetaOffset == 0, try both directions. -float -CCam::GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies) -{ - CColPoint point; - CEntity *ent = nil; - CVector ToSource; - float a; - - // This would be so much nicer if we just got the step variable before the loop...R* - - for(a = 0.0f; a <= PI; a += DEGTORAD(5.0f)){ - if(BetaOffset <= 0.0f){ - ToSource = CVector(Cos(Beta + BetaOffset + a), Sin(Beta + BetaOffset + a), 0.0f)*Dist; - if(!CWorld::ProcessLineOfSight(Target, Target + ToSource, - point, ent, checkBuildings, checkVehicles, checkPeds, - checkObjects, checkDummies, true, true)) - return a; - } - if(BetaOffset >= 0.0f){ - ToSource = CVector(Cos(Beta + BetaOffset - a), Sin(Beta + BetaOffset - a), 0.0f)*Dist; - if(!CWorld::ProcessLineOfSight(Target, Target + ToSource, - point, ent, checkBuildings, checkVehicles, checkPeds, - checkObjects, checkDummies, true, true)) - return -a; - } - } - return 0.0f; -} - float DefaultAcceleration = 0.045f; float DefaultMaxStep = 0.15f; +float fDefaultSpeedStep = 0.025f; +float fDefaultSpeedMultiplier = 0.09f; +float fDefaultSpeedLimit = 0.15f; +float fDefaultSpeedStep4Avoid = 0.02f; +float fDefaultSpeedMultiplier4Avoid = 0.05f; +float fDefaultSpeedLimit4Avoid = 0.25f; +float fAvoidGeomThreshhold = 1.5f; +float fMiniGunBetaOffset = 0.3f; void CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float) @@ -1016,85 +992,72 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl if(!CamTargetEntity->IsPed()) return; - const float GroundDist = 1.85f; - CVector TargetCoors, Dist, IdealSource; float Length = 0.0f; - float LateralLeft = 0.0f; - float LateralRight = 0.0f; - float Center = 0.0f; - static bool PreviouslyObscured; static bool PickedASide; static float FixedTargetOrientation = 0.0f; float AngleToGoTo = 0.0f; - float BetaOffsetAvoidBuildings = 0.45f; // ~25 deg - float BetaOffsetGoingBehind = 0.45f; - bool GoingBehind = false; - bool Obscured = false; - bool BuildingCheckObscured = false; bool StandingInTrain = false; + float ZoomGroundTarget = 0.0f; + float ZoomZTarget = 0.0f; static int TimeIndicatedWantedToGoDown = 0; static bool StartedCountingForGoDown = false; + static float ZoomGround = 0.0f; + static float ZoomGroundSpeed = 0.0f; + static float ZoomZ = 0.0f; + static float ZoomZSpeed = 0.0f; float DeltaBeta; m_bFixingBeta = false; bBelowMinDist = false; bBehindPlayerDesired = false; - // CenterDist should be > LateralDist because we don't have an angle for safety in this case - float CenterDist, LateralDist; - float AngleToGoToSpeed; - if(m_fCloseInPedHeightOffset > 0.00001f){ - LateralDist = 0.55f; - CenterDist = 1.25f; - BetaOffsetAvoidBuildings = 0.9f; // ~50 deg - BetaOffsetGoingBehind = 0.9f; - AngleToGoToSpeed = 0.88254666f; - }else{ - LateralDist = 0.8f; - CenterDist = 1.35f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 || TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN){ - LateralDist = 1.25f; - CenterDist = 1.6f; - } - AngleToGoToSpeed = 0.43254671f; - } - FOV = DefaultFOV; if(ResetStatics){ Rotating = false; m_bCollisionChecksOn = true; FixedTargetOrientation = 0.0f; - PreviouslyObscured = false; PickedASide = false; StartedCountingForGoDown = false; AngleToGoTo = 0.0f; - // unused LastAngleWithNoPickedASide + ZoomGround = 0.0f; + ZoomGroundSpeed = 0.0f; + ZoomZ = 0.0f; + ZoomZSpeed = 0.0f; + Distance = 500.0f; } TargetCoors = CameraTarget; + + // Take speed of thing we're standing on into account + CVector GroundMovement(0.0f, 0.0f, 0.0f); + CPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface; + if(ground && (ground->IsVehicle() || ground->IsObject())) + GroundMovement += ground->GetSpeed(CamTargetEntity->GetPosition() - ground->GetPosition()) * CTimer::GetTimeStep(); + + Source += GroundMovement; IdealSource = Source; TargetCoors.z += m_fSyphonModeTargetZOffSet; - TargetCoors = DoAverageOnVector(TargetCoors); - TargetCoors.z += m_fRoadOffSet; + TargetCoors.z = DoAverageOnVector(TargetCoors).z; Dist.x = IdealSource.x - TargetCoors.x; Dist.y = IdealSource.y - TargetCoors.y; Length = Dist.Magnitude2D(); // Cam on a string. With a fixed distance. Zoom in/out is done later. - if(Length != 0.0f) - IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * GroundDist; - else + if(Length != 0.0f){ + IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * m_fMinRealGroundDist; + IdealSource.z += GroundMovement.z; + }else IdealSource = TargetCoors + CVector(1.0f, 1.0f, 0.0f); if(TheCamera.m_bUseTransitionBeta && ResetStatics){ CVector VecDistance; - IdealSource.x = TargetCoors.x + GroundDist*Cos(m_fTransitionBeta); - IdealSource.y = TargetCoors.y + GroundDist*Sin(m_fTransitionBeta); + IdealSource.x = TargetCoors.x + m_fMinRealGroundDist*Cos(m_fTransitionBeta); + IdealSource.y = TargetCoors.y + m_fMinRealGroundDist*Sin(m_fTransitionBeta); Beta = CGeneral::GetATanOfXY(IdealSource.x - TargetCoors.x, IdealSource.y - TargetCoors.y); }else Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y); @@ -1116,24 +1079,30 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl while(Beta >= PI) Beta -= 2.0f * PI; while(Beta < -PI) Beta += 2.0f * PI; - // BUG? is this ever used? - // The values seem to be roughly m_fPedZoomValueSmooth + 1.85 + if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 && + ((CPed*)CamTargetEntity)->GetPedState() != PED_ENTER_CAR && + ((CPed*)CamTargetEntity)->GetPedState() != PED_CARJACK){ + ZoomGroundTarget = m_fTargetZoomGroundOne; + ZoomZTarget = m_fTargetZoomOneZExtra; + }else if(TheCamera.PedZoomIndicator == CAM_ZOOM_2 || TheCamera.PedZoomIndicator == CAM_ZOOM_1){ + ZoomGroundTarget = m_fTargetZoomGroundTwo; + ZoomZTarget = m_fTargetZoomTwoZExtra; + }else if(TheCamera.PedZoomIndicator == CAM_ZOOM_3){ + ZoomGroundTarget = m_fTargetZoomGroundThree; + ZoomZTarget = m_fTargetZoomThreeZExtra; + } + if(m_fCloseInPedHeightOffset > 0.00001f){ + ZoomGroundTarget = m_fTargetCloseInDist; + ZoomZTarget = m_fTargetZoomZCloseIn; + } if(ResetStatics){ - if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) m_fRealGroundDist = 2.090556f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) m_fRealGroundDist = 3.34973f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) m_fRealGroundDist = 4.704914f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN) m_fRealGroundDist = 2.090556f; + ZoomGround = ZoomGroundTarget; + ZoomZ = ZoomZTarget; } - // And what is this? It's only used for collision and rotation it seems - float RealGroundDist; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) RealGroundDist = 2.090556f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) RealGroundDist = 3.34973f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) RealGroundDist = 4.704914f; - if(TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN) RealGroundDist = 2.090556f; - if(m_fCloseInPedHeightOffset > 0.00001f) - RealGroundDist = 1.7016f; - + float SpeedStep = fDefaultSpeedStep; + float SpeedMultiplier = fDefaultSpeedMultiplier; + float SpeedLimit = fDefaultSpeedLimit; bool Shooting = false; CPed *ped = (CPed*)CamTargetEntity; if(ped->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) @@ -1144,166 +1113,52 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl Shooting = false; - if(m_fCloseInPedHeightOffset > 0.00001f) - TargetCoors.z -= m_fRoadOffSet; - // Figure out if and where we want to rotate - if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){ + if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup || Shooting){ // Center cam behind player - GoingBehind = true; - m_bCollisionChecksOn = true; - float OriginalBeta = Beta; - // Set Beta behind player - Beta = TargetOrientation + PI; - TargetCoors.z -= 0.1f; - - AngleToGoTo = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false); - if(AngleToGoTo != 0.0f){ - if(AngleToGoTo < 0.0f) - AngleToGoTo -= AngleToGoToSpeed; - else - AngleToGoTo += AngleToGoToSpeed; - }else{ - float LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetGoingBehind, true, false, false, true, false); - float LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetGoingBehind, true, false, false, true, false); - if(LateralLeft == 0.0f && LateralRight != 0.0f) - AngleToGoTo += LateralRight; - else if(LateralLeft != 0.0f && LateralRight == 0.0f) - AngleToGoTo += LateralLeft; - } - - TargetCoors.z += 0.1f; - Beta = OriginalBeta; - if(PickedASide){ - if(AngleToGoTo == 0.0f) + if(AngleToGoTo == 0.0f){ FixedTargetOrientation = TargetOrientation + PI; + if(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) + FixedTargetOrientation -= fMiniGunBetaOffset; + } Rotating = true; }else{ - FixedTargetOrientation = TargetOrientation + PI + AngleToGoTo; + FixedTargetOrientation = TargetOrientation + PI; Rotating = true; PickedASide = true; + if(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) + FixedTargetOrientation -= fMiniGunBetaOffset; } - }else{ - - // Rotate cam to avoid clipping into buildings + }else if(Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold && !Rotating ){ - TargetCoors.z -= 0.1f; - - Center = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false); - if(m_bCollisionChecksOn || PreviouslyObscured || Center != 0.0f || m_fCloseInPedHeightOffset > 0.00001f){ - if(Center != 0.0f){ - AngleToGoTo = Center; - }else{ - LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetAvoidBuildings, true, false, false, true, false); - LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetAvoidBuildings, true, false, false, true, false); - if(LateralLeft == 0.0f && LateralRight != 0.0f){ - AngleToGoTo += LateralRight; - if(m_fCloseInPedHeightOffset > 0.0f) - RwCameraSetNearClipPlane(Scene.camera, 0.7f); - }else if(LateralLeft != 0.0f && LateralRight == 0.0f){ - AngleToGoTo += LateralLeft; - if(m_fCloseInPedHeightOffset > 0.0f) - RwCameraSetNearClipPlane(Scene.camera, 0.7f); - } - } - if(LateralLeft != 0.0f || LateralRight != 0.0f || Center != 0.0f) - BuildingCheckObscured = true; - } - - TargetCoors.z += 0.1f; - } - - if(m_fCloseInPedHeightOffset > 0.00001f) - TargetCoors.z += m_fRoadOffSet; - - - // Have to fix to avoid collision - - if(AngleToGoTo != 0.0f){ - Obscured = true; - Rotating = true; - if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){ - if(!PickedASide) - FixedTargetOrientation = Beta + AngleToGoTo; // can this even happen? - }else - FixedTargetOrientation = Beta + AngleToGoTo; - - // This calculation is only really used to figure out how fast to rotate out of collision - - m_fAmountFractionObscured = 1.0f; - CVector PlayerPos = FindPlayerPed()->GetPosition(); - float RotationDist = (AngleToGoTo == Center ? CenterDist : LateralDist) * RealGroundDist; - // What's going on here? - AngleToGoTo? - CVector RotatedSource = PlayerPos + CVector(Cos(Beta - AngleToGoTo), Sin(Beta - AngleToGoTo), 0.0f) * RotationDist; - - CColPoint colpoint; - CEntity *entity; - if(CWorld::ProcessLineOfSight(PlayerPos, RotatedSource, colpoint, entity, true, false, false, true, false, false, false)){ - if((PlayerPos - RotatedSource).Magnitude() != 0.0f) - m_fAmountFractionObscured = (PlayerPos - colpoint.point).Magnitude() / (PlayerPos - RotatedSource).Magnitude(); - else - m_fAmountFractionObscured = 1.0f; - } - } - if(m_fAmountFractionObscured < 0.0f) m_fAmountFractionObscured = 0.0f; - if(m_fAmountFractionObscured > 1.0f) m_fAmountFractionObscured = 1.0f; - - - - // Figure out speed values for Beta rotation - - float Acceleration, MaxSpeed; - static float AccelerationMult = 0.35f; - static float MaxSpeedMult = 0.85f; - static float AccelerationMultClose = 0.7f; - static float MaxSpeedMultClose = 1.6f; - float BaseAcceleration = 0.025f; - float BaseMaxSpeed = 0.09f; - if(m_fCloseInPedHeightOffset > 0.00001f){ - if(AngleToGoTo == 0.0f){ - BaseAcceleration = 0.022f; - BaseMaxSpeed = 0.04f; - }else{ - BaseAcceleration = DefaultAcceleration; - BaseMaxSpeed = DefaultMaxStep; - } - } - if(AngleToGoTo == 0.0f){ - Acceleration = BaseAcceleration; - MaxSpeed = BaseMaxSpeed; - }else if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !Shooting){ - Acceleration = 0.051f; - MaxSpeed = 0.18f; - }else if(m_fCloseInPedHeightOffset > 0.00001f){ - Acceleration = BaseAcceleration + AccelerationMultClose*sq(m_fAmountFractionObscured - 1.05f); - MaxSpeed = BaseMaxSpeed + MaxSpeedMultClose*sq(m_fAmountFractionObscured - 1.05f); - }else{ - Acceleration = DefaultAcceleration + AccelerationMult*sq(m_fAmountFractionObscured - 1.05f); - MaxSpeed = DefaultMaxStep + MaxSpeedMult*sq(m_fAmountFractionObscured - 1.05f); + if(TheCamera.m_fAvoidTheGeometryProbsTimer < 0.0f) + FixedTargetOrientation = TargetOrientation; + else + FixedTargetOrientation = TargetOrientation + PI; + float dist = (Source - TargetCoors).Magnitude(); + float mult = dist > 0.1f ? 1.0f/dist : 10.0f; + SpeedStep = mult * fDefaultSpeedStep4Avoid; + SpeedMultiplier = mult * fDefaultSpeedMultiplier4Avoid; + SpeedLimit = mult * fDefaultSpeedLimit4Avoid; } - static float AccelerationLimit = 0.3f; - static float MaxSpeedLimit = 0.65f; - if(Acceleration > AccelerationLimit) Acceleration = AccelerationLimit; - if(MaxSpeed > MaxSpeedLimit) MaxSpeed = MaxSpeedLimit; - int MoveState = ((CPed*)CamTargetEntity)->m_nMoveState; if(MoveState != PEDMOVE_NONE && MoveState != PEDMOVE_STILL && - !CPad::GetPad(0)->ForceCameraBehindPlayer() && !Obscured && !Shooting){ + !(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup) && !Shooting){ Rotating = false; - BetaSpeed = 0.0f; + if(TheCamera.m_fAvoidTheGeometryProbsTimer <= fAvoidGeomThreshhold) + BetaSpeed = 0.0f; } // Now do the Beta rotation - float RotDistance = (IdealSource - TargetCoors).Magnitude2D(); - m_fDistanceBeforeChanges = RotDistance; + float RotDistance = m_fMinRealGroundDist; - if(Rotating){ + if(Rotating || TheCamera.m_fAvoidTheGeometryProbsTimer > fAvoidGeomThreshhold){ m_bFixingBeta = true; while(FixedTargetOrientation >= PI) FixedTargetOrientation -= 2*PI; @@ -1313,13 +1168,23 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl while(Beta < -PI) Beta += 2*PI; -/* - // This is inlined WellBufferMe + // This is inlined WellBufferMe - unfortunately modified so we can't just call it + { DeltaBeta = FixedTargetOrientation - Beta; while(DeltaBeta >= PI) DeltaBeta -= 2*PI; while(DeltaBeta < -PI) DeltaBeta += 2*PI; - float ReqSpeed = DeltaBeta * MaxSpeed; + // this is the added bit + if(!Rotating){ + if(TheCamera.m_nAvoidTheGeometryProbsDirn == -1 && DeltaBeta > 0.0f || + TheCamera.m_nAvoidTheGeometryProbsDirn == 1 && DeltaBeta < 0.0f) + DeltaBeta *= -1.0f; + } + + float ReqSpeed = DeltaBeta * SpeedMultiplier; + // this is also added + ReqSpeed = Clamp(ReqSpeed, -SpeedLimit, SpeedLimit); + // Add or subtract absolute depending on sign, genius! if(ReqSpeed - BetaSpeed > 0.0f) BetaSpeed += SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep(); @@ -1334,8 +1199,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl BetaSpeed = ReqSpeed; Beta += BetaSpeed * Min(10.0f, CTimer::GetTimeStep()); -*/ - WellBufferMe(FixedTargetOrientation, &Beta, &BetaSpeed, MaxSpeed, Acceleration, true); + } if(ResetStatics){ Beta = FixedTargetOrientation; @@ -1359,7 +1223,14 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront || - StandingInTrain || Rotating){ + StandingInTrain || Rotating || + TheCamera.m_bUseTransitionBeta && ResetStatics || + Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold){ + if(TheCamera.m_bUseTransitionBeta){ + Beta = m_fTransitionBeta; + Source.x = TargetCoors.x + RotDistance * Cos(m_fTransitionBeta); + Source.y = TargetCoors.y + RotDistance * Sin(m_fTransitionBeta); + } if(TheCamera.m_bCamDirectlyBehind){ Beta = TargetOrientation + PI; Source.x = TargetCoors.x + RotDistance * Cos(Beta); @@ -1378,59 +1249,42 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl m_fCamBufferedHeight = 0.0f; m_fCamBufferedHeightSpeed = 0.0f; } + if(StandingInTrain){ + Beta = TargetOrientation + PI; + Source.x = TargetCoors.x + RotDistance * Cos(Beta); + Source.y = TargetCoors.y + RotDistance * Sin(Beta); + m_fDimensionOfHighestNearCar = 0.0f; + m_fCamBufferedHeight = 0.0f; + m_fCamBufferedHeightSpeed = 0.0f; + } + // Beta and Source already set in the rotation code }else{ Source = IdealSource; BetaSpeed = 0.0f; } + Source.z = IdealSource.z; - // Subtract m_fRoadOffSet from both? - TargetCoors.z -= m_fRoadOffSet; - Source.z = IdealSource.z - m_fRoadOffSet; - - // Apply zoom now - // m_fPedZoomValueSmooth makes the cam go down the further out it is - // 0.25 -> 0.20 for nearest dist - // 1.50 -> -0.05 for mid dist - // 2.90 -> -0.33 for far dist - Source.z += (2.5f - TheCamera.m_fPedZoomValueSmooth)*0.2f - 0.25f; // Zoom out camera Front = TargetCoors - Source; Front.Normalise(); - Source -= Front * TheCamera.m_fPedZoomValueSmooth; - // and then we move up again - // -0.375 - // 0.25 - // 0.95 - Source.z += (TheCamera.m_fPedZoomValueSmooth - 1.0f)*0.5f + m_fCloseInPedHeightOffset; + WellBufferMe(ZoomGroundTarget, &ZoomGround, &ZoomGroundSpeed, 0.2f, 0.07f, false); + WellBufferMe(ZoomZTarget, &ZoomZ, &ZoomZSpeed, 0.2f, 0.07f, false); + Source.x -= Front.x*ZoomGround; + Source.y -= Front.y*ZoomGround; + Source.z += ZoomZ; // Process height offset to avoid peds and cars - float TargetZOffSet = m_fRoadOffSet + m_fDimensionOfHighestNearCar; - TargetZOffSet = Max(TargetZOffSet, m_fPedBetweenCameraHeightOffset); + float TargetZOffSet = Max(m_fDimensionOfHighestNearCar, m_fPedBetweenCameraHeightOffset); float TargetHeight = CameraTarget.z + TargetZOffSet - Source.z; if(TargetHeight > m_fCamBufferedHeight){ // Have to go up if(TargetZOffSet == m_fPedBetweenCameraHeightOffset && TargetZOffSet > m_fCamBufferedHeight) WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.04f, false); - else if(TargetZOffSet == m_fRoadOffSet && TargetZOffSet > m_fCamBufferedHeight){ - // TODO: figure this out - bool foo = false; - switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched) - case SURFACE_GRASS: - case SURFACE_GRAVEL: - case SURFACE_PAVEMENT: - case SURFACE_THICK_METAL_PLATE: - case SURFACE_RUBBER: - case SURFACE_STEEP_CLIFF: - foo = true; - if(foo) - WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.4f, 0.05f, false); - else - WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false); - }else + else WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false); StartedCountingForGoDown = false; }else{ @@ -1449,24 +1303,24 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl } Source.z += m_fCamBufferedHeight; - - - // Clip Source if necessary - - bool ClipSource = m_fCloseInPedHeightOffset > 0.00001f && m_fCamBufferedHeight > 0.001f; - if(GoingBehind || ResetStatics || ClipSource){ - CColPoint colpoint; - CEntity *entity; - if(CWorld::ProcessLineOfSight(TargetCoors, Source, colpoint, entity, true, false, false, true, false, true, true)){ - Source = colpoint.point; - if((TargetCoors - Source).Magnitude2D() < 1.0f) - RwCameraSetNearClipPlane(Scene.camera, 0.05f); - } - } - TargetCoors.z += Min(1.0f, m_fCamBufferedHeight/2.0f); m_cvecTargetCoorsForFudgeInter = TargetCoors; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); + float TargetDist = (TargetCoors - Source).Magnitude(); + if(TargetDist < Distance) + Distance = TargetDist; + else{ + float f = Pow(0.97f, CTimer::GetTimeStep()); + Distance = (1.0f - f)*TargetDist + f*Distance; + if(TargetDist > 0.05f) + Source = TargetCoors + (Source-TargetCoors)*Distance/TargetDist; + float clip = Distance-fRangePlayerRadius; + if(clip < RwCameraGetNearClipPlane(Scene.camera)) + RwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit)); + } + Front = TargetCoors - Source; m_fRealGroundDist = Front.Magnitude2D(); m_fMinDistAwayFromCamWhenInterPolating = m_fRealGroundDist; @@ -1474,7 +1328,6 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl GetVectorsReadyForRW(); TheCamera.m_bCamDirectlyBehind = false; TheCamera.m_bCamDirectlyInFront = false; - PreviouslyObscured = BuildingCheckObscured; ResetStatics = false; } @@ -1483,10 +1336,11 @@ float fBaseDist = 1.7f; float fAngleDist = 2.0f; float fFalloff = 3.0f; float fStickSens = 0.01f; -float fTweakFOV = 1.05f; +float fTweakFOV = 1.1f; float fTranslateCamUp = 0.8f; int16 nFadeControlThreshhold = 45; float fDefaultAlphaOrient = -0.22f; +float fMouseAvoidGeomReturnRate = 0.92f; void CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float) @@ -1510,30 +1364,45 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient bool OnTrain = FindPlayerVehicle() && FindPlayerVehicle()->IsTrain(); - // Look around - bool UseMouse = false; - float MouseX = CPad::GetPad(0)->GetMouseX(); - float MouseY = CPad::GetPad(0)->GetMouseY(); - float LookLeftRight, LookUpDown; - if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){ - UseMouse = true; - LookLeftRight = -2.5f*MouseX; - LookUpDown = 4.0f*MouseY; - }else{ - LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight(); - LookUpDown = CPad::GetPad(0)->LookAroundUpDown(); - } + TargetCoors = CameraTarget; + TargetCoors.z += fTranslateCamUp; + float AlphaOffset, BetaOffset; - if(UseMouse){ - BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f; - AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f; + if(CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_PLAYERINFO)){ + CVector ToCam = Source - TargetCoors; + ToCam.Normalise(); + if(ToCam.z < -0.9f) + BetaOffset = TargetOrientation + PI; + else + BetaOffset = Atan2(ToCam.y, ToCam.x); + BetaOffset -= Beta; + AlphaOffset = 0.0f; }else{ - BetaOffset = LookLeftRight * fStickSens * (1.0f/14.0f) * FOV/80.0f * CTimer::GetTimeStep(); - AlphaOffset = LookUpDown * fStickSens * (0.6f/14.0f) * FOV/80.0f * CTimer::GetTimeStep(); + // Look around + bool UseMouse = false; + float MouseX = CPad::GetPad(0)->GetMouseX(); + float MouseY = CPad::GetPad(0)->GetMouseY(); + float LookLeftRight, LookUpDown; + if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){ + UseMouse = true; + LookLeftRight = -2.5f*MouseX; + LookUpDown = 4.0f*MouseY; + }else{ + LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight(); + LookUpDown = CPad::GetPad(0)->LookAroundUpDown(); + } + if(UseMouse){ + BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f; + AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f; + }else{ + BetaOffset = LookLeftRight * fStickSens * (1.0f/14.0f) * FOV/80.0f * CTimer::GetTimeStep(); + AlphaOffset = LookUpDown * fStickSens * (0.6f/14.0f) * FOV/80.0f * CTimer::GetTimeStep(); + } } if(TheCamera.GetFading() && TheCamera.GetFadingDirection() == FADE_IN && nFadeControlThreshhold < CDraw::FadeValue || - CDraw::FadeValue > 200){ + CDraw::FadeValue > 200 || + CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_PLAYERINFO)){ if(Alpha < fDefaultAlphaOrient-0.05f) AlphaOffset = 0.05f; else if(Alpha < fDefaultAlphaOrient) @@ -1553,10 +1422,6 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient if(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f); else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); - TargetCoors = CameraTarget; - TargetCoors.z += fTranslateCamUp; - TargetCoors = DoAverageOnVector(TargetCoors); - // SA code #ifdef FREE_CAM if((CCamera::bFreeCam && Alpha > 0.0f) || (!CCamera::bFreeCam && Alpha > fBaseDist)) @@ -1568,17 +1433,17 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient CamDist = fBaseDist + Cos(Alpha)*fAngleDist; if(TheCamera.m_bUseTransitionBeta) - Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta)); + Beta = m_fTransitionBeta; if(TheCamera.m_bCamDirectlyBehind) - Beta = TheCamera.m_PedOrientForBehindOrInFront; - if(TheCamera.m_bCamDirectlyInFront) Beta = TheCamera.m_PedOrientForBehindOrInFront + PI; + if(TheCamera.m_bCamDirectlyInFront) + Beta = TheCamera.m_PedOrientForBehindOrInFront; if(OnTrain) Beta = TargetOrientation; - Front.x = Cos(Alpha) * Cos(Beta); - Front.y = Cos(Alpha) * Sin(Beta); + Front.x = Cos(Alpha) * -Cos(Beta); + Front.y = Cos(Alpha) * -Sin(Beta); Front.z = Sin(Alpha); Source = TargetCoors - Front*CamDist; m_cvecTargetCoorsForFudgeInter = TargetCoors; @@ -1608,7 +1473,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient CWorld::pIgnoreEntity = nil; float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); - float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV; + float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV; float Near = RwCameraGetNearClipPlane(Scene.camera); float radius = ViewPlaneWidth*Near; entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false); @@ -1629,8 +1494,8 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient Near = RwCameraGetNearClipPlane(Scene.camera); #ifndef FIX_BUGS - // this is totally wrong... - radius = Tan(FOV / 2.0f) * Near; + // this is wrong...DEGTORAD missing + radius = Tan(FOV / 2.0f) * CDraw::CalculateAspectRatio() * fTweakFOV * Near; #else radius = ViewPlaneWidth*Near; #endif @@ -1642,18 +1507,17 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient entity = nil; } - if(CamTargetEntity->m_rwObject){ - // what's going on here? - if(RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_STD_WEAPON_PUMP) || - RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_STD_WEAPON_THROW) || - RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_STD_THROW_UNDER) || - RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_STD_START_THROW)){ - CPed *player = FindPlayerPed(); - float PlayerDist = (Source - player->GetPosition()).Magnitude(); - if(PlayerDist < 2.75f) - Near = PlayerDist/2.75f * DEFAULT_NEAR - 0.3f; - RwCameraSetNearClipPlane(Scene.camera, Max(Near, 0.1f)); - } + float TargetDist = (TargetCoors - Source).Magnitude(); + if(TargetDist < Distance) + Distance = TargetDist; + else{ + float f = Pow(fMouseAvoidGeomReturnRate, CTimer::GetTimeStep()); + Distance = (1.0f - f)*TargetDist + f*Distance; + if(TargetDist > 0.05f) + Source = TargetCoors + (Source-TargetCoors)*Distance/TargetDist; + float clip = Distance-fRangePlayerRadius; + if(clip < RwCameraGetNearClipPlane(Scene.camera)) + RwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit)); } TheCamera.m_bCamDirectlyInFront = false; @@ -1662,7 +1526,8 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient GetVectorsReadyForRW(); if(((CPed*)CamTargetEntity)->CanStrafeOrMouseControl() && CDraw::FadeValue < 250 && - (TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100)){ + (TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100) && + !CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_PLAYERINFO)){ float Heading = Front.Heading(); ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading; ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading; @@ -1692,7 +1557,7 @@ CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, fl if(Length < 0.002f) Length = 0.002f; Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y); -#if 1 +#ifdef TOGGLEABLE_BETA_FEATURES // This is completely made up but Bill's cam manipulates an angle before calling this // and otherwise calculating Beta doesn't make much sense. Beta += fBillsBetaOffset; @@ -1710,303 +1575,171 @@ CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, fl } TargetCoors.z += 0.8f; - WorkOutCamHeightWeeCar(TargetCoors, TargetOrientation); + Alpha = DEGTORAD(25.0f); + Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha); + RotCamIfInFrontCar(TargetCoors, TargetOrientation); - FixCamIfObscured(TargetCoors, 1.2f, TargetOrientation); + m_cvecTargetCoorsForFudgeInter = TargetCoors; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV); Front = TargetCoors - Source; - m_cvecTargetCoorsForFudgeInter = TargetCoors; ResetStatics = false; GetVectorsReadyForRW(); } -void -CCam::WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation) -{ - CColPoint colpoint; - CEntity *ent; - float TargetZOffSet = 0.0f; - static bool PreviouslyFailedRoadHeightCheck = false; - static float RoadHeightFix = 0.0f; - static float RoadHeightFixSpeed = 0.0f; - - if(ResetStatics){ - RoadHeightFix = 0.0f; - RoadHeightFixSpeed = 0.0f; - Alpha = DEGTORAD(25.0f); - AlphaSpeed = 0.0f; - } - float AlphaTarget = DEGTORAD(25.0f); - if(CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) - AlphaTarget = DEGTORAD(14.0f); - WellBufferMe(AlphaTarget, &Alpha, &AlphaSpeed, 0.1f, 0.05f, true); - Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha); - - if(FindPlayerVehicle()){ - m_fRoadOffSet = 0.0f; - bool FoundRoad = false; - bool FoundRoof = false; - float RoadZ = 0.0f; - float RoofZ = 0.0f; - - if(CWorld::ProcessVerticalLine(Source, -1000.0f, colpoint, ent, true, false, false, false, false, false, nil) && - ent->IsBuilding()){ - FoundRoad = true; - RoadZ = colpoint.point.z; - } - - if(FoundRoad){ - if(Source.z - RoadZ < 0.9f){ - PreviouslyFailedRoadHeightCheck = true; - TargetZOffSet = RoadZ + 0.9f - Source.z; - }else{ - if(m_bCollisionChecksOn) - PreviouslyFailedRoadHeightCheck = false; - else - TargetZOffSet = 0.0f; - } - }else{ - if(CWorld::ProcessVerticalLine(Source, 1000.0f, colpoint, ent, true, false, false, false, false, false, nil) && - ent->IsBuilding()){ - FoundRoof = true; - RoofZ = colpoint.point.z; - } - if(FoundRoof){ - if(Source.z - RoofZ < 0.9f){ - PreviouslyFailedRoadHeightCheck = true; - TargetZOffSet = RoofZ + 0.9f - Source.z; - }else{ - if(m_bCollisionChecksOn) - PreviouslyFailedRoadHeightCheck = false; - else - TargetZOffSet = 0.0f; - } - } - } - } - - if(TargetZOffSet > RoadHeightFix) - RoadHeightFix = TargetZOffSet; - else - WellBufferMe(TargetZOffSet, &RoadHeightFix, &RoadHeightFixSpeed, 0.27f, 0.1f, false); - - if(colpoint.surfaceB != SURFACE_TARMAC && - colpoint.surfaceB != SURFACE_GRASS && - colpoint.surfaceB != SURFACE_GRAVEL && - colpoint.surfaceB != SURFACE_MUD_DRY && - colpoint.surfaceB != SURFACE_PAVEMENT && - colpoint.surfaceB != SURFACE_THICK_METAL_PLATE && - colpoint.surfaceB != SURFACE_STEEP_CLIFF && - RoadHeightFix > 1.4f) - RoadHeightFix = 1.4f; - - Source.z += RoadHeightFix; -} +float ZmOneAlphaOffset[] = { -0.01f, 0.1f, 0.125f, -0.1f, -0.06f }; +float ZmTwoAlphaOffset[] = { 0.045f, 0.12f, 0.045f, 0.045f, -0.035f }; +float ZmThreeAlphaOffset[] = { 0.005f, 0.005f, 0.15f, 0.005f, 0.12f }; +float INIT_RC_HELI_HORI_EXTRA = 6.0f; +float INIT_RC_PLANE_HORI_EXTRA = 9.5f; +float INIT_RC_HELI_ALPHA_EXTRA = 0.2f; +float INIT_RC_PLANE_ALPHA_EXTRA = 0.295f; void CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight) { - float AlphaOffset = 0.0f; - bool CamClear = true; + if(!CamTargetEntity->IsVehicle()) + return; - static float LastTargetAlphaWithCollisionOn = 0.0f; - static float LastTopAlphaSpeed = 0.0f; - static float LastAlphaSpeedStep = 0.0f; - static bool PreviousNearCheckNearClipSmall = false; + static float AlphaOffset = 0.0; + static float AlphaOffsetSpeed = 0.0; + static float AlphaDec = 0.0f; + + bool isHeli = false; + bool isBike = false; + int appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance(); + if(appearance == VEHICLE_APPEARANCE_BIKE) + isBike = true; + if(appearance == VEHICLE_APPEARANCE_HELI) + isHeli = true; + int index = 0; + TheCamera.GetArrPosForVehicleType(appearance, index); + + float ExtraOffset = 0.0f; + int id = CamTargetEntity->GetModelIndex(); + if(id == MI_RCRAIDER || id == MI_RCGOBLIN) + ExtraOffset = INIT_RC_HELI_ALPHA_EXTRA; + else if(id == MI_RCBARON) + ExtraOffset = INIT_RC_PLANE_ALPHA_EXTRA; if(ResetStatics){ - LastTargetAlphaWithCollisionOn = 0.0f; - LastTopAlphaSpeed = 0.0f; - LastAlphaSpeedStep = 0.0f; - PreviousNearCheckNearClipSmall = false; - } + AlphaOffset = 0.0f; + AlphaOffsetSpeed = 0.0f; + AlphaDec = 0.0f; - float TopAlphaSpeed = 0.15f; - float AlphaSpeedStep = 0.015f; + if(TheCamera.CarZoomIndicator == CAM_ZOOM_1) + AlphaOffset = ZmOneAlphaOffset[index] + ExtraOffset; + else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2) + AlphaOffset = ZmTwoAlphaOffset[index] + ExtraOffset; + else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3) + AlphaOffset = ZmThreeAlphaOffset[index] + ExtraOffset; + } - float zoomvalue = TheCamera.CarZoomValueSmooth; - if(zoomvalue < 0.1f) - zoomvalue = 0.1f; if(TheCamera.CarZoomIndicator == CAM_ZOOM_1) - AlphaOffset = CGeneral::GetATanOfXY(23.0f, zoomvalue); // near + WellBufferMe(ZmOneAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false); else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2) - AlphaOffset = CGeneral::GetATanOfXY(10.8f, zoomvalue); // mid + WellBufferMe(ZmTwoAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false); else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3) - AlphaOffset = CGeneral::GetATanOfXY(7.0f, zoomvalue); // far - + WellBufferMe(ZmThreeAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false); float Length = (Source - TargetCoors).Magnitude2D(); - if(m_bCollisionChecksOn){ // there's another variable (on PC) but it's uninitialised - float CarAlpha = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().Magnitude2D(), CamTargetEntity->GetForward().z); - // this shouldn't be necessary.... - while(CarAlpha >= PI) CarAlpha -= 2*PI; - while(CarAlpha < -PI) CarAlpha += 2*PI; - - while(Beta >= PI) Beta -= 2*PI; - while(Beta < -PI) Beta += 2*PI; - - float DeltaBeta = Beta - TargetOrientation; - while(DeltaBeta >= PI) DeltaBeta -= 2*PI; - while(DeltaBeta < -PI) DeltaBeta += 2*PI; - - float BehindCarNess = Cos(DeltaBeta); // 1 if behind car, 0 if side, -1 if in front - CarAlpha = -CarAlpha * BehindCarNess; - if(CarAlpha < -0.01f) - CarAlpha = -0.01f; - - float DeltaAlpha = CarAlpha - Alpha; - while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI; - while(DeltaAlpha < -PI) DeltaAlpha += 2*PI; - // What's this?? wouldn't it make more sense to clamp? - float AngleLimit = DEGTORAD(1.8f); - if(DeltaAlpha > AngleLimit) - DeltaAlpha -= AngleLimit; - else if(DeltaAlpha < -AngleLimit) - DeltaAlpha += AngleLimit; - else - DeltaAlpha = 0.0f; - - // Now the collision - - float TargetAlpha = 0.0f; - bool FoundRoofCenter = false; - bool FoundRoofSide1 = false; - bool FoundRoofSide2 = false; - bool FoundCamRoof = false; - bool FoundCamGround = false; - float CamRoof = 0.0f; - float CarBottom = TargetCoors.z - TargetHeight/2.0f; - // Check car center - float CarRoof = CWorld::FindRoofZFor3DCoord(TargetCoors.x, TargetCoors.y, CarBottom, &FoundRoofCenter); + CVector Forward = CamTargetEntity->GetForward(); + float CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z); + // this shouldn't be necessary.... + while(CarAlpha >= PI) CarAlpha -= 2*PI; + while(CarAlpha < -PI) CarAlpha += 2*PI; - // Check sides of the car - CVector Forward = CamTargetEntity->GetForward(); - Forward.Normalise(); // shouldn't be necessary - float CarSideAngle = CGeneral::GetATanOfXY(Forward.x, Forward.y) + PI/2.0f; - float SideX = 2.5f * Cos(CarSideAngle); - float SideY = 2.5f * Sin(CarSideAngle); - CWorld::FindRoofZFor3DCoord(TargetCoors.x + SideX, TargetCoors.y + SideY, CarBottom, &FoundRoofSide1); - CWorld::FindRoofZFor3DCoord(TargetCoors.x - SideX, TargetCoors.y - SideY, CarBottom, &FoundRoofSide2); - - // Now find out at what height we'd like to place the camera - float CamGround = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, TargetCoors.z + Length*Sin(Alpha + AlphaOffset) + m_fCloseInCarHeightOffset, &FoundCamGround); - float CamTargetZ = 0.0f; - if(FoundCamGround){ - // This is the normal case - CamRoof = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamGround + TargetHeight, &FoundCamRoof); - CamTargetZ = CamGround + TargetHeight*1.5f + 0.1f; - }else{ - FoundCamRoof = false; - CamTargetZ = TargetCoors.z; - } + while(Beta >= PI) Beta -= 2*PI; + while(Beta < -PI) Beta += 2*PI; - if(FoundRoofCenter && !FoundCamRoof && (FoundRoofSide1 || FoundRoofSide2)){ - // Car is under something but camera isn't - // This seems weird... - TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, CarRoof - CamTargetZ - 1.5f); - CamClear = false; - } - if(FoundCamRoof){ - // Camera is under something - float roof = FoundRoofCenter ? Min(CamRoof, CarRoof) : CamRoof; - // Same weirdness again? - TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, roof - CamTargetZ - 1.5f); - CamClear = false; - } - while(TargetAlpha >= PI) TargetAlpha -= 2*PI; - while(TargetAlpha < -PI) TargetAlpha += 2*PI; - if(TargetAlpha < DEGTORAD(-7.0f)) - TargetAlpha = DEGTORAD(-7.0f); - - // huh? - if(TargetAlpha > AlphaOffset) - CamClear = true; - // Camera is constrained by collision in some way - PreviousNearCheckNearClipSmall = false; - if(!CamClear){ - PreviousNearCheckNearClipSmall = true; - RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); - - DeltaAlpha = TargetAlpha - (Alpha + AlphaOffset); - while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI; - while(DeltaAlpha < -PI) DeltaAlpha += 2*PI; - - TopAlphaSpeed = 0.3f; - AlphaSpeedStep = 0.03f; - } + float DeltaBeta = Beta - TargetOrientation; + while(DeltaBeta >= PI) DeltaBeta -= 2*PI; + while(DeltaBeta < -PI) DeltaBeta += 2*PI; - // Now do things if CamClear...but what is that anyway? - float CamZ = TargetCoors.z + Length*Sin(Alpha + DeltaAlpha + AlphaOffset) + m_fCloseInCarHeightOffset; - bool FoundGround, FoundRoof; - float CamGround2 = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, CamZ, &FoundGround); - if(FoundGround && CamClear){ - if(CamZ - CamGround2 < 1.5f){ - PreviousNearCheckNearClipSmall = true; - RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); - - float dz = CamGround2 + 1.5f - TargetCoors.z; - float a; - if(Length == 0.0f || dz == 0.0f) - a = Alpha; - else - a = CGeneral::GetATanOfXY(Length, dz); - while(a > PI) a -= 2*PI; - while(a < -PI) a += 2*PI; - DeltaAlpha = a - Alpha; - } - }else if(CamClear){ - float CamRoof2 = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamZ, &FoundRoof); - if(FoundRoof && CamZ - CamRoof2 < 1.5f){ - PreviousNearCheckNearClipSmall = true; - RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); - - if(CamRoof2 > TargetCoors.z + 3.5f) - CamRoof2 = TargetCoors.z + 3.5f; - - float dz = CamRoof2 + 1.5f - TargetCoors.z; - float a; - if(Length == 0.0f || dz == 0.0f) - a = Alpha; - else - a = CGeneral::GetATanOfXY(Length, dz); - while(a > PI) a -= 2*PI; - while(a < -PI) a += 2*PI; - DeltaAlpha = a - Alpha; - } - } + float BehindCarNess = Cos(DeltaBeta); // 1 if behind car, 0 if side, -1 if in front + CarAlpha = -CarAlpha * BehindCarNess; + + float fwdSpeed = DotProduct(((CPhysical*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward())*180.0f; + if(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired()){ + CarAlpha = DEGTORAD(10.0f); + }else if(isHeli){ + CarAlpha = 0.0f; + float heliFwdZ = CamTargetEntity->GetForward().z; + float heliFwdXY = CamTargetEntity->GetForward().Magnitude2D(); + float alphaAmount = Min(Abs(fwdSpeed/90.0f), 1.0f); + if(heliFwdXY != 0.0f || heliFwdZ != 0.0f) + CarAlpha = CGeneral::GetATanOfXY(heliFwdXY, Abs(heliFwdZ)) * alphaAmount; + + CColPoint point; + CEntity *entity = nil; + CVector Test = Source; + Test.z = TargetCoors.z + 0.2f + Length*Sin(CarAlpha+AlphaOffset) + m_fCloseInCarHeightOffset; + if(CWorld::ProcessVerticalLine(Test, CamTargetEntity->GetPosition().z, point, entity, true, false, false, false, false, false, nil)){ + float sin = (point.point.z - TargetCoors.z - 0.2f - m_fCloseInCarHeightOffset)/Length; + CarAlpha = Asin(Clamp(sin, -1.0f, 1.0f)) - AlphaOffset; + if(CarAlpha < 0.0f) + AlphaOffset += CarAlpha; + } + } + + CarAlpha = CGeneral::LimitRadianAngle(CarAlpha); + if(CarAlpha < 0.0f) CarAlpha = 0.0f; + if(CarAlpha > DEGTORAD(89.0f)) CarAlpha = DEGTORAD(89.0f); - LastTargetAlphaWithCollisionOn = DeltaAlpha + Alpha; - LastTopAlphaSpeed = TopAlphaSpeed; - LastAlphaSpeedStep = AlphaSpeedStep; - }else{ - if(PreviousNearCheckNearClipSmall) - RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); - } + if(ResetStatics) + Alpha = CarAlpha; - WellBufferMe(LastTargetAlphaWithCollisionOn, &Alpha, &AlphaSpeed, LastTopAlphaSpeed, LastAlphaSpeedStep, true); + float TargetAlpha = Alpha; + float DeltaAlpha = CarAlpha - TargetAlpha; + while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI; + while(DeltaAlpha < -PI) DeltaAlpha += 2*PI; + if(Abs(DeltaAlpha) > 0.0f && !TheCamera.m_bVehicleSuspenHigh) + TargetAlpha = CarAlpha; + + if(isBike) + WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true); + else if(isHeli) + WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true); + else + WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.15f, 0.07f, true); Source.z = TargetCoors.z + Sin(Alpha + AlphaOffset)*Length + m_fCloseInCarHeightOffset; + AlphaOffset -= AlphaDec; } // Rotate cam behind the car when the car is moving forward bool CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation) { + float BetaMaxSpeed = 0.15f; + float BetaAcceleration = 0.007f; bool MovingForward = false; + float MaxDiffBeta = DEGTORAD(160.0f); CPhysical *phys = (CPhysical*)CamTargetEntity; float ForwardSpeed = DotProduct(phys->GetForward(), phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f))); if(ForwardSpeed > 0.02f) MovingForward = true; + if(phys->IsVehicle() && (phys->GetModelIndex() == MI_SPARROW || phys->GetModelIndex() == MI_HUNTER)){ + MaxDiffBeta = DEGTORAD(160.0f); + BetaMaxSpeed = 0.1f; + BetaAcceleration = 0.003f; + CVector speed = phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f)); + speed.z = 0.0f; + if(50.0f*speed.Magnitude() > 3.13f) + TargetOrientation = CGeneral::GetATanOfXY(speed.x, speed.y); + } + float Dist = (Source - TargetCoors).Magnitude2D(); float DeltaBeta = TargetOrientation - Beta; while(DeltaBeta >= PI) DeltaBeta -= 2*PI; while(DeltaBeta < -PI) DeltaBeta += 2*PI; - if(Abs(DeltaBeta) > DEGTORAD(20.0f) && MovingForward && TheCamera.m_uiTransitionState == 0) + if(Abs(DeltaBeta) > PI-MaxDiffBeta && MovingForward && TheCamera.m_uiTransitionState == 0) m_bFixingBeta = true; CPad *pad = CPad::GetPad(0); @@ -2023,7 +1756,7 @@ CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation) SetBeta = true; if(m_bFixingBeta || SetBeta){ - WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, 0.15f, 0.007f, true); + WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true); if(TheCamera.m_bCamDirectlyBehind && &TheCamera.Cams[TheCamera.ActiveCam] == this) Beta = TargetOrientation; @@ -2047,78 +1780,11 @@ CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation) return true; } -// Move the cam to avoid clipping through buildings -bool -CCam::FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation) -{ - CVector Target = TargetCoors; - bool UseEntityPos = false; - CVector EntityPos; - static CColPoint colPoint; - static bool LastObscured = false; - - if(Mode == MODE_BEHINDCAR) - Target.z += TargetHeight/2.0f; - if(Mode == MODE_CAM_ON_A_STRING){ - UseEntityPos = true; - Target.z += TargetHeight/2.0f; - EntityPos = CamTargetEntity->GetPosition(); - } - - CVector TempSource = Source; - - bool Obscured1 = false; - bool Obscured2 = false; - bool Fix1 = false; - float Dist1 = 0.0f; - float Dist2 = 0.0f; - CEntity *ent; - if(m_bCollisionChecksOn || LastObscured){ - Obscured1 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true); - if(Obscured1){ - Dist1 = (Target - colPoint.point).Magnitude2D(); - Fix1 = true; - if(UseEntityPos) - Obscured1 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true); - }else if(m_bFixingBeta){ - float d = (TempSource - Target).Magnitude(); - TempSource.x = Target.x - d*Cos(TargetOrientation); - TempSource.y = Target.y - d*Sin(TargetOrientation); - - // same check again - Obscured2 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true); - if(Obscured2){ - Dist2 = (Target - colPoint.point).Magnitude2D(); - if(UseEntityPos) - Obscured2 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true); - } - } - LastObscured = Obscured1 || Obscured2; - } - - // nothing to do - if(!LastObscured) - return false; - - if(Fix1){ - Source.x = Target.x - Cos(Beta)*Dist1; - Source.y = Target.y - Sin(Beta)*Dist1; - if(Mode == MODE_BEHINDCAR) - Source = colPoint.point; - }else{ - WellBufferMe(Dist2, &m_fDistanceBeforeChanges, &DistanceSpeed, 0.2f, 0.025f, false); - Source.x = Target.x - Cos(Beta)*m_fDistanceBeforeChanges; - Source.y = Target.y - Sin(Beta)*m_fDistanceBeforeChanges; - } - - if(ResetStatics){ - m_fDistanceBeforeChanges = (Source - Target).Magnitude2D(); - DistanceSpeed = 0.0f; - Source.x = colPoint.point.x; - Source.y = colPoint.point.y; - } - return true; -} +float FIRETRUCK_TRACKING_MULT = 0.1f; +float fTestShiftHeliCamTarget = 0.6f; +float TiltTopSpeed[] = { 0.035f, 0.035f, 0.001f, 0.005f, 0.035f }; +float TiltSpeedStep[] = { 0.016f, 0.016f, 0.0002f, 0.0014f, 0.016f }; +float TiltOverShoot[] = { 1.05f, 1.05f, 0.0f, 0.0f, 1.0f }; void CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float) @@ -2126,38 +1792,117 @@ CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientati if(!CamTargetEntity->IsVehicle()) return; + // unused + // ((CVehicle*)CamTargetEntity)->GetVehicleAppearance(); + FOV = DefaultFOV; if(ResetStatics){ AlphaSpeed = 0.0f; - if(TheCamera.m_bIdleOn) - TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds(); + m_fTilt = 0.0f; + m_fTiltSpeed = 0.0; } CBaseModelInfo *mi = CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex()); CVector Dimensions = mi->GetColModel()->boundingBox.max - mi->GetColModel()->boundingBox.min; CVector TargetCoors = CameraTarget; - float BaseDist = Dimensions.Magnitude2D(); + float BaseDist = Dimensions.Magnitude(); + + if(((CVehicle*)CamTargetEntity)->IsBike()) + BaseDist *= 1.45f; + if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI && + CamTargetEntity->GetStatus() != STATUS_PLAYER_REMOTE) + TargetCoors += fTestShiftHeliCamTarget * CamTargetEntity->GetUp() * Dimensions.z; + else + TargetCoors.z += 0.8f*Dimensions.z; - TargetCoors.z += Dimensions.z - 0.1f; // final Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y); - while(Alpha >= PI) Alpha -= 2*PI; - while(Alpha < -PI) Alpha += 2*PI; - while(Beta >= PI) Beta -= 2*PI; - while(Beta < -PI) Beta += 2*PI; + Alpha = CGeneral::LimitRadianAngle(Alpha); + Beta = CGeneral::LimitRadianAngle(Beta); + + if(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired() && + ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed.Magnitude2D() < 0.01f){ + float TargetBeta = CamTargetEntity->GetForward().Heading() - ((CAutomobile*)CamTargetEntity)->m_fCarGunLR + HALFPI; + TargetBeta = CGeneral::LimitRadianAngle(TargetBeta); + float DeltaBeta = TargetBeta - Beta; + if(DeltaBeta > PI) DeltaBeta -= TWOPI; + else if(DeltaBeta < -PI) DeltaBeta += TWOPI; + float dist = (TargetCoors - Source).Magnitude(); + dist = FIRETRUCK_TRACKING_MULT*dist*Clamp(DeltaBeta, -0.8f, 0.8f); + Source += dist*CrossProduct(Front, CVector(0.0f, 0.0f, 1.0f)); + } m_fDistanceBeforeChanges = (Source - TargetCoors).Magnitude2D(); Cam_On_A_String_Unobscured(TargetCoors, BaseDist); WorkOutCamHeight(TargetCoors, TargetOrientation, Dimensions.z); RotCamIfInFrontCar(TargetCoors, TargetOrientation); - FixCamIfObscured(TargetCoors, Dimensions.z, TargetOrientation); FixCamWhenObscuredByVehicle(TargetCoors); m_cvecTargetCoorsForFudgeInter = TargetCoors; + CVector OrigSource = Source; + if(CWorld::GetIsLineOfSightClear(CamTargetEntity->GetPosition(), m_cvecTargetCoorsForFudgeInter, true, false, false, true, false, false, true)) + TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV); + else + TheCamera.AvoidTheGeometry(OrigSource, CamTargetEntity->GetPosition(), Source, FOV); + Front = TargetCoors - Source; Front.Normalise(); - GetVectorsReadyForRW(); + + int appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance(); + int index = 0; + TheCamera.GetArrPosForVehicleType(appearance, index); + + if(appearance == VEHICLE_APPEARANCE_HELI){ + float TargetTilt = DotProduct(Front, ((CVehicle*)CamTargetEntity)->GetSpeed(CVector(0.0f, 0.0f, 0.0f))); + CVector UpTarget = CamTargetEntity->GetUp(); + UpTarget.Normalise(); + int dir = TargetTilt < 0.0f ? -1 : 1; + if(m_fTilt != 0.0f) + TargetTilt += TiltOverShoot[index]*TargetTilt/m_fTilt * dir; + WellBufferMe(TargetTilt, &m_fTilt, &m_fTiltSpeed, TiltTopSpeed[index], TiltSpeedStep[index], false); + + Up = CVector(0.0f, 0.0f, 1.0f) - (CVector(0.0f, 0.0f, 1.0f) - UpTarget)*m_fTilt; + Up.Normalise(); + Front.Normalise(); + CVector Left = CrossProduct(Up, Front); + Up = CrossProduct(Front, Left); + Up.Normalise(); + }else{ + float TargetRoll; + if(CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetDPadRight()){ + float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward()); + if(fwdSpeed > 210.0f) fwdSpeed = 210.0f; + if(CPad::GetPad(0)->GetDPadLeft()) + TargetRoll = DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle; + else + TargetRoll = -(DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle); + CVector FwdTarget = CamTargetEntity->GetForward(); + FwdTarget.Normalise(); + float AngleDiff = DotProduct(FwdTarget, Front); + AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f)); + TargetRoll *= fwdSpeed/210.0f * Sin(AngleDiff); + }else{ + float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward()); + if(fwdSpeed > 210.0f) fwdSpeed = 210.0f; + TargetRoll = CPad::GetPad(0)->GetLeftStickX()/128.0f * fwdSpeed/210.0f; + CVector FwdTarget = CamTargetEntity->GetForward(); + FwdTarget.Normalise(); + float AngleDiff = DotProduct(FwdTarget, Front); + AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f)); + TargetRoll *= (DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle) * Sin(AngleDiff); + } + + WellBufferMe(TargetRoll, &f_Roll, &f_rollSpeed, 0.15f, 0.07f, false); + Up = CVector(Cos(f_Roll + HALFPI), 0.0f, Sin(f_Roll + HALFPI)); + Up.Normalise(); + Front.Normalise(); + CVector Left = CrossProduct(Up, Front); + Left.Normalise(); + Up = CrossProduct(Front, Left); + Up.Normalise(); + } + ResetStatics = false; } @@ -2165,8 +1910,17 @@ CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientati void CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist) { - CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth; + int id = CamTargetEntity->GetModelIndex(); + float ExtraDist = 0.0f; + if(id == MI_RCRAIDER || id == MI_RCGOBLIN) + ExtraDist = INIT_RC_HELI_HORI_EXTRA; + else if(id == MI_RCBARON) + ExtraDist = INIT_RC_PLANE_HORI_EXTRA; + + CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth + ExtraDist; CA_MIN_DISTANCE = Min(BaseDist*0.6f, 3.5f); + if(CA_MIN_DISTANCE > CA_MAX_DISTANCE) + CA_MIN_DISTANCE = CA_MAX_DISTANCE - 0.05f; CVector Dist = Source - TargetCoors; @@ -2449,13 +2203,13 @@ CCam::Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, f ResetStatics = false; } -// Identical to M16 void CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) { if(!CamTargetEntity->IsPed()) return; + float BackOffset = 0.19f; static bool FailedTestTwelveFramesAgo = false; RwV3d HeadPos; CVector TargetCoors; @@ -2474,11 +2228,16 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) ResetStatics = false; } + if(((CPed*)CamTargetEntity)->bIsDucking) + BackOffset = 0.8f; + CamTargetEntity->GetMatrix().UpdateRW(); + CamTargetEntity->UpdateRwFrame(); + CamTargetEntity->UpdateRpHAnim(); ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; - Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); - Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation); + Source.x -= BackOffset*Cos(m_fInitialPlayerOrientation); + Source.y -= BackOffset*Sin(m_fInitialPlayerOrientation); // Look around bool UseMouse = false; @@ -2505,7 +2264,7 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) while(Beta >= PI) Beta -= 2*PI; while(Beta < -PI) Beta += 2*PI; if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f); - if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); + else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x; TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y; @@ -2549,22 +2308,30 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation; } -// Identical to Rocket +float fDuckingBackOffset = 0.5f; +float fDuckingRightOffset = 0.18f; + void CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) { if(!CamTargetEntity->IsPed()) return; + float BackOffset = 0.3f; static bool FailedTestTwelveFramesAgo = false; RwV3d HeadPos; CVector TargetCoors; + bool isAttached = ((CPed*)CamTargetEntity)->IsPlayer() && ((CPed*)CamTargetEntity)->m_attachedTo; + FOV = DefaultFOV; TargetCoors = CameraTarget; if(ResetStatics){ - Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI; + if(isAttached) + Beta = 0.0f; + else + Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI; Alpha = 0.0f; m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI; FailedTestTwelveFramesAgo = false; @@ -2574,14 +2341,6 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) ResetStatics = false; } -#if GTA_VERSION < GTA3_PC_11 - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); - Source = HeadPos; - Source.z += 0.1f; - Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); - Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation); -#endif - // Look around bool UseMouse = false; float MouseX = CPad::GetPad(0)->GetMouseX(); @@ -2598,73 +2357,153 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) if(UseMouse){ Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f; Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f; + }else if(Mode == MODE_HELICANNON_1STPERSON){ + LookLeftRight /= 128.0f; + LookUpDown /= 128.0f; + Beta += LookLeftRight*Abs(LookLeftRight)*0.56f/14.0f * FOV/80.0f * CTimer::GetTimeStep(); + Alpha += LookUpDown*Abs(LookUpDown)*0.48f/14.0f * FOV/80.0f * CTimer::GetTimeStep(); }else{ float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f; float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f; Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep(); Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep(); } - while(Beta >= PI) Beta -= 2*PI; - while(Beta < -PI) Beta += 2*PI; + if (!isAttached) { + while(Beta >= TWOPI) Beta -= TWOPI; + while(Beta < 0) Beta += TWOPI; + } if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f); else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); -#if GTA_VERSION >= GTA3_PC_11 - HeadPos.x = 0.0f; - HeadPos.y = 0.0f; - HeadPos.z = 0.0f; - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); - Source = HeadPos; - Source.z += 0.1f; - Source.x -= 0.19f * Cos(m_fInitialPlayerOrientation); - Source.y -= 0.19f * Sin(m_fInitialPlayerOrientation); -#endif + if(((CPed*)CamTargetEntity)->bIsDucking) + BackOffset = 0.8f; + if(isAttached){ + CMatrix mat, rot; + CPed *TargetPed = (CPed*)CamTargetEntity; + TargetPed->PositionAttachedPed(); + CamTargetEntity->GetMatrix().UpdateRW(); + CamTargetEntity->UpdateRwFrame(); + CamTargetEntity->UpdateRpHAnim(); + + HeadPos.x = 0.0f; + HeadPos.y = 0.0f; + HeadPos.z = 0.0f; + TargetPed->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); + Source = HeadPos; + Source += 0.1f*CamTargetEntity->GetUp(); + Source -= BackOffset*CamTargetEntity->GetForward(); + + if(TargetPed->m_attachRotStep < PI){ + if(Beta > TargetPed->m_attachRotStep){ + Beta = TargetPed->m_attachRotStep; + CAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo; + if(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){ + float heliOrient = heli->m_fHeliOrientation + CTimer::GetTimeStep()*0.01f; + if(heliOrient < 0.0f) heliOrient += TWOPI; + else if(heliOrient > TWOPI) heliOrient -= TWOPI; + heli->SetHeliOrientation(heliOrient); + } + }else if(Beta < -TargetPed->m_attachRotStep){ + Beta = -TargetPed->m_attachRotStep; + CAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo; + if(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){ + float heliOrient = heli->m_fHeliOrientation - CTimer::GetTimeStep()*0.01f; + if(heliOrient < 0.0f) heliOrient += TWOPI; + else if(heliOrient > TWOPI) heliOrient -= TWOPI; + heli->SetHeliOrientation(heliOrient); + } + } + }else{ + while(Beta < -PI) Beta += TWOPI; + while(Beta >= PI) Beta -= TWOPI; + } - TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x; - TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y; - TargetCoors.z = 3.0f * Sin(Alpha) + Source.z; - Front = TargetCoors - Source; - Front.Normalise(); - Source += Front*0.4f; + mat = TargetPed->m_attachedTo->GetMatrix(); + rot.SetRotateX(Alpha); + switch(TargetPed->m_attachType){ + case 0: rot.RotateZ(Beta); break; + case 1: rot.RotateZ(Beta + HALFPI); break; + case 2: rot.RotateZ(Beta + PI); break; + case 3: rot.RotateZ(Beta - HALFPI); break; + } + mat = mat * rot; + Front = mat.GetForward(); + Up = mat.GetUp(); + TargetCoors = Source + 3.0f*Front; + RwCameraSetNearClipPlane(Scene.camera, 0.4f); - if(m_bCollisionChecksOn){ - if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){ - RwCameraSetNearClipPlane(Scene.camera, 0.4f); - FailedTestTwelveFramesAgo = true; + float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI; + ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation; + ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation; + }else{ + CamTargetEntity->GetMatrix().UpdateRW(); + CamTargetEntity->UpdateRwFrame(); + CamTargetEntity->UpdateRpHAnim(); + HeadPos.x = 0.0f; + HeadPos.y = 0.0f; + HeadPos.z = 0.0f; + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); + Source = HeadPos; + Source.z += 0.1f; + if(((CPed*)CamTargetEntity)->bIsDucking){ + Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x; + Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y; + Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x; + Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y; }else{ - CVector TestPoint; - TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x; - TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y; - TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z; - if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){ + Source.x -= BackOffset*CamTargetEntity->GetForward().x; + Source.y -= BackOffset*CamTargetEntity->GetForward().y; + } + + TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x; + TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y; + TargetCoors.z = 3.0f * Sin(Alpha) + Source.z; + Front = TargetCoors - Source; + Front.Normalise(); + Source += Front*0.4f; + + if(m_bCollisionChecksOn){ + if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){ RwCameraSetNearClipPlane(Scene.camera, 0.4f); FailedTestTwelveFramesAgo = true; }else{ - TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x; - TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y; + CVector TestPoint; + TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x; + TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y; TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z; if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){ RwCameraSetNearClipPlane(Scene.camera, 0.4f); FailedTestTwelveFramesAgo = true; - }else - FailedTestTwelveFramesAgo = false; + }else{ + TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x; + TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y; + TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z; + if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){ + RwCameraSetNearClipPlane(Scene.camera, 0.4f); + FailedTestTwelveFramesAgo = true; + }else + FailedTestTwelveFramesAgo = false; + } } } - } - if(FailedTestTwelveFramesAgo) - RwCameraSetNearClipPlane(Scene.camera, 0.4f); - Source -= Front*0.4f; + if(FailedTestTwelveFramesAgo) + RwCameraSetNearClipPlane(Scene.camera, 0.4f); + Source -= Front*0.4f; - GetVectorsReadyForRW(); - float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI; - ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation; - ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation; + GetVectorsReadyForRW(); + float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI; + ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation; + ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation; + } } +float fBike1stPersonOffsetZ = 0.15f; + void -CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float, float) +CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar) { + float BackOffset = 0.3f; static float DontLookThroughWorldFixer = 0.0f; CVector TargetCoors; @@ -2682,6 +2521,7 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl Alpha = 0.0f; m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI; } + TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f; DontLookThroughWorldFixer = 0.0f; } @@ -2702,11 +2542,22 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl ResetStatics = false; } + CamTargetEntity->GetMatrix().UpdateRW(); + CamTargetEntity->UpdateRwFrame(); + CamTargetEntity->UpdateRpHAnim(); + ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; - Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); - Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation); + if(((CPed*)CamTargetEntity)->bIsDucking){ + Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x; + Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y; + Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x; + Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y; + }else{ + Source.x -= BackOffset*CamTargetEntity->GetForward().x; + Source.y -= BackOffset*CamTargetEntity->GetForward().y; + } float LookLeftRight, LookUpDown; LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight(); @@ -2762,16 +2613,48 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation; }else{ assert(CamTargetEntity->IsVehicle()); + + if(((CVehicle*)CamTargetEntity)->IsBike() && + (((CBike*)CamTargetEntity)->bWheelieCam || TheCamera.m_fAvoidTheGeometryProbsTimer > 0.0f)){ + if(CPad::GetPad(0)->GetLeftShoulder2() || CPad::GetPad(0)->GetRightShoulder2()){ + TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f; + ((CBike*)CamTargetEntity)->bWheelieCam = false; + }else if(Process_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar)){ + if(((CBike*)CamTargetEntity)->bWheelieCam) + TheCamera.m_fAvoidTheGeometryProbsTimer = 50.0f; + else{ + TheCamera.m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep(); + ((CBike*)CamTargetEntity)->bWheelieCam = true; + } + return; + }else{ + TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f; + ((CBike*)CamTargetEntity)->bWheelieCam = false; + } + } + + CMatrix *matrix = &CamTargetEntity->GetMatrix(); + if(((CVehicle*)CamTargetEntity)->IsBike()){ + ((CBike*)CamTargetEntity)->CalculateLeanMatrix(); + matrix = &((CBike*)CamTargetEntity)->m_leanMatrix; + } + CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex()); CVector CamPos = mi->GetFrontSeatPosn(); CamPos.x = 0.0f; CamPos.y += 0.08f; CamPos.z += 0.62f; FOV = 60.0f; - Source = Multiply3x3(CamTargetEntity->GetMatrix(), CamPos); + Source = Multiply3x3(*matrix, CamPos); Source += CamTargetEntity->GetPosition(); if(((CVehicle*)CamTargetEntity)->IsBoat()) Source.z += 0.5f; + else if(((CVehicle*)CamTargetEntity)->IsBike() && ((CVehicle*)CamTargetEntity)->pDriver){ + CVector Neck(0.0f, 0.0f, 0.0f); + ((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(Neck, PED_NECK); + Neck += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed * CTimer::GetTimeStep(); + Source.z = Neck.z + fBike1stPersonOffsetZ; + } if(((CVehicle*)CamTargetEntity)->IsUpsideDown()){ if(DontLookThroughWorldFixer < 0.5f) @@ -2789,9 +2672,9 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl DontLookThroughWorldFixer = 0.0f; } Source.z += DontLookThroughWorldFixer; - Front = CamTargetEntity->GetForward(); + Front = matrix->GetForward(); Front.Normalise(); - Up = CamTargetEntity->GetUp(); + Up = matrix->GetUp(); Up.Normalise(); CVector Right = CrossProduct(Front, Up); Right.Normalise(); @@ -2822,16 +2705,12 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, CVector TargetCoors; ((CPed*)CamTargetEntity)->TransformToNode(HeadPos, PED_HEAD); - // This is done on PC, but checking for the clump frame is not necessary apparently -/* - RwFrame *frm = ((CPed*)CamTargetEntity)->m_pFrames[PED_HEAD]->frame; - while(frm){ - RwV3dTransformPoints(&HeadPos, &HeadPos, 1, RwFrameGetMatrix(frm)); - frm = RwFrameGetParent(frm); - if(frm == RpClumpGetFrame(CamTargetEntity->GetClump())) - frm = nil; - } -*/ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(CamTargetEntity->GetClump()); + int32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD)); + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + RwV3dTransformPoints(&HeadPos, &HeadPos, 1, &mats[idx]); + RwV3d scl = { 0.0f, 0.0f, 0.0f }; + RwMatrixScale(&mats[idx], &scl, rwCOMBINEPRECONCAT); if(ResetStatics){ Beta = TargetOrientation; @@ -2900,6 +2779,32 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f); else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); + if(((CPed*)CamTargetEntity)->IsPlayer() && ((CPed*)CamTargetEntity)->m_attachedTo){ + CPed *pedTarget = ((CPed*)CamTargetEntity); + float NewBeta; + switch(pedTarget->m_attachType){ + case 0: + NewBeta = pedTarget->GetForward().Heading() + HALFPI; + break; + case 1: + NewBeta = pedTarget->GetForward().Heading() + PI; + break; + case 2: + NewBeta = pedTarget->GetForward().Heading() - HALFPI; + break; + case 3: + NewBeta = pedTarget->GetForward().Heading(); + break; + } + + float BetaOffset = Beta - NewBeta; + if(BetaOffset > PI) BetaOffset -= TWOPI; + else if(BetaOffset < PI) BetaOffset += TWOPI; + + BetaOffset = Clamp(BetaOffset, -pedTarget->m_attachRotStep, pedTarget->m_attachRotStep); + Beta = NewBeta + BetaOffset; + } + TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x; TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y; TargetCoors.z = 3.0f * Sin(Alpha) + Source.z; @@ -2939,12 +2844,15 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, RwCameraSetNearClipPlane(Scene.camera, 0.05f); } +float fCameraNearClipMult = 0.15f; + void CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float, float) { if(!CamTargetEntity->IsPed()) return; + float BackOffset = 0.19f; static bool FailedTestTwelveFramesAgo = false; RwV3d HeadPos; CVector TargetCoors; @@ -2965,11 +2873,23 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float ResetStatics = false; } + if(((CPed*)CamTargetEntity)->bIsDucking) + BackOffset = 0.8f; + CamTargetEntity->GetMatrix().UpdateRW(); + CamTargetEntity->UpdateRwFrame(); + CamTargetEntity->UpdateRpHAnim(); ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD); Source = HeadPos; Source.z += 0.1f; - Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation); - Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation); + if(((CPed*)CamTargetEntity)->bIsDucking){ + Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x; + Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y; + Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x; + Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y; + }else{ + Source.x -= BackOffset*CamTargetEntity->GetForward().x; + Source.y -= BackOffset*CamTargetEntity->GetForward().y; + } // Look around bool UseMouse = false; @@ -3038,8 +2958,13 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float if(FOV > DefaultFOV) FOV = DefaultFOV; - if(FOV < 15.0f) - FOV = 15.0f; + if(Mode == MODE_CAMERA){ + if(FOV < 3.0f) + FOV = 3.0f; + }else{ + if(FOV < 15.0f) + FOV = 15.0f; + } Front = TargetCoors - Source; Front.Normalise(); @@ -3072,6 +2997,8 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float if(FailedTestTwelveFramesAgo) RwCameraSetNearClipPlane(Scene.camera, 0.4f); + else if(Mode == MODE_CAMERA) + RwCameraSetNearClipPlane(Scene.camera, ((15.0f - Min(FOV, 15.0f))*fCameraNearClipMult + 1.0f)*DEFAULT_NEAR); Source -= Front*0.4f; GetVectorsReadyForRW(); @@ -3080,6 +3007,12 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation; } +float INIT_SYPHON_GROUND_DIST = 2.419f; +float INIT_SYPHON_ALPHA_OFFSET = -DEGTORAD(3.0f); +float INIT_SYPHON_DEGREE_OFFSET = -DEGTORAD(30.0f); +float FrontOffsetSyphon = -DEGTORAD(25.5f); // unused +float INIT_SYPHON_Z_OFFSET = -0.5f; + void CCam::Process_Syphon(const CVector &CameraTarget, float, float, float) { @@ -3090,82 +3023,123 @@ CCam::Process_Syphon(const CVector &CameraTarget, float, float, float) static bool CameraObscured = false; // unused FailedClippingTestPrevously - static float BetaOffset = DEGTORAD(18.0f); + static float BetaOffset = INIT_SYPHON_DEGREE_OFFSET; // unused AngleToGoTo // unused AngleToGoToSpeed // unused DistBetweenPedAndPlayerPreviouslyOn - static float HeightDown = -0.5f; - static float PreviousDistForInter; + static float HeightDown = INIT_SYPHON_Z_OFFSET; + static float AlphaOffset = INIT_SYPHON_ALPHA_OFFSET; + static bool NegateBetaOffset = true; CVector TargetCoors; - CVector2D vDist; - float fDist, fAimingDist; + float fAimingDist; float TargetAlpha; - CColPoint colPoint; - CEntity *entity; + bool StandingOnMovingThing = false; TargetCoors = CameraTarget; + AlphaOffset = INIT_SYPHON_ALPHA_OFFSET; + float GroundDist = INIT_SYPHON_GROUND_DIST; - if(TheCamera.Cams[TheCamera.ActiveCam].Mode != MODE_SYPHON) - return; - - vDist = Source - TargetCoors; - fDist = vDist.Magnitude(); - if(fDist == 0.0f) - Source = TargetCoors + CVector(1.0f, 1.0f, 0.0f); - else - Source = TargetCoors + CVector(vDist.x/fDist * 1.7f, vDist.y/fDist * 1.7f, 0.0f); - if(fDist > 1.7f) - fDist = 1.7f; - - Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y); while(Beta >= PI) Beta -= 2*PI; while(Beta < -PI) Beta += 2*PI; float NewBeta = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y) + PI; if(ResetStatics){ - CameraObscured = false; - float TestBeta1 = NewBeta - BetaOffset - Beta; - float TestBeta2 = NewBeta + BetaOffset - Beta; - MakeAngleLessThan180(TestBeta1); - MakeAngleLessThan180(TestBeta2); - if(Abs(TestBeta1) < Abs(TestBeta2)) - BetaOffset = -BetaOffset; + BetaOffset = INIT_SYPHON_DEGREE_OFFSET; + Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y); // some unuseds ResetStatics = false; } + if(NegateBetaOffset) + BetaOffset = -INIT_SYPHON_DEGREE_OFFSET; Beta = NewBeta + BetaOffset; Source = TargetCoors; - Source.x += 1.7f*Cos(Beta); - Source.y += 1.7f*Sin(Beta); + Source.x += GroundDist*Cos(Beta); + Source.y += GroundDist*Sin(Beta); + CPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface; + if(ground && (ground->IsVehicle() || ground->IsObject())) + StandingOnMovingThing = true; TargetCoors.z += m_fSyphonModeTargetZOffSet; + + bool PlayerTooClose = false; fAimingDist = (TheCamera.m_cvecAimingTargetCoors - TargetCoors).Magnitude2D(); - if(fAimingDist < 6.5f) + if(fAimingDist < 6.5f){ fAimingDist = 6.5f; + PlayerTooClose = true; + } TargetAlpha = CGeneral::GetATanOfXY(fAimingDist, TheCamera.m_cvecAimingTargetCoors.z - TargetCoors.z); + if(ResetStatics) // BUG: can never happen + Alpha = -TargetAlpha; while(TargetAlpha >= PI) TargetAlpha -= 2*PI; while(TargetAlpha < -PI) TargetAlpha += 2*PI; + while(Alpha >= PI) Alpha -= 2*PI; + while(Alpha < -PI) Alpha += 2*PI; // inlined - WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true); + if(StandingOnMovingThing) + WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f/2.0f, 0.015f/2.0f, true); + else + WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true); - Source.z += fDist*Sin(Alpha) + fDist*0.2f; + Source.z += GroundDist*Sin(Alpha+AlphaOffset) + GroundDist*0.2f; if(Source.z < TargetCoors.z + HeightDown) Source.z = TargetCoors.z + HeightDown; - CameraObscured = CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true); - // PreviousDistForInter unused - if(CameraObscured){ - PreviousDistForInter = (TargetCoors - colPoint.point).Magnitude2D(); - Source = colPoint.point; - }else - PreviousDistForInter = 1.7f; + if(!PlayerTooClose){ + CColPoint point; + CEntity *entity = nil; + CWorld::pIgnoreEntity = CamTargetEntity; + if(CWorld::ProcessLineOfSight(TheCamera.m_cvecAimingTargetCoors, Source, point, entity, true, false, false, true, false, false, true)){ + CVector TestFront = TheCamera.m_cvecAimingTargetCoors - Source; + TestFront.Normalise(); + CVector CamToPlayer = CameraTarget - Source; + CVector CamToCol = point.point - Source; + if(DotProduct(TestFront, CamToCol) > DotProduct(TestFront, CamToPlayer)){ + // collision is beyond player + float ColDist = (TheCamera.m_cvecAimingTargetCoors - point.point).Magnitude(); + CVector PlayerToTarget = TheCamera.m_cvecAimingTargetCoors - CameraTarget; + float PlayerToTargetDist = PlayerToTarget.Magnitude(); + PlayerToTarget.Normalise(); + CVector Center = TheCamera.m_cvecAimingTargetCoors - ColDist*PlayerToTarget; + float Radius = (point.point - Center).Magnitude(); + if(CWorld::TestSphereAgainstWorld(Center, Radius, nil, true, false, false, true, false, true)){ + CVector LineToCol = gaTempSphereColPoints[0].point - Center; + LineToCol -= DotProduct(LineToCol, PlayerToTarget)*PlayerToTarget; + // unused + CVector LineToPrevCol = point.point - Center; + LineToPrevCol -= DotProduct(LineToPrevCol, PlayerToTarget)*PlayerToTarget; + float LineDist = LineToCol.Magnitude(); + float NewBetaOffset = 0.0f; + if(LineDist > 0.0f && ColDist > 0.1f){ + // scale offset at center to offset at player + float DistOffset = LineDist/ColDist * PlayerToTargetDist; + // turn into an angle + NewBetaOffset = 0.9f*Asin(Min(DistOffset/GroundDist, 1.0f)); + } + if(NewBetaOffset < BetaOffset){ + float Ratio = NewBetaOffset / BetaOffset; + BetaOffset = NewBetaOffset; + Beta = NewBeta + NewBetaOffset; + GroundDist *= Max(Ratio, 0.5f); + Source.x = TargetCoors.x + GroundDist*Cos(Beta); + Source.y = TargetCoors.y + GroundDist*Sin(Beta); + Source.z += (1.0f-Ratio)*0.5f; + } + } + } + } + CWorld::pIgnoreEntity = nil; + } - m_cvecTargetCoorsForFudgeInter = TargetCoors; - Front = TargetCoors - Source; - m_fMinDistAwayFromCamWhenInterPolating = Front.Magnitude2D(); - if(m_fMinDistAwayFromCamWhenInterPolating < 1.1f) - RwCameraSetNearClipPlane(Scene.camera, Max(m_fMinDistAwayFromCamWhenInterPolating - 0.35f, 0.05f)); + Front = TheCamera.m_cvecAimingTargetCoors - Source; + float TargetDistGround = Front.Magnitude2D(); Front.Normalise(); + m_cvecTargetCoorsForFudgeInter = Source + TargetDistGround*Front; + m_cvecTargetCoorsForFudgeInter.z = TargetCoors.z; + + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, CameraTarget + CVector(0.0f, 0.0f, 0.75f), Source, FOV); + Source.z = OrigSource.z; + GetVectorsReadyForRW(); } @@ -3182,8 +3156,6 @@ CCam::Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, fl float fDist, TargetDist; float zOffset; float AimingAngle; - CColPoint colPoint; - CEntity *entity; TargetDist = TheCamera.m_fPedZoomValueSmooth * 0.5f + 4.0f; vDist = Source - TargetCoors; @@ -3214,22 +3186,24 @@ CCam::Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, fl Source.x += Cos(Beta) * TargetDist; Source.y += Sin(Beta) * TargetDist; - if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){ - Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y); - fDist = (TargetCoors - colPoint.point).Magnitude2D(); - Source.x = TargetCoors.x; - Source.y = TargetCoors.y; - Source.x += Cos(Beta) * fDist; - Source.y += Sin(Beta) * fDist; - } - TargetCoors = CameraTarget; TargetCoors.z += m_fSyphonModeTargetZOffSet; m_cvecTargetCoorsForFudgeInter = TargetCoors; + + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); + Front = TargetCoors - Source; GetVectorsReadyForRW(); } +float MAX_HEIGHT_UP = 15.0f; +float WATER_Z_ADDITION = 2.75f; +float WATER_Z_ADDITION_MIN = 1.5f; +float SMALLBOAT_CLOSE_ALPHA_MINUS = 0.2f; +float afBoatBetaDiffMult[3] = { 0.15f, 0.07f, 0.01f }; +float afBoatBetaSpeedDiffMult[3] = { 0.02f, 0.015f, 0.005f }; + void CCam::Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float) { @@ -3240,118 +3214,135 @@ CCam::Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, f CVector TargetCoors = CameraTarget; float DeltaBeta = 0.0f; - static CColPoint colPoint; - CEntity *entity; static float TargetWhenChecksWereOn = 0.0f; static float CenterObscuredWhenChecksWereOn = 0.0f; static float WaterZAddition = 2.75f; float WaterLevel = 0.0f; - float s, c; + float MaxHeightUp = MAX_HEIGHT_UP; + static float WaterLevelBuffered = 0.0f; + static float WaterLevelSpeed = 0.0f; + float BetaDiffMult = 0.0f; + float BetaSpeedDiffMult = 0.0f; Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y); FOV = DefaultFOV; + float TargetAlpha = 0.0f; if(ResetStatics){ CenterObscuredWhenChecksWereOn = 0.0f; TargetWhenChecksWereOn = 0.0f; - Beta = TargetOrientation + PI; + }else if(DirectionWasLooking != LOOKING_FORWARD) + Beta = TargetOrientation; + + if(!CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterLevel)) + WaterLevel = TargetCoors.z - 0.5f; + if(ResetStatics){ + WaterLevelBuffered = WaterLevel; + WaterLevelSpeed = 0.0f; } + WellBufferMe(WaterLevel, &WaterLevelBuffered, &WaterLevelSpeed, 0.2f, 0.07f, false); - CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterLevel); - WaterLevel += WaterZAddition; static float FixerForGoingBelowGround = 0.4f; - if(-FixerForGoingBelowGround < TargetCoors.z-WaterLevel) - WaterLevel += TargetCoors.z-WaterLevel - FixerForGoingBelowGround; - - bool Obscured; - if(m_bCollisionChecksOn || ResetStatics){ - CVector TestPoint; - // Weird calculations here, also casting bool to float... - c = Cos(TargetOrientation); - s = Sin(TargetOrientation); - TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) + - (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) + - TargetCoors; - TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth; - float Test1 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true); - - c = Cos(TargetOrientation + 0.8f); - s = Sin(TargetOrientation + DEGTORAD(40.0f)); - TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) + - (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) + - TargetCoors; - TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth; - float Test2 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true); - - c = Cos(TargetOrientation - 0.8); - s = Sin(TargetOrientation - DEGTORAD(40.0f)); - TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) + - (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) + - TargetCoors; - TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth; - float Test3 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true); - - if(Test2 == 0.0f){ - DeltaBeta = TargetOrientation - Beta - DEGTORAD(40.0f); - if(ResetStatics) - Beta = TargetOrientation - DEGTORAD(40.0f); - }else if(Test3 == 0.0f){ - DeltaBeta = TargetOrientation - Beta + DEGTORAD(40.0f); - if(ResetStatics) - Beta = TargetOrientation + DEGTORAD(40.0f); - }else if(Test1 == 0.0f){ - DeltaBeta = 0.0f; - }else if(Test2 != 0.0f && Test3 != 0.0f && Test1 != 0.0f){ - if(ResetStatics) - Beta = TargetOrientation; - DeltaBeta = TargetOrientation - Beta; - } - - c = Cos(Beta); - s = Sin(Beta); - TestPoint.x = TheCamera.CarZoomValueSmooth * -c + - (TheCamera.CarZoomValueSmooth + 7.0f) * -c + - TargetCoors.x; - TestPoint.y = TheCamera.CarZoomValueSmooth * -s + - (TheCamera.CarZoomValueSmooth + 7.0f) * -s + - TargetCoors.y; - TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth; - Obscured = CWorld::ProcessLineOfSight(TestPoint, TargetCoors, colPoint, entity, true, false, false, true, false, true, true); - CenterObscuredWhenChecksWereOn = Obscured; - - // now DeltaBeta == TargetWhenChecksWereOn - Beta, which we need for WellBufferMe below - TargetWhenChecksWereOn = DeltaBeta + Beta; - }else{ - // DeltaBeta = TargetWhenChecksWereOn - Beta; // unneeded since we don't inline WellBufferMe - Obscured = CenterObscuredWhenChecksWereOn != 0.0f; + if(-FixerForGoingBelowGround < TargetCoors.z-WaterLevelBuffered+WATER_Z_ADDITION) + WaterLevelBuffered += TargetCoors.z-WaterLevelBuffered+WATER_Z_ADDITION - FixerForGoingBelowGround; + + CVector BoatDimensions = CamTargetEntity->GetColModel()->boundingBox.GetSize(); + float BoatSize = BoatDimensions.Magnitude2D(); + int index = 0; + TheCamera.GetArrPosForVehicleType(((CVehicle*)CamTargetEntity)->GetVehicleAppearance(), index); + if(TheCamera.CarZoomIndicator == CAM_ZOOM_1){ + TargetAlpha = ZmOneAlphaOffset[index]; + BetaDiffMult = afBoatBetaDiffMult[0]; + BetaSpeedDiffMult = afBoatBetaSpeedDiffMult[0]; + }else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2){ + TargetAlpha = ZmTwoAlphaOffset[index]; + BetaDiffMult = afBoatBetaDiffMult[1]; + BetaSpeedDiffMult = afBoatBetaSpeedDiffMult[1]; + }else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3){ + TargetAlpha = ZmThreeAlphaOffset[index]; + BetaDiffMult = afBoatBetaDiffMult[2]; + BetaSpeedDiffMult = afBoatBetaSpeedDiffMult[2]; + } + if(TheCamera.CarZoomIndicator == CAM_ZOOM_1 && BoatSize < 10.0f){ + TargetAlpha -= SMALLBOAT_CLOSE_ALPHA_MINUS; + BoatSize = 10.0f; + }else if(CCullZones::Cam1stPersonForPlayer()){ + float Water = 0.0f; + // useless call + //CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &Water); + Water = (WaterLevel + WATER_Z_ADDITION_MIN - WaterLevelBuffered - WATER_Z_ADDITION)/(BoatDimensions.z/2.0f + MaxHeightUp); + TargetAlpha = Asin(Clamp(Water, -1.0f, 1.0f)); } - if(Obscured){ - CWorld::ProcessLineOfSight(Source, TargetCoors, colPoint, entity, true, false, false, true, false, true, true); - Source = colPoint.point; - }else{ - // inlined - WellBufferMe(TargetWhenChecksWereOn, &Beta, &BetaSpeed, 0.07f, 0.015f, true); - - s = Sin(Beta); - c = Cos(Beta); - Source = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) + - (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) + - TargetCoors; - Source.z = WaterLevel + TheCamera.CarZoomValueSmooth; + if(ResetStatics){ + Alpha = TargetAlpha; + AlphaSpeed = 0.0f; } + WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.15f, 0.07f, true); - if(TheCamera.CarZoomValueSmooth < 0.05f){ - static float AmountUp = 2.2f; - TargetCoors.z += AmountUp * (0.0f - TheCamera.CarZoomValueSmooth); + if(ResetStatics){ + Beta = TargetOrientation; + DeltaBeta = 0.0f; } - TargetCoors.z += TheCamera.CarZoomValueSmooth + 0.5f; + // inlined + WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, BetaDiffMult * ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed.Magnitude(), BetaSpeedDiffMult, true); + + Source = (TheCamera.CarZoomValueSmooth+BoatSize) * CVector(-Cos(Beta), -Sin(Beta), 0.0f) + TargetCoors; + Source.z = WaterLevelBuffered + WATER_Z_ADDITION + (BoatDimensions.z/2.0f + MaxHeightUp) * Sin(Alpha); + m_cvecTargetCoorsForFudgeInter = TargetCoors; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); Front = TargetCoors - Source; - GetVectorsReadyForRW(); + Front.Normalise(); + + + float TargetRoll; + if(CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetDPadRight()){ +#ifdef FIX_BUGS + float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward()); + if(fwdSpeed > 210.0f) fwdSpeed = 210.0f; +#endif + if(CPad::GetPad(0)->GetDPadLeft()) + TargetRoll = DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle; + else + TargetRoll = -(DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle); + CVector FwdTarget = CamTargetEntity->GetForward(); + FwdTarget.Normalise(); + float AngleDiff = DotProduct(FwdTarget, Front); + AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f)); +#ifdef FIX_BUGS + TargetRoll *= fwdSpeed/210.0f * Sin(AngleDiff); +#else + TargetRoll *= Sin(AngleDiff); +#endif + }else{ + float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward()); + if(fwdSpeed > 210.0f) fwdSpeed = 210.0f; + TargetRoll = CPad::GetPad(0)->GetLeftStickX()/128.0f * fwdSpeed/210.0f; + CVector FwdTarget = CamTargetEntity->GetForward(); + FwdTarget.Normalise(); + float AngleDiff = DotProduct(FwdTarget, Front); + AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f)); + TargetRoll *= (DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle) * Sin(AngleDiff); + } + + WellBufferMe(TargetRoll, &f_Roll, &f_rollSpeed, 0.15f, 0.07f, false); + Up = CVector(Cos(f_Roll + HALFPI), 0.0f, Sin(f_Roll + HALFPI)); + Up.Normalise(); + Front.Normalise(); + CVector Left = CrossProduct(Up, Front); + Left.Normalise(); + Up = CrossProduct(Front, Left); + Up.Normalise(); + ResetStatics = false; } +float FIGHT_HORIZ_DIST = 3.0f; +float FIGHT_VERT_DIST = 1.0f; +float FIGHT_BETA_ANGLE = 125.0f; + void CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float) { @@ -3359,26 +3350,25 @@ CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, fl return; FOV = DefaultFOV; + float HorizDist = FIGHT_HORIZ_DIST; + float VertDist = FIGHT_VERT_DIST; float BetaLeft, BetaRight, DeltaBetaLeft, DeltaBetaRight; - float BetaFix; - float Dist; - float BetaMaxSpeed = 0.015f; - float BetaAcceleration = 0.007f; static bool PreviouslyFailedBuildingChecks = false; float TargetCamHeight; CVector TargetCoors; - m_fMinDistAwayFromCamWhenInterPolating = 4.0f; + m_fMinDistAwayFromCamWhenInterPolating = FIGHT_HORIZ_DIST; Front = Source - CameraTarget; - Beta = CGeneral::GetATanOfXY(Front.x, Front.y); + if(ResetStatics) + Beta = CGeneral::GetATanOfXY(Front.x, Front.y); while(TargetOrientation >= PI) TargetOrientation -= 2*PI; while(TargetOrientation < -PI) TargetOrientation += 2*PI; while(Beta >= PI) Beta -= 2*PI; while(Beta < -PI) Beta += 2*PI; // Figure out Beta - BetaLeft = TargetOrientation - HALFPI; - BetaRight = TargetOrientation + HALFPI; + BetaLeft = TargetOrientation - DEGTORAD(FIGHT_BETA_ANGLE); + BetaRight = TargetOrientation + DEGTORAD(FIGHT_BETA_ANGLE); DeltaBetaLeft = Beta - BetaLeft; DeltaBetaRight = Beta - BetaRight; while(DeltaBetaLeft >= PI) DeltaBetaLeft -= 2*PI; @@ -3402,32 +3392,15 @@ CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, fl m_fTargetBeta = DeltaBetaRight; } - // Check collisions - BetaFix = 0.0f; - Dist = Front.Magnitude2D(); - if(m_bCollisionChecksOn || PreviouslyFailedBuildingChecks){ - BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.25f, 0.0f, true, false, false, true, false); - if(BetaFix == 0.0f){ - BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.5f, DEGTORAD(24.0f), true, false, false, true, false); - if(BetaFix == 0.0f) - BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.5f, -DEGTORAD(24.0f), true, false, false, true, false); - } - } - if(BetaFix != 0.0f){ - BetaMaxSpeed = 0.1f; - PreviouslyFailedBuildingChecks = true; - BetaAcceleration = 0.025f; - m_fTargetBeta = Beta + BetaFix; - } - WellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true); + WellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, 0.015f, 0.007f, true); - Source = CameraTarget + 4.0f*CVector(Cos(Beta), Sin(Beta), 0.0f); - Source.z -= 0.5f; + Source = CameraTarget + HorizDist*CVector(Cos(Beta), Sin(Beta), 0.0f); + Source.z += VertDist; WellBufferMe(TargetOrientation, &m_fBufferedTargetOrientation, &m_fBufferedTargetOrientationSpeed, 0.07f, 0.004f, true); - TargetCoors = CameraTarget + 0.5f*CVector(Cos(m_fBufferedTargetOrientation), Sin(m_fBufferedTargetOrientation), 0.0f); + TargetCoors = CameraTarget + 0.1f*CVector(Cos(m_fBufferedTargetOrientation), Sin(m_fBufferedTargetOrientation), 0.0f); - TargetCamHeight = CameraTarget.z - Source.z + Max(m_fPedBetweenCameraHeightOffset, m_fRoadOffSet + m_fDimensionOfHighestNearCar) - 0.5f; + TargetCamHeight = CameraTarget.z - Source.z + Max(m_fPedBetweenCameraHeightOffset, m_fDimensionOfHighestNearCar) + VertDist; if(TargetCamHeight > m_fCamBufferedHeight) WellBufferMe(TargetCamHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.15f, 0.04f, false); else @@ -3435,6 +3408,8 @@ CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, fl Source.z += m_fCamBufferedHeight; m_cvecTargetCoorsForFudgeInter = TargetCoors; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); Front = TargetCoors - Source; Front.Normalise(); GetVectorsReadyForRW(); @@ -3553,6 +3528,11 @@ CCam::Process_FlyBy(const CVector&, float, float, float) if(TheCamera.m_bcutsceneFinished) return; +#ifdef FIX_BUGS + // this would crash, not nice when cycling debug mode + if(TheCamera.m_arrPathArray[0].m_arr_PathData == nil) + return; +#endif Up = CVector(0.0f, 0.0f, 1.0f); if(TheCamera.m_bStartingSpline) @@ -3631,37 +3611,105 @@ CCam::Process_FlyBy(const CVector&, float, float, float) FOV = PsuedoFOV; } -void +CVector vecWheelCamBoatOffset(-0.5f, -0.8f, 0.3f); +CVector vecWheelCamBoatOffsetAlt(0.2f, -0.2f, -0.3f); +float fWheelCamCarXOffset = 0.33f; +float fWheelCamBikeXOffset = 0.2f; + +bool CCam::Process_WheelCam(const CVector&, float, float, float) { FOV = DefaultFOV; + CVector WheelPos; if(CamTargetEntity->IsPed()){ // what? ped with wheels or what? Source = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-0.3f, -0.5f, 0.1f)); Source += CamTargetEntity->GetPosition(); Front = CVector(1.0f, 0.0f, 0.0f); }else{ - Source = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f)); - Source += CamTargetEntity->GetPosition(); + WheelPos = CamTargetEntity->GetColModel()->boundingBox.min; + WheelPos.x -= 0.33f; + WheelPos.y = -2.3f; + WheelPos.z = 0.3f; + Source = CamTargetEntity->GetMatrix() * WheelPos; Front = CamTargetEntity->GetForward(); } - CVector NewUp(0.0f, 0.0f, 1.0f); - CVector Right = CrossProduct(Front, NewUp); - Right.Normalise(); - NewUp = CrossProduct(Right, Front); - NewUp.Normalise(); + CVector NewUp, Right; + if(CamTargetEntity->IsVehicle() && + (((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || + ((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)){ + WheelPos.x = -1.55f; + Right = CamTargetEntity->GetRight(); + NewUp = CamTargetEntity->GetUp(); + Source = CamTargetEntity->GetMatrix() * WheelPos; + }else if(CamTargetEntity->IsVehicle() && ((CVehicle*)CamTargetEntity)->IsBoat()){ + NewUp = CVector(0.0f, 0.0f, 1.0f); + Right = CrossProduct(Front, NewUp); + Right.Normalise(); + NewUp = CrossProduct(Right, Front); + NewUp.Normalise(); + + CVector BoatCamPos(0.0f, 0.0f, 0.0f); + if(((CVehicle*)CamTargetEntity)->pDriver){ + ((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(BoatCamPos, PED_HEAD); + BoatCamPos += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed * CTimer::GetTimeStep(); + BoatCamPos += vecWheelCamBoatOffset.x * Right; + BoatCamPos += vecWheelCamBoatOffset.y * CamTargetEntity->GetForward(); + BoatCamPos.z += vecWheelCamBoatOffset.z; + if(CamTargetEntity->GetModelIndex() == MI_PREDATOR){ + BoatCamPos += vecWheelCamBoatOffsetAlt.x * Right; + BoatCamPos += vecWheelCamBoatOffsetAlt.y * CamTargetEntity->GetForward(); + BoatCamPos.z += vecWheelCamBoatOffsetAlt.z; + } + Source = BoatCamPos; + }else + Source.z += 2.0f*vecWheelCamBoatOffset.z; + }else if(CamTargetEntity->IsVehicle() && ((CVehicle*)CamTargetEntity)->IsBike()){ + NewUp = CVector(0.0f, 0.0f, 1.0f); + Right = CrossProduct(Front, NewUp); + Right.Normalise(); + NewUp = CrossProduct(Right, Front); + NewUp.Normalise(); + + WheelPos.z += fWheelCamCarXOffset - fWheelCamBikeXOffset; + Source = CamTargetEntity->GetPosition(); + Source += WheelPos.x * CamTargetEntity->GetRight(); + Source += WheelPos.y * Front; + Source += WheelPos.z * Up; + }else{ + NewUp = CVector(0.0f, 0.0f, 1.0f); + Right = CrossProduct(Front, NewUp); + Right.Normalise(); + NewUp = CrossProduct(Right, Front); + NewUp.Normalise(); + } float Roll = Cos((CTimer::GetTimeInMilliseconds()&0x1FFFF)/(float)0x1FFFF * TWOPI); Up = Cos(Roll*0.4f)*NewUp + Sin(Roll*0.4f)*Right; + + CEntity *entity = nil; + CColPoint point; + CWorld::pIgnoreEntity = CamTargetEntity; + bool blocked = CWorld::ProcessLineOfSight(Source, CamTargetEntity->GetPosition(), point, entity, true, false, false, true, false, false, true); + CWorld::pIgnoreEntity = nil; + return !blocked; } +int BOAT_UNDERWATER_CAM_BLUR = 20; +float BOAT_UNDERWATER_CAM_COLORMAG_LIMIT = 10.0f; + +//--MIAIM: done void CCam::Process_Fixed(const CVector &CameraTarget, float, float, float) { + if(DirectionWasLooking != LOOKING_FORWARD) + DirectionWasLooking = LOOKING_FORWARD; + Source = m_cvecCamFixedModeSource; Front = CameraTarget - Source; + Front.Normalise(); m_cvecTargetCoorsForFudgeInter = CameraTarget; GetVectorsReadyForRW(); @@ -3675,8 +3723,23 @@ CCam::Process_Fixed(const CVector &CameraTarget, float, float, float) if(TheCamera.m_bUseSpecialFovTrain) FOV = TheCamera.m_fFovForTrain; + float WaterZ = 0.0f; + if(CWaterLevel::GetWaterLevel(Source, &WaterZ, true) && Source.z < WaterZ){ + float WaterLum = Sqrt(SQR(CTimeCycle::GetWaterRed()) + SQR(CTimeCycle::GetWaterGreen()) + SQR(CTimeCycle::GetWaterBlue())); + if(WaterLum > BOAT_UNDERWATER_CAM_COLORMAG_LIMIT){ + float f = BOAT_UNDERWATER_CAM_COLORMAG_LIMIT/WaterLum; + TheCamera.SetMotionBlur(CTimeCycle::GetWaterRed()*f, + CTimeCycle::GetWaterGreen()*f, + CTimeCycle::GetWaterBlue()*f, BOAT_UNDERWATER_CAM_BLUR, MOTION_BLUR_LIGHT_SCENE); + }else{ + TheCamera.SetMotionBlur(CTimeCycle::GetWaterRed(), + CTimeCycle::GetWaterGreen(), + CTimeCycle::GetWaterBlue(), BOAT_UNDERWATER_CAM_BLUR, MOTION_BLUR_LIGHT_SCENE); + } + } + #ifdef PC_PLAYER_CONTROLS - if(CMenuManager::m_ControlMethod == CONTROL_STANDARD && Using3rdPersonMouseCam()){ + if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD && Using3rdPersonMouseCam()){ CPed *player = FindPlayerPed(); if(player && player->CanStrafeOrMouseControl()){ float Heading = Front.Heading(); @@ -3690,16 +3753,81 @@ CCam::Process_Fixed(const CVector &CameraTarget, float, float, float) } void +CCam::Process_LightHouse(const CVector &CameraTarget, float, float, float) +{ + static float Timer; + + Source = CameraTarget; + Source.x = 474.3f; + Source.y = -1717.6f; + + int CamMode; + if(CameraTarget.z > 57.0f && (CameraTarget-Source).Magnitude2D() > 3.2f){ + // Outside at top + if(Timer > 0.0f){ + Timer -= CTimer::GetTimeStep(); + CamMode = 1; + }else{ + Timer = -24.0f; + CamMode = 2; + } + }else if(CameraTarget.z > 57.0f){ + // Inside at top + if(Timer < 0.0f){ + Timer += CTimer::GetTimeStep(); + CamMode = 2; + }else{ + Timer = 24.0f; + CamMode = 1; + } + }else{ + Timer = 0.0f; + CamMode = 0; + } + + if(CamMode == 2){ + Source.z = 57.5f; + Front = Source - CameraTarget; + Front.Normalise(); + Source.x = CameraTarget.x - 5.0f*Front.x; + Source.y = CameraTarget.y - 5.0f*Front.y; + }else if(CamMode == 1){ + Front = CameraTarget - Source; + Front.Normalise(); + Source.x = CameraTarget.x - 2.0f*Front.x; + Source.y = CameraTarget.y - 2.0f*Front.y; + }else{ + Source.z += 4.0f; + Front = CameraTarget - Source; + Front.Normalise(); + Source -= 4.0f*Front; + Source.z = Min(Source.z, 55.0f); + Front = CameraTarget - Source; + } + + m_cvecTargetCoorsForFudgeInter = CameraTarget; + GetVectorsReadyForRW(); + + Up = CVector(0.0f, 0.0f, 1.0f) + m_cvecCamFixedModeUpOffSet; + Up.Normalise(); + CVector Right = CrossProduct(Front, Up); + Right.Normalise(); + Up = CrossProduct(Right, Front); + + FOV = DefaultFOV; + if(TheCamera.m_bUseSpecialFovTrain) // uh, sure... + FOV = TheCamera.m_fFovForTrain; +} + +void CCam::Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float) { CColPoint colPoint; CEntity *entity = nil; FOV = DefaultFOV; - Source = CameraTarget; - Source.x += -4.5f*Cos(TargetOrientation); - Source.y += -4.5f*Sin(TargetOrientation); - Source.z = m_vecLastAboveWaterCamPosition.z + 4.0f; + Source = m_vecLastAboveWaterCamPosition; + Source.z += 4.0f; m_cvecTargetCoorsForFudgeInter = CameraTarget; Front = CameraTarget - Source; @@ -3711,20 +3839,6 @@ CCam::Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrien Front.Normalise(); } -// unused -void -CCam::Process_Circle(const CVector &CameraTarget, float, float, float) -{ - FOV = DefaultFOV; - - Front.x = Cos(0.7f) * Cos((CTimer::GetTimeInMilliseconds()&0xFFF)/(float)0xFFF * TWOPI); - Front.y = Cos(0.7f) * Sin((CTimer::GetTimeInMilliseconds()&0xFFF)/(float)0xFFF * TWOPI); - Front.z = -Sin(0.7f); - Source = CameraTarget - 4.0f*Front; - Source.z += 1.0f; - GetVectorsReadyForRW(); -} - void CCam::Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float) { @@ -3732,6 +3846,8 @@ CCam::Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, f m_cvecTargetCoorsForFudgeInter = CameraTarget; m_cvecTargetCoorsForFudgeInter.z += m_fSyphonModeTargetZOffSet; Front = CameraTarget - Source; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV); Front.z += m_fSyphonModeTargetZOffSet; GetVectorsReadyForRW(); @@ -3848,7 +3964,7 @@ CCam::Process_Debug(const CVector&, float, float, float) if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn) CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source, 12.0f, 0.0f, 0.0f, -12.0f, - 128, 128, 128, 128, 1000.0f, false, 1.0f); + 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false); if(CHud::m_Wants_To_Draw_Hud){ char str[256]; @@ -3913,7 +4029,7 @@ CCam::Process_Debug(const CVector&, float, float, float) if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn) CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source, 12.0f, 0.0f, 0.0f, -12.0f, - 128, 128, 128, 128, 1000.0f, false, 1.0f); + 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, 1.0f); if(CHud::m_Wants_To_Draw_Hud){ char str[256]; @@ -3994,7 +4110,7 @@ CCam::Process_Editor(const CVector&, float, float, float) if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn) CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source, 12.0f, 0.0f, 0.0f, -12.0f, - 128, 128, 128, 128, 1000.0f, false, 1.0f); + 128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false); if(CHud::m_Wants_To_Draw_Hud){ char str[256]; @@ -4034,109 +4150,374 @@ CCam::Process_ModelView(const CVector &CameraTarget, float, float, float) GetVectorsReadyForRW(); } +float DEADCAM_HEIGHT_START = 2.0f; +float DEADCAM_HEIGHT_RATE = 0.04f; +float DEADCAM_WAFT_AMPLITUDE = 2.0f; +float DEADCAM_WAFT_RATE = 600.0f; +float DEADCAM_WAFT_TILT_AMP = -0.35f; + void CCam::ProcessPedsDeadBaby(void) { - float Distance = 0.0f; - static bool SafeToRotate = false; - CVector TargetDist, TestPoint; + CVector TargetCoors; + CVector CamPos; - FOV = DefaultFOV; - TargetDist = Source - CamTargetEntity->GetPosition(); - Distance = TargetDist.Magnitude(); - Beta = CGeneral::GetATanOfXY(TargetDist.x, TargetDist.y); - while(Beta >= PI) Beta -= 2*PI; - while(Beta < -PI) Beta += 2*PI; + if(TheCamera.pTargetEntity->IsPed()) + ((CPed*)TheCamera.pTargetEntity)->m_pedIK.GetComponentPosition(TargetCoors, PED_MID); + else if(TheCamera.pTargetEntity->IsVehicle()){ + TargetCoors = TheCamera.pTargetEntity->GetPosition(); + TargetCoors.z += TheCamera.pTargetEntity->GetColModel()->boundingBox.max.z; + }else + return; if(ResetStatics){ - TestPoint = CamTargetEntity->GetPosition() + - CVector(4.0f * Cos(Alpha) * Cos(Beta), - 4.0f * Cos(Alpha) * Sin(Beta), - 4.0f * Sin(Alpha)); - bool Safe1 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true); - - TestPoint = CamTargetEntity->GetPosition() + - CVector(4.0f * Cos(Alpha) * Cos(Beta + DEGTORAD(120.0f)), - 4.0f * Cos(Alpha) * Sin(Beta + DEGTORAD(120.0f)), - 4.0f * Sin(Alpha)); - bool Safe2 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true); - - TestPoint = CamTargetEntity->GetPosition() + - CVector(4.0f * Cos(Alpha) * Cos(Beta - DEGTORAD(120.0f)), - 4.0f * Cos(Alpha) * Sin(Beta - DEGTORAD(120.0f)), - 4.0f * Sin(Alpha)); - bool Safe3 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true); - - SafeToRotate = Safe1 && Safe2 && Safe3; - + TheCamera.m_uiTimeLastChange = CTimer::GetTimeInMilliseconds(); + CamPos = TargetCoors; + CamPos.z += DEADCAM_HEIGHT_START; + float WaterZ = 0.0f; + if(CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterZ)){ + if(WaterZ + 1.5f > CamPos.z) + CamPos.z = WaterZ + 1.5f; + } + CVector Right = CrossProduct(TheCamera.pTargetEntity->GetForward(), CVector(0.0f, 0.0f, 1.0f)); + Right.z = 0.0f; + Right.Normalise(); + Front = TargetCoors - CamPos; + Front.Normalise(); + Up = CrossProduct(Right, Front); + Up.Normalise(); ResetStatics = false; + }else{ + CamPos = Source; + if(CWorld::TestSphereAgainstWorld(CamPos+CVector(0.0f, 0.0f, 0.2f), 0.3f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil) + CamPos.z += DEADCAM_HEIGHT_RATE*CTimer::GetTimeStep(); + CVector Right = CrossProduct(TheCamera.pTargetEntity->GetForward(), CVector(0.0f, 0.0f, 1.0f)); + Right.z = 0.0f; + Right.Normalise(); + + float Time = CTimer::GetTimeInMilliseconds() - TheCamera.m_uiTimeLastChange; + CVector WaftOffset = DEADCAM_WAFT_AMPLITUDE * Min(1000.0f,Time)/1000.0f * Sin(Time/DEADCAM_WAFT_RATE) * Right; + CVector WaftPos = TargetCoors + WaftOffset; + WaftPos.z = CamPos.z; + CVector WaftFront = WaftPos - CamPos; + WaftFront.Normalise(); + if(CWorld::TestSphereAgainstWorld(CamPos+0.2f*WaftFront, 0.3f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil) + CamPos = WaftPos; + + Front = CVector(0.0f, 0.0f, -1.0f); + Front += Cos(Time/DEADCAM_WAFT_RATE) * DEADCAM_WAFT_TILT_AMP * Min(2000.0f,Time)/2000.0f * Right; + + Front.Normalise(); + Up = CrossProduct(Right, Front); + Up.Normalise(); } - if(SafeToRotate) - WellBufferMe(Beta + DEGTORAD(175.0f), &Beta, &BetaSpeed, 0.015f, 0.007f, true); + Source = CamPos; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV); + TheCamera.m_bMoveCamToAvoidGeom = false; +} - WellBufferMe(DEGTORAD(89.5f), &Alpha, &AlphaSpeed, 0.015f, 0.07f, true); - WellBufferMe(35.0f, &Distance, &DistanceSpeed, 0.006f, 0.007f, false); +float ARRESTDIST_BEHIND_COP = 5.0f; +float ARRESTDIST_RIGHTOF_COP = 3.0f; +float ARRESTDIST_ABOVE_COP = 1.4f; // unused +float ARRESTDIST_MINFROM_PLAYER = 8.0f; +float ARRESTCAM_LAMP_BEST_DIST = 17.0f; +float ARRESTCAM_ROTATION_SPEED = 0.1f; +float ARRESTCAM_ROTATION_UP = 0.05f; +float ARRESTCAM_S_ROTATION_UP = 0.1f; +float ARRESTDIST_ALONG_GROUND = 5.0f; +float ARRESTDIST_SIDE_GROUND = 10.0f; +float ARRESTDIST_ABOVE_GROUND = 0.7f; +float ARRESTCAM_LAMPPOST_ROTATEDIST = 10.0f; +float ARRESTCAM_LAMPPOST_TRANSLATE = 0.1f; - Source = CamTargetEntity->GetPosition() + - CVector(Distance * Cos(Alpha) * Cos(Beta), - Distance * Cos(Alpha) * Sin(Beta), - Distance * Sin(Alpha)); - m_cvecTargetCoorsForFudgeInter = CamTargetEntity->GetPosition(); - Front = CamTargetEntity->GetPosition() - Source; - Front.Normalise(); - GetVectorsReadyForRW(); +bool +CCam::GetLookAlongGroundPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut) +{ + if(Target == nil || Cop == nil) + return false; + CVector CopToTarget = TargetCoors - Cop->GetPosition(); + CopToTarget.z = 0.0f; + CopToTarget.Normalise(); + SourceOut = TargetCoors + ARRESTDIST_ALONG_GROUND*CopToTarget; + CVector Side = CrossProduct(CopToTarget, CVector(0.0f, 0.0f, 1.0f)); + SourceOut += ARRESTDIST_SIDE_GROUND*Side; + SourceOut.z += 5.0f; + bool found = false; + float ground = CWorld::FindGroundZFor3DCoord(SourceOut.x, SourceOut.y, SourceOut.z, &found); + if(found) + SourceOut.z = ground + ARRESTDIST_ABOVE_GROUND; + return true; } bool +CCam::GetLookFromLampPostPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut) +{ + int i; + int16 NumObjects; + CEntity *Objects[16]; + CEntity *NearestLampPost = nil; + CWorld::FindObjectsInRange(TargetCoors, 30.0f, true, &NumObjects, 15, Objects, false, false, false, true, true); + float NearestDist = 10000.0f; + for(i = 0; i < NumObjects; i++){ + if(Objects[i]->GetIsStatic() && Objects[i]->GetUp().z > 0.9f && IsLampPost(Objects[i]->GetModelIndex())){ + float Dist = (Objects[i]->GetPosition() - TargetCoors).Magnitude2D(); + if(Abs(ARRESTCAM_LAMP_BEST_DIST - Dist) < NearestDist){ + CVector TestStart = Objects[i]->GetColModel()->boundingBox.max; + TestStart = Objects[i]->GetMatrix() * TestStart; + CVector TestEnd = TestStart - TargetCoors; + TestEnd.Normalise(); + TestEnd += TargetCoors; + if(CWorld::GetIsLineOfSightClear(TestStart, TestEnd, true, false, false, false, false, true, true)){ + NearestDist = Abs(ARRESTCAM_LAMP_BEST_DIST - Dist); + NearestLampPost = Objects[i]; + SourceOut = TestStart; + } + } + } + } + return NearestLampPost != nil; +} + +bool +CCam::GetLookOverShoulderPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut) +{ + if(Target == nil || Cop == nil) + return false; + CVector CopCoors = Cop->GetPosition(); + CVector CopToTarget = TargetCoors - CopCoors; + CVector Side = CrossProduct(CopToTarget, CVector(0.0f, 0.0f, 1.0f)); + Side.Normalise(); + CopCoors += ARRESTDIST_RIGHTOF_COP * Side; + CopToTarget.Normalise(); + if(CopToTarget.z < -0.7071f){ + CopToTarget.z = -0.7071f; + float GroundDist = CopToTarget.Magnitude2D(); + if(GroundDist > 0.0f){ + CopToTarget.x *= 0.7071f/GroundDist; + CopToTarget.y *= 0.7071f/GroundDist; + } + CopToTarget.Normalise(); + }else{ + if(CopToTarget.z > 0.0f){ + CopToTarget.z = 0.0f; + CopToTarget.Normalise(); + } + } + CopCoors -= ARRESTDIST_BEHIND_COP * CopToTarget; + CopToTarget = TargetCoors - CopCoors; + float Dist = CopToTarget.Magnitude(); + if(Dist < ARRESTDIST_MINFROM_PLAYER && Dist > 0.0f) + CopToTarget *= ARRESTDIST_MINFROM_PLAYER/Dist; + SourceOut = TargetCoors - CopToTarget; + return true; +} + +enum { + ARRESTCAM_OVERSHOULDER = 1, + ARRESTCAM_ALONGGROUND, + ARRESTCAM_ALONGGROUND_RIGHT, + ARRESTCAM_ALONGGROUND_RIGHT_UP, + ARRESTCAM_ALONGGROUND_LEFT, + ARRESTCAM_ALONGGROUND_LEFT_UP, + ARRESTCAM_LAMPPOST, +}; + +int nUsingWhichCamera; +CPed *pStoredCopPed; + +bool CCam::ProcessArrestCamOne(void) { + CVector TargetPos; + CVector CamSource; + CPed *cop = nil; FOV = 45.0f; - if(!ResetStatics) - return true; + bool foundPos = false; + int ArrestModes[5] = { -1, -1, -1, -1, -1 }; -#ifdef FIX_BUGS - if(!CamTargetEntity->IsPed() || ((CPlayerPed*)TheCamera.pTargetEntity)->m_pArrestingCop == nil) - return true; -#endif + if(ResetStatics){ + CPed *targetPed = (CPed*)TheCamera.pTargetEntity; + nUsingWhichCamera = 0; + if(TheCamera.pTargetEntity->IsPed()){ + ((CPed*)TheCamera.pTargetEntity)->m_pedIK.GetComponentPosition(TargetPos, PED_MID); + if(FindPlayerPed() && FindPlayerPed()->m_pArrestingCop) + cop = FindPlayerPed()->m_pArrestingCop; + if(cop && CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.5f){ + ArrestModes[0] = ARRESTCAM_OVERSHOULDER; + ArrestModes[1] = ARRESTCAM_ALONGGROUND; + ArrestModes[2] = ARRESTCAM_OVERSHOULDER; + ArrestModes[3] = ARRESTCAM_LAMPPOST; + }else{ + ArrestModes[0] = ARRESTCAM_ALONGGROUND; + ArrestModes[1] = ARRESTCAM_OVERSHOULDER; + ArrestModes[2] = ARRESTCAM_LAMPPOST; + } + }else if(TheCamera.pTargetEntity->IsVehicle()){ + CVehicle *targetVehicle = (CVehicle*)TheCamera.pTargetEntity; + if(targetVehicle->pDriver && targetVehicle->pDriver->IsPlayer()){ + targetPed = targetVehicle->pDriver; + targetPed->m_pedIK.GetComponentPosition(TargetPos, PED_MID); + }else{ + targetPed = nil; + TargetPos = targetVehicle->GetPosition(); + } - bool found; - float Ground; - CVector PlayerCoors = TheCamera.pTargetEntity->GetPosition(); - CVector CopCoors = ((CPlayerPed*)TheCamera.pTargetEntity)->m_pArrestingCop->GetPosition(); - Beta = CGeneral::GetATanOfXY(PlayerCoors.x - CopCoors.x, PlayerCoors.y - CopCoors.y); - - Source = PlayerCoors + 9.5f*CVector(Cos(Beta), Sin(Beta), 0.0f); - Source.z += 6.0f; - Ground = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, Source.z, &found); - if(!found){ - Ground = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, Source.z, &found); - if(!found) + if(FindPlayerPed() && FindPlayerPed()->m_pArrestingCop) + cop = FindPlayerPed()->m_pArrestingCop; + if(cop && CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.65f){ + ArrestModes[0] = ARRESTCAM_OVERSHOULDER; + ArrestModes[1] = ARRESTCAM_LAMPPOST; + ArrestModes[2] = ARRESTCAM_ALONGGROUND; + ArrestModes[3] = ARRESTCAM_OVERSHOULDER; + }else{ + ArrestModes[0] = ARRESTCAM_LAMPPOST; + ArrestModes[1] = ARRESTCAM_ALONGGROUND; + ArrestModes[2] = ARRESTCAM_OVERSHOULDER; + } + }else return false; + + for(int i = 0; nUsingWhichCamera == 0 && i < ARRAY_SIZE(ArrestModes) && ArrestModes[i] > 0; i++){ + switch(ArrestModes[i]){ + case ARRESTCAM_OVERSHOULDER: + if(cop){ + foundPos = GetLookOverShoulderPos(TheCamera.pTargetEntity, cop, TargetPos, CamSource); + pStoredCopPed = cop; + cop = nil; + }else if(targetPed){ + for(int j = 0; j < targetPed->m_numNearPeds; j++){ + CPed *nearPed = targetPed->m_nearPeds[j]; + if(nearPed->GetPedState() == PED_ARREST_PLAYER) + foundPos = GetLookOverShoulderPos(TheCamera.pTargetEntity, nearPed, TargetPos, CamSource); + if(foundPos){ + pStoredCopPed = nearPed; + break; + } + } + } + break; + case ARRESTCAM_ALONGGROUND: + if(cop){ + foundPos = GetLookAlongGroundPos(TheCamera.pTargetEntity, cop, TargetPos, CamSource); + pStoredCopPed = cop; + cop = nil; + }else if(targetPed){ + for(int j = 0; j < targetPed->m_numNearPeds; j++){ + CPed *nearPed = targetPed->m_nearPeds[j]; + if(nearPed->GetPedState() == PED_ARREST_PLAYER) + foundPos = GetLookAlongGroundPos(TheCamera.pTargetEntity, nearPed, TargetPos, CamSource); + if(foundPos){ + pStoredCopPed = nearPed; + break; + } + } + } + break; + case ARRESTCAM_LAMPPOST: + foundPos = GetLookFromLampPostPos(TheCamera.pTargetEntity, cop, TargetPos, CamSource); + break; + } + + if(foundPos){ + if(pStoredCopPed) + pStoredCopPed->RegisterReference((CEntity**)&pStoredCopPed); + nUsingWhichCamera = ArrestModes[i]; + if(ArrestModes[i] == ARRESTCAM_ALONGGROUND){ + float rnd = CGeneral::GetRandomNumberInRange(0.0f, 5.0f); + if(rnd < 1.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND; + else if(rnd < 2.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND_RIGHT; + else if(rnd < 3.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND_RIGHT_UP; + else if(rnd < 4.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND_LEFT; + else nUsingWhichCamera = ARRESTCAM_ALONGGROUND_LEFT_UP; + } + }else + pStoredCopPed = nil; + } + + Source = CamSource; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetPos, Source, FOV); + Front = TargetPos - Source; + Front.Normalise(); + Up = CVector(0.0f, 0.0f, 1.0f); + CVector Right = CrossProduct(Front, Up); + Right.Normalise(); + Up = CrossProduct(Right, Front); + if(nUsingWhichCamera != 0) + ResetStatics = false; + return true; } - Source.z = Ground + 0.25f; - if(!CWorld::GetIsLineOfSightClear(Source, CopCoors, true, true, false, true, false, true, true)){ - Beta += DEGTORAD(115.0f); - Source = PlayerCoors + 9.5f*CVector(Cos(Beta), Sin(Beta), 0.0f); - Source.z += 6.0f; - Ground = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, Source.z, &found); - if(!found){ - Ground = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, Source.z, &found); - if(!found) - return false; + + if(TheCamera.pTargetEntity->IsPed()){ + ((CPed*)TheCamera.pTargetEntity)->m_pedIK.GetComponentPosition(TargetPos, PED_MID); + }else if(TheCamera.pTargetEntity->IsVehicle()){ + CPed *driver = ((CVehicle*)TheCamera.pTargetEntity)->pDriver; + if(driver && driver->IsPlayer()) + driver->m_pedIK.GetComponentPosition(TargetPos, PED_MID); + else + TargetPos = TheCamera.pTargetEntity->GetPosition(); + }else + return false; + + if(nUsingWhichCamera == ARRESTCAM_OVERSHOULDER && pStoredCopPed){ + foundPos = GetLookOverShoulderPos(TheCamera.pTargetEntity, pStoredCopPed, TargetPos, CamSource); + float newZ = Source.z + ARRESTCAM_S_ROTATION_UP*CTimer::GetTimeStep(); + if(CamSource.z > newZ) + CamSource.z = newZ; + }else if(nUsingWhichCamera >= ARRESTCAM_ALONGGROUND_RIGHT && nUsingWhichCamera <= ARRESTCAM_ALONGGROUND_LEFT_UP){ + CamSource = Source; + Front = TargetPos - CamSource; + Front.Normalise(); + Up = CVector(0.0f, 0.0f, 1.0f); + CVector Right = CrossProduct(Front, Up); + if(nUsingWhichCamera == ARRESTCAM_ALONGGROUND_LEFT || nUsingWhichCamera == ARRESTCAM_ALONGGROUND_LEFT_UP) + Right *= -1.0f; + if(CWorld::TestSphereAgainstWorld(CamSource + 0.5f*Right, 0.4f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil){ + foundPos = true; + CamSource += Right*ARRESTCAM_ROTATION_SPEED*CTimer::GetTimeStep(); + if(nUsingWhichCamera == ARRESTCAM_ALONGGROUND_RIGHT_UP || nUsingWhichCamera == ARRESTCAM_ALONGGROUND_LEFT_UP){ + CamSource.z += ARRESTCAM_ROTATION_UP*CTimer::GetTimeStep(); + }else{ + bool found = false; + float ground = CWorld::FindGroundZFor3DCoord(CamSource.x, CamSource.y, CamSource.z, &found); + if(found) + CamSource.z = ground + ARRESTDIST_ABOVE_GROUND; + } } - Source.z = Ground + 0.25f; + }else if(nUsingWhichCamera == ARRESTCAM_LAMPPOST){ + CamSource = Source; + Front = TargetPos - CamSource; + Front.z = 0.0f; + Front.Normalise(); + Up = CVector(0.0f, 0.0f, 1.0f); + CVector Right = CrossProduct(Front, Up); + Right.Normalise(); + Front = TargetPos - CamSource + Right*ARRESTCAM_LAMPPOST_ROTATEDIST; + Front.z = 0.0f; + Front.Normalise(); + if(CWorld::TestSphereAgainstWorld(CamSource + 0.5f*Front, 0.4f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil){ + foundPos = true; + CamSource += Front*ARRESTCAM_LAMPPOST_TRANSLATE*CTimer::GetTimeStep(); + } + } - CopCoors.z += 0.35f; - Front = CopCoors - Source; - if(!CWorld::GetIsLineOfSightClear(Source, CopCoors, true, true, false, true, false, true, true)) - return false; + if(foundPos){ + Source = CamSource; + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetPos, Source, FOV); + Front = TargetPos - Source; + Front.Normalise(); + Up = CVector(0.0f, 0.0f, 1.0f); + CVector Right = CrossProduct(Front, Up); + Right.Normalise(); + Up = CrossProduct(Right, Front); + }else{ + CVector OrigSource = Source; + TheCamera.AvoidTheGeometry(OrigSource, TargetPos, Source, FOV); } - CopCoors.z += 0.35f; - m_cvecTargetCoorsForFudgeInter = CopCoors; - Front = CopCoors - Source; - ResetStatics = false; - GetVectorsReadyForRW(); + return true; } @@ -4186,376 +4567,6 @@ CCam::ProcessArrestCamTwo(void) } -/* - * Unused PS2 cams - */ - -void -CCam::Process_Chris_With_Binding_PlusRotation(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - static float AngleToBinned = 0.0f; - static float StartingAngleLastChange = 0.0f; - static float FixedTargetOrientation = 0.0f; - static float DeadZoneReachedOnePrevious; - - FOV = DefaultFOV; // missing in game - - bool FixOrientation = true; - if(ResetStatics){ - Rotating = false; - DeadZoneReachedOnePrevious = 0.0f; - FixedTargetOrientation = 0.0f; - ResetStatics = false; - } - - CVector TargetCoors = CameraTarget; - - float StickX = CPad::GetPad(0)->GetRightStickX(); - float StickY = CPad::GetPad(0)->GetRightStickY(); - float StickAngle; - if(StickX != 0.0 || StickY != 0.0f) // BUG: game checks StickX twice - StickAngle = CGeneral::GetATanOfXY(StickX, StickY); // result unused? - else - FixOrientation = false; - - CVector Dist = Source - TargetCoors; - Source.z = TargetCoors.z + 0.75f; - float Length = Dist.Magnitude2D(); - if(Length > 2.5f){ - Source.x = TargetCoors.x + Dist.x/Length * 2.5f; - Source.y = TargetCoors.y + Dist.y/Length * 2.5f; - }else if(Length < 2.4f){ - Source.x = TargetCoors.x + Dist.x/Length * 2.4f; - Source.y = TargetCoors.y + Dist.y/Length * 2.4f; - } - - Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y); - if(CPad::GetPad(0)->GetLeftShoulder1()){ - FixedTargetOrientation = TargetOrientation; - Rotating = true; - } - - if(FixOrientation){ - Rotating = true; - FixedTargetOrientation = StickX/128.0f + Beta - PI; - } - - if(Rotating){ - Dist = Source - TargetCoors; - Length = Dist.Magnitude2D(); - // inlined - WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true); - - Source.x = TargetCoors.x + Length*Cos(Beta); - Source.y = TargetCoors.y + Length*Sin(Beta); - - float DeltaBeta = FixedTargetOrientation+PI - Beta; - while(DeltaBeta >= PI) DeltaBeta -= 2*PI; - while(DeltaBeta < -PI) DeltaBeta += 2*PI; - if(Abs(DeltaBeta) < 0.06f) - Rotating = false; - } - - Front = TargetCoors - Source; - Front.Normalise(); - CVector Front2 = Front; - Front2.Normalise(); // What? - // FIX: the meaning of this value must have changed somehow - Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f; -// Source += Front2 * TheCamera.m_fPedZoomValueSmooth; - - GetVectorsReadyForRW(); -} - -void -CCam::Process_ReactionCam(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - static float AngleToBinned = 0.0f; - static float StartingAngleLastChange = 0.0f; - static float FixedTargetOrientation; - static float DeadZoneReachedOnePrevious; - static uint32 TimeOfLastChange; - uint32 Time; - bool DontBind = false; // BUG: left uninitialized - - FOV = DefaultFOV; // missing in game - - if(ResetStatics){ - Rotating = false; - DeadZoneReachedOnePrevious = 0.0f; - FixedTargetOrientation = 0.0f; - ResetStatics = false; - DontBind = false; - } - - CVector TargetCoors = CameraTarget; - - CVector Dist = Source - TargetCoors; - Source.z = TargetCoors.z + 0.75f; - float Length = Dist.Magnitude2D(); - if(Length > 2.5f){ - Source.x = TargetCoors.x + Dist.x/Length * 2.5f; - Source.y = TargetCoors.y + Dist.y/Length * 2.5f; - }else if(Length < 2.4f){ - Source.x = TargetCoors.x + Dist.x/Length * 2.4f; - Source.y = TargetCoors.y + Dist.y/Length * 2.4f; - } - - Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y); - - float StickX = CPad::GetPad(0)->GetLeftStickX(); - float StickY = CPad::GetPad(0)->GetLeftStickY(); - float StickAngle; - if(StickX != 0.0 || StickY != 0.0f){ - StickAngle = CGeneral::GetATanOfXY(StickX, StickY); - while(StickAngle >= PI) StickAngle -= 2*PI; - while(StickAngle < -PI) StickAngle += 2*PI; - }else - StickAngle = 1000.0f; - - if(Abs(StickAngle-AngleToBinned) > DEGTORAD(15.0f)){ - DontBind = true; - Time = CTimer::GetTimeInMilliseconds(); - } - - if(CTimer::GetTimeInMilliseconds()-TimeOfLastChange > 200){ - if(Abs(HALFPI-StickAngle) > DEGTORAD(50.0f)){ - FixedTargetOrientation = TargetOrientation; - Rotating = true; - TimeOfLastChange = CTimer::GetTimeInMilliseconds(); - } - } - - // These two together don't make much sense. - // Only prevents rotation for one frame - AngleToBinned = StickAngle; - if(DontBind) - TimeOfLastChange = Time; - - if(Rotating){ - Dist = Source - TargetCoors; - Length = Dist.Magnitude2D(); - // inlined - WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true); - - Source.x = TargetCoors.x + Length*Cos(Beta); - Source.y = TargetCoors.y + Length*Sin(Beta); - - float DeltaBeta = FixedTargetOrientation+PI - Beta; - while(DeltaBeta >= PI) DeltaBeta -= 2*PI; - while(DeltaBeta < -PI) DeltaBeta += 2*PI; - if(Abs(DeltaBeta) < 0.06f) - Rotating = false; - } - - Front = TargetCoors - Source; - Front.Normalise(); - CVector Front2 = Front; - Front2.Normalise(); // What? - // FIX: the meaning of this value must have changed somehow - Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f; -// Source += Front2 * TheCamera.m_fPedZoomValueSmooth; - - GetVectorsReadyForRW(); -} - -void -CCam::Process_FollowPed_WithBinding(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - static float AngleToBinned = 0.0f; - static float StartingAngleLastChange = 0.0f; - static float FixedTargetOrientation; - static float DeadZoneReachedOnePrevious; - static uint32 TimeOfLastChange; - uint32 Time; - bool DontBind = false; - - FOV = DefaultFOV; // missing in game - - if(ResetStatics){ - Rotating = false; - DeadZoneReachedOnePrevious = 0.0f; - FixedTargetOrientation = 0.0f; - ResetStatics = false; - } - - CVector TargetCoors = CameraTarget; - - CVector Dist = Source - TargetCoors; - Source.z = TargetCoors.z + 0.75f; - float Length = Dist.Magnitude2D(); - if(Length > 2.5f){ - Source.x = TargetCoors.x + Dist.x/Length * 2.5f; - Source.y = TargetCoors.y + Dist.y/Length * 2.5f; - }else if(Length < 2.4f){ - Source.x = TargetCoors.x + Dist.x/Length * 2.4f; - Source.y = TargetCoors.y + Dist.y/Length * 2.4f; - } - - Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y); - - float StickX = CPad::GetPad(0)->GetLeftStickX(); - float StickY = CPad::GetPad(0)->GetLeftStickY(); - float StickAngle; - if(StickX != 0.0 || StickY != 0.0f){ - StickAngle = CGeneral::GetATanOfXY(StickX, StickY); - while(StickAngle >= PI) StickAngle -= 2*PI; - while(StickAngle < -PI) StickAngle += 2*PI; - }else - StickAngle = 1000.0f; - - if(Abs(StickAngle-AngleToBinned) > DEGTORAD(15.0f)){ - DontBind = true; - Time = CTimer::GetTimeInMilliseconds(); - } - - if(CTimer::GetTimeInMilliseconds()-TimeOfLastChange > 200){ - if(Abs(HALFPI-StickAngle) > DEGTORAD(50.0f)){ - FixedTargetOrientation = TargetOrientation; - Rotating = true; - TimeOfLastChange = CTimer::GetTimeInMilliseconds(); - } - } - - if(CPad::GetPad(0)->GetLeftShoulder1JustDown()){ - FixedTargetOrientation = TargetOrientation; - Rotating = true; - TimeOfLastChange = CTimer::GetTimeInMilliseconds(); - } - - // These two together don't make much sense. - // Only prevents rotation for one frame - AngleToBinned = StickAngle; - if(DontBind) - TimeOfLastChange = Time; - - if(Rotating){ - Dist = Source - TargetCoors; - Length = Dist.Magnitude2D(); - // inlined - WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true); - - Source.x = TargetCoors.x + Length*Cos(Beta); - Source.y = TargetCoors.y + Length*Sin(Beta); - - float DeltaBeta = FixedTargetOrientation+PI - Beta; - while(DeltaBeta >= PI) DeltaBeta -= 2*PI; - while(DeltaBeta < -PI) DeltaBeta += 2*PI; - if(Abs(DeltaBeta) < 0.06f) - Rotating = false; - } - - Front = TargetCoors - Source; - Front.Normalise(); - CVector Front2 = Front; - Front2.Normalise(); // What? - // FIX: the meaning of this value must have changed somehow - Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f; -// Source += Front2 * TheCamera.m_fPedZoomValueSmooth; - - GetVectorsReadyForRW(); -} - -void -CCam::Process_Bill(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar) -{ -#ifdef FIX_BUGS - fBillsBetaOffset += CPad::GetPad(0)->GetRightStickX()/1000.0f; -#else - // just wtf is this? this code must be ancient - if(CPad::GetPad(0)->GetStart()) - fBillsBetaOffset += CPad::GetPad(0)->GetLeftStickX()/1000.0f; -#endif - while(fBillsBetaOffset > TWOPI) fBillsBetaOffset -= TWOPI; - while(fBillsBetaOffset < 0.0f) fBillsBetaOffset += TWOPI; - TargetOrientation += fBillsBetaOffset; - while(TargetOrientation > TWOPI) TargetOrientation -= TWOPI; - while(TargetOrientation < 0.0f) TargetOrientation += TWOPI; - Process_BehindCar(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); -} - -void -CCam::Process_Im_The_Passenger_Woo_Woo(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - FOV = 50.0f; - - Source = CamTargetEntity->GetPosition(); - Source.z += 2.5f; - Front = CamTargetEntity->GetForward(); - Front.Normalise(); - Source += 1.35f*Front; - float heading = CGeneral::GetATanOfXY(Front.x, Front.y) + DEGTORAD(45.0f); - Front.x = Cos(heading); - Front.y = Sin(heading); - Up = CamTargetEntity->GetUp(); - - GetVectorsReadyForRW(); -} - -void -CCam::Process_Blood_On_The_Tracks(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - FOV = 50.0f; - - Source = CamTargetEntity->GetPosition(); - Source.z += 5.45f; - - static CVector Test = -CamTargetEntity->GetForward(); -#ifdef FIX_BUGS - if(ResetStatics){ - Test = -CamTargetEntity->GetForward(); - ResetStatics = false; - } -#endif - - Source.x += 19.45*Test.x; - Source.y += 19.45*Test.y; - Front = Test; - Front.Normalise(); - Up = CamTargetEntity->GetUp(); - - GetVectorsReadyForRW(); -} - -void -CCam::Process_Cam_Running_Side_Train(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - FOV = 60.0f; - - Source = CamTargetEntity->GetPosition(); - Source.z += 4.0f; - CVector fwd = CamTargetEntity->GetForward(); - float heading = CGeneral::GetATanOfXY(fwd.x, fwd.y) - DEGTORAD(15.0f); - Source.x -= Cos(heading)*10.0f; - Source.y -= Sin(heading)*10.0f; - heading -= DEGTORAD(5.0f); - Front = fwd; - Front.x += Cos(heading); - Front.y += Sin(heading); - Front.z -= 0.056f; - Front.Normalise(); - Up = CamTargetEntity->GetUp(); - - GetVectorsReadyForRW(); -} - -void -CCam::Process_Cam_On_Train_Roof(const CVector &CameraTarget, float TargetOrientation, float, float) -{ - static float RoofMultiplier = 1.5f; - - Source = CamTargetEntity->GetPosition(); - Source.z += 4.8f; - Front = CamTargetEntity->GetForward(); - Front.Normalise(); - Source += Front*RoofMultiplier; - Up = CamTargetEntity->GetUp(); - Up.Normalise(); - - GetVectorsReadyForRW(); -} - - #ifdef FREE_CAM void CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float) @@ -4683,6 +4694,8 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient Rotating = false; } + if(TheCamera.m_bUseTransitionBeta) + Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta)); if(TheCamera.m_bUseTransitionBeta) Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta)); @@ -4730,7 +4743,7 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient CWorld::pIgnoreEntity = nil; float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); - float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV; + float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV; float Near = RwCameraGetNearClipPlane(Scene.camera); float radius = ViewPlaneWidth*Near; entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false); @@ -4786,9 +4799,9 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, uint8 camSetArrPos = 0; // We may need those later - bool isPlane = car->GetModelIndex() == MI_DODO; - bool isHeli = false; - bool isBike = false; + bool isPlane = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE; + bool isHeli = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI; + bool isBike = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE; bool isCar = car->IsCar() && !isPlane && !isHeli && !isBike; CPad* pad = CPad::GetPad(0); @@ -4799,8 +4812,10 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, if (car->GetModelIndex() == MI_FIRETRUCK) { camSetArrPos = 7; - } else if (car->GetModelIndex() == MI_RCBANDIT) { + } else if (car->GetModelIndex() == MI_RCBANDIT || car->GetModelIndex() == MI_RCBARON) { camSetArrPos = 5; + } else if (car->GetModelIndex() == MI_RCGOBLIN || car->GetModelIndex() == MI_RCRAIDER) { + camSetArrPos = 6; } else if (car->IsBoat()) { camSetArrPos = 4; } else if (isBike) { @@ -4857,6 +4872,14 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float newDistance = TheCamera.CarZoomValueSmooth + CARCAM_SET[camSetArrPos][1] + approxCarLength; + // Taken from VC CCam::Cam_On_A_String_Unobscured. If we don't this, we will end up seeing the world from the inside of RC Goblin/Raider. + // I couldn't find where SA does that. It's possible that they've increased the size of these veh.'s collision bounding box. + + if (car->m_modelIndex == MI_RCRAIDER || car->m_modelIndex == MI_RCGOBLIN) + newDistance += INIT_RC_HELI_HORI_EXTRA; + else if (car->m_modelIndex == MI_RCBARON) + newDistance += INIT_RC_PLANE_HORI_EXTRA; + float minDistForThisCar = approxCarLength * CARCAM_SET[camSetArrPos][3]; if (!isHeli || car->GetStatus() == STATUS_PLAYER_REMOTE) { @@ -4871,6 +4894,9 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, TargetCoors += 0.6f * car->GetUp() * colMaxZ; } + if (car->m_modelIndex == MI_RCGOBLIN) + zoomModeAlphaOffset += 0.178997f; + float minDistForVehType = CARCAM_SET[camSetArrPos][4]; if (TheCamera.CarZoomIndicator == CAM_ZOOM_1 && (camSetArrPos < 2 || camSetArrPos == 7)) { @@ -4884,10 +4910,6 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, if (ResetStatics) { FOV = DefaultFOV; - - // GTA 3 has this in veh. camera - if (TheCamera.m_bIdleOn) - TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds(); } else { if (isCar || isBike) { // 0.4f: CAR_FOV_START_SPEED @@ -4917,17 +4939,14 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, ResetStatics = false; Rotating = false; m_bCollisionChecksOn = true; - // TheCamera.m_bResetOldMatrix = 1; - // Garage exit cam is not working well in III... - // if (!TheCamera.m_bJustCameOutOfGarage) // && !sthForScript) - // { - Alpha = 0.0f; - Beta = car->GetForward().Heading() - HALFPI; - if (TheCamera.m_bCamDirectlyInFront) { - Beta += PI; + if (!TheCamera.m_bJustCameOutOfGarage) { + Alpha = 0.0f; + Beta = car->GetForward().Heading() - HALFPI; + if (TheCamera.m_bCamDirectlyInFront) { + Beta += PI; + } } - // } BetaSpeed = 0.0; AlphaSpeed = 0.0; @@ -4942,7 +4961,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, m_aTargetHistoryPosTwo = TargetCoors - newDistance * Front; m_nCurrentHistoryPoints = 0; - if (!TheCamera.m_bJustCameOutOfGarage) // && !sthForScript) + if (!TheCamera.m_bJustCameOutOfGarage) Alpha = -zoomModeAlphaOffset; } @@ -4994,9 +5013,9 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, // This is also original LCS and SA bug, or some attempt to fix lag. We'll never know // if (car->m_vecMoveSpeed.MagnitudeSqr() < sq(0.2f)) - if (car->GetModelIndex() != MI_FIRETRUCK) { - // if (!isBike || GetMysteriousWheelRelatedThingBike(car) > 3) - // if (!isHeli && (!isPlane || car->GetWheelsOnGround())) { + if (car->GetModelIndex() != MI_FIRETRUCK) + if (!isBike || ((CBike*)car)->m_nWheelsOnGround > 3) + if (!isHeli && (!isPlane || ((CAutomobile*)car)->m_nWheelsOnGround)) { CVector left = CrossProduct(car->GetForward(), CVector(0.0f, 0.0f, 1.0f)); left.Normalise(); @@ -5041,20 +5060,19 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float stickX = -(pad->GetCarGunLeftRight()); float stickY = -pad->GetCarGunUpDown(); - // In SA this is for not let num2/num8 move camera when Keyboard & Mouse controls are used. - // if (CCamera::m_bUseMouse3rdPerson) - // stickY = 0.0f; -#ifdef INVERT_LOOK_FOR_PAD - if (CPad::bInvertLook4Pad) + // In SA this checks for m_bUseMouse3rdPerson so num2 / num8 do not move camera + // when Keyboard & Mouse controls are used. To make it work better with III/VC, check for actual pad state instead + if (!CPad::IsAffectedByController && !isCar) + stickY = 0.0f; + else if (CPad::bInvertLook4Pad) stickY = -stickY; -#endif float xMovement = Abs(stickX) * (FOV / 80.0f * 5.f / 70.f) * stickX * 0.007f * 0.007f; float yMovement = Abs(stickY) * (FOV / 80.0f * 3.f / 70.f) * stickY * 0.007f * 0.007f; bool correctAlpha = true; // if (SA checks if we aren't in work car, why?) { - if (!isCar || car->GetModelIndex() != MI_YARDIE) { + if (!isCar || car->GetModelIndex() != MI_VOODOO) { correctAlpha = false; } else { @@ -5158,8 +5176,8 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, Beta += TWOPI; if ((camSetArrPos <= 1 || camSetArrPos == 7) && targetAlpha < Alpha && carPosChange >= newDistance) { - if (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1) - // || isBike && GetMysteriousWheelRelatedThingBike(car) > 1) + if (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1 || + isBike && ((CBike*)car)->m_nWheelsOnGround > 1) alphaSpeedFromStickY += (targetAlpha - Alpha) * 0.075f; } @@ -5244,7 +5262,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, dontCollideWithCars = (timestepFactor * dontCollideWithCars) + ((1.0f - timestepFactor) * car->m_vecMoveSpeed.Magnitude()); // Our addition -#define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && (IsStreetLight(ent->GetModelIndex()))) +#define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && IsLightObject(ent->GetModelIndex())) // Clip Source and fix near clip CColPoint colPoint; @@ -5269,14 +5287,14 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); } } - + CWorld::pIgnoreEntity = nil; // If we're seeing blue hell due to camera intersects some surface, fix it. // SA and LCS have this unrolled. float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); - float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV; + float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV; float Near = RwCameraGetNearClipPlane(Scene.camera); float radius = ViewPlaneWidth*Near; entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, true); @@ -5318,19 +5336,13 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, if (camSetArrPos == 5 && Source.z < 1.0f) // RC Bandit and Baron Source.z = 1.0f; - // Obviously some specific place in LC - if (Source.x > 11.0f && Source.x < 91.0f) { - if (Source.y > -680.0f && Source.y < -600.0f && Source.z < 24.4f) - Source.z = 24.4f; - } - // CCam::FixSourceAboveWaterLevel if (CameraTarget.z >= -2.0f) { float level = -6000.0; - // +0.5f is needed for III + if (CWaterLevel::GetWaterLevelNoWaves(Source.x, Source.y, Source.z, &level)) { - if (Source.z < level + 0.5f) - Source.z = level + 0.5f; + if (Source.z < level) + Source.z = level; } } Front = TargetCoors - Source; @@ -5383,7 +5395,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float alphaToFace = Atan2(hi.z, hi.Magnitude2D()) + DEGTORAD(15.0f); float neededAlphaTurn = alphaToFace - carGunUD; - float alphaTurnPerFrame = CTimer::GetTimeStep() * 0.02f; + float alphaTurnPerFrame = CTimer::GetTimeStepInSeconds(); if (neededAlphaTurn > alphaTurnPerFrame) { neededTurn = alphaTurnPerFrame; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index f3b41655..3ebd52f2 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -14,12 +14,14 @@ #include "General.h" #include "ZoneCull.h" #include "SurfaceTable.h" +#include "Particle.h" #include "WaterLevel.h" #include "World.h" #include "Garages.h" #include "Replay.h" #include "CutsceneMgr.h" #include "Renderer.h" +#include "Timecycle.h" #include "MBlur.h" #include "Text.h" #include "Hud.h" @@ -30,7 +32,6 @@ #include "Pools.h" #include "Debug.h" #include "GenericGameStorage.h" -#include "MemoryCard.h" #include "Camera.h" enum @@ -51,6 +52,14 @@ enum OBBE_11, OBBE_12, OBBE_13, + // heli + OBBE_14, + OBBE_15, + OBBE_16, + OBBE_17, + OBBE_18, + OBBE_19, + OBBE_ONSTRING_HELI, OBBE_INVALID }; @@ -66,6 +75,11 @@ bool CCamera::m_bUseMouse3rdPerson = true; bool CCamera::m_bUseMouse3rdPerson = false; #endif bool bDidWeProcessAnyCinemaCam; +static bool bSwitchedToObbeCam; +float CCamera::m_fMouseAccelHorzntl; +float CCamera::m_fMouseAccelVertical; +float CCamera::m_f3rdPersonCHairMultX; +float CCamera::m_f3rdPersonCHairMultY; #ifdef IMPROVED_CAMERA #define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k) @@ -76,46 +90,27 @@ bool bDidWeProcessAnyCinemaCam; #define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key)) #endif -CCamera::CCamera(void) -{ -#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS) - m_fMouseAccelHorzntl = 0.0025f; - m_fMouseAccelVertical = 0.003f; +const float ZOOM_ONE_DISTANCE[] = { -0.6f, 0.05f, -3.2f, 0.05f, -2.41f }; +const float ZOOM_TWO_DISTANCE[] = { 1.9f, 1.4f, 0.65f, 1.9f, 6.49f }; +const float ZOOM_THREE_DISTANCE[] = { 15.9f, 15.9f, 15.9f, 15.9f, 25.25f }; + +#ifdef FREE_CAM +const float LCS_ZOOM_ONE_DISTANCE[] = { -1.0f, -0.2f, -3.2f, 0.05f, -2.41f }; +const float LCS_ZOOM_TWO_DISTANCE[] = { 2.0f, 2.2f, 1.65f, 2.9f, 6.49f }; +const float LCS_ZOOM_THREE_DISTANCE[] = { 6.0f, 6.0f, 15.9f, 15.9f, 15.0f }; #endif - Init(); -} -CCamera::CCamera(float) +CCamera::CCamera(void) { + Init(); } void CCamera::Init(void) { -#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS) - float fMouseAccelHorzntl = m_fMouseAccelHorzntl; - float fMouseAccelVertical = m_fMouseAccelVertical; -#endif - -#ifdef PS2_MENU - if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart ) -#endif - { - #ifdef FIX_BUGS - static const CCamera DummyCamera = CCamera(0.f); - *this = DummyCamera; - #else - memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh? - #endif - - #if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS) - m_fMouseAccelHorzntl = fMouseAccelHorzntl; - m_fMouseAccelVertical = fMouseAccelVertical; - #endif - m_pRwCamera = nil; - - } - + memset(this, 0, sizeof(CCamera)); // this is fine, no vtable + m_pRwCamera = nil; + m_bPlayerWasOnBike = false; m_1rstPersonRunCloseToAWall = false; m_fPositionAlongSpline = 0.0f; m_bCameraJustRestored = false; @@ -124,8 +119,21 @@ CCamera::Init(void) Cams[2].Init(); Cams[0].Mode = CCam::MODE_FOLLOWPED; Cams[1].Mode = CCam::MODE_FOLLOWPED; - unknown = 0; - m_bUnknown = false; + m_bEnable1rstPersonCamCntrlsScript = false; + m_bAllow1rstPersonWeaponsCamera = false; + m_bVehicleSuspenHigh = false; + Cams[0].m_fMinRealGroundDist = 1.85f; + // TODO: what weird value is this? + Cams[0].m_fTargetCloseInDist = 2.0837801f - Cams[0].m_fMinRealGroundDist; + Cams[0].m_fTargetZoomGroundOne = 0.25f; + Cams[0].m_fTargetZoomGroundTwo = 1.5f; + Cams[0].m_fTargetZoomGroundThree = 4.0f; + Cams[0].m_fTargetZoomOneZExtra = -0.14f; + Cams[0].m_fTargetZoomTwoZExtra = 0.16f; + Cams[0].m_fTargetZoomThreeZExtra = 0.25f; + // TODO: another weird value + Cams[0].m_fTargetZoomZCloseIn = 0.90040702f; + m_bMoveCamToAvoidGeom = false; ClearPlayerWeaponMode(); m_bInATunnelAndABigVehicle = false; m_iModeObbeCamIsInForCar = OBBE_INVALID; @@ -182,26 +190,18 @@ CCamera::Init(void) PlayerExhaustion = 1.0f; DebugCamMode = CCam::MODE_NONE; m_PedOrientForBehindOrInFront = 0.0f; -#ifdef PS2_MENU - if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart ) -#else - if(!FrontEndMenuManager.m_bWantToRestart) -#endif - { + if(!FrontEndMenuManager.m_bWantToRestart){ m_bFading = false; CDraw::FadeValue = 0; m_fFLOATingFade = 0.0f; m_bMusicFading = false; m_fTimeToFadeMusic = 0.0f; m_fFLOATingFadeMusic = 0.0f; + m_fMouseAccelVertical = 0.003f; + m_fMouseAccelHorzntl = 0.0025f; } - m_bMoveCamToAvoidGeom = false; -#ifdef PS2_MENU - if ( TheMemoryCard.m_bWantToLoad || FrontEndMenuManager.m_bWantToRestart ) -#else if(FrontEndMenuManager.m_bWantToRestart) -#endif - m_bMoveCamToAvoidGeom = true; + m_fTimeToFadeMusic = 0.0f; m_bStartingSpline = false; m_iTypeOfSwitch = INTERPOLATION; m_bUseScriptZoomValuePed = false; @@ -220,6 +220,8 @@ CCamera::Init(void) m_uiTimeLastChange = 0; m_uiTimeWeEnteredIdle = 0; m_bIdleOn = false; + m_uiTimeWeLeftIdle_StillNoInput = 0; + m_uiTimeWeEnteredIdle = 0; LODDistMultiplier = 1.0f; m_bCamDirectlyBehind = false; m_bCamDirectlyInFront = false; @@ -239,21 +241,18 @@ CCamera::Init(void) m_uiTransitionState = 0; m_uiTimeTransitionStart = 0; m_bLookingAtPlayer = true; -#if GTA_VERSION < GTA3_PC_11 && !defined(FIX_BUGS) - m_fMouseAccelHorzntl = 0.0025f; - m_fMouseAccelVertical = 0.003f; -#endif m_f3rdPersonCHairMultX = 0.53f; m_f3rdPersonCHairMultY = 0.4f; + m_fAvoidTheGeometryProbsTimer = 0.0f; + m_nAvoidTheGeometryProbsDirn = 0; } void CCamera::Process(void) { // static bool InterpolatorNotInitialised = true; // unused - static CVector PreviousFudgedTargetCoors; // only PS2 - static float PlayerMinDist = 1.6f; // not on PS2 - static bool WasPreviouslyInterSyhonFollowPed = false; // only used on PS2 + static float PlayerMinDist = 1.3f; + static bool WasPreviouslyInterSyhonFollowPed = false; // only written float FOV = 0.0f; float oldBeta, newBeta; float deltaBeta = 0.0f; @@ -281,6 +280,7 @@ CCamera::Process(void) if(m_WideScreenOn) ProcessWideScreenOn(); +#ifndef MASTER #ifdef IMPROVED_CAMERA if(CPad::GetPad(1)->GetCircleJustDown() || CTRLJUSTDOWN('B')){ #else @@ -292,6 +292,7 @@ CCamera::Process(void) else CPad::m_bMapPadOneToPadTwo = false; } +#endif RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); @@ -311,19 +312,11 @@ CCamera::Process(void) // Stop transition when it's done if(m_uiTransitionState != 0){ -#ifdef PS2_CAM_TRANSITION - if(!m_bWaitForInterpolToFinish){ - Cams[(ActiveCam+1)%2].Process(); - Cams[(ActiveCam+1)%2].ProcessSpecialHeightRoutines(); - } -#else - // done in CamControl on PS2 it seems if(CTimer::GetTimeInMilliseconds() > m_uiTransitionDuration+m_uiTimeTransitionStart){ m_uiTransitionState = 0; m_vecDoingSpecialInterPolation = false; m_bWaitForInterpolToFinish = false; } -#endif } if(m_bUseNearClipScript) @@ -335,169 +328,50 @@ CCamera::Process(void) if(Abs(deltaBeta) > 0.3f) m_bJust_Switched = true; +#ifndef MASTER // Debug stuff if(!gbModelViewer) - Cams[ActiveCam].PrintMode(); + Cams[ActiveCam].PrintMode(); // actually missing in VC if(WorldViewerBeingUsed) Cams[2].Process(); +#endif if(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && pTargetEntity->IsVehicle()) lookLRBVehicle = true; if(m_uiTransitionState != 0 && !lookLRBVehicle){ // Process transition -#ifdef PS2_CAM_TRANSITION - bool lookingAtPlayerNow = false; - bool wasLookingAtPlayer = false; - bool transitionPedMode = false; - bool setWait = false; - if(Cams[ActiveCam].CamTargetEntity == Cams[(ActiveCam+1)%2].CamTargetEntity){ - if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON || - Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT || - Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED || - Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) - lookingAtPlayerNow = true; - if(Cams[(ActiveCam+1)%2].Mode == CCam::MODE_SYPHON || - Cams[(ActiveCam+1)%2].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT || - Cams[(ActiveCam+1)%2].Mode == CCam::MODE_FOLLOWPED || - Cams[(ActiveCam+1)%2].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) // checked twice for some reason - wasLookingAtPlayer = true; - - if(!m_vecDoingSpecialInterPolation && - (Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM) && - (Cams[(ActiveCam+1)%2].Mode == CCam::MODE_FOLLOWPED || Cams[(ActiveCam+1)%2].Mode == CCam::MODE_FIGHT_CAM)) - transitionPedMode = true; - } - - if(lookingAtPlayerNow && wasLookingAtPlayer){ - CVector playerDist; - playerDist.x = FindPlayerPed()->GetPosition().x - GetPosition().x; - playerDist.y = FindPlayerPed()->GetPosition().y - GetPosition().y; - playerDist.z = FindPlayerPed()->GetPosition().z - GetPosition().z; - if(playerDist.Magnitude() > 17.5f && - (Cams[ActiveCam].Mode == CCam::MODE_SYPHON || Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT)) - setWait = true; - } - if(setWait) - m_bWaitForInterpolToFinish = true; - uint32 currentTime = CTimer::GetTimeInMilliseconds() - m_uiTimeTransitionStart; if(currentTime >= m_uiTransitionDuration) currentTime = m_uiTransitionDuration; - float inter = (float) currentTime / m_uiTransitionDuration; - inter = 0.5f - 0.5*Cos(inter*PI); // smooth it - - if(m_vecDoingSpecialInterPolation){ - Cams[(ActiveCam+1)%2].Source = m_vecOldSourceForInter; - Cams[(ActiveCam+1)%2].Front = m_vecOldFrontForInter; - Cams[(ActiveCam+1)%2].Up = m_vecOldUpForInter; - Cams[(ActiveCam+1)%2].FOV = m_vecOldFOVForInter; - if(WasPreviouslyInterSyhonFollowPed) - Cams[(ActiveCam+1)%2].m_cvecTargetCoorsForFudgeInter.z = PreviousFudgedTargetCoors.z; - } + float fractionInter = (float) currentTime / m_uiTransitionDuration; + float fractionInterTarget = (float) currentTime / m_uiTransitionDurationTargetCoors; + fractionInterTarget = Clamp(fractionInterTarget, 0.0f, 1.0f); - CamSource = inter*Cams[ActiveCam].Source + (1.0f-inter)*Cams[(ActiveCam+1)%2].Source; - FOV = inter*Cams[ActiveCam].FOV + (1.0f-inter)*Cams[(ActiveCam+1)%2].FOV; - - CVector tmpFront = Cams[(ActiveCam+1)%2].Front; - float Alpha_other = CGeneral::GetATanOfXY(tmpFront.Magnitude2D(), tmpFront.z); - if(Alpha_other > PI) Alpha_other -= TWOPI; - float Beta_other = 0.0f; - if(tmpFront.x != 0.0f || tmpFront.y != 0.0f) - Beta_other = CGeneral::GetATanOfXY(-tmpFront.y, tmpFront.x); - tmpFront = Cams[ActiveCam].Front; - float Alpha_active = CGeneral::GetATanOfXY(tmpFront.Magnitude2D(), tmpFront.z); - if(Alpha_active > PI) Alpha_active -= TWOPI; - float Beta_active = 0.0f; - if(tmpFront.x != 0.0f || tmpFront.y != 0.0f) - Beta_active = CGeneral::GetATanOfXY(-tmpFront.y, tmpFront.x); - - float DeltaBeta = Beta_active - Beta_other; - float Alpha = inter*Alpha_active + (1.0f-inter)*Alpha_other; - - if(m_uiTransitionJUSTStarted){ - while(DeltaBeta > PI) DeltaBeta -= TWOPI; - while(DeltaBeta <= -PI) DeltaBeta += TWOPI; - m_uiTransitionJUSTStarted = false; - }else{ - if(DeltaBeta < m_fOldBetaDiff) - while(Abs(DeltaBeta - m_fOldBetaDiff) > PI) DeltaBeta += TWOPI; + // Interpolate target separately + if(fractionInterTarget <= m_fFractionInterToStopMovingTarget){ + float inter; + if(m_fFractionInterToStopMovingTarget == 0.0f) + inter = 0.0f; else - while(Abs(DeltaBeta - m_fOldBetaDiff) > PI) DeltaBeta -= TWOPI; - } - m_fOldBetaDiff = DeltaBeta; - float Beta = inter*DeltaBeta + Beta_other; - - CVector FudgedTargetCoors; - if(lookingAtPlayerNow && wasLookingAtPlayer){ - // BUG? how is this interpolation ever used when values are overwritten below? - float PlayerDist = (pTargetEntity->GetPosition() - CamSource).Magnitude2D(); - float MinDist = Min(Cams[(ActiveCam+1)%2].m_fMinDistAwayFromCamWhenInterPolating, Cams[ActiveCam].m_fMinDistAwayFromCamWhenInterPolating); - if(PlayerDist < MinDist){ - CamSource.x = pTargetEntity->GetPosition().x - MinDist*Cos(Beta - HALFPI); - CamSource.y = pTargetEntity->GetPosition().y - MinDist*Sin(Beta - HALFPI); - }else{ - CamSource.x = pTargetEntity->GetPosition().x - PlayerDist*Cos(Beta - HALFPI); - CamSource.y = pTargetEntity->GetPosition().y - PlayerDist*Sin(Beta - HALFPI); - } - - CColPoint colpoint; - CEntity *entity = nil; - if(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), CamSource, colpoint, entity, true, false, false, true, false, true, true)){ - CamSource = colpoint.point; - RwCameraSetNearClipPlane(Scene.camera, 0.05f); - } + inter = (m_fFractionInterToStopMovingTarget - fractionInterTarget)/m_fFractionInterToStopMovingTarget; + inter = 0.5f - 0.5*Cos(inter*PI); // smooth it - CamFront = pTargetEntity->GetPosition() - CamSource; - FudgedTargetCoors = inter*Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter + (1.0f-inter)*Cams[(ActiveCam+1)%2].m_cvecTargetCoorsForFudgeInter; - PreviousFudgedTargetCoors = FudgedTargetCoors; - CamFront.Normalise(); - CamUp = CVector(0.0f, 0.0f, 1.0f); - CamRight = CrossProduct(CamFront, CamUp); - CamRight.Normalise(); - CamUp = CrossProduct(CamRight, CamFront); + m_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol + inter*m_cvecTargetSpeedAtStartInter; + Target = m_vecTargetWhenInterPol; + }else if(fractionInterTarget > m_fFractionInterToStopMovingTarget){ + float inter; + if(m_fFractionInterToStopCatchUpTarget == 0.0f) + inter = 0.0f; + else + inter = (fractionInterTarget - m_fFractionInterToStopMovingTarget)/m_fFractionInterToStopCatchUpTarget; + inter = 0.5f - 0.5*Cos(inter*PI); // smooth it - WasPreviouslyInterSyhonFollowPed = true; - }else - WasPreviouslyInterSyhonFollowPed = false; - - if(transitionPedMode){ - FudgedTargetCoors = inter*Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter + (1.0f-inter)*Cams[(ActiveCam+1)%2].m_cvecTargetCoorsForFudgeInter; - PreviousFudgedTargetCoors = FudgedTargetCoors; - CVector CamToTarget = pTargetEntity->GetPosition() - CamSource; - float tmpBeta = CGeneral::GetATanOfXY(CamToTarget.x, CamToTarget.y); - float PlayerDist = (pTargetEntity->GetPosition() - CamSource).Magnitude2D(); - float MinDist = Min(Cams[(ActiveCam+1)%2].m_fMinDistAwayFromCamWhenInterPolating, Cams[ActiveCam].m_fMinDistAwayFromCamWhenInterPolating); - if(PlayerDist < MinDist){ - CamSource.x = pTargetEntity->GetPosition().x - MinDist*Cos(tmpBeta - HALFPI); - CamSource.y = pTargetEntity->GetPosition().y - MinDist*Sin(tmpBeta - HALFPI); - } - CamFront = FudgedTargetCoors - CamSource; - CamFront.Normalise(); - CamUp = CVector(0.0f, 0.0f, 1.0f); - CamUp.Normalise(); - CamRight = CrossProduct(CamFront, CamUp); - CamRight.Normalise(); - CamUp = CrossProduct(CamRight, CamFront); - CamUp.Normalise(); - }else{ - CamFront.x = Cos(Alpha) * Sin(Beta); - CamFront.y = Cos(Alpha) * -Cos(Beta); - CamFront.z = Sin(Alpha); - CamFront.Normalise(); - CamUp = inter*Cams[ActiveCam].Up + (1.0f-inter)*Cams[(ActiveCam+1)%2].Up; - CamUp.Normalise(); - CamRight = CrossProduct(CamFront, CamUp); - CamRight.Normalise(); - CamUp = CrossProduct(CamRight, CamFront); - CamUp.Normalise(); + if(m_fFractionInterToStopMovingTarget == 0.0f) + m_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol; + Target = m_vecTargetWhenInterPol + inter*(Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - m_vecTargetWhenInterPol); } -#else - uint32 currentTime = CTimer::GetTimeInMilliseconds() - m_uiTimeTransitionStart; - if(currentTime >= m_uiTransitionDuration) - currentTime = m_uiTransitionDuration; - float fractionInter = (float) currentTime / m_uiTransitionDuration; if(fractionInter <= m_fFractionInterToStopMoving){ float inter; @@ -508,37 +382,22 @@ CCamera::Process(void) inter = 0.5f - 0.5*Cos(inter*PI); // smooth it m_vecSourceWhenInterPol = m_cvecStartingSourceForInterPol + inter*m_cvecSourceSpeedAtStartInter; - m_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol + inter*m_cvecTargetSpeedAtStartInter; - m_vecUpWhenInterPol = m_cvecStartingUpForInterPol + inter*m_cvecUpSpeedAtStartInter; - m_fFOVWhenInterPol = m_fStartingFOVForInterPol + inter*m_fFOVSpeedAtStartInter; - CamSource = m_vecSourceWhenInterPol; - - if(m_bItsOkToLookJustAtThePlayer){ - m_vecTargetWhenInterPol.x = FindPlayerPed()->GetPosition().x; - m_vecTargetWhenInterPol.y = FindPlayerPed()->GetPosition().y; - m_fBetaWhenInterPol = m_fStartingBetaForInterPol + inter*m_fBetaSpeedAtStartInter; - - float dist = (CamSource - m_vecTargetWhenInterPol).Magnitude2D(); - if(dist < PlayerMinDist){ - if(dist > 0.0f){ - CamSource.x = m_vecTargetWhenInterPol.x + PlayerMinDist*Cos(m_fBetaWhenInterPol); - CamSource.y = m_vecTargetWhenInterPol.y + PlayerMinDist*Sin(m_fBetaWhenInterPol); - }else{ - // can only be 0.0 now... - float beta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); - CamSource.x = m_vecTargetWhenInterPol.x + PlayerMinDist*Cos(beta); - CamSource.y = m_vecTargetWhenInterPol.y + PlayerMinDist*Sin(beta); - } - }else{ - CamSource.x = m_vecTargetWhenInterPol.x + dist*Cos(m_fBetaWhenInterPol); - CamSource.y = m_vecTargetWhenInterPol.y + dist*Sin(m_fBetaWhenInterPol); + if(m_bLookingAtPlayer){ + CVector ToCam = m_vecSourceWhenInterPol - Target; + if(ToCam.Magnitude2D() < PlayerMinDist){ + float beta = CGeneral::GetATanOfXY(ToCam.x, ToCam.y); + CamSource.x = Target.x + PlayerMinDist*Cos(beta); + CamSource.y = Target.y + PlayerMinDist*Sin(beta); } } - CamFront = m_vecTargetWhenInterPol - CamSource; + m_vecUpWhenInterPol = m_cvecStartingUpForInterPol + inter*m_cvecUpSpeedAtStartInter; + m_fFOVWhenInterPol = m_fStartingFOVForInterPol + inter*m_fFOVSpeedAtStartInter; + + CamSource = m_vecSourceWhenInterPol; + CamFront = Target - CamSource; StoreValuesDuringInterPol(CamSource, m_vecTargetWhenInterPol, m_vecUpWhenInterPol, m_fFOVWhenInterPol); - Target = m_vecTargetWhenInterPol; CamFront.Normalise(); if(m_bLookingAtPlayer) CamUp = CVector(0.0f, 0.0f, 1.0f); @@ -569,33 +428,20 @@ CCamera::Process(void) inter = 0.5f - 0.5*Cos(inter*PI); // smooth it CamSource = m_vecSourceWhenInterPol + inter*(Cams[ActiveCam].Source - m_vecSourceWhenInterPol); + + if(m_bLookingAtPlayer){ + CVector ToCam = m_vecSourceWhenInterPol - Target; + if(ToCam.Magnitude2D() < PlayerMinDist){ + float beta = CGeneral::GetATanOfXY(ToCam.x, ToCam.y); + CamSource.x = Target.x + PlayerMinDist*Cos(beta); + CamSource.y = Target.y + PlayerMinDist*Sin(beta); + } + } + FOV = m_fFOVWhenInterPol + inter*(Cams[ActiveCam].FOV - m_fFOVWhenInterPol); - Target = m_vecTargetWhenInterPol + inter*(Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - m_vecTargetWhenInterPol); CamUp = m_vecUpWhenInterPol + inter*(Cams[ActiveCam].Up - m_vecUpWhenInterPol); deltaBeta = Cams[ActiveCam].m_fTrueBeta - m_fBetaWhenInterPol; MakeAngleLessThan180(deltaBeta); - float interpBeta = m_fBetaWhenInterPol + inter*deltaBeta; - - if(m_bItsOkToLookJustAtThePlayer){ - Target.x = FindPlayerPed()->GetPosition().x; - Target.y = FindPlayerPed()->GetPosition().y; - - float dist = (CamSource - Target).Magnitude2D(); - if(dist < PlayerMinDist){ - if(dist > 0.0f){ - CamSource.x = Target.x + PlayerMinDist*Cos(interpBeta); - CamSource.y = Target.y + PlayerMinDist*Sin(interpBeta); - }else{ - // can only be 0.0 now... - float beta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); - CamSource.x = Target.x + PlayerMinDist*Cos(beta); - CamSource.y = Target.y + PlayerMinDist*Sin(beta); - } - }else{ - CamSource.x = Target.x + dist*Cos(interpBeta); - CamSource.y = Target.y + dist*Sin(interpBeta); - } - } CamFront = Target - CamSource; StoreValuesDuringInterPol(CamSource, Target, CamUp, FOV); @@ -627,21 +473,34 @@ CCamera::Process(void) float Alpha = CGeneral::GetATanOfXY(DistOnGround, Dist.z); float Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y); Cams[ActiveCam].KeepTrackOfTheSpeed(CamSource, Target, CamUp, Alpha, Beta, FOV); -#endif }else{ // No transition, take Cam values directly +#ifndef MASTER if(WorldViewerBeingUsed){ CamSource = Cams[2].Source; CamFront = Cams[2].Front; CamUp = Cams[2].Up; FOV = Cams[2].FOV; - }else{ + }else +#endif + { CamSource = Cams[ActiveCam].Source; - CamFront = Cams[ActiveCam].Front; CamUp = Cams[ActiveCam].Up; + if(m_bMoveCamToAvoidGeom){ + CamSource += m_vecClearGeometryVec; + CamFront = Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - CamSource; + CamFront.Normalise(); + CVector Right = CrossProduct(CamFront, CamUp); + Right.Normalise(); + CamUp = CrossProduct(Right, CamFront); + CamUp.Normalise(); + }else{ + CamFront = Cams[ActiveCam].Front; + CamUp = Cams[ActiveCam].Up; + } FOV = Cams[ActiveCam].FOV; } - WasPreviouslyInterSyhonFollowPed = false; // only used on PS2 + WasPreviouslyInterSyhonFollowPed = false; // unused } if(m_uiTransitionState != 0) @@ -654,6 +513,37 @@ CCamera::Process(void) } } + if(CMBlur::Drunkness > 0.0f){ + static float DrunkAngle; + + int tableIndex = (int)(DEGTORAD(DrunkAngle)/TWOPI * CParticle::SIN_COS_TABLE_SIZE) & CParticle::SIN_COS_TABLE_SIZE-1; + DrunkAngle += 5.0f; +#ifndef FIX_BUGS + // This just messes up interpolation, probably not what they intended + // and multiplying the interpolated FOV is also a bit extreme + // so let's not do any of this nonsense + Cams[ActiveCam].FOV *= (1.0f + CMBlur::Drunkness); +#endif + + CamSource.x += -0.02f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex]; + CamSource.y += -0.02f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex]; + + CamUp.Normalise(); + CamUp.x += 0.05f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex]; + CamUp.y += 0.05f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex]; + CamUp.Normalise(); + + CamFront.Normalise(); + CamFront.x += -0.1f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex]; + CamFront.y += -0.1f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex]; + CamFront.Normalise(); + + CamRight = CrossProduct(CamFront, CamUp); + CamRight.Normalise(); + CamUp = CrossProduct(CamRight, CamFront); + CamUp.Normalise(); + } + GetMatrix().GetRight() = CrossProduct(CamUp, CamFront); // actually Left GetMatrix().GetForward() = CamFront; GetMatrix().GetUp() = CamUp; @@ -670,13 +560,21 @@ CCamera::Process(void) if(shakeOffset > 0.0f && m_BlurType != MOTION_BLUR_SNIPER) SetMotionBlurAlpha(Min((int)(shakeStrength*255.0f) + 25, 150)); - if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && FindPlayerVehicle() && FindPlayerVehicle()->GetUp().z < 0.2f) + + static bool bExtra1stPrsBlur = false; + if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && FindPlayerVehicle() && FindPlayerVehicle()->GetUp().z < 0.2f){ SetMotionBlur(230, 230, 230, 215, MOTION_BLUR_LIGHT_SCENE); + bExtra1stPrsBlur = true; + }else if(bExtra1stPrsBlur){ + SetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MOTION_BLUR_LIGHT_SCENE); + bExtra1stPrsBlur = false; + } CalculateDerivedValues(); CDraw::SetFOV(FOV); // Set RW camera +#ifndef MASTER if(WorldViewerBeingUsed){ RwFrame *frame = RwCameraGetFrame(m_pRwCamera); CVector Source = Cams[2].Source; @@ -697,7 +595,9 @@ CCamera::Process(void) *RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight(); RwMatrixUpdate(RwFrameGetMatrix(frame)); RwFrameUpdateObjects(frame); - }else{ + }else +#endif + { RwFrame *frame = RwCameraGetFrame(m_pRwCamera); m_vecGameCamPos = GetPosition(); *RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition(); @@ -706,11 +606,9 @@ CCamera::Process(void) *RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight(); RwMatrixUpdate(RwFrameGetMatrix(frame)); RwFrameUpdateObjects(frame); + RwFrameOrthoNormalize(frame); } - CDraw::SetNearClipZ(RwCameraGetNearClipPlane(m_pRwCamera)); - CDraw::SetFarClipZ(RwCameraGetFarClipPlane(m_pRwCamera)); - UpdateSoundDistances(); if((CTimer::GetFrameCounter()&0xF) == 3) @@ -719,16 +617,22 @@ CCamera::Process(void) // LOD dist if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){ LODDistMultiplier = 70.0f/CDraw::GetFOV(); -#ifndef FIX_BUGS - // makes no sense and gone in VC - LODDistMultiplier *= CDraw::GetAspectRatio()/(4.0f/3.0f); -#endif + + if(GetPosition().z > 55.0f && FindPlayerVehicle() && FindPlayerVehicle()->pHandling->Flags & (HANDLING_IS_HELI|HANDLING_IS_PLANE) || + FindPlayerPed()->m_attachedTo){ + LODDistMultiplier *= 1.0f + Max((GetPosition().z - 55.0f)/60.0f, 0.0f); + float NewNear = DEFAULT_NEAR * (1.0f + Max((GetPosition().z - 55.0f)/60.0f, 0.0f)); + if(RwCameraGetNearClipPlane(Scene.camera) >= DEFAULT_NEAR) + RwCameraSetNearClipPlane(Scene.camera, NewNear); + } + if(LODDistMultiplier > 2.2f) LODDistMultiplier = 2.2f; }else LODDistMultiplier = 1.0f; -#if GTA_VERSION > GTA3_PS2_160 GenerationDistMultiplier = LODDistMultiplier; LODDistMultiplier *= CRenderer::ms_lodDistScale; -#endif + + CDraw::SetNearClipZ(RwCameraGetNearClipPlane(m_pRwCamera)); + CDraw::SetFarClipZ(RwCameraGetFarClipPlane(m_pRwCamera)); // Keep track of speed if(m_bJustInitalised || m_bJust_Switched){ @@ -744,8 +648,6 @@ CCamera::Process(void) } m_PreviousCameraPosition = GetPosition(); - // PS2 normalizes a CVector2D GetForward() here. is it used anywhere? - if(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED){ Cams[ActiveCam].Source = Cams[ActiveCam].SourceBeforeLookBehind; Orientation += PI; @@ -763,6 +665,7 @@ CCamera::Process(void) } m_bCameraJustRestored = false; + m_bMoveCamToAvoidGeom = false; } void @@ -770,10 +673,10 @@ CCamera::CamControl(void) { static bool PlaceForFixedWhenSniperFound = false; static int16 ReqMode; - bool disableGarageCam = false; bool switchByJumpCut = false; bool stairs = false; bool boatTarget = false; + int PrevMode = Cams[ActiveCam].Mode; CVector targetPos; CVector garageCenter, garageDoorPos1, garageDoorPos2; CVector garageCenterToDoor, garageCamPos; @@ -786,20 +689,12 @@ CCamera::CamControl(void) m_bJustCameOutOfGarage = false; m_bTargetJustCameOffTrain = false; m_bInATunnelAndABigVehicle = false; + m_bJustJumpedOutOf1stPersonBecauseOfTarget = false; + bSwitchedToObbeCam = false; if(Cams[ActiveCam].CamTargetEntity == nil && pTargetEntity == nil) pTargetEntity = PLAYER; -#ifdef PS2_CAM_TRANSITION - // Stop transition when it's done - if(m_uiTransitionState != 0) - if(CTimer::GetTimeInMilliseconds() > m_uiTransitionDuration+m_uiTimeTransitionStart){ - m_uiTransitionState = 0; - m_vecDoingSpecialInterPolation = false; - m_bWaitForInterpolToFinish = false; - } -#endif - m_iZoneCullFrameNumWereAt++; if(m_iZoneCullFrameNumWereAt > m_iCheckCullZoneThisNumFrames) m_iZoneCullFrameNumWereAt = 1; @@ -808,11 +703,11 @@ CCamera::CamControl(void) m_bFailedCullZoneTestPreviously = CCullZones::CamCloseInForPlayer(); if(m_bLookingAtPlayer){ - CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA); + CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_CAMERA; FindPlayerPed()->bIsVisible = true; } - if(!CTimer::GetIsPaused()){ + if(!CTimer::GetIsPaused() && !m_bIdleOn){ float CloseInCarHeightTarget = 0.0f; float CloseInPedHeightTarget = 0.0f; @@ -828,25 +723,35 @@ CCamera::CamControl(void) // Vehicle target if(pTargetEntity->IsVehicle()){ +#ifdef GTA_TRAIN if(((CVehicle*)pTargetEntity)->IsTrain()){ if(!m_bTargetJustBeenOnTrain){ m_bInitialNodeFound = false; m_bInitialNoNodeStaticsSet = false; } Process_Train_Camera_Control(); - }else{ - if(((CVehicle*)pTargetEntity)->IsBoat()) + }else +#endif + { + if(((CVehicle*)pTargetEntity)->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) boatTarget = true; // Change user selected mode if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && - !m_WideScreenOn) + !m_WideScreenOn){ CarZoomIndicator--; + // disable topdown here + if(CarZoomIndicator == CAM_ZOOM_TOPDOWN) + CarZoomIndicator--; + } if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && - !m_WideScreenOn) + !m_WideScreenOn){ CarZoomIndicator++; + if(CarZoomIndicator == CAM_ZOOM_TOPDOWN) + CarZoomIndicator++; + } if(!m_bFailedCullZoneTestPreviously){ if(CarZoomIndicator < CAM_ZOOM_1STPRS) CarZoomIndicator = CAM_ZOOM_CINEMATIC; else if(CarZoomIndicator > CAM_ZOOM_CINEMATIC) CarZoomIndicator = CAM_ZOOM_1STPRS; @@ -856,45 +761,88 @@ CCamera::CamControl(void) if(CarZoomIndicator != CAM_ZOOM_1STPRS && CarZoomIndicator != CAM_ZOOM_TOPDOWN) ReqMode = CCam::MODE_CAM_ON_A_STRING; - switch(((CVehicle*)pTargetEntity)->m_vehType){ + int vehType = ((CVehicle*)pTargetEntity)->m_vehType; + if(((CVehicle*)pTargetEntity)->IsBoat() && pTargetEntity->GetModelIndex() == MI_SKIMMER) + vehType = VEHICLE_TYPE_CAR; + + switch(vehType){ case VEHICLE_TYPE_CAR: - case VEHICLE_TYPE_BIKE: - if(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition())){ + case VEHICLE_TYPE_BIKE:{ + CAttributeZone *stairsZone = nil; + if(vehType == VEHICLE_TYPE_BIKE && CCullZones::CamStairsForPlayer()){ + stairsZone = CCullZones::FindZoneWithStairsAttributeForPlayer(); + if(stairsZone) + stairs = true; + } + if(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs){ if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){ - if(pToGarageWeAreIn){ + if(pToGarageWeAreIn || stairsZone){ float ground; bool foundGround; - // This is all very strange.... - // targetPos = pTargetEntity->GetPosition(); // unused - if(pToGarageWeAreIn->m_pDoor1){ - whichDoor = 1; - garageDoorPos1.x = pToGarageWeAreIn->m_fDoor1X; - garageDoorPos1.y = pToGarageWeAreIn->m_fDoor1Y; - garageDoorPos1.z = 0.0f; - // targetPos.z = 0.0f; // unused - // (targetPos - doorPos1).Magnitude(); // unused - }else if(pToGarageWeAreIn->m_pDoor2){ - whichDoor = 2; + if(pToGarageWeAreIn){ + // This is all very strange.... + // targetPos = pTargetEntity->GetPosition(); // unused + if(pToGarageWeAreIn->m_pDoor1){ + whichDoor = 1; + garageDoorPos1.x = pToGarageWeAreIn->m_fDoor1X; + garageDoorPos1.y = pToGarageWeAreIn->m_fDoor1Y; + garageDoorPos1.z = 0.0f; + // targetPos.z = 0.0f; // unused + // (targetPos - doorPos1).Magnitude(); // unused + }else if(pToGarageWeAreIn->m_pDoor2){ + whichDoor = 2; #ifdef FIX_BUGS - garageDoorPos2.x = pToGarageWeAreIn->m_fDoor2X; - garageDoorPos2.y = pToGarageWeAreIn->m_fDoor2Y; - garageDoorPos2.z = 0.0f; + garageDoorPos2.x = pToGarageWeAreIn->m_fDoor2X; + garageDoorPos2.y = pToGarageWeAreIn->m_fDoor2Y; + garageDoorPos2.z = 0.0f; #endif - }else{ - whichDoor = 1; - garageDoorPos1.x = pTargetEntity->GetPosition().x; - garageDoorPos1.y = pTargetEntity->GetPosition().y; + }else{ + whichDoor = 1; + garageDoorPos1.x = pTargetEntity->GetPosition().x; + garageDoorPos1.y = pTargetEntity->GetPosition().y; #ifdef FIX_BUGS - garageDoorPos1.z = 0.0f; + garageDoorPos1.z = 0.0f; #else - garageDoorPos2.z = 0.0f; + garageDoorPos2.z = 0.0f; #endif + } + }else{ + assert(stairsZone); + whichDoor = 1; + garageDoorPos1 = Cams[ActiveCam].Source; + garageCenter = CVector((stairsZone->minx+stairsZone->maxx)/2.0f, (stairsZone->miny+stairsZone->maxy)/2.0f, 0.0f); + if((garageCenter-garageDoorPos1).Magnitude() > 15.0f){ + bool bClearViewOutside = true; + CVector dirOutside = pTargetEntity->GetPosition() - garageCenter; + dirOutside.z = 0.0f; + dirOutside.Normalise(); + float zoneDim = stairsZone->maxx - stairsZone->minx; + if(zoneDim < stairsZone->maxy - stairsZone->miny) + zoneDim = stairsZone->maxy - stairsZone->miny; + zoneDim *= 2.0f; + CVector posOutside = pTargetEntity->GetPosition() + zoneDim*dirOutside; + if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)){ + posOutside = pTargetEntity->GetPosition() - zoneDim*dirOutside; + if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)) + bClearViewOutside = false; + } + if(bClearViewOutside) + garageDoorPos1 = posOutside; + } } - garageCenter.x = (pToGarageWeAreIn->m_fX1 + pToGarageWeAreIn->m_fX2)/2.0f; - garageCenter.y = (pToGarageWeAreIn->m_fY1 + pToGarageWeAreIn->m_fY2)/2.0f; - garageCenter.z = 0.0f; + + if(pToGarageWeAreIn){ + garageCenter.x = pToGarageWeAreIn->GetGarageCenterX(); + garageCenter.y = pToGarageWeAreIn->GetGarageCenterY(); + garageCenter.z = 0.0f; + }else{ + garageDoorPos1.z = 0.0f; + if(stairsZone == nil) // how can this be true? + garageCenter = CVector(pTargetEntity->GetPosition().x, pTargetEntity->GetPosition().y, 0.0f); + } + if(whichDoor == 1) garageCenterToDoor = garageDoorPos1 - garageCenter; else @@ -905,9 +853,15 @@ CCamera::CamControl(void) ground = targetPos.z - 0.2f; garageCenterToDoor.z = 0.0f; garageCenterToDoor.Normalise(); - if(whichDoor == 1) - garageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor; - else + if(whichDoor == 1){ + if(pToGarageWeAreIn == nil && stairsZone){ + float zoneDim = stairsZone->maxx - stairsZone->minx; + if(zoneDim < stairsZone->maxy - stairsZone->miny) + zoneDim = stairsZone->maxy - stairsZone->miny; + garageCamPos = garageCenter + (0.7f*zoneDim + 3.75f)*garageCenterToDoor; + }else + garageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor; + }else garageCamPos = garageDoorPos2 + 13.0f*garageCenterToDoor; garageCamPos.z = ground + 3.1f; SetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f)); @@ -937,33 +891,38 @@ CCamera::CamControl(void) ReqMode = CCam::MODE_CAM_ON_A_STRING; } break; + } case VEHICLE_TYPE_BOAT: ReqMode = CCam::MODE_BEHINDBOAT; break; default: break; } + int vehApp = ((CVehicle*)pTargetEntity)->GetVehicleAppearance(); + int vehArrPos = 0; + GetArrPosForVehicleType(vehApp, vehArrPos); + // Car zoom value - if(CarZoomIndicator == CAM_ZOOM_1STPRS && !m_bPlayerIsInGarage){ + if (CarZoomIndicator == CAM_ZOOM_1STPRS && !m_bPlayerIsInGarage) { CarZoomValue = 0.0f; ReqMode = CCam::MODE_1STPERSON; } #ifdef FREE_CAM else if (bFreeCam) { if (CarZoomIndicator == CAM_ZOOM_1) - CarZoomValue = ((CVehicle*)pTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_1 : FREE_CAR_ZOOM_VALUE_1; + CarZoomValue = LCS_ZOOM_ONE_DISTANCE[vehArrPos]; else if (CarZoomIndicator == CAM_ZOOM_2) - CarZoomValue = ((CVehicle*)pTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_2 : FREE_CAR_ZOOM_VALUE_2; + CarZoomValue = LCS_ZOOM_TWO_DISTANCE[vehArrPos]; else if (CarZoomIndicator == CAM_ZOOM_3) - CarZoomValue = ((CVehicle*)pTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_3 : FREE_CAR_ZOOM_VALUE_3; + CarZoomValue = LCS_ZOOM_THREE_DISTANCE[vehArrPos]; } #endif - else if(CarZoomIndicator == CAM_ZOOM_1) - CarZoomValue = DEFAULT_CAR_ZOOM_VALUE_1; + else if (CarZoomIndicator == CAM_ZOOM_1) + CarZoomValue = ZOOM_ONE_DISTANCE[vehArrPos]; else if(CarZoomIndicator == CAM_ZOOM_2) - CarZoomValue = DEFAULT_CAR_ZOOM_VALUE_2; + CarZoomValue = ZOOM_TWO_DISTANCE[vehArrPos]; else if(CarZoomIndicator == CAM_ZOOM_3) - CarZoomValue = DEFAULT_CAR_ZOOM_VALUE_3; + CarZoomValue = ZOOM_THREE_DISTANCE[vehArrPos]; if(CarZoomIndicator == CAM_ZOOM_TOPDOWN && !m_bPlayerIsInGarage){ CarZoomValue = 1.0f; @@ -971,7 +930,7 @@ CCamera::CamControl(void) } // Check if we have to go into first person - if(((CVehicle*)pTargetEntity)->IsCar() && !m_bPlayerIsInGarage){ + if(vehType == VEHICLE_TYPE_CAR && !m_bPlayerIsInGarage){ if(CCullZones::Cam1stPersonForPlayer() && pTargetEntity->GetColModel()->boundingBox.GetSize().z >= 3.026f && pToGarageWeAreInForHackAvoidFirstPerson == nil){ @@ -1015,7 +974,8 @@ CCamera::CamControl(void) // Fallen into water if(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) && !boatTarget && - !Cams[ActiveCam].CamTargetEntity->IsPed()) + !Cams[ActiveCam].CamTargetEntity->IsPed() && + pTargetEntity->GetModelIndex() != MI_SKIMMER && pTargetEntity->GetModelIndex() != MI_SEASPAR) ReqMode = CCam::MODE_PLAYER_FALLEN_WATER; } } @@ -1025,49 +985,55 @@ CCamera::CamControl(void) // Change user selected mode if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && - !m_WideScreenOn && !m_bFailedCullZoneTestPreviously){ + !m_WideScreenOn && !m_bFailedCullZoneTestPreviously && !m_bFirstPersonBeingUsed){ if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){ - if(PedZoomIndicator == CAM_ZOOM_TOPDOWN) + if(PedZoomIndicator == CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1; else - PedZoomIndicator = CAM_ZOOM_TOPDOWN; + PedZoomIndicator = CAM_ZOOM_3; }else PedZoomIndicator--; } if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && - !m_WideScreenOn && !m_bFailedCullZoneTestPreviously){ + !m_WideScreenOn && !m_bFailedCullZoneTestPreviously && !m_bFirstPersonBeingUsed){ if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){ - if(PedZoomIndicator == CAM_ZOOM_TOPDOWN) + if(PedZoomIndicator == CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1; else - PedZoomIndicator = CAM_ZOOM_TOPDOWN; + PedZoomIndicator = CAM_ZOOM_3; }else PedZoomIndicator++; } - // disabled obbe's cam here - if(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_TOPDOWN; - else if(PedZoomIndicator > CAM_ZOOM_TOPDOWN) PedZoomIndicator = CAM_ZOOM_1; + // disabled top down and obbe's cam here + if(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_3; + else if(PedZoomIndicator > CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1; ReqMode = CCam::MODE_FOLLOWPED; // Check 1st person mode - if(m_bLookingAtPlayer && pTargetEntity->IsPed() && !m_WideScreenOn && !Cams[0].Using3rdPersonMouseCam() + if((m_bLookingAtPlayer || m_bEnable1rstPersonCamCntrlsScript) && pTargetEntity->IsPed() && + (!m_WideScreenOn || m_bEnable1rstPersonCamCntrlsScript) && !Cams[0].Using3rdPersonMouseCam() #ifdef FREE_CAM - && !CCamera::bFreeCam + && (!CCamera::bFreeCam || m_bEnable1rstPersonCamCntrlsScript) #endif ){ // See if we want to enter first person mode if(CPad::GetPad(0)->LookAroundLeftRight() || CPad::GetPad(0)->LookAroundUpDown()){ m_uiFirstPersonCamLastInputTime = CTimer::GetTimeInMilliseconds(); m_bFirstPersonBeingUsed = true; - }else if(m_bFirstPersonBeingUsed){ + } + if(m_bFirstPersonBeingUsed){ // Or if we want to go back to 3rd person if(CPad::GetPad(0)->GetPedWalkLeftRight() || CPad::GetPad(0)->GetPedWalkUpDown() || CPad::GetPad(0)->GetSquare() || CPad::GetPad(0)->GetTriangle() || CPad::GetPad(0)->GetCross() || CPad::GetPad(0)->GetCircle() || - CTimer::GetTimeInMilliseconds() - m_uiFirstPersonCamLastInputTime > 2850.0f) + CTimer::GetTimeInMilliseconds() - m_uiFirstPersonCamLastInputTime > 2850.0f){ + m_bFirstPersonBeingUsed = false; + }else if(CPad::GetPad(0)->TargetJustDown()){ m_bFirstPersonBeingUsed = false; + m_bJustJumpedOutOf1stPersonBecauseOfTarget = true; + } } }else m_bFirstPersonBeingUsed = false; @@ -1076,7 +1042,7 @@ CCamera::CamControl(void) m_bFirstPersonBeingUsed = false; if(m_bFirstPersonBeingUsed){ ReqMode = CCam::MODE_1STPERSON; - CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_CAMERA); + CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_CAMERA; } // Zoom value @@ -1114,6 +1080,8 @@ CCamera::CamControl(void) m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); m_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, m_fPedZoomValue); } + if(PedZoomIndicator == CAM_ZOOM_3 && m_fPedZoomValue == 0.0f) + m_fPedZoomValueSmooth = m_fPedZoomValue; } WellBufferMe(CloseInPedHeightTarget, &Cams[ActiveCam].m_fCloseInPedHeightOffset, &Cams[ActiveCam].m_fCloseInPedHeightOffsetSpeed, 0.1f, 0.025f, false); @@ -1128,15 +1096,13 @@ CCamera::CamControl(void) } // Garage cam - if(CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer()) - stairs = true; - // Some hack for Mr Whoopee in a bomb shop - if(Cams[ActiveCam].Using3rdPersonMouseCam() && CCollision::ms_collisionInMemory == LEVEL_COMMERCIAL){ - if(pTargetEntity->GetPosition().x < 83.0f && pTargetEntity->GetPosition().x > 18.0f && - pTargetEntity->GetPosition().y < -305.0f && pTargetEntity->GetPosition().y > -390.0f) - disableGarageCam = true; + CAttributeZone *stairsZone = nil; + if(CCullZones::CamStairsForPlayer()){ + stairsZone = CCullZones::FindZoneWithStairsAttributeForPlayer(); + if(stairsZone) + stairs = true; } - if(!disableGarageCam && (CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs)){ + if(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) && !m_bUseMouse3rdPerson || stairs){ if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){ if(pToGarageWeAreIn || stairs){ float ground; @@ -1171,20 +1137,41 @@ CCamera::CamControl(void) }else{ whichDoor = 1; garageDoorPos1 = Cams[ActiveCam].Source; + + if(stairsZone){ // always true + garageCenter = CVector((stairsZone->minx+stairsZone->maxx)/2, (stairsZone->miny+stairsZone->maxy)/2, 0.0f); + if(pTargetEntity->GetPosition().x > 376.0f && pTargetEntity->GetPosition().x < 383.0f && + pTargetEntity->GetPosition().y > -496.0f && pTargetEntity->GetPosition().y < -489.0f && + pTargetEntity->GetPosition().z > 11.6f && pTargetEntity->GetPosition().z < 13.6f){ + garageDoorPos1 = CVector(382.6f, -489.6f, 13.1f); + }else{ + bool bClearViewOutside = true; + CVector dirOutside = pTargetEntity->GetPosition() - garageCenter; + dirOutside.z = 0.0f; + dirOutside.Normalise(); + float zoneDim = stairsZone->maxx - stairsZone->minx; + if(zoneDim < stairsZone->maxy - stairsZone->miny) + zoneDim = stairsZone->maxy - stairsZone->miny; + zoneDim *= 2.0f; + CVector posOutside = pTargetEntity->GetPosition() + zoneDim*dirOutside; + if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)){ + posOutside = pTargetEntity->GetPosition() - zoneDim*dirOutside; + if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)) + bClearViewOutside = false; + } + if(bClearViewOutside) + garageDoorPos1 = posOutside; + } + } } if(pToGarageWeAreIn){ - garageCenter.x = (pToGarageWeAreIn->m_fX1 + pToGarageWeAreIn->m_fX2)/2.0f; - garageCenter.y = (pToGarageWeAreIn->m_fY1 + pToGarageWeAreIn->m_fY2)/2.0f; + garageCenter.x = pToGarageWeAreIn->GetGarageCenterX(); + garageCenter.y = pToGarageWeAreIn->GetGarageCenterY(); garageCenter.z = 0.0f; }else{ garageDoorPos1.z = 0.0f; - if(stairs){ - CAttributeZone *az = CCullZones::FindZoneWithStairsAttributeForPlayer(); - garageCenter.x = (az->minx + az->maxx)/2.0f; - garageCenter.y = (az->miny + az->maxy)/2.0f; - garageCenter.z = 0.0f; - }else + if(!stairs) // how can this be true? garageCenter = CVector(pTargetEntity->GetPosition().x, pTargetEntity->GetPosition().y, 0.0f); } if(whichDoor == 1) @@ -1198,9 +1185,15 @@ CCamera::CamControl(void) garageCenterToDoor.z = 0.0f; garageCenterToDoor.Normalise(); if(whichDoor == 1){ - if(pToGarageWeAreIn == nil && stairs) - garageCamPos = garageDoorPos1 + 3.75f*garageCenterToDoor; - else + if(pToGarageWeAreIn == nil && stairs){ + if(stairsZone){ + float zoneDim = stairsZone->maxx - stairsZone->minx; + if(zoneDim < stairsZone->maxy - stairsZone->miny) + zoneDim = stairsZone->maxy - stairsZone->miny; + garageCamPos = garageCenter + (0.7f*zoneDim + 3.75f)*garageCenterToDoor; + }else // how can this be true? + garageCamPos = garageDoorPos1 + 3.75f*garageCenterToDoor; + }else garageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor; }else{ garageCamPos = garageDoorPos2 + 13.0f*garageCenterToDoor; @@ -1208,8 +1201,8 @@ CCamera::CamControl(void) if(PedZoomIndicator == CAM_ZOOM_TOPDOWN && !stairs){ garageCamPos = garageCenter; garageCamPos.z += FindPlayerPed()->GetPosition().z + 2.1f; - if(pToGarageWeAreIn && garageCamPos.z > pToGarageWeAreIn->m_fX2) // What? - garageCamPos.z = pToGarageWeAreIn->m_fX2; + if(pToGarageWeAreIn && garageCamPos.z > pToGarageWeAreIn->m_fSupX) // What? + garageCamPos.z = pToGarageWeAreIn->m_fSupX; }else garageCamPos.z = ground + 3.1f; SetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f)); @@ -1237,6 +1230,13 @@ CCamera::CamControl(void) m_bGarageFixedCamPositionSet = false; } + // Lighthouse + if(!m_bFirstPersonBeingUsed && (pTargetEntity->GetPosition() - CVector(474.3f, -1717.6f, 0.0f)).Magnitude2D() < 6.0f) + if((pTargetEntity->GetPosition() - CVector(474.3f, -1717.6f, 0.0f)).Magnitude2D() < 3.8f || + pTargetEntity->GetPosition().z > 50.0f) + if(!Cams[ActiveCam].Using3rdPersonMouseCam()) + ReqMode = CCam::MODE_LIGHTHOUSE; + // Fallen into water if(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) && Cams[ActiveCam].CamTargetEntity->IsPed()) @@ -1259,8 +1259,10 @@ CCamera::CamControl(void) if(PlayerWeaponMode.Mode != CCam::MODE_NONE && !stairs){ if(PlayerWeaponMode.Mode == CCam::MODE_SNIPER || PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER || + // game also checks MODE_MODELVIEW here but that does make any sense... PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || + PlayerWeaponMode.Mode == CCam::MODE_CAMERA || Cams[ActiveCam].GetWeaponFirstPersonOn()){ // First person weapon mode if(PLAYER->GetPedState() == PED_SEEK_CAR){ @@ -1270,7 +1272,7 @@ CCamera::CamControl(void) ReqMode = CCam::MODE_FOLLOWPED; }else ReqMode = PlayerWeaponMode.Mode; - }else if(ReqMode != CCam::MODE_TOP_DOWN_PED){ + }else if(ReqMode != CCam::MODE_TOP_DOWN_PED && PedZoomIndicator != CAM_ZOOM_3){ // Syphon mode float playerTargetDist; float deadPedDist = 4.0f; @@ -1312,7 +1314,7 @@ CCamera::CamControl(void) if(ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT) fixedModeDist = 5.0f; else - fixedModeDist = 3.0f; + fixedModeDist = 5.6f; ReqMode = CCam::MODE_SPECIAL_FIXED_FOR_SYPHON; } if(ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){ @@ -1338,8 +1340,6 @@ CCamera::CamControl(void) } } - m_bIdleOn = false; - if(DebugCamMode) ReqMode = DebugCamMode; @@ -1348,56 +1348,66 @@ CCamera::CamControl(void) static int ThePickedArrestMode; static int LastPedState; bool startArrestCam = false; + static bool beingArrested = false; + bool stopArrestCam = false; + if(PLAYER->GetPedState() == PED_ARRESTED) + beingArrested = true; + else if(beingArrested){ + stopArrestCam = true; + beingArrested = false; + } if(LastPedState != PED_ARRESTED && PLAYER->GetPedState() == PED_ARRESTED){ - if(CarZoomIndicator != CAM_ZOOM_1STPRS && pTargetEntity->IsVehicle()) + if(CarZoomIndicator != CAM_ZOOM_1STPRS || !pTargetEntity->IsVehicle()) startArrestCam = true; }else startArrestCam = false; LastPedState = PLAYER->GetPedState(); + if(startArrestCam){ - if(m_uiTransitionState) - ReqMode = Cams[ActiveCam].Mode; - else{ - bool valid; - if(pTargetEntity->IsPed()){ - // How can this happen if arrest cam is only done in cars? - Cams[(ActiveCam+1)%2].ResetStatics = true; - valid = Cams[(ActiveCam+1)%2].ProcessArrestCamOne(); - ReqMode = CCam::MODE_ARRESTCAM_ONE; - }else{ - Cams[(ActiveCam+1)%2].ResetStatics = true; - valid = Cams[(ActiveCam+1)%2].ProcessArrestCamTwo(); - ReqMode = CCam::MODE_ARRESTCAM_TWO; - } - if(!valid) - ReqMode = Cams[ActiveCam].Mode; - } - } - ThePickedArrestMode = ReqMode; - if(PLAYER->GetPedState() == PED_ARRESTED) - ReqMode = ThePickedArrestMode; // this is rather useless... + ThePickedArrestMode = CCam::MODE_ARRESTCAM_ONE; + ReqMode = CCam::MODE_ARRESTCAM_ONE; + Cams[ActiveCam].ResetStatics = true; + }else if(PLAYER->GetPedState() == PED_ARRESTED) + ReqMode = ThePickedArrestMode; // Process dead player if(PLAYER->GetPedState() == PED_DEAD){ if(Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY) ReqMode = CCam::MODE_PED_DEAD_BABY; else{ - bool foundRoof; - CVector pos = FindPlayerPed()->GetPosition(); - CWorld::FindRoofZFor3DCoord(pos.x, pos.y, pos.z, &foundRoof); - if(!foundRoof) + bool useArrestCam = false; + if(pTargetEntity->IsPed()){ + for(int i = 0; i < ((CPed*)pTargetEntity)->m_numNearPeds; i++){ + CPed *ped = ((CPed*)pTargetEntity)->m_nearPeds[i]; + if(ped && ped->GetPedState() == PED_ARREST_PLAYER) + if((ped->GetPosition() - pTargetEntity->GetPosition()).Magnitude() < 4.0f){ + ReqMode = CCam::MODE_ARRESTCAM_ONE; + Cams[ActiveCam].ResetStatics = true; + useArrestCam = true; + break; + } + } + } + if(!useArrestCam){ ReqMode = CCam::MODE_PED_DEAD_BABY; + Cams[ActiveCam].ResetStatics = true; + } } } // Restore with a jump cut if(m_bRestoreByJumpCut){ - // PS2 just sets m_bCamDirectlyBehind here if(ReqMode != CCam::MODE_FOLLOWPED && + ReqMode != CCam::MODE_BEHINDCAR && + ReqMode != CCam::MODE_CAM_ON_A_STRING && ReqMode != CCam::MODE_M16_1STPERSON && + ReqMode != CCam::MODE_SYPHON && + ReqMode != CCam::MODE_SYPHON_CRIM_IN_FRONT && + ReqMode != CCam::MODE_SPECIAL_FIXED_FOR_SYPHON && ReqMode != CCam::MODE_SNIPER && - ReqMode != CCam::MODE_ROCKETLAUNCHER || + ReqMode != CCam::MODE_ROCKETLAUNCHER && + ReqMode != CCam::MODE_CAMERA && !m_bUseMouse3rdPerson) SetCameraDirectlyBehindForFollowPed_CamOnAString(); @@ -1409,7 +1419,6 @@ CCamera::CamControl(void) Cams[ActiveCam].CamTargetEntity = pTargetEntity; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet; - // PS2 sets this to m_bLookingAtVector Cams[ActiveCam].m_bCamLookingAtVector = false; Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition; m_bRestoreByJumpCut = false; @@ -1443,16 +1452,20 @@ CCamera::CamControl(void) ReqMode == CCam::MODE_SNIPER || ReqMode == CCam::MODE_ROCKETLAUNCHER || ReqMode == CCam::MODE_M16_1STPERSON || ReqMode == CCam::MODE_SNIPER_RUNABOUT || ReqMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT || - ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || ReqMode == CCam::MODE_HELICANNON_1STPERSON || + ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || ReqMode == CCam::MODE_HELICANNON_1STPERSON || ReqMode == CCam::MODE_CAMERA || WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT || m_bJustCameOutOfGarage || m_bPlayerIsInGarage) canUseObbeCam = false; if(m_bObbeCinematicPedCamOn && canUseObbeCam) ProcessObbeCinemaCameraPed(); - else if(m_bObbeCinematicCarCamOn && canUseObbeCam) - ProcessObbeCinemaCameraCar(); - else{ + else if(m_bObbeCinematicCarCamOn && canUseObbeCam){ + if(pTargetEntity->IsVehicle() && ((CVehicle*)pTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || + ((CVehicle*)pTargetEntity)->IsBoat()) + ProcessObbeCinemaCameraHeli(); + else + ProcessObbeCinemaCameraCar(); + }else{ if(m_bPlayerIsInGarage && m_bObbeCinematicCarCamOn) switchByJumpCut = true; canUseObbeCam = false; @@ -1476,6 +1489,10 @@ CCamera::CamControl(void) switchByJumpCut = true; } + // Going into Syphon mode + if(ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT) + switchByJumpCut = true; + // Top down modes can interpolate between each other if(ReqMode == CCam::MODE_TOPDOWN){ if(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY) @@ -1490,7 +1507,7 @@ CCamera::CamControl(void) ReqMode == CCam::MODE_SNIPER_RUNABOUT || ReqMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || - ReqMode == CCam::MODE_HELICANNON_1STPERSON || + ReqMode == CCam::MODE_HELICANNON_1STPERSON || ReqMode == CCam::MODE_CAMERA || ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO){ // Going into any 1st person mode is a jump cut if(pTargetEntity->IsPed()) @@ -1508,11 +1525,16 @@ CCamera::CamControl(void) Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT || - Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT){ + Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT || + Cams[ActiveCam].Mode == CCam::MODE_CAMERA){ if(pTargetEntity && pTargetEntity->IsVehicle()) switchByJumpCut = true; } }else if(ReqMode == CCam::MODE_FOLLOWPED){ + bool syphonJumpCut = false; + if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON || Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT) + if(!((CPed*)pTargetEntity)->CanWeRunAndFireWithWeapon()) + syphonJumpCut = true; if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER || @@ -1527,8 +1549,10 @@ CCamera::CamControl(void) Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON || + Cams[ActiveCam].Mode == CCam::MODE_CAMERA || Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || - Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ + Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || + syphonJumpCut || stopArrestCam){ if(!m_bJustCameOutOfGarage){ if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER || @@ -1539,7 +1563,8 @@ CCamera::CamControl(void) Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT || - Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON){ + Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON || + Cams[ActiveCam].Mode == CCam::MODE_CAMERA){ float angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI; ((CPed*)pTargetEntity)->m_fRotationCur = angle; ((CPed*)pTargetEntity)->m_fRotationDest = angle; @@ -1548,7 +1573,7 @@ CCamera::CamControl(void) switchByJumpCut = true; if(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ CVector front = Cams[ActiveCam].Source - FindPlayerPed()->GetPosition(); - front.z = 0.0f; // missing on PS2 + front.z = 0.0f; front.Normalise(); #ifdef FIX_BUGS // this is almost as bad as the bugged code @@ -1567,7 +1592,12 @@ CCamera::CamControl(void) }else if(ReqMode == CCam::MODE_FIGHT_CAM){ if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON) switchByJumpCut = true; - } + }else if(ReqMode == CCam::MODE_LIGHTHOUSE || + ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO || + ReqMode == CCam::MODE_PED_DEAD_BABY) + switchByJumpCut = true; + else if(Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY && ReqMode != CCam::MODE_PED_DEAD_BABY) + switchByJumpCut = true; if(ReqMode != Cams[ActiveCam].Mode && Cams[ActiveCam].CamTargetEntity == nil) switchByJumpCut = true; @@ -1587,12 +1617,11 @@ CCamera::CamControl(void) if((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){ if(switchByJumpCut){ - // PS2 just sets m_bCamDirectlyBehind here if(!m_bPlayerIsInGarage || m_bJustCameOutOfGarage){ if(ReqMode != CCam::MODE_FOLLOWPED && ReqMode != CCam::MODE_M16_1STPERSON && ReqMode != CCam::MODE_SNIPER && - ReqMode != CCam::MODE_ROCKETLAUNCHER || + ReqMode != CCam::MODE_ROCKETLAUNCHER && !m_bUseMouse3rdPerson) SetCameraDirectlyBehindForFollowPed_CamOnAString(); } @@ -1626,8 +1655,6 @@ CCamera::CamControl(void) if(ReqMode == CCam::MODE_FOLLOWPED && Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM) startTransition = false; -#ifndef PS2_CAM_TRANSITION - // done in Process on PS2 if(!m_bWaitForInterpolToFinish && m_bLookingAtPlayer && m_uiTransitionState != 0){ CVector playerDist; playerDist.x = FindPlayerPed()->GetPosition().x - GetPosition().x; @@ -1640,7 +1667,6 @@ CCamera::CamControl(void) m_bWaitForInterpolToFinish = true; } } -#endif if(m_bWaitForInterpolToFinish) startTransition = false; @@ -1650,19 +1676,32 @@ CCamera::CamControl(void) Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); } }else if(ReqMode == CCam::MODE_FIXED && pTargetEntity != Cams[ActiveCam].CamTargetEntity && m_bPlayerIsInGarage){ -#ifdef PS2_CAM_TRANSITION - StartTransitionWhenNotFinishedInter(ReqMode); -#else if(m_uiTransitionState != 0) StartTransitionWhenNotFinishedInter(ReqMode); else StartTransition(ReqMode); -#endif pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); } }else{ // not following player + bool useWeaponMode = false; + bool jumpCutTo1stPrs = false; + if(m_bEnable1rstPersonCamCntrlsScript || m_bAllow1rstPersonWeaponsCamera){ + if(ReqMode == CCam::MODE_1STPERSON){ + if(Cams[ActiveCam].Mode != ReqMode) + jumpCutTo1stPrs = true; + }else if((PlayerWeaponMode.Mode == CCam::MODE_SNIPER || PlayerWeaponMode.Mode == CCam::MODE_1STPERSON || PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER) && + CPad::GetPad(0)->GetTarget() && m_bAllow1rstPersonWeaponsCamera){ + useWeaponMode = true; + jumpCutTo1stPrs = true; + }else if(Cams[ActiveCam].Mode != m_iModeToGoTo){ + m_bStartInterScript = true; + m_iTypeOfSwitch = JUMP_CUT; + CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_CAMERA; + } + } + if(m_uiTransitionState == 0 && m_bStartInterScript && m_iTypeOfSwitch == INTERPOLATION){ ReqMode = m_iModeToGoTo; StartTransition(ReqMode); @@ -1673,10 +1712,15 @@ CCamera::CamControl(void) StartTransitionWhenNotFinishedInter(ReqMode); pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); - }else if(m_bStartInterScript && m_iTypeOfSwitch == JUMP_CUT){ + }else if(m_bStartInterScript && m_iTypeOfSwitch == JUMP_CUT || jumpCutTo1stPrs){ m_uiTransitionState = 0; m_vecDoingSpecialInterPolation = false; - Cams[ActiveCam].Mode = m_iModeToGoTo; + if(m_bEnable1rstPersonCamCntrlsScript && ReqMode == CCam::MODE_1STPERSON) + Cams[ActiveCam].Mode = ReqMode; + else if(useWeaponMode) + Cams[ActiveCam].Mode = PlayerWeaponMode.Mode; + else + Cams[ActiveCam].Mode = m_iModeToGoTo; m_bJust_Switched = true; Cams[ActiveCam].ResetStatics = true; Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector; @@ -1702,23 +1746,42 @@ CCamera::CamControl(void) if((Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || - Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER) && pTargetEntity->IsPed() || + Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER || + Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON || + Cams[ActiveCam].Mode == CCam::MODE_CAMERA) && pTargetEntity->IsPed() || Cams[ActiveCam].Mode == CCam::MODE_FLYBY) FindPlayerPed()->bIsVisible = false; else FindPlayerPed()->bIsVisible = true; - if(!canUseObbeCam && WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) - Restore(); + bool switchedFromObbe = false; + if(!canUseObbeCam && WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){ + RestoreWithJumpCut(); + switchedFromObbe = true; + SetCameraDirectlyBehindForFollowPed_CamOnAString(); + } + + if(PrevMode != Cams[ActiveCam].Mode || switchedFromObbe || + Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED || Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING) + if(CPad::GetPad(0)->CycleCameraModeJustDown() && + !CReplay::IsPlayingBack() && + (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && + !m_WideScreenOn && + (WhoIsInControlOfTheCamera != CAMCONTROL_OBBE || bSwitchedToObbeCam)) + DMAudio.PlayFrontEndSound(SOUND_HUD, 0); } // What a mess! void CCamera::UpdateTargetEntity(void) { - bool enteringCar = false; // not on PS2 but only used as && !enteringCar so we can keep it + bool enteringCar = false; bool obbeCam = false; + m_bPlayerWasOnBike = false; + if(pTargetEntity && pTargetEntity->IsVehicle() && ((CVehicle*)pTargetEntity)->IsBike()) + m_bPlayerWasOnBike = true; + if(WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){ obbeCam = true; if(m_iModeObbeCamIsInForCar == OBBE_COPCAR_WHEEL || m_iModeObbeCamIsInForCar == OBBE_COPCAR){ @@ -1736,7 +1799,6 @@ CCamera::UpdateTargetEntity(void) pTargetEntity = FindPlayerVehicle(); else{ pTargetEntity = FindPlayerPed(); -#ifndef GTA_PS2_STUFF // this keeps the camera on the player while entering cars if(PLAYER->GetPedState() == PED_ENTER_CAR || PLAYER->GetPedState() == PED_CARJACK || @@ -1746,14 +1808,21 @@ CCamera::UpdateTargetEntity(void) if(!enteringCar) if(Cams[ActiveCam].CamTargetEntity != pTargetEntity) Cams[ActiveCam].CamTargetEntity = pTargetEntity; -#endif } bool cantOpen = true; - if(PLAYER && - PLAYER->m_pMyVehicle && - PLAYER->m_pMyVehicle->CanPedOpenLocks(PLAYER)) - cantOpen = false; + if(PLAYER){ + if(PLAYER->m_pMyVehicle){ + if(FindPlayerPed()->m_pMyVehicle->CanPedOpenLocks(PLAYER)) + cantOpen = false; + }else if(FindPlayerPed()->m_carInObjective && + (FindPlayerPed()->GetPedState() == PED_ENTER_CAR || + FindPlayerPed()->GetPedState() == PED_CARJACK || + FindPlayerPed()->GetPedState() == PED_OPEN_DOOR)){ + if(FindPlayerPed()->m_carInObjective->CanPedOpenLocks(FindPlayerPed())) + cantOpen = false; + } + } if(PLAYER->GetPedState() == PED_ENTER_CAR && !cantOpen){ if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS){ @@ -1765,16 +1834,9 @@ CCamera::UpdateTargetEntity(void) if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){ if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS) -#ifdef GTA_PS2_STUFF -// dunno if this has any amazing effects - { -#endif pTargetEntity = PLAYER->m_pMyVehicle; if(PLAYER->m_pMyVehicle == nil) pTargetEntity = PLAYER; -#ifdef GTA_PS2_STUFF - } -#endif } if(PLAYER->GetPedState() == PED_EXIT_CAR) @@ -1805,6 +1867,7 @@ CCamera::UpdateSoundDistances(void) Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON || + Cams[ActiveCam].Mode == CCam::MODE_CAMERA || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER) && pTargetEntity->IsPed()) @@ -1823,33 +1886,6 @@ CCamera::UpdateSoundDistances(void) } f = (n + 1) / 6.0f; SoundDistUp = (1.0f-f)*SoundDistUpAsReadOld + f*SoundDistUpAsRead; - - // check left - n = (CTimer::GetFrameCounter()+2) % 12; - if(n == 0){ - SoundDistLeftAsReadOld = SoundDistLeftAsRead; - end = center + SOUND_DIST*GetRight(); - if(CWorld::ProcessLineOfSight(center, end, colPoint, entity, true, false, false, false, true, true, true)) - SoundDistLeftAsRead = (colPoint.point - center).Magnitude(); - else - SoundDistLeftAsRead = SOUND_DIST; - } - f = (n + 1) / 6.0f; - SoundDistLeft = (1.0f-f)*SoundDistLeftAsReadOld + f*SoundDistLeftAsRead; - - // check right - // end = center - SOUND_DIST*GetRight(); // useless - n = (CTimer::GetFrameCounter()+4) % 12; - if(n == 0){ - SoundDistRightAsReadOld = SoundDistRightAsRead; - end = center - SOUND_DIST*GetRight(); - if(CWorld::ProcessLineOfSight(center, end, colPoint, entity, true, false, false, false, true, true, true)) - SoundDistRightAsRead = (colPoint.point - center).Magnitude(); - else - SoundDistRightAsRead = SOUND_DIST; - } - f = (n + 1) / 6.0f; - SoundDistRight = (1.0f-f)*SoundDistRightAsReadOld + f*SoundDistRightAsRead; } void @@ -1894,6 +1930,147 @@ CamShakeNoPos(CCamera *cam, float strength) } } +bool bAvoidTest1 = false; +bool bAvoidTest2 = false; // unused +bool bAvoidTest3 = false; // unused +float fRangePlayerRadius = 0.5f; +float fCloseNearClipLimit = 0.15f; +float fAvoidTweakFOV = 1.15f; +float fAvoidProbTimerDamp = 0.9f; + +void +CCamera::AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV) +{ + float Beta = 0.0f; + float Alpha = 0.0f; + + CVector vDist = TargetPos - Source; + m_vecClearGeometryVec = CVector(0.0f, 0.0f, 0.0f); + float fDist = vDist.Magnitude(); + float fDistOnGround = vDist.Magnitude2D(); + if(vDist.x == 0.0f && vDist.y == 0.0f) + Beta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y); + else + Beta = CGeneral::GetATanOfXY(vDist.x, vDist.y); + if(fDistOnGround != 0.0f || vDist.z != 0.0f) + Alpha = CGeneral::GetATanOfXY(fDistOnGround, vDist.z); + CVector Front(Cos(Alpha)*Cos(Beta), Cos(Alpha)*Sin(Beta), Sin(Alpha)); + NewSource = TargetPos - Front*fDist; + Front.Normalise(); + + // Clip camera source + CColPoint point; + CEntity *entity = nil; + CWorld::pIgnoreEntity = pTargetEntity; + if(CWorld::ProcessLineOfSight(TargetPos, NewSource, point, entity, true, false, false, true, false, false, true)){ + CVector ClipPoint1 = point.point; + NewSource = point.point; + if(!bAvoidTest1){ + if(CWorld::ProcessLineOfSight(NewSource, TargetPos, point, entity, false, true, true, true, false, false, true)){ + if((NewSource - point.point).Magnitude() < RwCameraGetNearClipPlane(Scene.camera)) + NewSource = point.point; + else if((NewSource - ClipPoint1).Magnitude() < RwCameraGetNearClipPlane(Scene.camera)) + NewSource = ClipPoint1; + } + } + } + CWorld::pIgnoreEntity = nil; + + + vDist = TargetPos - NewSource; + fDist = vDist.Magnitude(); + if(FindPlayerPed()) + if(fDist - fRangePlayerRadius < RwCameraGetNearClipPlane(Scene.camera)) + RwCameraSetNearClipPlane(Scene.camera, Max(fDist - fRangePlayerRadius, fCloseNearClipLimit)); + + + static float fClearGeomAmount; + static float fClearGeomAmountSpeed; + float Near = RwCameraGetNearClipPlane(Scene.camera); + float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); + float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fAvoidTweakFOV; + CVector Center = NewSource + Front*Near; + float fClearGeomTarget = 0.0f; + if(CWorld::TestSphereAgainstWorld(Center, ViewPlaneWidth, nil, true, false, false, true, false, true)){ + CVector CamToCol = gaTempSphereColPoints[0].point - NewSource; + float FrontDist = DotProduct(CamToCol, Front); + CVector CenterToCol = gaTempSphereColPoints[0].point - Center; + if(FrontDist < DEFAULT_NEAR && FrontDist > fCloseNearClipLimit){ + if(FrontDist < RwCameraGetNearClipPlane(Scene.camera)) + RwCameraSetNearClipPlane(Scene.camera, FrontDist); + }else if(FrontDist < fCloseNearClipLimit) + RwCameraSetNearClipPlane(Scene.camera, fCloseNearClipLimit); + + float ColDepth = ViewPlaneWidth - CenterToCol.Magnitude(); // amount of radius in collision + CenterToCol.Normalise(); + CVector Normal = gaTempSphereColPoints[0].normal; + Normal.Normalise(); + if(-DotProduct(CenterToCol, Normal) < 0.0f) + Normal = -Normal; // always push away from col surface + float DistToMove = DotProduct(-ColDepth*CenterToCol, Normal); + m_vecClearGeometryVec = DistToMove*Normal; // move source so this point is out of collision + + if(pTargetEntity && pTargetEntity->IsPed() && RwCameraGetNearClipPlane(Scene.camera) < 2.0f*fCloseNearClipLimit){ + float TargetNormalDir = DotProduct(Normal, pTargetEntity->GetForward()); + if(TargetNormalDir < 0.0f){ + // target looking towards collision + if(m_fAvoidTheGeometryProbsTimer < 0.0f) + m_fAvoidTheGeometryProbsTimer = 0.0f; + m_fAvoidTheGeometryProbsTimer += CTimer::GetTimeStep(); + }else if(TargetNormalDir > 0.5f){ + // target looking away from collision + if(m_fAvoidTheGeometryProbsTimer > 0.0f) + m_fAvoidTheGeometryProbsTimer = 0.0f; + m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep(); + } + + if(m_nAvoidTheGeometryProbsDirn == 0){ + if(CrossProduct(pTargetEntity->GetPosition() - NewSource, Normal).z > 0.0f) + m_nAvoidTheGeometryProbsDirn = -1; + else + m_nAvoidTheGeometryProbsDirn = 1; + } + } + + fClearGeomTarget = 1.0f; + } + + m_fAvoidTheGeometryProbsTimer *= Pow(fAvoidProbTimerDamp, CTimer::GetTimeStep()); + WellBufferMe(fClearGeomTarget, &fClearGeomAmount, &fClearGeomAmountSpeed, 0.2f, 0.05f, false); + m_vecClearGeometryVec *= fClearGeomAmount; + m_bMoveCamToAvoidGeom = true; +} + +void +CCamera::GetArrPosForVehicleType(int apperance, int &index) +{ + switch(apperance){ + case VEHICLE_APPEARANCE_CAR: index = 0; break; + case VEHICLE_APPEARANCE_BIKE: index = 1; break; + case VEHICLE_APPEARANCE_HELI: index = 2; break; + case VEHICLE_APPEARANCE_PLANE: index = 3; break; + case VEHICLE_APPEARANCE_BOAT: index = 4; break; + } +} + +void +CCamera::GetScreenRect(CRect &rect) +{ + rect.left = 0.0f; + rect.right = SCREEN_WIDTH; + if(m_WideScreenOn +#ifdef CUTSCENE_BORDERS_SWITCH + && CMenuManager::m_PrefsCutsceneBorders +#endif + ){ + float borderSize = (SCREEN_HEIGHT / 2) * (m_ScreenReductionPercentage / 100.f); + rect.top = borderSize - SCREEN_SCALE_Y(22.f); + rect.bottom = SCREEN_HEIGHT - borderSize - SCREEN_SCALE_Y(14.f); + }else{ + rect.top = 0.0f; + rect.bottom = SCREEN_HEIGHT; + } +} void @@ -1923,7 +2100,6 @@ CCamera::TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 cont m_iTypeOfSwitch = typeOfSwitch; m_bLookingAtPlayer = false; m_bStartInterScript = true; - // FindPlayerPed(); // unused } } @@ -1953,8 +2129,6 @@ CCamera::TakeControlWithSpline(int16 typeOfSwitch) m_bcutsceneFinished = false; m_iTypeOfSwitch = typeOfSwitch; m_bStartInterScript = true; - - //FindPlayerPed(); // unused }; void @@ -1989,10 +2163,13 @@ CCamera::Restore(void) pTargetEntity = PLAYER; } + m_bEnable1rstPersonCamCntrlsScript = false; + m_bAllow1rstPersonWeaponsCamera = false; m_bUseScriptZoomValuePed = false; m_bUseScriptZoomValueCar = false; m_bStartInterScript = true; m_bCameraJustRestored = true; + m_fAvoidTheGeometryProbsTimer = 0.0f; } void @@ -2009,6 +2186,8 @@ CCamera::RestoreWithJumpCut(void) m_bScriptParametersSetForInterPol = false; WhoIsInControlOfTheCamera = CAMCONTROL_GAME; m_bCameraJustRestored = true; + m_bEnable1rstPersonCamCntrlsScript = false; + m_bAllow1rstPersonWeaponsCamera = false; if(FindPlayerVehicle()){ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING; @@ -2038,27 +2217,25 @@ CCamera::SetCamPositionForFixedMode(const CVector &Source, const CVector &UpOffS { m_vecFixedModeSource = Source; m_vecFixedModeUpOffSet = UpOffSet; + m_bGarageFixedCamPositionSet = false; } - -/* - * On PS2 the transition happens between Cams[0] and Cams[1]. - * On PC the whole system has been changed. - */ void CCamera::StartTransition(int16 newMode) { + bool switchFromFixedSyphon = false; bool switchSyphonMode = false; + bool switchPedMode = false; bool switchPedToCar = false; bool switchFromFight = false; + bool switchBikeToPed = false; bool switchFromFixed = false; bool switch1stPersonToVehicle = false; float betaOffset, targetBeta, camBeta, deltaBeta; int door; bool vehicleVertical; -#ifndef PS2_CAM_TRANSITION m_bItsOkToLookJustAtThePlayer = false; m_fFractionInterToStopMoving = 0.25f; m_fFractionInterToStopCatchUp = 0.75f; @@ -2071,20 +2248,21 @@ CCamera::StartTransition(int16 newMode) newMode == CCam::MODE_FOLLOWPED || newMode == CCam::MODE_SYPHON || newMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) - m_bItsOkToLookJustAtThePlayer = true; + switchPedMode = true; if(newMode == CCam::MODE_CAM_ON_A_STRING) switchPedToCar = true; } -#endif + if(Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) + switchFromFixedSyphon = true; + if(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING && newMode == CCam::MODE_FOLLOWPED && m_bPlayerWasOnBike) + switchBikeToPed = true; if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT && newMode == CCam::MODE_SYPHON) switchSyphonMode = true; if(Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM && newMode == CCam::MODE_FOLLOWPED) switchFromFight = true; -#ifndef PS2_CAM_TRANSITION if(Cams[ActiveCam].Mode == CCam::MODE_FIXED) switchFromFixed = true; -#endif m_bUseTransitionBeta = false; @@ -2096,6 +2274,7 @@ CCamera::StartTransition(int16 newMode) Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON || + Cams[ActiveCam].Mode == CCam::MODE_CAMERA || Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT) && pTargetEntity->IsPed()){ float angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI; @@ -2103,12 +2282,6 @@ CCamera::StartTransition(int16 newMode) ((CPed*)pTargetEntity)->m_fRotationDest = angle; } -#ifdef PS2_CAM_TRANSITION - ActiveCam = (ActiveCam+1)%2; - Cams[ActiveCam].Init(); - Cams[ActiveCam].Mode = newMode; -#endif - Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector; Cams[ActiveCam].CamTargetEntity = pTargetEntity; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; @@ -2123,70 +2296,42 @@ CCamera::StartTransition(int16 newMode) newMode == CCam::MODE_1STPERSON_RUNABOUT || newMode == CCam::MODE_M16_1STPERSON_RUNABOUT || newMode == CCam::MODE_FIGHT_CAM_RUNABOUT || - newMode == CCam::MODE_HELICANNON_1STPERSON) + newMode == CCam::MODE_HELICANNON_1STPERSON || + newMode == CCam::MODE_CAMERA) Cams[ActiveCam].Alpha = 0.0f; - // PS2 also copies values to ActiveCam here switch(Cams[ActiveCam].Mode) case CCam::MODE_SNIPER_RUNABOUT: case CCam::MODE_ROCKETLAUNCHER_RUNABOUT: case CCam::MODE_1STPERSON_RUNABOUT: case CCam::MODE_M16_1STPERSON_RUNABOUT: case CCam::MODE_FIGHT_CAM_RUNABOUT: + case CCam::MODE_CAMERA: if(newMode == CCam::MODE_CAM_ON_A_STRING || newMode == CCam::MODE_BEHINDBOAT) switch1stPersonToVehicle = true; switch(newMode){ case CCam::MODE_BEHINDCAR: -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; - Cams[ActiveCam].Beta = Cams[(ActiveCam+1)%2].Beta; -#endif Cams[ActiveCam].BetaSpeed = 0.0f; break; case CCam::MODE_BEHINDBOAT: -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; - Cams[ActiveCam].Beta = Cams[(ActiveCam+1)%2].Beta; -#endif Cams[ActiveCam].BetaSpeed = 0.0f; break; case CCam::MODE_FOLLOWPED: // Getting out of vehicle normally betaOffset = DEGTORAD(55.0f); -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; -#endif if(m_bJustCameOutOfGarage){ m_bUseTransitionBeta = true; -/* - // weird logic... - if(CMenuManager::m_ControlMethod == CONTROL_CLASSIC) - Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI; - else if(Cams[ActiveCam].Front.x != 0.0f && Cams[ActiveCam].Front.y != 0.0f) // && is wrong here - Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI; - else - Cams[ActiveCam].m_fTransitionBeta = 0.0f; -*/ - // this is better: if(Cams[ActiveCam].Front.x != 0.0f || Cams[ActiveCam].Front.y != 0.0f) -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[(ActiveCam+1)%2].Front.x, Cams[(ActiveCam+1)%2].Front.y) + PI; -#else Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI; -#endif else Cams[ActiveCam].m_fTransitionBeta = 0.0f; } if(m_bTargetJustCameOffTrain) m_bCamDirectlyInFront = true; -#ifdef PS2_CAM_TRANSITION - if(Cams[(ActiveCam+1)%2].Mode != CCam::MODE_CAM_ON_A_STRING) -#else if(Cams[ActiveCam].Mode != CCam::MODE_CAM_ON_A_STRING) -#endif break; m_bUseTransitionBeta = true; vehicleVertical = false; @@ -2198,11 +2343,7 @@ CCamera::StartTransition(int16 newMode) Cams[ActiveCam].m_fTransitionBeta = 0.0f; break; } -#ifdef PS2_CAM_TRANSITION - camBeta = CGeneral::GetATanOfXY(Cams[(ActiveCam+1)%2].Front.x, Cams[(ActiveCam+1)%2].Front.y); -#else camBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); -#endif if(((CPed*)pTargetEntity)->m_carInObjective) targetBeta = CGeneral::GetATanOfXY(((CPed*)pTargetEntity)->m_carInObjective->GetForward().x, ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y); else @@ -2251,6 +2392,7 @@ CCamera::StartTransition(int16 newMode) case CCam::MODE_M16_1STPERSON_RUNABOUT: case CCam::MODE_FIGHT_CAM_RUNABOUT: case CCam::MODE_HELICANNON_1STPERSON: + case CCam::MODE_CAMERA: if(FindPlayerVehicle()) Cams[ActiveCam].Beta = Atan2(FindPlayerVehicle()->GetForward().x, FindPlayerVehicle()->GetForward().y); else @@ -2258,10 +2400,6 @@ CCamera::StartTransition(int16 newMode) break; case CCam::MODE_SYPHON: -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Beta = Cams[(ActiveCam+1)%2].Beta; - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; -#endif Cams[ActiveCam].Alpha = 0.0f; Cams[ActiveCam].AlphaSpeed = 0.0f; break; @@ -2269,73 +2407,17 @@ CCamera::StartTransition(int16 newMode) case CCam::MODE_CAM_ON_A_STRING: // Get into vehicle betaOffset = DEGTORAD(57.0f); -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; -#endif if(!m_bLookingAtPlayer || m_bJustCameOutOfGarage) break; m_bUseTransitionBeta = true; - targetBeta = CGeneral::GetATanOfXY(pTargetEntity->GetForward().x, pTargetEntity->GetForward().y); -#ifdef PS2_CAM_TRANSITION - camBeta = CGeneral::GetATanOfXY(Cams[(ActiveCam+1)%2].Front.x, Cams[(ActiveCam+1)%2].Front.y); -#else - camBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); -#endif - deltaBeta = targetBeta - camBeta; - while(deltaBeta >= PI) deltaBeta -= 2*PI; - while(deltaBeta < -PI) deltaBeta += 2*PI; - deltaBeta = Abs(deltaBeta); -#ifndef PS2_CAM_TRANSITION - switchFromFixed = Cams[ActiveCam].Mode == CCam::MODE_FIXED; - if(switchFromFixed){ - Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); - break; - } -#endif - - door = FindPlayerPed()->m_vehDoor; - if(deltaBeta > HALFPI){ - if(((CVehicle*)pTargetEntity)->IsUpsideDown()){ - if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) // BUG: game checks LF twice - betaOffset = -DEGTORAD(57.0f); - }else{ - if(door == CAR_DOOR_RF || door == CAR_DOOR_RR) - betaOffset = -DEGTORAD(57.0f); - } - Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset + PI; - }else{ - if(((CVehicle*)pTargetEntity)->IsUpsideDown()){ - if(door == CAR_DOOR_RF || door == CAR_DOOR_RR) - betaOffset = -DEGTORAD(57.0f); - else if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) - betaOffset = DEGTORAD(57.0f); - }else{ - if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) - betaOffset = -DEGTORAD(57.0f); - else if(door == CAR_DOOR_RF || door == CAR_DOOR_RR) - betaOffset = DEGTORAD(57.0f); - } - Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset; - } + Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); break; case CCam::MODE_PED_DEAD_BABY: -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; -#endif Cams[ActiveCam].Alpha = DEGTORAD(15.0f); break; -#ifdef PS2_CAM_TRANSITION - case CCam::MODE_PLAYER_FALLEN_WATER: - Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition; - break; -#endif - case CCam::MODE_FIGHT_CAM: -#ifdef PS2_CAM_TRANSITION - Cams[ActiveCam].Source = Cams[(ActiveCam+1)%2].Source; -#endif Cams[ActiveCam].Beta = 0.0f; Cams[ActiveCam].BetaSpeed = 0.0f; Cams[ActiveCam].Alpha = 0.0f; @@ -2343,7 +2425,6 @@ CCamera::StartTransition(int16 newMode) break; } -#ifndef PS2_CAM_TRANSITION Cams[ActiveCam].Init(); Cams[ActiveCam].Mode = newMode; @@ -2353,30 +2434,31 @@ CCamera::StartTransition(int16 newMode) else if(switchFromFight) m_uiTransitionDuration = 750; else if(switchPedToCar){ - m_fFractionInterToStopMoving = 0.2f; - m_fFractionInterToStopCatchUp = 0.8f; - m_uiTransitionDuration = 950; + m_fFractionInterToStopMoving = 0.1f; + m_fFractionInterToStopCatchUp = 0.9f; + m_uiTransitionDuration = 750; + }else if(switchFromFixedSyphon){ + m_fFractionInterToStopMoving = 0.0f; + m_fFractionInterToStopCatchUp = 1.0f; + m_uiTransitionDuration = 600; }else if(switchFromFixed){ m_fFractionInterToStopMoving = 0.05f; m_fFractionInterToStopCatchUp = 0.95f; + }else if(switchBikeToPed){ + m_uiTransitionDuration = 800; }else if(switch1stPersonToVehicle){ m_fFractionInterToStopMoving = 0.0f; m_fFractionInterToStopCatchUp = 1.0f; m_uiTransitionDuration = 1; + }else if(switchPedMode){ + m_fFractionInterToStopMoving = 0.5f; + m_fFractionInterToStopCatchUp = 0.5f; + m_uiTransitionDuration = 350; }else m_uiTransitionDuration = 1350; // already set above -#else - if(switchSyphonMode) - m_uiTransitionDuration = 1800; - else if(switchFromFight) - m_uiTransitionDuration = 750; - else - m_uiTransitionDuration = 1350; -#endif m_uiTransitionState = 1; m_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds(); m_uiTransitionJUSTStarted = 1; -#ifndef PS2_CAM_TRANSITION if(m_vecDoingSpecialInterPolation){ m_cvecStartingSourceForInterPol = SourceDuringInter; m_cvecStartingTargetForInterPol = TargetDuringInter; @@ -2407,28 +2489,32 @@ CCamera::StartTransition(int16 newMode) m_fBetaSpeedAtStartInter = Cams[ActiveCam].m_fBetaSpeedOverOneFrame; m_fFOVSpeedAtStartInter = Cams[ActiveCam].m_fFovSpeedOverOneFrame; Cams[ActiveCam].ResetStatics = true; - if(!m_bLookingAtPlayer && m_bScriptParametersSetForInterPol){ - m_fFractionInterToStopMoving = m_fScriptPercentageInterToStopMoving; - m_fFractionInterToStopCatchUp = m_fScriptPercentageInterToCatchUp; - m_uiTransitionDuration = m_fScriptTimeForInterPolation; + if(m_bLookingAtPlayer){ + if(switchPedMode) + m_uiTransitionDurationTargetCoors = 350; + else + m_uiTransitionDurationTargetCoors = 600; + m_fFractionInterToStopMovingTarget = 0.0f; + m_fFractionInterToStopCatchUpTarget = 1.0f; + }else{ + if(m_bScriptParametersSetForInterPol){ + m_fFractionInterToStopMoving = m_fScriptPercentageInterToStopMoving; + m_fFractionInterToStopCatchUp = m_fScriptPercentageInterToCatchUp; + m_uiTransitionDuration = m_fScriptTimeForInterPolation; + } + m_uiTransitionDurationTargetCoors = m_uiTransitionDuration; + m_fFractionInterToStopMovingTarget = m_fFractionInterToStopMoving; + m_fFractionInterToStopCatchUpTarget = m_fFractionInterToStopCatchUp; } -#endif } void CCamera::StartTransitionWhenNotFinishedInter(int16 mode) { -#ifdef PS2_CAM_TRANSITION - m_vecOldSourceForInter = GetPosition(); - m_vecOldFrontForInter = GetForward(); - m_vecOldUpForInter = GetUp(); - m_vecOldFOVForInter = CDraw::GetFOV(); -#endif m_vecDoingSpecialInterPolation = true; StartTransition(mode); } -#ifndef PS2_CAM_TRANSITION void CCamera::StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up, float &FOV) { @@ -2441,7 +2527,7 @@ CCamera::StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up m_fBetaDuringInterPol = CGeneral::GetATanOfXY(Dist.x, Dist.y); m_fAlphaDuringInterPol = CGeneral::GetATanOfXY(DistOnGround, Dist.z); } -#endif + void @@ -2475,26 +2561,24 @@ CCamera::ProcessWideScreenOn(void) void CCamera::DrawBordersForWideScreen(void) { + float bottom, top; + if (m_WideScreenOn) { + float borderSize = (SCREEN_HEIGHT / 2) * (m_ScreenReductionPercentage / 100.f); + top = borderSize - SCREEN_SCALE_Y(22.f); + bottom = SCREEN_HEIGHT - borderSize - SCREEN_SCALE_Y(14.f); + } else { + top = 0.f; + bottom = SCREEN_HEIGHT; + } + if(m_BlurType == MOTION_BLUR_NONE || m_BlurType == MOTION_BLUR_LIGHT_SCENE) SetMotionBlurAlpha(80); - CSprite2d::DrawRect( -#ifdef FIX_BUGS - CRect(0.0f, (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - SCREEN_SCALE_Y(8.0f), -#else - CRect(0.0f, (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - 8.0f, -#endif - SCREEN_WIDTH, 0.0f), - CRGBA(0, 0, 0, 255)); + // top border + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, top), CRGBA(0, 0, 0, 255)); - CSprite2d::DrawRect( - CRect(0.0f, SCREEN_HEIGHT, -#ifdef FIX_BUGS - SCREEN_WIDTH, SCREEN_HEIGHT - (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - SCREEN_SCALE_Y(8.0f)), -#else - SCREEN_WIDTH, SCREEN_HEIGHT - (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - 8.0f), -#endif - CRGBA(0, 0, 0, 255)); + // bottom border + CSprite2d::DrawRect(CRect(0.0f, bottom, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } @@ -2512,7 +2596,9 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) case OBBE_WHEEL: veh = FindPlayerVehicle(); if(veh){ - if(veh->IsBoat() || veh->GetModelIndex() == MI_RHINO) + if(veh->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) + return true; + if(veh->GetModelIndex() == MI_RHINO) return true; if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false)) return true; @@ -2522,7 +2608,7 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) SetNearClipScript(0.6f); return false; case OBBE_1: - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return true; if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) return true; @@ -2531,14 +2617,14 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) fwd.z = 0.0f; // too far and driving away from cam - if(fwd.Magnitude() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + if(fwd.Magnitude() > 40.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; // too close if(fwd.Magnitude() < 1.6f) return true; return false; case OBBE_2: - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return true; if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) return true; @@ -2550,10 +2636,10 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) // very close, fix near clip SetNearClipScript(Max(fwd.Magnitude()*0.5f, 0.05f)); // too far and driving away from cam - if(fwd.Magnitude() > 19.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + if(fwd.Magnitude() > 29.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; // too close - if(fwd.Magnitude() < 1.6f) + if(fwd.Magnitude() < 2.0f) return true; return false; case OBBE_3: @@ -2564,13 +2650,13 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) fwd.z = 0.0f; // too far and driving away from cam - if(fwd.Magnitude() > 28.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + if(fwd.Magnitude() > 48.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; return false; case OBBE_1STPERSON: return CTimer::GetTimeInMilliseconds() > t+3000; case OBBE_5: - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return true; if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) return true; @@ -2579,7 +2665,7 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) fwd.z = 0.0f; // too far and driving away from cam - if(fwd.Magnitude() > 28.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + if(fwd.Magnitude() > 38.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; return false; case OBBE_ONSTRING: @@ -2643,6 +2729,90 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) return false; case OBBE_13: return CTimer::GetTimeInMilliseconds() > t+5000; + + // Heli modes + case OBBE_14: + if(FindPlayerVehicle()) + if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false)) + return true; + return CTimer::GetTimeInMilliseconds() > t+8000; + case OBBE_15: + if(FindPlayerVehicle()){ + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) + return true; + fwd = FindPlayerCoors() - m_vecFixedModeSource; + fwd.z = 0.0f; + + // too far and driving away from cam + if(fwd.Magnitude() > 44.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + return true; + // too close + if(fwd.Magnitude() < 2.0f) + return true; + } + return false; + case OBBE_16: + if(FindPlayerVehicle()){ + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) + return true; + fwd = FindPlayerCoors() - m_vecFixedModeSource; + fwd.z = 0.0f; + + // too far and driving away from cam + if(fwd.Magnitude() > 50.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + return true; + // too close + if(fwd.Magnitude() < 3.0f) + return true; + } + return false; + case OBBE_17: + if(FindPlayerVehicle()){ + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) + return true; + fwd = FindPlayerCoors() - m_vecFixedModeSource; + fwd.z = 0.0f; + + // too far + if(fwd.Magnitude() > 50.0f) + return true; + // too close + if(fwd.Magnitude() < 2.0f) + return true; + } + return false; + case OBBE_18: + if(FindPlayerVehicle()){ + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) + return true; + fwd = FindPlayerCoors() - m_vecFixedModeSource; + + // too far + if(fwd.Magnitude() > 57.0f) + return true; + // too close + if(fwd.Magnitude() < 1.0f) + return true; + } + return false; + case OBBE_19: + if(FindPlayerVehicle()){ + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) + return true; + fwd = FindPlayerCoors() - m_vecFixedModeSource; + fwd.z = 0.0f; + + // too far + if(fwd.Magnitude() > 36.0f) + return true; + // too close + if(fwd.Magnitude() < 2.0f) + return true; + } + return false; + case OBBE_ONSTRING_HELI: + return CTimer::GetTimeInMilliseconds() > t+5000; + default: return false; } @@ -2652,7 +2822,8 @@ bool CCamera::TryToStartNewCamMode(int obbeMode) { CVehicle *veh; - CVector target, camPos, playerSpeed, fwd; + CVector target, camPos, playerSpeed, fwd, fwd2; + float angle; float ground; bool foundGround; int i; @@ -2662,7 +2833,7 @@ CCamera::TryToStartNewCamMode(int obbeMode) switch(obbeMode){ case OBBE_WHEEL: veh = FindPlayerVehicle(); - if(veh == nil || veh->IsBoat() || veh->GetModelIndex() == MI_RHINO) + if(veh == nil || (veh->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) || veh->GetModelIndex() == MI_RHINO) return false; target = Multiply3x3(FindPlayerVehicle()->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f)); target += FindPlayerVehicle()->GetPosition(); @@ -2677,7 +2848,7 @@ CCamera::TryToStartNewCamMode(int obbeMode) playerSpeed.Normalise(); camPos += 20.0f*playerSpeed; camPos += 3.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f); - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); @@ -2694,17 +2865,17 @@ CCamera::TryToStartNewCamMode(int obbeMode) fwd = FindPlayerCoors() - camPos; fwd.z = 0.0f; // too far and driving away from cam - if(fwd.Magnitude() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + if(fwd.Magnitude() > 40.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return false; // too close - if(fwd.Magnitude() < 1.6f) + if(fwd.Magnitude() < 2.5f) return true; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_2: - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); @@ -2727,10 +2898,10 @@ CCamera::TryToStartNewCamMode(int obbeMode) fwd = FindPlayerCoors() - camPos; fwd.z = 0.0f; // too far and driving away from cam - if(fwd.Magnitude() > 19.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) + if(fwd.Magnitude() > 29.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return false; // too close - if(fwd.Magnitude() < 1.6f) + if(fwd.Magnitude() < 2.0f) return true; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); @@ -2787,7 +2958,7 @@ CCamera::TryToStartNewCamMode(int obbeMode) return false; if(FindPlayerVehicle() == nil) return false; - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; i = CPools::GetVehiclePool()->GetSize(); while(--i >= 0){ @@ -2815,7 +2986,7 @@ CCamera::TryToStartNewCamMode(int obbeMode) return false; if(FindPlayerVehicle() == nil) return false; - if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; i = CPools::GetVehiclePool()->GetSize(); while(--i >= 0){ @@ -2910,12 +3081,219 @@ CCamera::TryToStartNewCamMode(int obbeMode) TakeControl(FindPlayerEntity(), CCam::MODE_TOPDOWN, JUMP_CUT, CAMCONTROL_OBBE); #endif return true; + + // Heli modes + case OBBE_14: + veh = FindPlayerVehicle(); + if(veh == nil) + return false; + target = Multiply3x3(FindPlayerVehicle()->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f)); + target += FindPlayerVehicle()->GetPosition(); + if(!veh->IsBoat() && !CWorld::GetIsLineOfSightClear(veh->GetPosition(), target, true, false, false, false, false, false, false)) + return false; + TakeControl(veh, CCam::MODE_WHEELCAM, JUMP_CUT, CAMCONTROL_OBBE); + return true; + case OBBE_15: + if(FindPlayerVehicle() == nil) + return false; + camPos = FindPlayerCoors(); + playerSpeed = FindPlayerSpeed(); + playerSpeed.z = 0.0f; + playerSpeed.Normalise(); + camPos += 34.0f*playerSpeed; + camPos.z = FindPlayerCoors().z + 0.5f; + if(FindPlayerVehicle()->IsBoat()) + camPos.z += 1.0f; + + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) + return false; + + fwd = FindPlayerCoors() - camPos; + fwd2 = FindPlayerCoors() - camPos; + fwd2.z = 0.0f; + // too far and driving away from cam + if(fwd.Magnitude() > 44.0f && DotProduct(FindPlayerSpeed(), fwd2) > 0.0f) + return false; + // too close + if(fwd.Magnitude() < 3.0f) + return true; + + SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); + TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); + return true; + case OBBE_16: + if(FindPlayerVehicle() == nil) + return false; + camPos = FindPlayerCoors(); + playerSpeed = FindPlayerSpeed(); + playerSpeed.z = 0.0f; + playerSpeed.Normalise(); + angle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(60.0f); + playerSpeed += CVector(Cos(angle), Sin(angle), 0.0f); + playerSpeed.Normalise(); + camPos += 30.0f*playerSpeed; + camPos.z = FindPlayerCoors().z - 5.5f; + + foundGround = false; + ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); + if(foundGround) + camPos.z = ground + 0.5f; + else if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){ + float waterOffset = 1.0f; + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + waterOffset = -2.0f; + if(camPos.z < ground + waterOffset) + camPos.z = ground + waterOffset; + } + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) + return false; + + fwd = FindPlayerCoors() - camPos; + // too far + if(fwd.Magnitude() > 50.0f) + return false; + // too close + if(fwd.Magnitude() < 3.0f) + return true; + + SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); + TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); + return true; + case OBBE_17: + if(FindPlayerVehicle() == nil) + return false; + camPos = FindPlayerCoors(); + playerSpeed = FindPlayerSpeed(); + playerSpeed.z = 0.0f; + playerSpeed.Normalise(); + angle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(190.0f); + playerSpeed += CVector(Cos(angle), Sin(angle), 0.0f); + playerSpeed.Normalise(); + camPos += 25.0f*playerSpeed; + camPos.z = FindPlayerCoors().z - 1.0f; + + foundGround = false; + ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); + if(foundGround) + camPos.z = ground + 0.5f; + else if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){ + float waterOffset = 1.0f; + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + waterOffset = -2.0f; + if(camPos.z < ground + waterOffset) + camPos.z = ground + waterOffset; + } + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) + return false; + + fwd = FindPlayerCoors() - camPos; + fwd2 = FindPlayerCoors() - camPos; + fwd2.z = 0.0f; + // too far and driving away from cam + if(fwd.Magnitude() > 50.0f && DotProduct(FindPlayerSpeed(), fwd2) > 0.0f) + return false; + // too close + if(fwd.Magnitude() < 2.0f) + return true; + + SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); + TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); + return true; + case OBBE_18: + camPos = FindPlayerCoors(); + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + camPos.z += 23.0f; + else + camPos.z -= 23.0f; + playerSpeed = FindPlayerSpeed(); + angle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(145.0f); + playerSpeed += CVector(Cos(angle), Sin(angle), 0.0f); + playerSpeed.Normalise(); + camPos += 15.0f*playerSpeed; + + foundGround = false; + ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); +#ifdef FIX_BUGS + if(foundGround) +#else + if(ground == true) +#endif + { + if(camPos.z < ground) + camPos.z = ground + 0.5f; + }else if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){ + float waterOffset = 1.0f; + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + waterOffset = -2.0f; + if(camPos.z < ground + waterOffset) + camPos.z = ground + waterOffset; + } + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) + return false; + + fwd = FindPlayerCoors() - camPos; + // too far + if(fwd.Magnitude() > 57.0f) + return false; + // too close + if(fwd.Magnitude() < 1.0f) + return true; + + SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); + TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); + return true; + case OBBE_19: + camPos = FindPlayerCoors(); + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + camPos.z += 4.0f; + else + camPos.z -= 1.0f; + playerSpeed = FindPlayerSpeed(); + angle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(28.0f); + playerSpeed += CVector(Cos(angle), Sin(angle), 0.0f); + playerSpeed.Normalise(); + camPos += 12.5f*playerSpeed; + + foundGround = false; + ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); +#ifdef FIX_BUGS + if(foundGround) +#else + if(ground == true) +#endif + { + if(camPos.z < ground) + camPos.z = ground + 0.5f; + }else if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){ + float waterOffset = 1.0f; + if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) + waterOffset = -2.0f; + if(camPos.z < ground + waterOffset) + camPos.z = ground + waterOffset; + } + if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) + return false; + + fwd = FindPlayerCoors() - camPos; + // too far + if(fwd.Magnitude() > 36.0f) + return false; + // too close + if(fwd.Magnitude() < 2.0f) + return true; + + SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); + TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); + return true; + case OBBE_ONSTRING_HELI: + TakeControl(FindPlayerEntity(), CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE); + return true; default: return false; } } -int32 SequenceOfCams[16] = { +int32 SequenceOfCarCams[16] = { OBBE_WHEEL, OBBE_COPCAR, OBBE_3, OBBE_1, OBBE_3, OBBE_COPCAR_WHEEL, OBBE_2, OBBE_3, OBBE_COPCAR_WHEEL, OBBE_COPCAR, OBBE_2, OBBE_3, OBBE_5, OBBE_3, @@ -2931,19 +3309,19 @@ CCamera::ProcessObbeCinemaCameraCar(void) if(!bDidWeProcessAnyCinemaCam){ OldMode = -1; - CHud::SetHelpMessage(TheText.Get("CINCAM"), true); + bSwitchedToObbeCam = true; } - if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfCams[OldMode], TimeForNext)){ + if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfCarCams[OldMode], TimeForNext)){ // This is very strange code... for(OldMode = (OldMode+1) % 14; - !TryToStartNewCamMode(SequenceOfCams[OldMode]) && i <= 14; + !TryToStartNewCamMode(SequenceOfCarCams[OldMode]) && i <= 14; OldMode = (OldMode+1) % 14) i++; TimeForNext = CTimer::GetTimeInMilliseconds(); if(i >= 14){ OldMode = 14; - TryToStartNewCamMode(SequenceOfCams[14]); + TryToStartNewCamMode(SequenceOfCarCams[14]); } } @@ -2951,6 +3329,40 @@ CCamera::ProcessObbeCinemaCameraCar(void) bDidWeProcessAnyCinemaCam = true; } +int32 SequenceOfHeliCams[6] = { OBBE_14, OBBE_15, OBBE_16, OBBE_17, OBBE_18, OBBE_19 }; + +void +CCamera::ProcessObbeCinemaCameraHeli(void) +{ + static int OldMode = -1; + static int32 TimeForNext = 0; + int i = 0; + + if(!bDidWeProcessAnyCinemaCam){ + OldMode = -1; + bSwitchedToObbeCam = true; + } + + if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfHeliCams[OldMode], TimeForNext)){ + // This is very strange code... + for(OldMode = (OldMode+1) % 6; + !TryToStartNewCamMode(SequenceOfCarCams[OldMode]) && i <= 6; + OldMode = (OldMode+1) % 6) + i++; + if(i >= 6){ + OldMode = 6; + if(Cams[ActiveCam].Mode != CCam::MODE_CAM_ON_A_STRING){ + TryToStartNewCamMode(OBBE_ONSTRING_HELI); + TimeForNext = CTimer::GetTimeInMilliseconds(); + } + }else + TimeForNext = CTimer::GetTimeInMilliseconds(); + } + + m_iModeObbeCamIsInForCar = OldMode; + bDidWeProcessAnyCinemaCam = true; +} + int32 SequenceOfPedCams[5] = { OBBE_9, OBBE_10, OBBE_11, OBBE_12, OBBE_13 }; void @@ -2978,6 +3390,7 @@ CCamera::DontProcessObbeCinemaCamera(void) bDidWeProcessAnyCinemaCam = false; } +#ifdef GTA_TRAIN void CCamera::LoadTrainCamNodes(char const *name) { @@ -3162,6 +3575,7 @@ CCamera::Process_Train_Camera_Control(void) } } } +#endif void @@ -3173,9 +3587,14 @@ CCamera::LoadPathSplines(int file) n = 0; + DeleteCutSceneCamDataMemory(); for(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++) - for(j = 0; j < CCamPathSplines::MAXPATHLENGTH; j++) - m_arrPathArray[i].m_arr_PathData[j] = 0.0f; + m_arrPathArray[i].m_arr_PathData = new float[CCamPathSplines::MAXPATHLENGTH]; + +// Why is this gone? +// for(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++) +// for(j = 0; j < CCamPathSplines::MAXPATHLENGTH; j++) +// m_arrPathArray[i].m_arr_PathData[j] = 0.0f; m_bStartingSpline = false; @@ -3212,6 +3631,8 @@ CCamera::LoadPathSplines(int file) m_arrPathArray[i].m_arr_PathData[j] = atof(token); i++; j = 0; + if (i == MAX_NUM_OF_SPLINETYPES) + reading = false; memset(token, 0, 32); n = 0; } @@ -3219,6 +3640,17 @@ CCamera::LoadPathSplines(int file) } void +CCamera::DeleteCutSceneCamDataMemory(void) +{ + int i; + for(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++) + if(m_arrPathArray[i].m_arr_PathData){ + delete[] m_arrPathArray[i].m_arr_PathData; + m_arrPathArray[i].m_arr_PathData = nil; + } +} + +void CCamera::FinishCutscene(void) { SetPercentAlongCutScene(100.0f); @@ -3279,26 +3711,42 @@ CCamera::SetZoomValueFollowPedScript(int16 dist) void CCamera::SetZoomValueCamStringScript(int16 dist) { + if (Cams[ActiveCam].CamTargetEntity->IsVehicle()) { + int vehApp = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->GetVehicleAppearance(); + int vehArrPos = 0; + GetArrPosForVehicleType(vehApp, vehArrPos); + #ifdef FREE_CAM - if (bFreeCam) { - switch (dist) { - case 0: m_fCarZoomValueScript = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_1 : FREE_CAR_ZOOM_VALUE_1; break; - case 1: m_fCarZoomValueScript = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_2 : FREE_CAR_ZOOM_VALUE_2; break; - case 2: m_fCarZoomValueScript = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->IsBoat() ? FREE_BOAT_ZOOM_VALUE_3 : FREE_CAR_ZOOM_VALUE_3; break; - default: break; + if (bFreeCam) { + switch (dist) { + case 0: m_fCarZoomValueScript = LCS_ZOOM_ONE_DISTANCE[vehArrPos]; break; + case 1: m_fCarZoomValueScript = LCS_ZOOM_TWO_DISTANCE[vehArrPos]; break; + case 2: m_fCarZoomValueScript = LCS_ZOOM_THREE_DISTANCE[vehArrPos]; break; + default: break; + } } - } else + else #endif - { + { + switch (dist) { + case 0: m_fCarZoomValueScript = ZOOM_ONE_DISTANCE[vehArrPos]; break; + case 1: m_fCarZoomValueScript = ZOOM_TWO_DISTANCE[vehArrPos]; break; + case 2: m_fCarZoomValueScript = ZOOM_THREE_DISTANCE[vehArrPos]; break; + default: break; + } + } + + m_bUseScriptZoomValueCar = true; + } else { switch (dist) { - case 0: m_fCarZoomValueScript = DEFAULT_CAR_ZOOM_VALUE_1; break; - case 1: m_fCarZoomValueScript = DEFAULT_CAR_ZOOM_VALUE_2; break; - case 2: m_fCarZoomValueScript = DEFAULT_CAR_ZOOM_VALUE_3; break; + case 0: m_fPedZoomValueScript = 0.25f; break; + case 1: m_fPedZoomValueScript = 1.5f; break; + case 2: m_fPedZoomValueScript = 2.9f; break; default: break; } - } - m_bUseScriptZoomValueCar = true; + m_bUseScriptZoomValuePed = true; + } } void @@ -3313,33 +3761,23 @@ CCamera::SetNearClipScript(float clip) void CCamera::ProcessFade(void) { - float fade = (CTimer::GetTimeInMilliseconds() - m_uiFadeTimeStarted)/1000.0f; - // Why even set CDraw::FadeValue if m_fFLOATingFade sets it anyway? if(m_bFading){ if(m_iFadingDirection == FADE_IN){ - if(m_fTimeToFadeOut != 0.0f){ - m_fFLOATingFade = 255.0f - 255.0f*fade/m_fTimeToFadeOut; - if(m_fFLOATingFade <= 0.0f){ - m_bFading = false; - CDraw::FadeValue = 0; - m_fFLOATingFade = 0.0f; - } - }else{ + if(m_fTimeToFadeOut != 0.0f) + m_fFLOATingFade -= CTimer::GetTimeStepInSeconds() * 255.0f / m_fTimeToFadeOut; + else + m_fFLOATingFade = 0.0f; + if (m_fFLOATingFade <= 0.0f) { m_bFading = false; - CDraw::FadeValue = 0; m_fFLOATingFade = 0.0f; } }else if(m_iFadingDirection == FADE_OUT){ - if(m_fTimeToFadeOut != 0.0f){ - m_fFLOATingFade = 255.0f*fade/m_fTimeToFadeOut; - if(m_fFLOATingFade >= 255.0f){ - m_bFading = false; - CDraw::FadeValue = 255; - m_fFLOATingFade = 255.0f; - } - }else{ + if(m_fTimeToFadeOut != 0.0f) + m_fFLOATingFade += CTimer::GetTimeStepInSeconds() * 255.0f / m_fTimeToFadeOut; + else + m_fFLOATingFade = 255.0f; + if (m_fFLOATingFade >= 255.0f) { m_bFading = false; - CDraw::FadeValue = 255; m_fFLOATingFade = 255.0f; } } @@ -3350,46 +3788,28 @@ CCamera::ProcessFade(void) void CCamera::ProcessMusicFade(void) { - float fade = (CTimer::GetTimeInMilliseconds() - m_uiFadeTimeStartedMusic)/1000.0f; if(m_bMusicFading){ if(m_iMusicFadingDirection == FADE_IN){ if(m_fTimeToFadeMusic == 0.0f) - m_fTimeToFadeMusic = 1.0f; - - m_fFLOATingFadeMusic = 255.0f*fade/m_fTimeToFadeMusic; - if(m_fFLOATingFadeMusic > 255.0f){ + m_fFLOATingFadeMusic = 0.0f; + else + m_fFLOATingFadeMusic -= 255.0f*CTimer::GetTimeStepInSeconds()/m_fTimeToFadeMusic; + if(m_fFLOATingFadeMusic <= 0.0f){ m_bMusicFading = false; m_fFLOATingFadeMusic = 0.0f; - DMAudio.SetEffectsFadeVol(127); - DMAudio.SetMusicFadeVol(127); - }else{ - DMAudio.SetEffectsFadeVol(m_fFLOATingFadeMusic/255.0f * 127); - DMAudio.SetMusicFadeVol(m_fFLOATingFadeMusic/255.0f * 127); } }else if(m_iMusicFadingDirection == FADE_OUT){ if(m_fTimeToFadeMusic == 0.0f) - m_fTimeToFadeMusic = 1.0f; - -#ifdef PS2_MENU - if(m_bMoveCamToAvoidGeom || TheMemoryCard.StillToFadeOut){ -#else - if(m_bMoveCamToAvoidGeom || StillToFadeOut){ -#endif - m_fFLOATingFadeMusic = 256.0f; - m_bMoveCamToAvoidGeom = false; - }else - m_fFLOATingFadeMusic = 255.0f*fade/m_fTimeToFadeMusic; - - if(m_fFLOATingFadeMusic > 255.0f){ + m_fFLOATingFadeMusic = 255.0f; + else + m_fFLOATingFadeMusic += 255.0f*CTimer::GetTimeStepInSeconds()/m_fTimeToFadeMusic; + if(m_fFLOATingFadeMusic >= 255.0f){ m_bMusicFading = false; m_fFLOATingFadeMusic = 255.0f; - DMAudio.SetEffectsFadeVol(0); - DMAudio.SetMusicFadeVol(0); - }else{ - DMAudio.SetEffectsFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127); - DMAudio.SetMusicFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127); } } + DMAudio.SetEffectsFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127); + DMAudio.SetMusicFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127); } } @@ -3405,22 +3825,13 @@ CCamera::Fade(float timeout, int16 direction) m_iMusicFadingDirection = direction; m_fTimeToFadeMusic = timeout; m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds(); -// Not on PS2 - if(!m_bUnknown && m_iMusicFadingDirection == FADE_OUT){ - unknown++; - if(unknown >= 2){ - m_bUnknown = true; - unknown = 0; - }else - m_bMoveCamToAvoidGeom = true; - } } } void CCamera::SetFadeColour(uint8 r, uint8 g, uint8 b) { - m_FadeTargetIsSplashScreen = r == 0 && g == 0 && b == 0; + m_FadeTargetIsSplashScreen = r == 2 && g == 2 && b == 2; CDraw::FadeRed = r; CDraw::FadeGreen = g; CDraw::FadeBlue = b; @@ -3527,6 +3938,7 @@ CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString(void) void CCamera::SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom) { + SetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MOTION_BLUR_LIGHT_SCENE); PlayerWeaponMode.Mode = mode; PlayerWeaponMode.MaxZoom = maxZoom; PlayerWeaponMode.MinZoom = minZoom; @@ -3536,6 +3948,7 @@ CCamera::SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom) void CCamera::ClearPlayerWeaponMode(void) { + SetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MOTION_BLUR_LIGHT_SCENE); PlayerWeaponMode.Mode = 0; PlayerWeaponMode.MaxZoom = 1; PlayerWeaponMode.MinZoom = -1; @@ -3579,6 +3992,18 @@ CCamera::Find3rdPersonQuickAimPitch(void) return -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot); } +bool +CCamera::Using1stPersonWeaponMode(void) +{ + switch(PlayerWeaponMode.Mode) + case CCam::MODE_SNIPER: + case CCam::MODE_M16_1STPERSON: + case CCam::MODE_ROCKETLAUNCHER: + case CCam::MODE_HELICANNON_1STPERSON: + case CCam::MODE_CAMERA: + return true; + return false; +} void @@ -3603,8 +4028,9 @@ CCamera::CalculateDerivedValues(void) // left plane m_vecFrustumNormals[1] = CVector(-c, -s, 0.0f); - c /= CDraw::FindAspectRatio(); - s /= CDraw::FindAspectRatio(); + CDraw::CalculateAspectRatio(); + c /= SCREEN_ASPECT_RATIO; + s /= SCREEN_ASPECT_RATIO; // bottom plane m_vecFrustumNormals[2] = CVector(0.0f, -s, -c); // top plane @@ -3675,14 +4101,7 @@ CCamera::IsSphereVisible(const CVector ¢er, float radius, Const CMatrix *mat bool CCamera::IsSphereVisible(const CVector ¢er, float radius) { -#if GTA_VERSION < GTA3_PC_10 // not sure this condition is the right one - // Maybe this was a copy of the other function with m_cameraMatrix - return IsSphereVisible(center, radius, &m_cameraMatrix); -#else - // ...and on PC they decided to call the other one with a default matrix. - CMatrix mat(GetCameraMatrix()); // this matrix construction is stupid and gone in VC - return IsSphereVisible(center, radius, &mat); -#endif + return IsSphereVisible(center, radius, &GetCameraMatrix()); } bool @@ -3720,7 +4139,5 @@ CCamera::IsBoxVisible(CVUVECTOR *box, const CMatrix *mat) CCamPathSplines::CCamPathSplines(void) { - int i; - for(i = 0; i < MAXPATHLENGTH; i++) - m_arr_PathData[i] = 0.0f; + m_arr_PathData = nil; } diff --git a/src/core/Camera.h b/src/core/Camera.h index 07a05cb4..7612b937 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -26,20 +26,6 @@ enum CAM_ZOOM_CINEMATIC, }; -#ifdef FREE_CAM // LCS values -#define FREE_CAR_ZOOM_VALUE_1 (-1.0f) -#define FREE_CAR_ZOOM_VALUE_2 (2.0f) -#define FREE_CAR_ZOOM_VALUE_3 (6.0f) - -#define FREE_BOAT_ZOOM_VALUE_1 (-2.41f) -#define FREE_BOAT_ZOOM_VALUE_2 (6.49f) -#define FREE_BOAT_ZOOM_VALUE_3 (15.0f) -#endif - -#define DEFAULT_CAR_ZOOM_VALUE_1 (0.05f) -#define DEFAULT_CAR_ZOOM_VALUE_2 (1.9f) -#define DEFAULT_CAR_ZOOM_VALUE_3 (3.9f) - const float DefaultFOV = 70.0f; // beta: 80.0f class CCam @@ -85,13 +71,15 @@ public: MODE_SPECIAL_FIXED_FOR_SYPHON, MODE_FIGHT_CAM, MODE_TOP_DOWN_PED, + MODE_LIGHTHOUSE, MODE_SNIPER_RUNABOUT, MODE_ROCKETLAUNCHER_RUNABOUT, MODE_1STPERSON_RUNABOUT, MODE_M16_1STPERSON_RUNABOUT, MODE_FIGHT_CAM_RUNABOUT, MODE_EDITOR, - MODE_HELICANNON_1STPERSON, // vice city leftover + MODE_HELICANNON_1STPERSON, + MODE_CAMERA, }; bool bBelowMinDist; //used for follow ped mode @@ -121,7 +109,6 @@ public: float f_Roll; //used for adding a slight roll to the camera in the float f_rollSpeed; float m_fSyphonModeTargetZOffSet; - float m_fRoadOffSet; float m_fAmountFractionObscured; float m_fAlphaSpeedOverOneFrame; float m_fBetaSpeedOverOneFrame; @@ -144,7 +131,8 @@ public: float m_fRealGroundDist; //used for follow ped mode float m_fTargetBeta; float m_fTimeElapsedFloat; - + float m_fTilt; + float m_fTiltSpeed; float m_fTransitionBeta; float m_fTrueBeta; float m_fTrueAlpha; @@ -162,6 +150,16 @@ public: float CA_MAX_DISTANCE; float SpeedVar; + float m_fTargetZoomGroundOne; + float m_fTargetZoomGroundTwo; + float m_fTargetZoomGroundThree; + float m_fTargetZoomOneZExtra; + float m_fTargetZoomTwoZExtra; + float m_fTargetZoomThreeZExtra; + float m_fTargetZoomZCloseIn; + float m_fMinRealGroundDist; + float m_fTargetCloseInDist; + CVector m_cvecSourceSpeedOverOneFrame; CVector m_cvecTargetSpeedOverOneFrame; CVector m_cvecUpOverOneFrame; @@ -194,13 +192,11 @@ public: void ProcessSpecialHeightRoutines(void); void GetVectorsReadyForRW(void); CVector DoAverageOnVector(const CVector &vec); - float GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies); - void WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation); void WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight); bool RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation); - bool FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation); void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist); void FixCamWhenObscuredByVehicle(const CVector &TargetCoors); + bool GetBoatLook_L_R_HeightOffset(float &Offset); void LookBehind(void); void LookLeft(void); void LookRight(void); @@ -233,42 +229,29 @@ public: void Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_FlyBy(const CVector&, float, float, float); - void Process_WheelCam(const CVector&, float, float, float); + bool Process_WheelCam(const CVector&, float, float, float); void Process_Fixed(const CVector &CameraTarget, float, float, float); void Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float); - void Process_Circle(const CVector &CameraTarget, float, float, float); void Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float); + void Process_LightHouse(const CVector &CameraTarget, float, float, float); void ProcessPedsDeadBaby(void); bool ProcessArrestCamOne(void); bool ProcessArrestCamTwo(void); - - /* Some of the unused PS2 cams */ - void Process_Chris_With_Binding_PlusRotation(const CVector &CameraTarget, float, float, float); - void Process_ReactionCam(const CVector &CameraTarget, float TargetOrientation, float, float); - void Process_FollowPed_WithBinding(const CVector &CameraTarget, float TargetOrientation, float, float); - // TODO: - // CCam::Process_CushyPillows_Arse - // CCam::Process_Look_At_Cars - // CCam::Process_CheesyZoom - // CCam::Process_Aiming - void Process_Bill(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar); - void Process_Im_The_Passenger_Woo_Woo(const CVector &CameraTarget, float TargetOrientation, float, float); - void Process_Blood_On_The_Tracks(const CVector &CameraTarget, float TargetOrientation, float, float); - void Process_Cam_Running_Side_Train(const CVector &CameraTarget, float TargetOrientation, float, float); - void Process_Cam_On_Train_Roof(const CVector &CameraTarget, float TargetOrientation, float, float); + bool GetLookAlongGroundPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut); + bool GetLookFromLampPostPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut); + bool GetLookOverShoulderPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut); // custom stuff void Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_FollowCar_SA(const CVector &CameraTarget, float TargetOrientation, float, float); }; -VALIDATE_SIZE(CCam, 0x1A4); - class CCamPathSplines { public: enum {MAXPATHLENGTH=800}; - float m_arr_PathData[MAXPATHLENGTH]; +// float m_arr_PathData[MAXPATHLENGTH]; + float *m_arr_PathData; CCamPathSplines(void); }; @@ -350,13 +333,14 @@ public: bool m_bcutsceneFinished; bool m_bCullZoneChecksOn; bool m_bFirstPersonBeingUsed; - bool m_bUnknown; + bool m_bJustJumpedOutOf1stPersonBecauseOfTarget; bool m_bIdleOn; bool m_bInATunnelAndABigVehicle; bool m_bInitialNodeFound; bool m_bInitialNoNodeStaticsSet; bool m_bIgnoreFadingStuffForMusic; bool m_bPlayerIsInGarage; + bool m_bPlayerWasOnBike; bool m_bJustCameOutOfGarage; bool m_bJustInitalised; bool m_bJust_Switched; @@ -381,6 +365,9 @@ public: bool m_WideScreenOn; bool m_1rstPersonRunCloseToAWall; bool m_bHeadBob; + bool m_bVehicleSuspenHigh; + bool m_bEnable1rstPersonCamCntrlsScript; + bool m_bAllow1rstPersonWeaponsCamera; bool m_bFailedCullZoneTestPreviously; bool m_FadeTargetIsSplashScreen; @@ -396,15 +383,16 @@ public: uint8 m_uiTransitionState; // 0:one mode 1:transition uint32 m_uiTimeLastChange; + uint32 m_uiTimeWeLeftIdle_StillNoInput; uint32 m_uiTimeWeEnteredIdle; uint32 m_uiTimeTransitionStart; uint32 m_uiTransitionDuration; + uint32 m_uiTransitionDurationTargetCoors; int m_BlurBlue; int m_BlurGreen; int m_BlurRed; int m_BlurType; - uint32 unknown; // some counter having to do with music int m_iWorkOutSpeedThisNumFrames; int m_iNumFramesSoFar; @@ -427,12 +415,9 @@ public: float CarZoomValueSmooth; float DistanceToWater; -#ifndef PS2_CAM_TRANSITION float FOVDuringInter; -#endif float LODDistMultiplier; float GenerationDistMultiplier; -#ifndef PS2_CAM_TRANSITION float m_fAlphaSpeedAtStartInter; float m_fAlphaWhenInterPol; float m_fAlphaDuringInterPol; @@ -443,7 +428,6 @@ public: float m_fFOVSpeedAtStartInter; float m_fStartingBetaForInterPol; float m_fStartingAlphaForInterPol; -#endif float m_PedOrientForBehindOrInFront; float m_CameraAverageSpeed; float m_CameraSpeedSoFar; @@ -468,17 +452,18 @@ public: float PedZoomIndicator; #endif float PlayerExhaustion; - float SoundDistUp, SoundDistLeft, SoundDistRight; - float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead; - float SoundDistUpAsReadOld, SoundDistLeftAsReadOld, SoundDistRightAsReadOld; + float SoundDistUp; + float SoundDistUpAsRead; + float SoundDistUpAsReadOld; + float m_fAvoidTheGeometryProbsTimer; + int16 m_nAvoidTheGeometryProbsDirn; float m_fWideScreenReductionAmount; float m_fStartingFOVForInterPol; - // not static yet - float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls - float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls - float m_f3rdPersonCHairMultX; - float m_f3rdPersonCHairMultY; + static float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls + static float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls + static float m_f3rdPersonCHairMultX; + static float m_f3rdPersonCHairMultY; CCam Cams[3]; @@ -493,7 +478,7 @@ public: CVector m_vecFixedModeSource; CVector m_vecFixedModeUpOffSet; CVector m_vecCutSceneOffset; -#ifndef PS2_CAM_TRANSITION + CVector m_cvecStartingSourceForInterPol; CVector m_cvecStartingTargetForInterPol; CVector m_cvecStartingUpForInterPol; @@ -503,17 +488,17 @@ public: CVector m_vecSourceWhenInterPol; CVector m_vecTargetWhenInterPol; CVector m_vecUpWhenInterPol; -#endif + CVector m_vecClearGeometryVec; CVector m_vecGameCamPos; -#ifndef PS2_CAM_TRANSITION CVector SourceDuringInter; CVector TargetDuringInter; CVector UpDuringInter; -#endif RwCamera *m_pRwCamera; CEntity *pTargetEntity; CCamPathSplines m_arrPathArray[MAX_NUM_OF_SPLINETYPES]; +#ifdef GTA_TRAIN CTrainCamNode m_arrTrainCamNode[MAX_NUM_OF_NODES]; +#endif CMatrix m_cameraMatrix; bool m_bGarageFixedCamPositionSet; bool m_vecDoingSpecialInterPolation; @@ -532,6 +517,8 @@ public: float m_fTimeToFadeMusic; float m_fFractionInterToStopMoving; float m_fFractionInterToStopCatchUp; + float m_fFractionInterToStopMovingTarget; + float m_fFractionInterToStopCatchUpTarget; float m_fGaitSwayBuffer; float m_fScriptPercentageInterToStopMoving; float m_fScriptPercentageInterToCatchUp; @@ -555,7 +542,6 @@ public: // High level and misc CCamera(void); - CCamera(float); void Init(void); void Process(void); void CamControl(void); @@ -564,6 +550,9 @@ public: void InitialiseCameraForDebugMode(void); void CamShake(float strength, float x, float y, float z); bool Get_Just_Switched_Status() { return m_bJust_Switched; } + void AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV); + void GetArrPosForVehicleType(int apperance, int &index); + void GetScreenRect(CRect &rect); // Who's in control void TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller); @@ -589,6 +578,7 @@ public: bool TryToStartNewCamMode(int32 obbeMode); void DontProcessObbeCinemaCamera(void); void ProcessObbeCinemaCameraCar(void); + void ProcessObbeCinemaCameraHeli(void); void ProcessObbeCinemaCameraPed(void); // Train @@ -597,6 +587,7 @@ public: // Script void LoadPathSplines(int file); + void DeleteCutSceneCamDataMemory(void); void FinishCutscene(void); float GetPositionAlongSpline(void) { return m_fPositionAlongSpline; } uint32 GetCutSceneFinishTime(void); @@ -632,6 +623,7 @@ public: void UpdateAimingCoors(CVector const &coors); bool Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target); float Find3rdPersonQuickAimPitch(void); + bool Using1stPersonWeaponMode(void); // Physical camera void SetRwCamera(RwCamera *cam); diff --git a/src/core/Clock.cpp b/src/core/Clock.cpp index e4b908e0..a3298343 100644 --- a/src/core/Clock.cpp +++ b/src/core/Clock.cpp @@ -4,6 +4,7 @@ #include "Pad.h" #include "Clock.h" #include "Stats.h" +#include "VarConsole.h" _TODO("gbFastTime"); bool gbFastTime; @@ -18,6 +19,10 @@ uint32 CClock::ms_nMillisecondsPerGameMinute; uint32 CClock::ms_nLastClockTick; bool CClock::ms_bClockHasBeenStored; +#ifndef MASTER +bool gbFreezeTime; +#endif + void CClock::Initialise(uint32 scale) { @@ -29,6 +34,10 @@ CClock::Initialise(uint32 scale) ms_nLastClockTick = CTimer::GetTimeInMilliseconds(); ms_bClockHasBeenStored = false; debug("CClock ready\n"); +#ifndef MASTER + VarConsole.Add("Time (hour of day)", &ms_nGameClockHours, 1, 0, 23, true); + VarConsole.Add("Freeze time", &gbFreezeTime, true); +#endif } void @@ -48,6 +57,10 @@ CClock::Update(void) } } +#ifndef MASTER + else if (gbFreezeTime) + ms_nLastClockTick = CTimer::GetTimeInMilliseconds(); +#endif else if(CTimer::GetTimeInMilliseconds() - ms_nLastClockTick > ms_nMillisecondsPerGameMinute || gbFastTime) { ms_nGameClockMinutes++; @@ -73,8 +86,14 @@ CClock::Update(void) void CClock::SetGameClock(uint8 h, uint8 m) { - ms_nGameClockHours = h; + while (m >= 60) { + m -= 60; + h++; + } ms_nGameClockMinutes = m; + while (h >= 24) + h -= 24; + ms_nGameClockHours = h; ms_nGameClockSeconds = 0; ms_nLastClockTick = CTimer::GetTimeInMilliseconds(); } diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index e72af7e4..72d31137 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -130,7 +130,7 @@ void CControllerConfigManager::SaveSettings(int32 file) void CControllerConfigManager::LoadSettings(int32 file) { bool bValid = true; - + int nVersion = 0; #ifdef BIND_VEHICLE_FIREWEAPON bool skipVehicleFireWeapon = false; #endif @@ -144,35 +144,15 @@ void CControllerConfigManager::LoadSettings(int32 file) bValid = false; else { CFileMgr::Seek(file, 0, 0); - -#ifdef BIND_VEHICLE_FIREWEAPON - // HACK! - // All of this is hacky as fuck. - // We are checking the file size to read the .set file correctly. - // But because .set file is opened in text mode we have to read - // the WHOLE file to get the size we should be working with. - // Joy, ain't it? - char tempBuf[0x1000]; - size_t fileSize = 0, blockSize; - do - { - blockSize = CFileMgr::Read(file, tempBuf, sizeof(tempBuf)); - fileSize += blockSize; - } while (blockSize == sizeof(tempBuf)); - - CFileMgr::Seek(file, 0, 0); - - if (fileSize == 0x671) - skipVehicleFireWeapon = true; -#endif + CFileMgr::Read(file, (char*)&nVersion, sizeof(nVersion)); } } - if (bValid) + if (bValid && nVersion >= 3) { ControlsManager.MakeControllerActionsBlank(); - #ifdef BIND_VEHICLE_FIREWEAPON + skipVehicleFireWeapon = nVersion < 4; // Set the default settings of VEHICLE_FIREWEAPON if (skipVehicleFireWeapon) { SetControllerKeyAssociatedWithAction(VEHICLE_FIREWEAPON, rsPADINS, KEYBOARD); @@ -242,9 +222,13 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (GO_BACK, rsDOWN, KEYBOARD); SetControllerKeyAssociatedWithAction (GO_BACK, 'S', OPTIONAL_EXTRA); + + SetControllerKeyAssociatedWithAction (NETWORK_TALK, 'T', KEYBOARD); SetControllerKeyAssociatedWithAction (PED_LOOKBEHIND, rsPADEND, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_LOOKBEHIND, rsCAPSLK, OPTIONAL_EXTRA); + + SetControllerKeyAssociatedWithAction (PED_DUCK, 'C', KEYBOARD); SetControllerKeyAssociatedWithAction (PED_FIREWEAPON, rsPADINS, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_FIREWEAPON, rsLCTRL, OPTIONAL_EXTRA); @@ -260,6 +244,8 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (PED_JUMPING, rsRCTRL, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_JUMPING, ' ', OPTIONAL_EXTRA); + + SetControllerKeyAssociatedWithAction (PED_ANSWER_PHONE, rsTAB, KEYBOARD); if ( _dwOperatingSystemVersion == OS_WIN98 ) SetControllerKeyAssociatedWithAction(PED_SPRINT, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? @@ -302,7 +288,7 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (VEHICLE_TURRETDOWN, rsPADRIGHT, KEYBOARD); SetControllerKeyAssociatedWithAction (CAMERA_CHANGE_VIEW_ALL_SITUATIONS, rsHOME, KEYBOARD); - SetControllerKeyAssociatedWithAction (CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 'C', OPTIONAL_EXTRA); + SetControllerKeyAssociatedWithAction (CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 'V', OPTIONAL_EXTRA); for (int32 i = 0; i < MAX_SIMS; i++) { @@ -345,6 +331,10 @@ void CControllerConfigManager::InitDefaultControlConfigMouse(CMouseControllerSta SetMouseButtonAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 5); SetMouseButtonAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 4); + + SetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_IN, 4); + + SetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_OUT, 5); } } @@ -407,13 +397,14 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) SetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, 11, JOYSTICK); IF_BTN_IN_RANGE(10) SetControllerKeyAssociatedWithAction(VEHICLE_HORN, 10, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_DUCK, 10, JOYSTICK); IF_BTN_IN_RANGE(9) SetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 9, JOYSTICK); IF_BTN_IN_RANGE(8) SetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, 8, JOYSTICK); SetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, 8, JOYSTICK); IF_BTN_IN_RANGE(7) - SetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, 7, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, 7, JOYSTICK); SetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 7, JOYSTICK); IF_BTN_IN_RANGE(6) SetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 6, JOYSTICK); @@ -458,13 +449,14 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) SetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, 11, JOYSTICK); IF_BTN_IN_RANGE(10) SetControllerKeyAssociatedWithAction(VEHICLE_HORN, 10, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_DUCK, 10, JOYSTICK); IF_BTN_IN_RANGE(9) SetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 9, JOYSTICK); IF_BTN_IN_RANGE(8) SetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, 8, JOYSTICK); SetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, 8, JOYSTICK); IF_BTN_IN_RANGE(7) - SetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, 7, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, 7, JOYSTICK); SetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 7, JOYSTICK); IF_BTN_IN_RANGE(6) SetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 6, JOYSTICK); @@ -507,8 +499,11 @@ void CControllerConfigManager::InitialiseControllerActionNameArray() SETACTIONNAME(PED_SPRINT); SETACTIONNAME(PED_CYCLE_TARGET_LEFT); SETACTIONNAME(PED_CYCLE_TARGET_RIGHT); + SETACTIONNAME(PED_LOCK_TARGET); // duplicate SETACTIONNAME(PED_CENTER_CAMERA_BEHIND_PLAYER); SETACTIONNAME(VEHICLE_LOOKBEHIND); + SETACTIONNAME(PED_DUCK); + SETACTIONNAME(PED_ANSWER_PHONE); SETACTIONNAME(VEHICLE_LOOKLEFT); SETACTIONNAME(VEHICLE_LOOKRIGHT); SETACTIONNAME(VEHICLE_HORN); @@ -534,6 +529,10 @@ void CControllerConfigManager::InitialiseControllerActionNameArray() SETACTIONNAME(GO_RIGHT); SETACTIONNAME(GO_FORWARD); SETACTIONNAME(GO_BACK); + SETACTIONNAME(VEHICLE_TURRETLEFT); + SETACTIONNAME(VEHICLE_TURRETRIGHT); + SETACTIONNAME(VEHICLE_TURRETUP); + SETACTIONNAME(VEHICLE_TURRETDOWN); SETACTIONNAME(NETWORK_TALK); SETACTIONNAME(TOGGLE_DPAD); SETACTIONNAME(SWITCH_DEBUG_CAM_ON); @@ -563,11 +562,12 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int32 button, i case 13: pad->PCTempJoyState.DPadUp = 255; break; -#ifdef REGISTER_START_BUTTON case 12: - pad->PCTempJoyState.Start = 255; - break; +#ifndef REGISTER_START_BUTTON + if (padnumber == 1) #endif + pad->PCTempJoyState.Start = 255; + break; case 11: pad->PCTempJoyState.RightShock = 255; break; @@ -671,6 +671,7 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown(int32 button, if ( mode == CCam::MODE_1STPERSON || mode == CCam::MODE_SNIPER || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_CAMERA || mode == CCam::MODE_M16_1STPERSON) { firstPerson = true; @@ -779,10 +780,7 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_Driving(int32 if (FindPlayerVehicle() && (FindPlayerVehicle()->IsVehicle() && ( FindPlayerVehicle()->GetModelIndex() == MI_DODO #ifdef FIX_BUGS - || CVehicle::bAllDodosCheat -#ifdef ALLCARSHELI_CHEAT - || bAllCarCheat -#endif + || (CVehicle::bAllDodosCheat && !FindPlayerVehicle()->IsRealHeli()) #endif ))) { @@ -843,6 +841,8 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstPersonOnl state.Square = 255; if (button == GetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_OUT, type)) state.Cross = 255; + if (button == GetControllerKeyAssociatedWithAction(PED_DUCK, type)) + state.LeftShock = 255; } void CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnly(int32 button, eControllerType type, CControllerState &state) @@ -851,14 +851,18 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnl state.RightShock = 255; if (button == GetControllerKeyAssociatedWithAction(PED_JUMPING, type)) state.Square = 255; + if (button == GetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, type)) + state.LeftShoulder1 = 255; if (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_LEFT, type)) state.LeftShoulder2 = 255; if (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, type)) state.RightShoulder2 = 255; if (button == GetControllerKeyAssociatedWithAction(PED_SPRINT, type)) state.Cross = 255; + if (button == GetControllerKeyAssociatedWithAction(PED_DUCK, type)) + state.LeftShock = 255; - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type)) state.LeftShoulder2 = 255; @@ -928,7 +932,7 @@ void CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstAndThirdP state.RightStickX = 128; } - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (button == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_UP, type)) { @@ -1686,12 +1690,12 @@ void CControllerConfigManager::DeleteMatchingCommonControls(e_ControllerAction a { if (!GetIsKeyBlank(key, type)) { - CLEAR_ACTION_IF_NEEDED(CAMERA_CHANGE_VIEW_ALL_SITUATIONS); #ifndef BIND_VEHICLE_FIREWEAPON CLEAR_ACTION_IF_NEEDED(PED_FIREWEAPON); #endif CLEAR_ACTION_IF_NEEDED(GO_LEFT); CLEAR_ACTION_IF_NEEDED(GO_RIGHT); + CLEAR_ACTION_IF_NEEDED(CAMERA_CHANGE_VIEW_ALL_SITUATIONS); CLEAR_ACTION_IF_NEEDED(NETWORK_TALK); CLEAR_ACTION_IF_NEEDED(SWITCH_DEBUG_CAM_ON); CLEAR_ACTION_IF_NEEDED(TOGGLE_DPAD); @@ -1704,13 +1708,15 @@ void CControllerConfigManager::DeleteMatching3rdPersonControls(e_ControllerActio { if (!GetIsKeyBlank(key, type)) { - CLEAR_ACTION_IF_NEEDED(PED_LOOKBEHIND); CLEAR_ACTION_IF_NEEDED(PED_CYCLE_WEAPON_LEFT); CLEAR_ACTION_IF_NEEDED(PED_CYCLE_WEAPON_RIGHT); CLEAR_ACTION_IF_NEEDED(PED_JUMPING); CLEAR_ACTION_IF_NEEDED(PED_SPRINT); + CLEAR_ACTION_IF_NEEDED(PED_LOOKBEHIND); + CLEAR_ACTION_IF_NEEDED(PED_DUCK); + CLEAR_ACTION_IF_NEEDED(PED_ANSWER_PHONE); - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { CLEAR_ACTION_IF_NEEDED(PED_CYCLE_TARGET_LEFT); CLEAR_ACTION_IF_NEEDED(PED_CYCLE_TARGET_RIGHT); @@ -1730,7 +1736,7 @@ void CControllerConfigManager::DeleteMatching1rst3rdPersonControls(e_ControllerA CLEAR_ACTION_IF_NEEDED(GO_FORWARD); CLEAR_ACTION_IF_NEEDED(GO_BACK); - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { CLEAR_ACTION_IF_NEEDED(PED_1RST_PERSON_LOOK_LEFT); CLEAR_ACTION_IF_NEEDED(PED_1RST_PERSON_LOOK_RIGHT); @@ -1747,16 +1753,15 @@ void CControllerConfigManager::DeleteMatchingVehicleControls(e_ControllerAction #ifdef BIND_VEHICLE_FIREWEAPON CLEAR_ACTION_IF_NEEDED(VEHICLE_FIREWEAPON); #endif - CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKBEHIND); - CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKLEFT); - CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKRIGHT); - CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKBEHIND); // note: duplicate - CLEAR_ACTION_IF_NEEDED(VEHICLE_HORN); - CLEAR_ACTION_IF_NEEDED(VEHICLE_HANDBRAKE); CLEAR_ACTION_IF_NEEDED(VEHICLE_ACCELERATE); CLEAR_ACTION_IF_NEEDED(VEHICLE_BRAKE); CLEAR_ACTION_IF_NEEDED(VEHICLE_CHANGE_RADIO_STATION); + CLEAR_ACTION_IF_NEEDED(VEHICLE_HORN); CLEAR_ACTION_IF_NEEDED(TOGGLE_SUBMISSIONS); + CLEAR_ACTION_IF_NEEDED(VEHICLE_HANDBRAKE); + CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKLEFT); + CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKRIGHT); + CLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKBEHIND); CLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETLEFT); CLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETRIGHT); CLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETUP); @@ -1799,7 +1804,6 @@ bool CControllerConfigManager::IsAnyVehicleActionAssignedToMouseKey(int32 key) CHECK_ACTION(VEHICLE_LOOKBEHIND); CHECK_ACTION(VEHICLE_LOOKLEFT); CHECK_ACTION(VEHICLE_LOOKRIGHT); - CHECK_ACTION(VEHICLE_LOOKBEHIND); // note: duplicate CHECK_ACTION(VEHICLE_HORN); CHECK_ACTION(VEHICLE_HANDBRAKE); CHECK_ACTION(VEHICLE_ACCELERATE); @@ -1841,36 +1845,36 @@ void CControllerConfigManager::DeleteMatchingActionInitiators(e_ControllerAction DeleteMatching1rst3rdPersonControls (action, key, type); break; case ACTIONTYPE_3RDPERSON: - DeleteMatching3rdPersonControls (action, key, type); DeleteMatchingCommonControls (action, key, type); - DeleteMatchingVehicle_3rdPersonControls(action, key, type); DeleteMatching1rst3rdPersonControls (action, key, type); + DeleteMatching3rdPersonControls (action, key, type); + DeleteMatchingVehicle_3rdPersonControls(action, key, type); break; case ACTIONTYPE_VEHICLE: - DeleteMatchingVehicleControls (action, key, type); DeleteMatchingCommonControls (action, key, type); + DeleteMatchingVehicleControls (action, key, type); DeleteMatchingVehicle_3rdPersonControls(action, key, type); break; case ACTIONTYPE_VEHICLE_3RDPERSON: - DeleteMatching3rdPersonControls (action, key, type); - DeleteMatchingVehicleControls (action, key, type); DeleteMatchingCommonControls (action, key, type); DeleteMatching1rst3rdPersonControls (action, key, type); - break; - case ACTIONTYPE_1RST3RDPERSON: - DeleteMatching1rstPersonControls (action, key, type); DeleteMatching3rdPersonControls (action, key, type); - DeleteMatchingCommonControls (action, key, type); - DeleteMatchingVehicle_3rdPersonControls(action, key, type); - DeleteMatching1rst3rdPersonControls (action, key, type); + DeleteMatchingVehicleControls (action, key, type); break; case ACTIONTYPE_COMMON: + DeleteMatchingCommonControls (action, key, type); DeleteMatching1rstPersonControls (action, key, type); + DeleteMatching1rst3rdPersonControls (action, key, type); DeleteMatching3rdPersonControls (action, key, type); DeleteMatchingVehicleControls (action, key, type); DeleteMatchingVehicle_3rdPersonControls(action, key, type); + break; + case ACTIONTYPE_1RST3RDPERSON: DeleteMatchingCommonControls (action, key, type); + DeleteMatching1rstPersonControls (action, key, type); DeleteMatching1rst3rdPersonControls (action, key, type); + DeleteMatching3rdPersonControls (action, key, type); + DeleteMatchingVehicle_3rdPersonControls(action, key, type); break; default: break; } @@ -1906,25 +1910,27 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio { switch (action) { - case CAMERA_CHANGE_VIEW_ALL_SITUATIONS: #ifndef BIND_VEHICLE_FIREWEAPON case PED_FIREWEAPON: #endif case GO_LEFT: case GO_RIGHT: + case CAMERA_CHANGE_VIEW_ALL_SITUATIONS: case NETWORK_TALK: - case SWITCH_DEBUG_CAM_ON: case TOGGLE_DPAD: + case SWITCH_DEBUG_CAM_ON: case TAKE_SCREEN_SHOT: case SHOW_MOUSE_POINTER_TOGGLE: return ACTIONTYPE_COMMON; break; - case PED_LOOKBEHIND: - case PED_CYCLE_WEAPON_LEFT: case PED_CYCLE_WEAPON_RIGHT: + case PED_CYCLE_WEAPON_LEFT: case PED_JUMPING: case PED_SPRINT: + case PED_LOOKBEHIND: + case PED_DUCK: + case PED_ANSWER_PHONE: case PED_CYCLE_TARGET_LEFT: case PED_CYCLE_TARGET_RIGHT: case PED_CENTER_CAMERA_BEHIND_PLAYER: @@ -1934,15 +1940,15 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio #ifdef BIND_VEHICLE_FIREWEAPON case VEHICLE_FIREWEAPON: #endif - case VEHICLE_LOOKBEHIND: - case VEHICLE_LOOKLEFT: - case VEHICLE_LOOKRIGHT: - case VEHICLE_HORN: - case VEHICLE_HANDBRAKE: case VEHICLE_ACCELERATE: case VEHICLE_BRAKE: case VEHICLE_CHANGE_RADIO_STATION: + case VEHICLE_HORN: case TOGGLE_SUBMISSIONS: + case VEHICLE_HANDBRAKE: + case VEHICLE_LOOKLEFT: + case VEHICLE_LOOKRIGHT: + case VEHICLE_LOOKBEHIND: case VEHICLE_TURRETLEFT: case VEHICLE_TURRETRIGHT: case VEHICLE_TURRETUP: @@ -1957,13 +1963,13 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio #ifdef BIND_VEHICLE_FIREWEAPON case PED_FIREWEAPON: #endif - case PED_LOCK_TARGET: case GO_FORWARD: case GO_BACK: case PED_1RST_PERSON_LOOK_LEFT: case PED_1RST_PERSON_LOOK_RIGHT: - case PED_1RST_PERSON_LOOK_DOWN: + case PED_LOCK_TARGET: case PED_1RST_PERSON_LOOK_UP: + case PED_1RST_PERSON_LOOK_DOWN: return ACTIONTYPE_1RST3RDPERSON; break; @@ -2433,15 +2439,15 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act #define VFB(b) #endif -#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT) \ +#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT, RSU, RSD, RSL, RSR) \ {{ \ O, /* PED_FIREWEAPON */ \ R2, /* PED_CYCLE_WEAPON_RIGHT */ \ L2, /* PED_CYCLE_WEAPON_LEFT */ \ nil, /* GO_FORWARD */ \ nil, /* GO_BACK */ \ - nil, /* GO_LEFT */ \ - nil, /* GO_RIGHT */ \ + LEFT, /* GO_LEFT */ \ + RIGHT, /* GO_RIGHT */ \ Q, /* PED_SNIPER_ZOOM_IN */ \ X, /* PED_SNIPER_ZOOM_OUT */ \ T, /* VEHICLE_ENTER_EXIT */ \ @@ -2449,6 +2455,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act Q, /* PED_JUMPING */ \ X, /* PED_SPRINT */ \ R3, /* PED_LOOKBEHIND */ \ + L3, /* PED_DUCK */ \ + L1, /* PED_ANSWER_PHONE */ \ VFB(O) /* VEHICLE_FIREWEAPON */ \ X, /* VEHICLE_ACCELERATE */ \ Q, /* VEHICLE_BRAKE */ \ @@ -2461,10 +2469,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* VEHICLE_LOOKLEFT */ \ R2, /* VEHICLE_LOOKRIGHT */ \ nil, /* VEHICLE_LOOKBEHIND */ \ - nil, /* VEHICLE_TURRETLEFT */ \ - nil, /* VEHICLE_TURRETRIGHT */ \ - nil, /* VEHICLE_TURRETUP */ \ - nil, /* VEHICLE_TURRETDOWN */ \ + RSL, /* VEHICLE_TURRETLEFT */ \ + RSR, /* VEHICLE_TURRETRIGHT */ \ + UP, /* VEHICLE_TURRETUP */ \ + DOWN, /* VEHICLE_TURRETDOWN */ \ L2, /* PED_CYCLE_TARGET_LEFT */ \ R2, /* PED_CYCLE_TARGET_RIGHT */ \ L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ @@ -2476,6 +2484,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act nil, /* TOGGLE_DPAD */ \ nil, /* SWITCH_DEBUG_CAM_ON */ \ nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* UNKNOWN_ACTION */ \ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ }, \ { \ @@ -2484,8 +2493,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* PED_CYCLE_WEAPON_LEFT */ \ nil, /* GO_FORWARD */ \ nil, /* GO_BACK */ \ - nil, /* GO_LEFT */ \ - nil, /* GO_RIGHT */ \ + LEFT, /* GO_LEFT */ \ + RIGHT, /* GO_RIGHT */ \ Q, /* PED_SNIPER_ZOOM_IN */ \ X, /* PED_SNIPER_ZOOM_OUT */ \ T, /* VEHICLE_ENTER_EXIT */ \ @@ -2493,6 +2502,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act Q, /* PED_JUMPING */ \ X, /* PED_SPRINT */ \ R3, /* PED_LOOKBEHIND */ \ + L3, /* PED_DUCK */ \ + L1, /* PED_ANSWER_PHONE */ \ VFB(O) /* VEHICLE_FIREWEAPON */ \ X, /* VEHICLE_ACCELERATE */ \ Q, /* VEHICLE_BRAKE */ \ @@ -2505,10 +2516,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* VEHICLE_LOOKLEFT */ \ R2, /* VEHICLE_LOOKRIGHT */ \ nil, /* VEHICLE_LOOKBEHIND */ \ - nil, /* VEHICLE_TURRETLEFT */ \ - nil, /* VEHICLE_TURRETRIGHT */ \ - nil, /* VEHICLE_TURRETUP */ \ - nil, /* VEHICLE_TURRETDOWN */ \ + RSL, /* VEHICLE_TURRETLEFT */ \ + RSR, /* VEHICLE_TURRETRIGHT */ \ + UP, /* VEHICLE_TURRETUP */ \ + DOWN, /* VEHICLE_TURRETDOWN */ \ L2, /* PED_CYCLE_TARGET_LEFT */ \ R2, /* PED_CYCLE_TARGET_RIGHT */ \ L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ @@ -2520,6 +2531,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act nil, /* TOGGLE_DPAD */ \ nil, /* SWITCH_DEBUG_CAM_ON */ \ nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* UNKNOWN_ACTION */ \ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ }, \ { \ @@ -2528,8 +2540,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* PED_CYCLE_WEAPON_LEFT */ \ nil, /* GO_FORWARD */ \ nil, /* GO_BACK */ \ - nil, /* GO_LEFT */ \ - nil, /* GO_RIGHT */ \ + LEFT, /* GO_LEFT */ \ + RIGHT, /* GO_RIGHT */ \ T, /* PED_SNIPER_ZOOM_IN */ \ Q, /* PED_SNIPER_ZOOM_OUT */ \ L1, /* VEHICLE_ENTER_EXIT */ \ @@ -2537,6 +2549,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act Q, /* PED_JUMPING */ \ O, /* PED_SPRINT */ \ R3, /* PED_LOOKBEHIND */ \ + L3, /* PED_DUCK */ \ + T, /* PED_ANSWER_PHONE */ \ VFB(O) /* VEHICLE_FIREWEAPON */ \ X, /* VEHICLE_ACCELERATE */ \ Q, /* VEHICLE_BRAKE */ \ @@ -2549,10 +2563,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* VEHICLE_LOOKLEFT */ \ R2, /* VEHICLE_LOOKRIGHT */ \ nil, /* VEHICLE_LOOKBEHIND */ \ - nil, /* VEHICLE_TURRETLEFT */ \ - nil, /* VEHICLE_TURRETRIGHT */ \ - nil, /* VEHICLE_TURRETUP */ \ - nil, /* VEHICLE_TURRETDOWN */ \ + RSL, /* VEHICLE_TURRETLEFT */ \ + RSR, /* VEHICLE_TURRETRIGHT */ \ + UP, /* VEHICLE_TURRETUP */ \ + DOWN, /* VEHICLE_TURRETDOWN */ \ L2, /* PED_CYCLE_TARGET_LEFT */ \ R2, /* PED_CYCLE_TARGET_RIGHT */ \ T, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ @@ -2564,6 +2578,7 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act nil, /* TOGGLE_DPAD */ \ nil, /* SWITCH_DEBUG_CAM_ON */ \ nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* UNKNOWN_ACTION */ \ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ }, \ { \ @@ -2572,8 +2587,8 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* PED_CYCLE_WEAPON_LEFT */ \ nil, /* GO_FORWARD */ \ nil, /* GO_BACK */ \ - nil, /* GO_LEFT */ \ - nil, /* GO_RIGHT */ \ + LEFT, /* GO_LEFT */ \ + RIGHT, /* GO_RIGHT */ \ Q, /* PED_SNIPER_ZOOM_IN */ \ X, /* PED_SNIPER_ZOOM_OUT */ \ T, /* VEHICLE_ENTER_EXIT */ \ @@ -2581,9 +2596,11 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act Q, /* PED_JUMPING */ \ X, /* PED_SPRINT */ \ R3, /* PED_LOOKBEHIND */ \ + L3, /* PED_DUCK */ \ + O, /* PED_ANSWER_PHONE */ \ VFB(R1) /* VEHICLE_FIREWEAPON */ \ - nil, /* VEHICLE_ACCELERATE */ \ - nil, /* VEHICLE_BRAKE */ \ + RSU, /* VEHICLE_ACCELERATE */ \ + RSD, /* VEHICLE_BRAKE */ \ O, /* VEHICLE_CHANGE_RADIO_STATION */ \ L3, /* VEHICLE_HORN */ \ Q, /* TOGGLE_SUBMISSIONS */ \ @@ -2593,10 +2610,10 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act L2, /* VEHICLE_LOOKLEFT */ \ R2, /* VEHICLE_LOOKRIGHT */ \ nil, /* VEHICLE_LOOKBEHIND */ \ - nil, /* VEHICLE_TURRETLEFT */ \ - nil, /* VEHICLE_TURRETRIGHT */ \ - nil, /* VEHICLE_TURRETUP */ \ - nil, /* VEHICLE_TURRETDOWN */ \ + RSL, /* VEHICLE_TURRETLEFT */ \ + RSR, /* VEHICLE_TURRETRIGHT */ \ + UP, /* VEHICLE_TURRETUP */ \ + DOWN, /* VEHICLE_TURRETDOWN */ \ L2, /* PED_CYCLE_TARGET_LEFT */ \ R2, /* PED_CYCLE_TARGET_RIGHT */ \ O, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \ @@ -2608,14 +2625,26 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act nil, /* TOGGLE_DPAD */ \ nil, /* SWITCH_DEBUG_CAM_ON */ \ nil, /* TAKE_SCREEN_SHOT */ \ + nil, /* UNKNOWN_ACTION */ \ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \ }} +#ifdef BUTTON_ICONS +#define UP "~U~" +#define DOWN "~D~" +#define LEFT "~<~" +#define RIGHT "~>~" +#else +#define UP "UP" +#define DOWN "DOWN" +#define LEFT "LEFT" +#define RIGHT "RIGHT" +#endif -const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK"); +const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK", "right stick up", "right stick down", "right stick left", "right stick right"); #ifdef BUTTON_ICONS -const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK"); +const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK", "~H~", "~L~", "~(~", "~)~"); #endif @@ -2632,11 +2661,11 @@ const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O #endif const char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] = - CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT"); + CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT", "right stick up", "right stick down", "right stick left", "right stick right"); #ifdef BUTTON_ICONS const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = - CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT"); + CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT", "~H~", "~L~", "~(~", "~)~"); #endif #undef PS2_TRIANGLE @@ -2644,6 +2673,11 @@ const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] = #undef PS2_CROSS #undef PS2_SQUARE +#undef UP +#undef DOWN +#undef LEFT +#undef RIGHT + #undef CONTROLLER_BUTTONS #undef VFB diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 295f03b9..d61e23e6 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -32,6 +32,8 @@ enum e_ControllerAction PED_JUMPING, PED_SPRINT, PED_LOOKBEHIND, + PED_DUCK, + PED_ANSWER_PHONE, #ifdef BIND_VEHICLE_FIREWEAPON VEHICLE_FIREWEAPON, #endif @@ -62,6 +64,7 @@ enum e_ControllerAction SWITCH_DEBUG_CAM_ON, TAKE_SCREEN_SHOT, SHOW_MOUSE_POINTER_TOGGLE, + UNKNOWN_ACTION, MAX_CONTROLLERACTIONS, }; diff --git a/src/core/Crime.h b/src/core/Crime.h index 05829040..4c7ea315 100644 --- a/src/core/Crime.h +++ b/src/core/Crime.h @@ -18,6 +18,9 @@ enum eCrimeType { CRIME_COP_BURNED, CRIME_VEHICLE_BURNED, CRIME_DESTROYED_CESSNA, + CRIME_EXPLOSION, + CRIME_HIT_PED_NASTYWEAPON, + CRIME_HIT_COP_NASTYWEAPON, NUM_CRIME_TYPES }; diff --git a/src/core/Debug.cpp b/src/core/Debug.cpp index e794dcaf..e319388c 100644 --- a/src/core/Debug.cpp +++ b/src/core/Debug.cpp @@ -55,7 +55,7 @@ CDebug::DebugDisplayTextBuffer() CFont::SetJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); #else // this is not even readable CFont::SetPropOff(); @@ -65,7 +65,7 @@ CDebug::DebugDisplayTextBuffer() CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::SetPropOff(); #endif do { @@ -113,7 +113,7 @@ CDebug::DisplayScreenStrings() CFont::SetRightJustifyWrap(0.0f); CFont::SetWrapx(9999.0f); CFont::SetBackGroundOnlyTextOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); for(i = 0; i < ms_nScreenStrs; i++){ /* diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp index 93f72d4e..b7f139b4 100644 --- a/src/core/EventList.cpp +++ b/src/core/EventList.cpp @@ -75,8 +75,6 @@ CEventList::RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent switch(entityType){ case EVENT_ENTITY_PED: ref = CPools::GetPedRef((CPed*)ent); - if(ent->GetModelIndex() >= MI_GANG01 && ent->GetModelIndex() <= MI_CRIMINAL02) - copsDontCare = true; break; case EVENT_ENTITY_VEHICLE: ref = CPools::GetVehicleRef((CVehicle*)ent); @@ -211,27 +209,43 @@ CEventList::ReportCrimeForEvent(eEventType type, intptr crimeId, bool copsDontCa case EVENT_HIT_AND_RUN_COP: crime = CRIME_RUNOVER_COP; break; case EVENT_SHOOT_PED: crime = CRIME_SHOOT_PED; break; case EVENT_SHOOT_COP: crime = CRIME_SHOOT_COP; break; + case EVENT_EXPLOSION: crime = CRIME_EXPLOSION; break; case EVENT_PED_SET_ON_FIRE: crime = CRIME_PED_BURNED; break; case EVENT_COP_SET_ON_FIRE: crime = CRIME_COP_BURNED; break; case EVENT_CAR_SET_ON_FIRE: crime = CRIME_VEHICLE_BURNED; break; + case EVENT_ASSAULT_NASTYWEAPON: crime = CRIME_HIT_PED_NASTYWEAPON; break; + case EVENT_ASSAULT_NASTYWEAPON_POLICE: crime = CRIME_HIT_COP_NASTYWEAPON; break; default: crime = CRIME_NONE; break; } + if (crime == CRIME_HIT_PED && IsPedPointerValid((CPed*)crimeId) && FindPlayerPed()->m_pWanted->GetWantedLevel() == 0 && ((CPed*)crimeId)->bBeingChasedByPolice) { + if (!((CPed*)crimeId)->DyingOrDead()) { + CMessages::AddBigMessage(TheText.Get("GOODBOY"), 5000, 0); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 50; + } + return; + } + if(crime == CRIME_NONE) return; +#ifdef FIX_BUGS + CVector playerPedCoors = FindPlayerCoors(); +#else CVector playerPedCoors = FindPlayerPed()->GetPosition(); +#endif CVector playerCoors = FindPlayerCoors(); - if(CWanted::WorkOutPolicePresence(playerCoors, 14.0f) != 0){ - FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(crime, playerPedCoors, crimeId, copsDontCare); + if(CWanted::WorkOutPolicePresence(playerCoors, 14.0f) != 0 || + CGame::germanGame && (crime == CRIME_SHOOT_PED || crime == CRIME_SHOOT_COP || crime == CRIME_COP_BURNED || crime == CRIME_VEHICLE_BURNED)){ + FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(crime, playerPedCoors, (uint32)crimeId, copsDontCare); FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1); }else - FindPlayerPed()->m_pWanted->RegisterCrime(crime, playerPedCoors, crimeId, copsDontCare); + FindPlayerPed()->m_pWanted->RegisterCrime(crime, playerPedCoors, (uint32)crimeId, copsDontCare); if(type == EVENT_ASSAULT_POLICE) FindPlayerPed()->SetWantedLevelNoDrop(1); - if(type == EVENT_SHOOT_COP) + if(type == EVENT_SHOOT_COP || type == EVENT_ASSAULT_NASTYWEAPON_POLICE) FindPlayerPed()->SetWantedLevelNoDrop(2); } diff --git a/src/core/EventList.h b/src/core/EventList.h index 4ced3a83..3e9d8fd4 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -22,10 +22,13 @@ enum eEventType EVENT_PED_SET_ON_FIRE, EVENT_COP_SET_ON_FIRE, EVENT_CAR_SET_ON_FIRE, - EVENT_ASSAULT_NASTYWEAPON, // not sure + EVENT_ASSAULT_NASTYWEAPON, + EVENT_ASSAULT_NASTYWEAPON_POLICE, + EVENT_UNK, // Not on SA it seems EVENT_ICECREAM, EVENT_ATM, - EVENT_SHOPSTALL, // used on graffitis + EVENT_SHOPSTALL, + EVENT_SHOPWINDOW, EVENT_LAST_EVENT }; diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index afa2a66f..dbf2cad9 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include <ctype.h> #include "main.h" #include "General.h" @@ -25,6 +26,9 @@ #include "CdStream.h" #include "FileLoader.h" #include "MemoryHeap.h" +#include "Streaming.h" +#include "ColStore.h" +#include "Occlusion.h" char CFileLoader::ms_line[256]; @@ -47,36 +51,24 @@ CFileLoader::LoadLevel(const char *filename) { int fd; RwTexDictionary *savedTxd; - eLevelName savedLevel; bool objectsLoaded; char *line; char txdname[64]; savedTxd = RwTexDictionaryGetCurrent(); objectsLoaded = false; - savedLevel = CGame::currLevel; if(savedTxd == nil){ savedTxd = RwTexDictionaryCreate(); RwTexDictionarySetCurrent(savedTxd); } -#if GTA_VERSION <= GTA3_PS2_160 - CFileMgr::ChangeDir("\\DATA\\"); - fd = CFileMgr::OpenFile(filename, "r"); - CFileMgr::ChangeDir("\\"); -#else fd = CFileMgr::OpenFile(filename, "r"); -#endif assert(fd > 0); for(line = LoadLine(fd); line; line = LoadLine(fd)){ if(*line == '#') continue; -#ifdef FIX_BUGS if(strncmp(line, "EXIT", 4) == 0) -#else - if(strncmp(line, "EXIT", 9) == 0) -#endif break; if(strncmp(line, "IMAGEPATH", 9) == 0){ @@ -90,12 +82,8 @@ CFileLoader::LoadLevel(const char *filename) RwTexDictionaryDestroy(txd); POP_MEMID(); }else if(strncmp(line, "COLFILE", 7) == 0){ - int level; - sscanf(line+8, "%d", &level); - CGame::currLevel = (eLevelName)level; LoadingScreenLoadingFile(line+10); - LoadCollisionFile(line+10); - CGame::currLevel = savedLevel; + LoadCollisionFile(line+10, 0); }else if(strncmp(line, "MODELFILE", 9) == 0){ LoadingScreenLoadingFile(line + 10); LoadModelFile(line + 10); @@ -107,19 +95,23 @@ CFileLoader::LoadLevel(const char *filename) LoadObjectTypes(line + 4); }else if(strncmp(line, "IPL", 3) == 0){ if(!objectsLoaded){ - PUSH_MEMID(MEMID_DEF_MODELS); - CModelInfo::ConstructMloClumps(); - POP_MEMID(); + LoadingScreenLoadingFile("Collision"); + PUSH_MEMID(MEMID_WORLD); CObjectData::Initialise("DATA\\OBJECT.DAT"); + CStreaming::Init(); + POP_MEMID(); + PUSH_MEMID(MEMID_COLLISION); + CColStore::LoadAllCollision(); + POP_MEMID(); + for(int i = 0; i < MODELINFOSIZE; i++) + if(CModelInfo::GetModelInfo(i)) + CModelInfo::GetModelInfo(i)->ConvertAnimFileIndex(); objectsLoaded = true; } PUSH_MEMID(MEMID_WORLD); LoadingScreenLoadingFile(line + 4); LoadScene(line + 4); POP_MEMID(); - }else if(strncmp(line, "MAPZONE", 7) == 0){ - LoadingScreenLoadingFile(line + 8); - LoadMapZones(line + 8); }else if(strncmp(line, "SPLASH", 6) == 0){ #ifndef DISABLE_LOADING_SCREEN LoadSplash(GetRandomSplashScreen()); @@ -133,30 +125,13 @@ CFileLoader::LoadLevel(const char *filename) CFileMgr::CloseFile(fd); RwTexDictionarySetCurrent(savedTxd); -} -void -CFileLoader::LoadCollisionFromDatFile(int currlevel) -{ - int fd; - char *line; - - fd = CFileMgr::OpenFile(CGame::aDatFile, "r"); - assert(fd > 0); - - for(line = LoadLine(fd); line; line = LoadLine(fd)){ - if(*line == '#') - continue; - - if(strncmp(line, "COLFILE", 7) == 0){ - int level; - sscanf(line+8, "%d", &level); - if(currlevel == level) - LoadCollisionFile(line+10); - } - } - - CFileMgr::CloseFile(fd); + int i; + for(i = 1; i < COLSTORESIZE; i++) + if(CColStore::GetSlot(i)) + CColStore::GetBoundingBox(i).Grow(120.0f); + CWorld::RepositionCertainDynamicObjects(); + CColStore::RemoveAllCollision(); } char* @@ -200,7 +175,7 @@ struct ColHeader }; void -CFileLoader::LoadCollisionFile(const char *filename) +CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot) { int fd; char modelname[24]; @@ -211,6 +186,7 @@ CFileLoader::LoadCollisionFile(const char *filename) debug("Loading collision file %s\n", filename); fd = CFileMgr::OpenFile(filename, "rb"); + assert(fd > 0); while(CFileMgr::Read(fd, (char*)&header, sizeof(header))){ assert(header.ident == 'LLOC'); @@ -219,10 +195,11 @@ CFileLoader::LoadCollisionFile(const char *filename) mi = CModelInfo::GetModelInfo(modelname, nil); if(mi){ - if(mi->GetColModel()){ + if(mi->GetColModel() && mi->DoesOwnColModel()){ LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname); }else{ CColModel *model = new CColModel; + model->level = colSlot; LoadCollisionModel(work_buff+24, *model, modelname); mi->SetColModel(model, true); } @@ -236,6 +213,79 @@ CFileLoader::LoadCollisionFile(const char *filename) POP_MEMID(); } + +bool +CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot) +{ + uint32 modelsize; + char modelname[24]; + CBaseModelInfo *mi; + ColHeader *header; + int modelIndex; + + while(size > 8){ + header = (ColHeader*)buffer; + modelsize = header->size; + if(header->ident != 'LLOC') + return size-8 < CDSTREAM_SECTOR_SIZE; + memcpy(modelname, buffer+8, 24); + memcpy(work_buff, buffer+32, modelsize-24); + size -= 32 + (modelsize-24); + buffer += 32 + (modelsize-24); + if(modelsize > 15*1024) + debug("colmodel %s is huge, size %d\n", modelname, modelsize); + + mi = CModelInfo::GetModelInfo(modelname, &modelIndex); + if(mi){ + CColStore::IncludeModelIndex(colSlot, modelIndex); + CColModel *model = new CColModel; + model->level = colSlot; + LoadCollisionModel(work_buff, *model, modelname); + mi->SetColModel(model, true); + }else{ + debug("colmodel %s can't find a modelinfo\n", modelname); + } + } + return true; +} + +bool +CFileLoader::LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot) +{ + uint32 modelsize; + char modelname[24]; + CBaseModelInfo *mi; + ColHeader *header; + + while(size > 8){ + header = (ColHeader*)buffer; + modelsize = header->size; + if(header->ident != 'LLOC') + return size-8 < CDSTREAM_SECTOR_SIZE; + memcpy(modelname, buffer+8, 24); + memcpy(work_buff, buffer+32, modelsize-24); + size -= 32 + (modelsize-24); + buffer += 32 + (modelsize-24); + if(modelsize > 15*1024) + debug("colmodel %s is huge, size %d\n", modelname, modelsize); + + mi = CModelInfo::GetModelInfo(modelname, CColStore::GetSlot(colSlot)->minIndex, CColStore::GetSlot(colSlot)->maxIndex); + if(mi){ + if(mi->GetColModel()){ + LoadCollisionModel(work_buff, *mi->GetColModel(), modelname); + }else{ + CColModel *model = new CColModel; + model->level = colSlot; + LoadCollisionModel(work_buff, *model, modelname); + mi->SetColModel(model, true); + } + }else{ + debug("colmodel %s can't find a modelinfo\n", modelname); + } + } + return true; +} + void CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) { @@ -266,14 +316,16 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) model.numLines = *(int16*)buf; buf += 4; if(model.numLines > 0){ - model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); + //model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); REGISTER_MEMPTR(&model.lines); for(i = 0; i < model.numLines; i++){ - model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); + //model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); buf += 24; } }else model.lines = nil; + model.numLines = 0; + model.lines = nil; model.numBoxes = *(int16*)buf; buf += 4; @@ -294,10 +346,12 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) REGISTER_MEMPTR(&model.vertices); for(i = 0; i < numVertices; i++){ model.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8)); +#if 0 if(Abs(*(float*)buf) >= 256.0f || Abs(*(float*)(buf+4)) >= 256.0f || Abs(*(float*)(buf+8)) >= 256.0f) printf("%s:Collision volume too big\n", modelname); +#endif buf += 12; } }else @@ -309,7 +363,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle)); REGISTER_MEMPTR(&model.triangles); for(i = 0; i < model.numTriangles; i++){ - model.triangles[i].Set(model.vertices, *(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12], buf[13]); + model.triangles[i].Set(*(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12]); buf += 16; } }else @@ -321,7 +375,7 @@ GetNameAndLOD(char *nodename, char *name, int *n) { char *underscore = nil; for(char *s = nodename; *s != '\0'; s++){ - if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L')) + if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L') && isdigit(s[2])) underscore = s; } if(underscore){ @@ -347,11 +401,11 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data) mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil); if(mi){ assert(mi->IsSimple()); + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); mi->SetAtomic(n, atomic); RpClumpRemoveAtomic(clump, atomic); RpAtomicSetFrame(atomic, RwFrameCreate()); CVisibilityPlugins::SetAtomicModelInfo(atomic, mi); - CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); }else{ debug("Can't find Atomic %s\n", name); } @@ -427,17 +481,9 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id) clump = RpClumpStreamRead(stream); if(clump == nil) return false; + InitClump(clump); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); mi->SetClump(clump); - if (mi->GetModelType() == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) { - // Read LOD ped - clump = RpClumpStreamRead(stream); - InitClump(clump); - if(clump){ - ((CPedModelInfo*)mi)->SetLowDetailClump(clump); - RpClumpDestroy(clump); - } - } return true; } @@ -492,425 +538,6 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id) return true; } -#ifdef HARDCODED_MODEL_FLAGS -char *DoubleSidedNames[] = { - "chnabankdoor", - "Security_Hut", - "Hospital_Sub", - "phonebooth1", - "trafficlight1", - "sub_roadbarrier", - "redlightbuild09", - "doublestreetlght1", - "doc_shedbig31", - "com_land_128", - "garage7", - "proj_garage01", - "buildingground2", - "buildingground3", - "ch_roof_kb", - "overpassind", - "casino", - "ind_land100", - "fuckedup_skewlbus", - "Police_Station_ind", - "flagsitaly", - "sidebarrier_gaz1", - "bar_barrier12", - "bar_barrier10b", - "sidebarrier_gaz2", - "doc_shedbig3", - "doc_shedbig4", - "verticalift_bridge", - "verticalift_bridg2", - "usdcrdlrbuild01", - "apairporthanger", - "apairporthangerA", - "porthangerclosed", - "redlightbuild13", - "doc_rave", - "const_woodfence", - "const_woodfence2", - "const_woodfence3", - "subfraightback01", - "subfraightback02", - "subfraightback03", - "subfraightback04", - "subind_build03", - "chinabanner1", - "chinabanner2", - "chinabanner3", - "chinabanner4", - "Pumpfirescape", - "Pumphouse", - "amcounder", - "barrel1", - "barrel2", - "barrel3", - "barrel4", - "com_1way50", - "com_1way20", - "overpasscom01", - "overpasscom02", - "overpasscom03", - "overpasscom04", - "overpass_comse", - "newdockbuilding", - "newdockbuilding2", - "policeballhall", - "fuzballdoor", - "ind_land106", - "PoliceBallSigns", - "amcoudet", - "rustship_structure", - "impexpgrgesub", - "ind_land128", - "fshfctry_dstryd", - "railtrax_bentl", - "railtrax_lo4b", - "railtrax_straight", - "railtrax_bentrb", - "railtrax_skew", - "newtrackaaa", - "railtrax_skew5", - // these they forgot: - "railtrax_skewp", - "railtrax_ske2b", - "railtrax_strtshort", - "railtrax_2b", - "railtrax_straightss", - "railtrax_bentr", - "ind_land125", - "salvstrans", - "bridge_liftsec", - "subsign1", - "carparkfence", - "newairportwall4", - "apair_terminal", - "Helipad", - "bar_barrier10", - "damissionfence", - "sub_floodlite", - "suburbbridge1", - "damfencing", - "demfence08", - "damfence07", - "damfence06", - "damfence05", - "damfence04", - "damfence03", - "damfence02", - "damfence01", - "Dam_pod2", - "Dam_pod1", - "columansion_wall", - "wrckdhse020", - "wrckdhse01", - "arc_bridge", - "gRD_overpass19kbc", - "gRD_overpass19bkb", - "gRD_overpass19kb", - "gRD_overpass18kb", - "road_under", - "com_roadkb23", - "com_roadkb22", - "nbbridgerda", - "nbbridgerdb", - "policetenkb1", - "block3_scraper2", - "Clnm_cthdrlfcde", - "broadwaybuild", - "combillboard03", - "com_park3b", - "com_docksaa", - "newdockbuilding2", - "com_roadkb22", - "sidebarrier_gaz2", - "tunnelsupport1", - "skyscrpunbuilt2", - "cons_buid02", - "rail_platformw", - "railtrax_bent1", - "nrailstepswest", - "building_fucked", - "franksclb02", - "salvsdetail", - "crgoshp01", - "shp_wlkway", - "bar_barriergate1", - "plnt_pylon01", - "fishfctory", - "doc_crane_cab", - "nrailsteps", - "iten_club01", - "mak_Watertank", - "basketballcourt" - "carlift01", - "carlift02", - "iten_chinatown4", - "iten_details7", - "ind_customroad002" - "ind_brgrd1way", - "ind_customroad060", - "ind_customroad002", - "ind_land108", - "ind_customroad004", - "ind_customroad003", - "nbbridgcabls01", - "sbwy_tunl_bit", - "sbwy_tunl_bend", - "sbwy_tunl_cstm11", - "sbwy_tunl_cstm10", - "sbwy_tunl_cstm9", - "sbwy_tunl_cstm8", - "sbwy_tunl_cstm7", - "sbwy_tunl_cstm6", - "sbwy_tunl_cstm5", - "sbwy_tunl_cstm4", - "sbwy_tunl_cstm3", - "sbwy_tunl_cstm2", - "sbwy_tunl_cstm1", - "tenmnt6ad", - "" - -}; -char *TreeNames[] = { - "coast_treepatch", - "comparknewtrees", - "comtreepatchprk", - "condotree01", - "condotree1", - "indatree03", - "indtreepatch5", - "indtreepatch06f", - "new_carprktrees", - "new_carprktrees4", - "newcoasttrees1", - "newcoasttrees2", - "newcoasttrees3", - "newtreepatch_sub", - "newtrees1_sub", - "newunitrepatch", - "pinetree_narrow", - "pinetree_wide", - "treencom2", - "treepatch", - "treepatch01_sub", - "treepatch02_sub", - "treepatch2", - "treepatch2b", - "treepatch03", - "treepatch03_sub", - "treepatch04_sub", - "treepatch05_sub", - "treepatch06_sub", - "treepatch07_sub", - "treepatch08_sub", - "treepatch09_sub", - "treepatch10_sub", - "treepatch11_sub", - "treepatch12_sub", - "treepatch13_sub", - "treepatch14_sub", - "treepatch15_sub", - "treepatch16_sub", - "treepatch17_sub", - "treepatch18_sub", - "treepatch19_sub", - "treepatch20_sub", - "treepatch21_sub", - "treepatch22_sub", - "treepatch23_sub", - "treepatch24_sub", - "treepatch25_sub", - "treepatch26_sub", - "treepatch27_sub", - "treepatch28_sub", - "treepatch29_sub", - "treepatch30_sub", - "treepatch31_sub", - "treepatch32_sub", - "treepatch33_sub", - "treepatch34_sub", - "treepatch35_sub", - "treepatch69", - "treepatch152_sub", - "treepatch153_sub", - "treepatch171_sub", - "treepatch172_sub", - "treepatch173_sub", - "treepatch212_sub", - "treepatch213_sub", - "treepatch214_sub", - "treepatcha", - "treepatchb", - "treepatchcomtop1", - "treepatchd", - "treepatche", - "treepatchh", - "treepatchindaa2", - "treepatchindnew", - "treepatchindnew2", - "treepatchk", - "treepatchkb4", - "treepatchkb5", - "treepatchkb6", - "treepatchkb7", - "treepatchkb9", - "treepatchl", - "treepatchm", - "treepatchnew_sub", - "treepatchttwrs", - "treesuni1", - "trepatchindaa1", - "veg_bush2", - "veg_bush14", - "veg_tree1", - "veg_tree3", - "veg_treea1", - "veg_treea3", - "veg_treeb1", - "veg_treenew01", - "veg_treenew03", - "veg_treenew05", - "veg_treenew06", - "veg_treenew08", - "veg_treenew09", - "veg_treenew10", - "veg_treenew16", - "veg_treenew17", - "vegclubtree01", - "vegclubtree02", - "vegclubtree03", - "vegpathtree", - "" -}; -char *OptimizedNames[] = { - "coast_treepatch", - "comparknewtrees", - "comtreepatchprk", - "indtreepatch5", - "indtreepatch06f", - "new_carprktrees", - "new_carprktrees4", - "newcoasttrees1", - "newcoasttrees2", - "newcoasttrees3", - "newtreepatch_sub", - "newtrees1_sub", - "newunitrepatch", - "treepatch", - "treepatch01_sub", - "treepatch02_sub", - "treepatch2", - "treepatch2b", - "treepatch03", - "treepatch03_sub", - "treepatch04_sub", - "treepatch05_sub", - "treepatch06_sub", - "treepatch07_sub", - "treepatch08_sub", - "treepatch09_sub", - "treepatch10_sub", - "treepatch11_sub", - "treepatch12_sub", - "treepatch13_sub", - "treepatch14_sub", - "treepatch15_sub", - "treepatch16_sub", - "treepatch17_sub", - "treepatch18_sub", - "treepatch19_sub", - "treepatch20_sub", - "treepatch21_sub", - "treepatch22_sub", - "treepatch23_sub", - "treepatch24_sub", - "treepatch25_sub", - "treepatch26_sub", - "treepatch27_sub", - "treepatch28_sub", - "treepatch29_sub", - "treepatch30_sub", - "treepatch31_sub", - "treepatch32_sub", - "treepatch33_sub", - "treepatch34_sub", - "treepatch35_sub", - "treepatch69", - "treepatch152_sub", - "treepatch153_sub", - "treepatch171_sub", - "treepatch172_sub", - "treepatch173_sub", - "treepatch212_sub", - "treepatch213_sub", - "treepatch214_sub", - "treepatcha", - "treepatchb", - "treepatchcomtop1", - "treepatchd", - "treepatche", - "treepatchh", - "treepatchindaa2", - "treepatchindnew", - "treepatchindnew2", - "treepatchk", - "treepatchkb4", - "treepatchkb5", - "treepatchkb6", - "treepatchkb7", - "treepatchkb9", - "treepatchl", - "treepatchm", - "treepatchnew_sub", - "treepatchttwrs", - "treesuni1", - "trepatchindaa1", - "combtm_treeshad01", - "combtm_treeshad02", - "combtm_treeshad03", - "combtm_treeshad04", - "combtm_treeshad05", - "combtm_treeshad06", - "comtop_tshad", - "comtop_tshad2", - "comtop_tshad3", - "comtop_tshad4", - "comtop_tshad5", - "comtop_tshad6", - "se_treeshad01", - "se_treeshad02", - "se_treeshad03", - "se_treeshad04", - "se_treeshad05", - "se_treeshad06", - "treeshads01", - "treeshads02", - "treeshads03", - "treeshads04", - "treeshads05", - "" -}; -// not from mobile -static bool -MatchModelName(char *name, char **list) -{ - int i; - char *s; - for(i = 0; *list[i] != '\0'; i++) - if(strncmp(name, "LOD", 3) == 0){ - if(!CGeneral::faststricmp(name+3, list[i]+3)) - return true; - }else{ - if(!CGeneral::faststricmp(name, list[i])) - return true; - } - return false; -} -#endif - RpAtomic* CFileLoader::SetRelatedModelInfoCB(RpAtomic *atomic, void *data) { @@ -920,11 +547,11 @@ CFileLoader::SetRelatedModelInfoCB(RpAtomic *atomic, void *data) nodename = GetFrameNodeName(RpAtomicGetFrame(atomic)); GetNameAndLOD(nodename, name, &n); + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); gpRelatedModelInfo->SetAtomic(n, atomic); RpClumpRemoveAtomic(clump, atomic); RpAtomicSetFrame(atomic, RwFrameCreate()); CVisibilityPlugins::SetAtomicModelInfo(atomic, gpRelatedModelInfo); - CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); return atomic; } @@ -967,8 +594,9 @@ CFileLoader::LoadObjectTypes(const char *filename) enum { NONE, OBJS, - MLO, + MLO, // unused but enum still has it TOBJ, + WEAP, HIER, CARS, PEDS, @@ -979,16 +607,17 @@ CFileLoader::LoadObjectTypes(const char *filename) int fd; int section; int pathIndex; - char pathTypeStr[20]; int id, pathType; - int mlo; + int minID, maxID; section = NONE; + minID = INT32_MAX; + maxID = -1; pathIndex = -1; - mlo = 0; debug("Loading object types from %s...\n", filename); fd = CFileMgr::OpenFile(filename, "rb"); + assert(fd > 0); for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){ if(*line == '\0' || *line == '#') continue; @@ -996,25 +625,27 @@ CFileLoader::LoadObjectTypes(const char *filename) if(section == NONE){ if(isLine4(line, 'o','b','j','s')) section = OBJS; else if(isLine4(line, 't','o','b','j')) section = TOBJ; + else if(isLine4(line, 'w','e','a','p')) section = WEAP; else if(isLine4(line, 'h','i','e','r')) section = HIER; else if(isLine4(line, 'c','a','r','s')) section = CARS; else if(isLine4(line, 'p','e','d','s')) section = PEDS; else if(isLine4(line, 'p','a','t','h')) section = PATH; else if(isLine4(line, '2','d','f','x')) section = TWODFX; }else if(isLine3(line, 'e','n','d')){ - section = section == MLO ? OBJS : NONE; + section = NONE; }else switch(section){ case OBJS: - if(isLine3(line, 's','t','a')) - mlo = LoadMLO(line); - else - LoadObject(line); - break; - case MLO: - LoadMLOInstance(mlo, line); + id = LoadObject(line); + if(id > maxID) maxID = id; + if(id < minID) minID = id; break; case TOBJ: - LoadTimeObject(line); + id = LoadTimeObject(line); + if(id > maxID) maxID = id; + if(id < minID) minID = id; + break; + case WEAP: + LoadWeaponObject(line); break; case HIER: LoadClumpObject(line); @@ -1027,17 +658,15 @@ CFileLoader::LoadObjectTypes(const char *filename) break; case PATH: if(pathIndex == -1){ - id = LoadPathHeader(line, pathTypeStr); - if(strcmp(pathTypeStr, "ped") == 0) - pathType = 1; - else if(strcmp(pathTypeStr, "car") == 0) - pathType = 0; + id = LoadPathHeader(line, pathType); pathIndex = 0; }else{ - if(pathType == 1) + if(pathType == 0) LoadPedPathNode(line, id, pathIndex); - else if(pathType == 0) - LoadCarPathNode(line, id, pathIndex); + else if (pathType == 1) + LoadCarPathNode(line, id, pathIndex, false); + else if (pathType == 2) + LoadCarPathNode(line, id, pathIndex, true); pathIndex++; if(pathIndex == 12) pathIndex = -1; @@ -1050,41 +679,30 @@ CFileLoader::LoadObjectTypes(const char *filename) } CFileMgr::CloseFile(fd); - for(id = 0; id < MODELINFOSIZE; id++){ + for(id = minID; id <= maxID; id++){ CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); - if(mi && mi->IsSimple()) - mi->SetupBigBuilding(); + if(mi && mi->IsBuilding()) + mi->SetupBigBuilding(minID, maxID); } } void SetModelInfoFlags(CSimpleModelInfo *mi, uint32 flags) { - mi->m_normalCull = !!(flags & 1); + mi->m_wetRoadReflection = !!(flags & 1); mi->m_noFade = !!(flags & 2); mi->m_drawLast = !!(flags & (4|8)); mi->m_additive = !!(flags & 8); mi->m_isSubway = !!(flags & 0x10); mi->m_ignoreLight = !!(flags & 0x20); mi->m_noZwrite = !!(flags & 0x40); -#ifdef EXTRA_MODEL_FLAGS - // same flag values as SA - mi->m_bIsTree = !!(flags & 0x2000); - mi->m_bIsDoubleSided = !!(flags & 0x200000); - // new value otherwise unused - mi->m_bCanBeIgnored = !!(flags & 0x10000); - -#ifdef HARDCODED_MODEL_FLAGS - // mobile sets these flags in CFileLoader::SetRelatedModelInfoCB, but that's stupid - if(MatchModelName(mi->GetModelName(), DoubleSidedNames)) mi->m_bIsDoubleSided = true; - if(MatchModelName(mi->GetModelName(), TreeNames)) mi->m_bIsTree = true; - if(MatchModelName(mi->GetModelName(), OptimizedNames)) mi->m_bCanBeIgnored = true; -#endif - -#endif + mi->m_noShadows = !!(flags & 0x80); + mi->m_ignoreDrawDist = !!(flags & 0x100); + mi->m_isCodeGlass = !!(flags & 0x200); + mi->m_isArtistGlass = !!(flags & 0x400); } -void +int CFileLoader::LoadObject(const char *line) { int id, numObjs; @@ -1095,7 +713,7 @@ CFileLoader::LoadObject(const char *line) CSimpleModelInfo *mi; if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4) - return; + return 0; // game returns return value switch(numObjs){ case 1: @@ -1127,60 +745,11 @@ CFileLoader::LoadObject(const char *line) mi->m_firstDamaged = damaged; mi->SetTexDictionary(txd); MatchModelString(model, id); -} - -int -CFileLoader::LoadMLO(const char *line) -{ - char smth[8]; - char name[24]; - int modelIndex; - float drawDist; - - sscanf(line, "%s %s %d %f", smth, name, &modelIndex, &drawDist); - CMloModelInfo *minfo = CModelInfo::AddMloModel(modelIndex); - minfo->SetModelName(name); - minfo->drawDist = drawDist; - int instId = CModelInfo::GetMloInstanceStore().allocPtr; - minfo->firstInstance = instId; - minfo->lastInstance = instId; - minfo->SetTexDictionary("generic"); - return modelIndex; -} - -void -CFileLoader::LoadMLOInstance(int id, const char *line) -{ - char name[24]; - RwV3d pos, scale, rot; - float angle; - int modelIndex; - - CMloModelInfo *minfo = (CMloModelInfo*)CModelInfo::GetModelInfo(id); - sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f", - &modelIndex, - name, - &pos.x, &pos.y, &pos.z, - &scale.x, &scale.y, &scale.z, - &rot.x, &rot.y, &rot.z, - &angle); - float rad = Acos(angle) * 2.0f; - CInstance *inst = CModelInfo::GetMloInstanceStore().Alloc(); - minfo->lastInstance++; - - RwMatrix *matrix = RwMatrixCreate(); - RwMatrixScale(matrix, &scale, rwCOMBINEREPLACE); - RwMatrixRotate(matrix, &rot, -RADTODEG(rad), rwCOMBINEPOSTCONCAT); - RwMatrixTranslate(matrix, &pos, rwCOMBINEPOSTCONCAT); - inst->GetMatrix() = CMatrix(matrix); - inst->GetMatrix().UpdateRW(); - - inst->m_modelIndex = modelIndex; - RwMatrixDestroy(matrix); + return id; } -void +int CFileLoader::LoadTimeObject(const char *line) { int id, numObjs; @@ -1192,7 +761,7 @@ CFileLoader::LoadTimeObject(const char *line) CTimeModelInfo *mi, *other; if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4) - return; + return 0; // game returns return value switch(numObjs){ case 1: @@ -1228,6 +797,29 @@ CFileLoader::LoadTimeObject(const char *line) if(other) other->SetOtherTimeModel(id); MatchModelString(model, id); + + return id; +} + +int +CFileLoader::LoadWeaponObject(const char *line) +{ + int id, numObjs; + char model[24], txd[24], animFile[16]; + float dist; + CWeaponModelInfo *mi; + + sscanf(line, "%d %s %s %s %d %f", &id, model, txd, animFile, &numObjs, &dist); + + mi = CModelInfo::AddWeaponModel(id); + mi->SetModelName(model); + mi->SetNumAtomics(1); + mi->m_lodDistances[0] = dist; + mi->SetTexDictionary(txd); + mi->SetAnimFile(animFile); + mi->SetColModel(&CTempColModels::ms_colModelWeapon); + MatchModelString(model, id); + return id; } void @@ -1250,21 +842,22 @@ CFileLoader::LoadVehicleObject(const char *line) { int id; char model[24], txd[24]; - char type[8], handlingId[16], gamename[32], vehclass[12]; + char type[8], handlingId[16], gamename[32], animFile[16], vehclass[12]; uint32 frequency, comprules; int32 level, misc; float wheelScale; CVehicleModelInfo *mi; char *p; - sscanf(line, "%d %s %s %s %s %s %s %d %d %x %d %f", + sscanf(line, "%d %s %s %s %s %s %s %s %d %d %x %d %f", &id, model, txd, - type, handlingId, gamename, vehclass, + type, handlingId, gamename, animFile, vehclass, &frequency, &level, &comprules, &misc, &wheelScale); mi = CModelInfo::AddVehicleModel(id); mi->SetModelName(model); mi->SetTexDictionary(txd); + mi->SetAnimFile(animFile); for(p = gamename; *p; p++) if(*p == '_') *p = ' '; strcpy(mi->m_gameName, gamename); @@ -1294,36 +887,34 @@ CFileLoader::LoadVehicleObject(const char *line) mi->m_handlingId = mod_HandlingManager.GetHandlingId(handlingId); - // Well this is kinda dumb.... - if(strcmp(vehclass, "poorfamily") == 0){ + if(strcmp(vehclass, "normal") == 0) + mi->m_vehicleClass = CCarCtrl::NORMAL; + else if(strcmp(vehclass, "poorfamily") == 0) mi->m_vehicleClass = CCarCtrl::POOR; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::POOR); - }else if(strcmp(vehclass, "richfamily") == 0){ + else if(strcmp(vehclass, "richfamily") == 0) mi->m_vehicleClass = CCarCtrl::RICH; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::RICH); - }else if(strcmp(vehclass, "executive") == 0){ + else if(strcmp(vehclass, "executive") == 0) mi->m_vehicleClass = CCarCtrl::EXEC; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::EXEC); - }else if(strcmp(vehclass, "worker") == 0){ + else if(strcmp(vehclass, "worker") == 0) mi->m_vehicleClass = CCarCtrl::WORKER; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::WORKER); - }else if(strcmp(vehclass, "special") == 0){ - mi->m_vehicleClass = CCarCtrl::SPECIAL; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::SPECIAL); - }else if(strcmp(vehclass, "big") == 0){ + else if(strcmp(vehclass, "big") == 0) mi->m_vehicleClass = CCarCtrl::BIG; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::BIG); - }else if(strcmp(vehclass, "taxi") == 0){ + else if(strcmp(vehclass, "taxi") == 0) mi->m_vehicleClass = CCarCtrl::TAXI; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::TAXI); + else if(strcmp(vehclass, "moped") == 0) + mi->m_vehicleClass = CCarCtrl::MOPED; + else if(strcmp(vehclass, "motorbike") == 0) + mi->m_vehicleClass = CCarCtrl::MOTORBIKE; + else if(strcmp(vehclass, "leisureboat") == 0) + mi->m_vehicleClass = CCarCtrl::LEISUREBOAT; + else if(strcmp(vehclass, "workerboat") == 0) + mi->m_vehicleClass = CCarCtrl::WORKERBOAT; + else if(strcmp(vehclass, "ignore") == 0) { + mi->m_vehicleClass = -1; + return; } + CCarCtrl::AddToCarArray(id, mi->m_vehicleClass); + mi->m_frequency = frequency; } void @@ -1331,67 +922,87 @@ CFileLoader::LoadPedObject(const char *line) { int id; char model[24], txd[24]; - char pedType[24], pedStats[24], animGroup[24]; + char pedType[24], pedStats[24], animGroup[24], animFile[16]; int carsCanDrive; CPedModelInfo *mi; int animGroupId; + int radio1, radio2; - if(sscanf(line, "%d %s %s %s %s %s %x", + sscanf(line, "%d %s %s %s %s %s %x %s %d %d", &id, model, txd, - pedType, pedStats, animGroup, &carsCanDrive) != 7) - return; + pedType, pedStats, animGroup, &carsCanDrive, + animFile, &radio1, &radio2); mi = CModelInfo::AddPedModel(id); mi->SetModelName(model); mi->SetTexDictionary(txd); + mi->SetAnimFile(animFile); mi->SetColModel(&CTempColModels::ms_colModelPed1); mi->m_pedType = CPedType::FindPedType(pedType); mi->m_pedStatType = CPedStats::GetPedStatType(pedStats); for(animGroupId = 0; animGroupId < NUM_ANIM_ASSOC_GROUPS; animGroupId++) if(strcmp(animGroup, CAnimManager::GetAnimGroupName((AssocGroupId)animGroupId)) == 0) break; + assert(animGroupId < NUM_ANIM_ASSOC_GROUPS); mi->m_animGroup = animGroupId; mi->m_carsCanDrive = carsCanDrive; - - // ??? - CModelInfo::GetModelInfo(MI_LOPOLYGUY)->SetColModel(&CTempColModels::ms_colModelPed1); + mi->radio1 = radio1; + mi->radio2 = radio2; } int -CFileLoader::LoadPathHeader(const char *line, char *type) +CFileLoader::LoadPathHeader(const char *line, int &type) { int id; char modelname[32]; - sscanf(line, "%s %d %s", type, &id, modelname); + sscanf(line, "%d %d %s", &type, &id, modelname); return id; } void CFileLoader::LoadPedPathNode(const char *line, int id, int node) { - int type, next, cross; - float x, y, z, width; - - sscanf(line, "%d %d %d %f %f %f %f", &type, &next, &cross, &x, &y, &z, &width); - ThePaths.StoreNodeInfoPed(id, node, type, next, x, y, z, 0, !!cross); + int type, next, cross, numLeft, numRight, speed, flags; + float x, y, z, width, spawnRate; + + if(sscanf(line, "%d %d %d %f %f %f %f %d %d %d %d %f", + &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight, + &speed, &flags, &spawnRate) != 12) + spawnRate = 1.0f; + + if(id == -1) + ThePaths.StoreDetachedNodeInfoPed(node, type, next, x, y, z, + width, !!cross, !!(flags&1), !!(flags&4), spawnRate*15.0f); + else + ThePaths.StoreNodeInfoPed(id, node, type, next, x, y, z, + width, !!cross, spawnRate*15.0f); } void -CFileLoader::LoadCarPathNode(const char *line, int id, int node) +CFileLoader::LoadCarPathNode(const char *line, int id, int node, bool waterPath) { - int type, next, cross, numLeft, numRight; - float x, y, z, width; - - sscanf(line, "%d %d %d %f %f %f %f %d %d", &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight); - ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight); + int type, next, cross, numLeft, numRight, speed, flags; + float x, y, z, width, spawnRate; + + if(sscanf(line, "%d %d %d %f %f %f %f %d %d %d %d %f", + &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight, + &speed, &flags, &spawnRate) != 12) + spawnRate = 1.0f; + + if(id == -1) + ThePaths.StoreDetachedNodeInfoCar(node, type, next, x, y, z, width, numLeft, numRight, + !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15, false); + else + ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight, + !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15); } void CFileLoader::Load2dEffect(const char *line) { - int id, r, g, b, a, type; + int id, r, g, b, a, type, ptype; float x, y, z; char corona[32], shadow[32]; int shadowIntens, lightType, roadReflection, flare, flags, probability; @@ -1468,6 +1079,18 @@ CFileLoader::Load2dEffect(const char *line) effect->attractor.probability = probability; #endif break; + case EFFECT_PED_ATTRACTOR: + sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f", + &id, &x, &y, &z, &r, &g, &b, &a, &type, + &ptype, + &effect->pedattr.queueDir.x, + &effect->pedattr.queueDir.y, + &effect->pedattr.queueDir.z, + &effect->pedattr.useDir.x, + &effect->pedattr.useDir.y, + &effect->pedattr.useDir.z); + effect->pedattr.type = ptype; + break; } CTxdStore::PopCurrentTxd(); @@ -1481,20 +1104,21 @@ CFileLoader::LoadScene(const char *filename) INST, ZONE, CULL, + OCCL, PICK, PATH, }; char *line; int fd; int section; - int pathIndex; - char pathTypeStr[20]; + int pathType, pathIndex; section = NONE; pathIndex = -1; debug("Creating objects from %s...\n", filename); fd = CFileMgr::OpenFile(filename, "rb"); + assert(fd > 0); for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){ if(*line == '\0' || *line == '#') continue; @@ -1505,6 +1129,7 @@ CFileLoader::LoadScene(const char *filename) else if(isLine4(line, 'c','u','l','l')) section = CULL; else if(isLine4(line, 'p','i','c','k')) section = PICK; else if(isLine4(line, 'p','a','t','h')) section = PATH; + else if(isLine4(line, 'o','c','c','l')) section = OCCL; }else if(isLine3(line, 'e','n','d')){ section = NONE; }else switch(section){ @@ -1517,19 +1142,24 @@ CFileLoader::LoadScene(const char *filename) case CULL: LoadCullZone(line); break; + case OCCL: + LoadOcclusionVolume(line); + break; case PICK: // unused LoadPickup(line); break; case PATH: - // unfinished in the game if(pathIndex == -1){ - LoadPathHeader(line, pathTypeStr); - strcmp(pathTypeStr, "ped"); - // type not set + LoadPathHeader(line, pathType); pathIndex = 0; }else{ - // nodes not loaded + if(pathType == 0) + LoadPedPathNode(line, -1, pathIndex); + else if (pathType == 1) + LoadCarPathNode(line, -1, pathIndex, false); + else if (pathType == 2) + LoadCarPathNode(line, -1, pathIndex, true); pathIndex++; if(pathIndex == 12) pathIndex = -1; @@ -1552,19 +1182,31 @@ CFileLoader::LoadObjectInstance(const char *line) CSimpleModelInfo *mi; RwMatrix *xform; CEntity *entity; - if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f", - &id, name, + float area; + + if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f %f", + &id, name, &area, &trans.x, &trans.y, &trans.z, &scale.x, &scale.y, &scale.z, - &axis.x, &axis.y, &axis.z, &angle) != 12) - return; + &axis.x, &axis.y, &axis.z, &angle) != 13){ + if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f", + &id, name, + &trans.x, &trans.y, &trans.z, + &scale.x, &scale.y, &scale.z, + &axis.x, &axis.y, &axis.z, &angle) != 12) + return; + area = 0; + } mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); if(mi == nil) return; assert(mi->IsSimple()); - angle = -RADTODEG(2.0f * acosf(angle)); + if(!CStreaming::IsObjectInCdImage(id)) + debug("Not in cdimage %s\n", mi->GetModelName()); + + angle = -RADTODEG(2.0f * Acos(angle)); xform = RwMatrixCreate(); RwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE); RwMatrixTranslate(xform, &trans, rwCOMBINEPOSTCONCAT); @@ -1578,7 +1220,8 @@ CFileLoader::LoadObjectInstance(const char *line) entity->SetModelIndexNoCreate(id); entity->GetMatrix() = CMatrix(xform); entity->m_level = CTheZones::GetLevelFromPosition(&entity->GetPosition()); - if(mi->IsSimple()){ + entity->m_area = area; + if(mi->IsBuilding()){ if(mi->m_isBigBuilding) entity->SetupBigBuilding(); if(mi->m_isSubway) @@ -1587,14 +1230,25 @@ CFileLoader::LoadObjectInstance(const char *line) if(mi->GetLargestLodDistance() < 2.0f) entity->bIsVisible = false; CWorld::Add(entity); + + CColModel *col = entity->GetColModel(); + if(col->numSpheres || col->numBoxes || col->numTriangles){ + if(col->level != 0) + CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect()); + }else + entity->bUsesCollision = false; + + if(entity->GetPosition().z + col->boundingBox.min.z < 6.0f) + entity->bUnderwater = true; }else{ entity = new CDummyObject; entity->SetModelIndexNoCreate(id); entity->GetMatrix() = CMatrix(xform); CWorld::Add(entity); - if(IsGlass(entity->GetModelIndex())) + if(IsGlass(entity->GetModelIndex()) && !mi->m_isArtistGlass) entity->bIsVisible = false; entity->m_level = CTheZones::GetLevelFromPosition(&entity->GetPosition()); + entity->m_area = area; } RwMatrixDestroy(xform); @@ -1640,53 +1294,21 @@ CFileLoader::LoadPickup(const char *line) } void -CFileLoader::LoadMapZones(const char *filename) +CFileLoader::LoadOcclusionVolume(const char *line) { - enum { - NONE, - INST, - ZONE, - CULL, - PICK, - PATH, - }; - char *line; - int fd; - int section; - - section = NONE; - debug("Creating zones from %s...\n", filename); - - fd = CFileMgr::OpenFile(filename, "rb"); - for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){ - if(*line == '\0' || *line == '#') - continue; - - if(section == NONE){ - if(isLine4(line, 'z','o','n','e')) section = ZONE; - }else if(isLine3(line, 'e','n','d')){ - section = NONE; - }else switch(section){ - case ZONE: { - char name[24]; - int type, level; - float minx, miny, minz; - float maxx, maxy, maxz; - if(sscanf(line, "%s %d %f %f %f %f %f %f %d", - name, &type, - &minx, &miny, &minz, - &maxx, &maxy, &maxz, - &level) == 9) - CTheZones::CreateMapZone(name, (eZoneType)type, minx, miny, minz, maxx, maxy, maxz, (eLevelName)level); - } - break; - } - } - CFileMgr::CloseFile(fd); + float x, y, z; + float width, length, height; + float angle; - debug("Finished loading IPL\n"); + sscanf(line, "%f %f %f %f %f %f %f", + &x, &y, &z, + &width, &length, &height, + &angle); + COcclusion::AddOne(x, y, z + height/2.0f, width, length, height, angle); } + +// unused void CFileLoader::ReloadPaths(const char *filename) { @@ -1697,10 +1319,10 @@ CFileLoader::ReloadPaths(const char *filename) char *line; int section = NONE; int id, pathType, pathIndex = -1; - char pathTypeStr[20]; debug("Reloading paths from %s...\n", filename); int fd = CFileMgr::OpenFile(filename, "r"); + assert(fd > 0); for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) { if (*line == '\0' || *line == '#') continue; @@ -1716,17 +1338,15 @@ CFileLoader::ReloadPaths(const char *filename) switch (section) { case PATH: if (pathIndex == -1) { - id = LoadPathHeader(line, pathTypeStr); - if (strcmp(pathTypeStr, "ped") == 0) - pathType = 1; - else if (strcmp(pathTypeStr, "car") == 0) - pathType = 0; + id = LoadPathHeader(line, pathType); pathIndex = 0; } else { - if (pathType == 1) + if(pathType == 0) LoadPedPathNode(line, id, pathIndex); - else if (pathType == 0) - LoadCarPathNode(line, id, pathIndex); + else if (pathType == 1) + LoadCarPathNode(line, id, pathIndex, false); + else if (pathType == 2) + LoadCarPathNode(line, id, pathIndex, true); pathIndex++; if (pathIndex == 12) pathIndex = -1; @@ -1756,6 +1376,7 @@ CFileLoader::ReloadObjectTypes(const char *filename) CFileMgr::ChangeDir("\\DATA\\MAPS\\"); int fd = CFileMgr::OpenFile(filename, "r"); + assert(fd > 0); CFileMgr::ChangeDir("\\"); for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) { if (*line == '\0' || *line == '#') @@ -1831,17 +1452,14 @@ CFileLoader::ReLoadScene(const char *filename) char *line; CFileMgr::ChangeDir("\\DATA\\"); int fd = CFileMgr::OpenFile(filename, "r"); + assert(fd > 0); CFileMgr::ChangeDir("\\"); for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) { if (*line == '#') continue; -#ifdef FIX_BUGS if (strncmp(line, "EXIT", 4) == 0) -#else - if (strncmp(line, "EXIT", 9) == 0) -#endif break; if (strncmp(line, "IDE", 3) == 0) { diff --git a/src/core/FileLoader.h b/src/core/FileLoader.h index 87b8fe61..077e7bdd 100644 --- a/src/core/FileLoader.h +++ b/src/core/FileLoader.h @@ -5,10 +5,11 @@ class CFileLoader static char ms_line[256]; public: static void LoadLevel(const char *filename); - static void LoadCollisionFromDatFile(int currlevel); static char *LoadLine(int fd); static RwTexDictionary *LoadTexDictionary(const char *filename); - static void LoadCollisionFile(const char *filename); + static void LoadCollisionFile(const char *filename, uint8 colSlot); + static bool LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot); + static bool LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot); static void LoadCollisionModel(uint8 *buf, struct CColModel &model, char *name); static void LoadModelFile(const char *filename); static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data); @@ -22,16 +23,15 @@ public: static void AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src); static void LoadObjectTypes(const char *filename); - static void LoadObject(const char *line); - static int LoadMLO(const char *line); - static void LoadMLOInstance(int id, const char *line); - static void LoadTimeObject(const char *line); + static int LoadObject(const char *line); + static int LoadTimeObject(const char *line); + static int LoadWeaponObject(const char *line); static void LoadClumpObject(const char *line); static void LoadVehicleObject(const char *line); static void LoadPedObject(const char *line); - static int LoadPathHeader(const char *line, char *type); + static int LoadPathHeader(const char *line, int &type); static void LoadPedPathNode(const char *line, int id, int node); - static void LoadCarPathNode(const char *line, int id, int node); + static void LoadCarPathNode(const char *line, int id, int node, bool waterPath); static void Load2dEffect(const char *line); static void LoadScene(const char *filename); @@ -39,8 +39,7 @@ public: static void LoadZone(const char *line); static void LoadCullZone(const char *line); static void LoadPickup(const char *line); - - static void LoadMapZones(const char *filename); + static void LoadOcclusionVolume(const char *line); static void ReloadPaths(const char *filename); static void ReloadObjectTypes(const char *filename); diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index 8b184622..57315b15 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -15,6 +15,8 @@ #include "DamageManager.h" #include "Ped.h" #include "Fire.h" +#include "GameLogic.h" +#include "CarAI.h" CFireManager gFireManager; @@ -25,14 +27,13 @@ CFire::CFire() m_bPropagationFlag = true; m_bAudioSet = true; m_vecPos = CVector(0.0f, 0.0f, 0.0f); - m_pEntity = nil; - m_pSource = nil; - m_nFiremenPuttingOut = 0; m_nExtinguishTime = 0; m_nStartTime = 0; - field_20 = 1; - m_nNextTimeToAddFlames = 0; + m_pEntity = nil; + m_pSource = nil; m_fStrength = 0.8f; + m_fWaterExtinguishCountdown = 1.0f; + m_bExtinguishedWithWater = false; } CFire::~CFire() {} @@ -51,6 +52,8 @@ CFire::ProcessFire(void) CPed *ped = (CPed *)m_pEntity; CVehicle *veh = (CVehicle*)m_pEntity; + m_fWaterExtinguishCountdown = Min(1.0f, 0.002f * CTimer::GetTimeStep() + m_fWaterExtinguishCountdown); + if (m_pEntity) { m_vecPos = m_pEntity->GetPosition(); @@ -59,6 +62,12 @@ CFire::ProcessFire(void) Extinguish(); return; } +#if defined GTAVC_JP_PATCH && !defined FIX_BUGS + if (m_pEntity == CGameLogic::pShortCutTaxi && CGameLogic::ShortCutState == CGameLogic::SHORTCUT_TRANSITION) { + Extinguish(); + return; + } +#endif if (ped->m_nMoveState != PEDMOVE_RUN) m_vecPos.z -= 1.0f; if (ped->bInVehicle && ped->m_pMyVehicle) { @@ -84,6 +93,12 @@ CFire::ProcessFire(void) Extinguish(); return; } +#ifdef FIX_BUGS + if (m_pEntity == CGameLogic::pShortCutTaxi && CGameLogic::ShortCutState == CGameLogic::SHORTCUT_TRANSITION) { + Extinguish(); + return; + } +#endif if (!m_bIsScriptFire) { fDamageVehicle = 1.2f * CTimer::GetTimeStep(); veh->InflictDamage((CVehicle *)m_pSource, WEAPONTYPE_FLAMETHROWER, fDamageVehicle); @@ -92,7 +107,7 @@ CFire::ProcessFire(void) } if (!FindPlayerVehicle() && #ifdef FIX_BUGS - FindPlayerPed() && + FindPlayerPed() && #endif !FindPlayerPed()->m_pFire && !(FindPlayerPed()->bFireProof) && ((FindPlayerPed()->GetPosition() - m_vecPos).MagnitudeSqr() < 2.0f)) { @@ -100,7 +115,7 @@ CFire::ProcessFire(void) gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1); } if (CTimer::GetTimeInMilliseconds() > m_nNextTimeToAddFlames) { - m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + 80; + m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + (m_fWaterExtinguishCountdown < 0.3f ? 400 : (m_fWaterExtinguishCountdown < 0.7f ? 200 : 80)); firePos = m_vecPos; if (veh && veh->IsVehicle() && veh->IsCar()) { @@ -138,7 +153,7 @@ CFire::ProcessFire(void) fGreen = nRandNumber / 128.f; fRed = nRandNumber / 128.f; - CPointLights::AddLight(CPointLights::LIGHT_POINT, m_vecPos, CVector(0.0f, 0.0f, 0.0f), 12.0f, fRed, fGreen, 0, 0, 0); + CPointLights::AddLight(CPointLights::LIGHT_POINT, m_vecPos, CVector(0.0f, 0.0f, 0.0f), 12.0f, fRed, fGreen, 0.0f, 0, 0); } else { Extinguish(); } @@ -160,11 +175,23 @@ CFire::Extinguish(void) m_nExtinguishTime = 0; m_bIsOngoing = false; + m_bExtinguishedWithWater = false; if (m_pEntity) { if (m_pEntity->IsPed()) { - ((CPed *)m_pEntity)->RestorePreviousState(); - ((CPed *)m_pEntity)->m_pFire = nil; + CPed *ped = (CPed*)m_pEntity; + if (ped->CanSetPedState()) { + if (ped->m_nPedState != PED_DRIVING && ped->m_nPedState != PED_FALL) { + if (ped->IsPlayer()) { + ped->SetIdle(); + } else { + ped->m_nLastPedState = PED_NONE; + ped->SetWanderPath(0); + ped->SetWaitState(WAITSTATE_FINISH_FLEE, 0); + } + } + } + ped->m_pFire = nil; } else if (m_pEntity->IsVehicle()) { ((CVehicle *)m_pEntity)->m_pCarFire = nil; } @@ -174,7 +201,7 @@ CFire::Extinguish(void) } void -CFireManager::StartFire(CVector pos, float size, bool propagation) +CFireManager::StartFire(CVector pos, float size, uint8 propagation) { CFire *fire = GetNextFreeFire(); @@ -191,11 +218,12 @@ CFireManager::StartFire(CVector pos, float size, bool propagation) fire->m_nNextTimeToAddFlames = 0; fire->ReportThisFire(); fire->m_fStrength = size; + fire->m_bExtinguishedWithWater = false; } } CFire * -CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation) +CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation) { CPed *ped = (CPed *)entityOnFire; CVehicle *veh = (CVehicle *)entityOnFire; @@ -224,6 +252,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength ped->SetFlee(pos, 10000); ped->m_fleeFrom = nil; } + ped->m_fleeTimer = CTimer::GetTimeInMilliseconds() + 10000; ped->bDrawLast = false; ped->SetMoveState(PEDMOVE_SPRINT); ped->SetMoveAnim(); @@ -241,6 +270,9 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength } else { if (entityOnFire->IsVehicle()) { veh->m_pCarFire = fire; + if (CModelInfo::IsBikeModel(veh->GetModelIndex()) || CModelInfo::IsCarModel(veh->GetModelIndex())) + CCarAI::TellOccupantsToFleeCar(veh); + if (fleeFrom) { CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE, entityOnFire, (CPed *)fleeFrom, 10000); @@ -249,6 +281,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength } fire->m_bIsOngoing = true; + fire->m_bExtinguishedWithWater = false; fire->m_bIsScriptFire = false; fire->m_vecPos = entityOnFire->GetPosition(); @@ -287,26 +320,23 @@ CFireManager::Update(void) CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance) { - for (int i = 0; i < MAX_FIREMEN_ATTENDING; i++) { - int fireId = -1; - float minDistance = 999999; - for (int j = 0; j < NUM_FIRES; j++) { - if (!m_aFires[j].m_bIsOngoing) - continue; - if (m_aFires[j].m_bIsScriptFire) - continue; - if (m_aFires[j].m_nFiremenPuttingOut != i) - continue; - float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); - if (distance < minDistance) { - minDistance = distance; - fireId = j; - } + int fireId = -1; + float minDistance = 999999; + for (int j = 0; j < NUM_FIRES; j++) { + if (!m_aFires[j].m_bIsOngoing) + continue; + if (m_aFires[j].m_bIsScriptFire) + continue; + float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); + if (distance < minDistance) { + minDistance = distance; + fireId = j; } - *pDistance = minDistance; - if (fireId != -1) - return &m_aFires[fireId]; } + *pDistance = minDistance; + if (fireId != -1) + return &m_aFires[fireId]; + return nil; } @@ -359,8 +389,36 @@ CFireManager::ExtinguishPoint(CVector point, float range) } } +bool +CFireManager::ExtinguishPointWithWater(CVector point, float range) +{ + int i; + for (i = 0; i < NUM_FIRES;) { + if (m_aFires[i].m_bIsOngoing && (point - m_aFires[i].m_vecPos).MagnitudeSqr() < sq(range)) { + break; + } + if (++i >= NUM_FIRES) + return false; + } + + CFire *fireToExtinguish = &m_aFires[i]; + fireToExtinguish->m_fWaterExtinguishCountdown -= 0.012f * CTimer::GetTimeStep(); + CVector steamPos = fireToExtinguish->m_vecPos + + CVector((CGeneral::GetRandomNumber() - 128) * 3.1f / 200.f, + (CGeneral::GetRandomNumber() - 128) * 3.1f / 200.f, + CGeneral::GetRandomNumber() / 200.f); + + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.2f), nil, 0.5f); + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.1f), nil, 0.8f); + fireToExtinguish->m_bExtinguishedWithWater = true; + if (fireToExtinguish->m_fWaterExtinguishCountdown < 0.0f ) + fireToExtinguish->Extinguish(); + + return true; +} + int32 -CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation) +CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation) { CFire *fire; CPed *ped = (CPed *)target; @@ -387,12 +445,15 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt fire->m_vecPos = pos; fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400; fire->m_pEntity = target; + fire->m_bExtinguishedWithWater = false; if (target) target->RegisterReference(&fire->m_pEntity); fire->m_pSource = nil; fire->m_nNextTimeToAddFlames = 0; fire->m_fStrength = strength; + fire->m_fWaterExtinguishCountdown = 1.0f; + if (target) { if (target->IsPed()) { ped->m_pFire = fire; @@ -420,8 +481,7 @@ CFireManager::RemoveAllScriptFires(void) { for (int i = 0; i < NUM_FIRES; i++) { if (m_aFires[i].m_bIsScriptFire) { - m_aFires[i].Extinguish(); - m_aFires[i].m_bIsScriptFire = false; + RemoveScriptFire(i); } } } diff --git a/src/core/Fire.h b/src/core/Fire.h index 85e53f61..8126f830 100644 --- a/src/core/Fire.h +++ b/src/core/Fire.h @@ -14,10 +14,10 @@ public: CEntity *m_pSource; uint32 m_nExtinguishTime; uint32 m_nStartTime; - int32 field_20; uint32 m_nNextTimeToAddFlames; - uint32 m_nFiremenPuttingOut; float m_fStrength; + float m_fWaterExtinguishCountdown; + bool m_bExtinguishedWithWater; CFire(); ~CFire(); @@ -34,15 +34,17 @@ class CFireManager public: uint32 m_nTotalFires; CFire m_aFires[NUM_FIRES]; - void StartFire(CVector pos, float size, bool propagation); - CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation); + + void StartFire(CVector pos, float size, uint8 propagation); + CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation); void Update(void); CFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange); CFire *FindNearestFire(CVector vecPos, float *pDistance); CFire *GetNextFreeFire(void); uint32 GetTotalActiveFires() const; void ExtinguishPoint(CVector point, float range); - int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation); + bool ExtinguishPointWithWater(CVector point, float range); + int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation); bool IsScriptFireExtinguish(int16 index); void RemoveAllScriptFires(void); void RemoveScriptFire(int16 index); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index ecb893b4..64e27a32 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -33,47 +33,35 @@ #include "Stats.h" #include "Messages.h" #include "FileLoader.h" -#include "frontendoption.h" +#include "User.h" +#include "sampman.h" +// Similar story to Hud.cpp: // Game has colors inlined in code. // For easier modification we collect them here: -const CRGBA LABEL_COLOR(235, 170, 50, 255); -const CRGBA SELECTION_HIGHLIGHTBG_COLOR(100, 200, 50, 50); +const CRGBA LABEL_COLOR(255, 150, 225, 255); +const CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255); const CRGBA MENUOPTION_COLOR = LABEL_COLOR; -const CRGBA SELECTEDMENUOPTION_COLOR(255, 217, 106, 255); -const CRGBA HEADER_COLOR(0, 0, 0, 255); -const CRGBA DARKMENUOPTION_COLOR(155, 117, 6, 255); -const CRGBA SLIDERON_COLOR = SELECTEDMENUOPTION_COLOR; -const CRGBA SLIDEROFF_COLOR(185, 120, 0, 255); -const CRGBA LIST_BACKGROUND_COLOR(200, 200, 50, 50); +const CRGBA SELECTEDMENUOPTION_COLOR = LABEL_COLOR; +const CRGBA HEADER_COLOR = LABEL_COLOR; +const CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); +const CRGBA SLIDERON_COLOR(97, 194, 247, 255); +const CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); +const CRGBA LIST_BACKGROUND_COLOR(49, 101, 148, 130); const CRGBA LIST_OPTION_COLOR(155, 155, 155, 255); -const CRGBA INACTIVE_RADIO_COLOR(225, 0, 0, 170); +const CRGBA RADIO_SELECTOR_COLOR = SLIDEROFF_COLOR; +const CRGBA INACTIVE_RADIO_COLOR(100, 100, 255, 100); const CRGBA SCROLLBAR_COLOR = LABEL_COLOR; -const CRGBA CONTSETUP_HIGHLIGHTBG_COLOR(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, 210); -const CRGBA CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, 150); -// This is PS2 menu leftover, and variable name is original. They forgot it here and used in PrintBriefs once (but didn't use the output) -#if defined(FIX_BUGS) && !defined(PS2_LIKE_MENU) -const CRGBA TEXT_COLOR = LABEL_COLOR; -#else -const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); // PS2 option color -#endif +#define MAP_MIN_SIZE 162.f +#define MAP_SIZE_TO_ALLOW_X_MOVE 297.f -#define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 #define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result #define SCROLLABLE_PAGES -#define RED_DELETE_BACKGROUND -#ifdef SCROLLABLE_STATS_PAGE -#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS) -#else -#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS) -#endif +#define hasNativeList(screen) (screen == MENUPAGE_SKIN_SELECT || screen == MENUPAGE_KEYBOARD_CONTROLS) -#define hasNativeList(screen) (screen == MENUPAGE_MULTIPLAYER_FIND_GAME || screen == MENUPAGE_SKIN_SELECT \ - || screen == MENUPAGE_KEYBOARD_CONTROLS) - #ifdef SCROLLABLE_PAGES #define MAX_VISIBLE_OPTION 12 #define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION) @@ -95,9 +83,12 @@ int GetOptionCount(int screen) m_nScrollbarTopMargin = 0; \ } \ } + +#define MINUS_SCROLL_OFFSET - scrollOffset #else #define MAX_VISIBLE_OPTION_ON_SCREEN MAX_VISIBLE_LIST_ROW #define SETUP_SCROLLING(screen) +#define MINUS_SCROLL_OFFSET #endif #ifdef TRIANGLE_BACK_BUTTON @@ -111,169 +102,67 @@ int GetOptionCount(int screen) #define GetBackJustDown GetSquareJustDown #endif -#ifdef MENU_MAP -bool CMenuManager::bMenuMapActive = false; -float CMenuManager::fMapSize; -float CMenuManager::fMapCenterY; -float CMenuManager::fMapCenterX; -#endif - -#ifdef PS2_LIKE_MENU -BottomBarOption bbNames[8]; -int bbTabCount = 0; -bool bottomBarActive = false; -int pendingScreen = -1; -int pendingOption = -1; -int curBottomBarOption = -1; -int hoveredBottomBarOption = -1; +#ifdef MAP_ENHANCEMENTS +CVector2D mapCrosshair; #endif #ifdef CUTSCENE_BORDERS_SWITCH bool CMenuManager::m_PrefsCutsceneBorders = true; #endif -#ifdef MULTISAMPLING -int8 CMenuManager::m_nPrefsMSAALevel = 0; -int8 CMenuManager::m_nDisplayMSAALevel = 0; -#endif - -#ifdef NO_ISLAND_LOADING -int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW; -#endif - -#ifdef GAMEPAD_MENU -int8 CMenuManager::m_PrefsControllerType = CONTROLLER_XBOXONE; -#endif - -int32 CMenuManager::OS_Language = LANG_ENGLISH; -int8 CMenuManager::m_PrefsUseVibration; -int8 CMenuManager::m_DisplayControllerOnFoot; -int8 CMenuManager::m_PrefsVsync = 1; -int8 CMenuManager::m_PrefsVsyncDisp = 1; -int8 CMenuManager::m_PrefsFrameLimiter = 1; -int8 CMenuManager::m_PrefsShowSubtitles = 1; -int8 CMenuManager::m_PrefsSpeakers; -int32 CMenuManager::m_ControlMethod; -int8 CMenuManager::m_PrefsDMA = 1; -int32 CMenuManager::m_PrefsLanguage; -uint8 CMenuManager::m_PrefsStereoMono; // unused except restore settings - -bool CMenuManager::m_PrefsAllowNastyGame = true; -bool CMenuManager::m_bStartUpFrontEndRequested; -bool CMenuManager::m_bShutDownFrontEndRequested; - -#ifdef ASPECT_RATIO_SCALE -int8 CMenuManager::m_PrefsUseWideScreen = AR_AUTO; -#else -int8 CMenuManager::m_PrefsUseWideScreen; -#endif - -int8 CMenuManager::m_PrefsRadioStation; -int32 CMenuManager::m_PrefsBrightness = 256; -float CMenuManager::m_PrefsLOD = CRenderer::ms_lodDistScale; -int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; -int32 CMenuManager::m_PrefsMusicVolume = 102; -int32 CMenuManager::m_PrefsSfxVolume = 102; - -char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME; - -int32 CMenuManager::m_KeyPressedCode = -1; - -float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; -float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; - -bool holdingScrollBar; // *(bool*)0x628D59; // not original name -int32 CMenuManager::m_SelectedMap; -int32 CMenuManager::m_SelectedGameType; - -// Used in a hidden menu -uint8 CMenuManager::m_PrefsPlayerRed = 255; -uint8 CMenuManager::m_PrefsPlayerGreen = 128; -uint8 CMenuManager::m_PrefsPlayerBlue; // why?? +bool holdingScrollBar; // *(bool*)0x7039B9; // not original name CMenuManager FrontEndMenuManager; +MenuTrapezoid menuBg(CGeneral::GetRandomNumber() % 40 + 65, CGeneral::GetRandomNumber() % 40 + 21, + CGeneral::GetRandomNumber() % 40 + 568, CGeneral::GetRandomNumber() % 40 + 44, + CGeneral::GetRandomNumber() % 40 + 36, CGeneral::GetRandomNumber() % 40 + 352, + CGeneral::GetRandomNumber() % 40 + 593, CGeneral::GetRandomNumber() % 40 + 312); -uint32 TimeToStopPadShaking; -char *pEditString; -int32 *pControlEdit; -bool DisplayComboButtonErrMsg; -int32 MouseButtonJustClicked; -int32 JoyButtonJustClicked; -//int32 *pControlTemp = 0; +MenuTrapezoid menuOptionHighlight(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); #ifndef MASTER bool CMenuManager::m_PrefsMarketing = false; bool CMenuManager::m_PrefsDisableTutorials = false; #endif // !MASTER -const char* FrontendFilenames[][2] = { - {"fe2_mainpanel_ul", "" }, - {"fe2_mainpanel_ur", "" }, - {"fe2_mainpanel_dl", "" }, - {"fe2_mainpanel_dr", "" }, - {"fe2_mainpanel_dr2", "" }, - {"fe2_tabactive", "" }, - {"fe_iconbrief", "" }, - {"fe_iconstats", "" }, - {"fe_iconcontrols", "" }, - {"fe_iconsave", "" }, - {"fe_iconaudio", "" }, - {"fe_icondisplay", "" }, - {"fe_iconlanguage", "" }, - {"fe_controller", "" }, - {"fe_controllersh", "" }, - {"fe_arrows1", "" }, - {"fe_arrows2", "" }, - {"fe_arrows3", "" }, - {"fe_arrows4", "" }, - {"fe_radio1", "" }, - {"fe_radio2", "" }, - {"fe_radio3", "" }, - {"fe_radio4", "" }, - {"fe_radio5", "" }, - {"fe_radio6", "" }, - {"fe_radio7", "" }, - {"fe_radio8", "" }, - {"fe_radio9", "" }, -}; +#ifdef GAMEPAD_MENU +uint32 TimeToStopPadShaking; +#endif -#ifdef MENU_MAP -const char* MapFilenames[][2] = { +const char* FrontendFilenames[][2] = { + {"background", ""}, + {"vc_logo", "vc_logom"}, + {"mouse", "mousea"}, + {"mapTop01", "mapTop01A"}, + {"mapTop02", "mapTop02A"}, + {"mapTop03", "mapTop03A"}, {"mapMid01", "mapMid01A"}, {"mapMid02", "mapMid02A"}, {"mapMid03", "mapMid03A"}, {"mapBot01", "mapBot01A"}, {"mapBot02", "mapBot02A"}, {"mapBot03", "mapBot03A"}, - {"mapTop01", "mapTop01A"}, - {"mapTop02", "mapTop02A"}, - {"mapTop03", "mapTop03A"}, -}; -CSprite2d CMenuManager::m_aMapSprites[NUM_MAP_SPRITES]; -#endif - -// 0x5F3344 -const char* MenuFilenames[][2] = { - {"connection24", ""}, - {"findgame24", ""}, - {"hostgame24", ""}, - {"mainmenu24", ""}, - {"Playersetup24", ""}, - {"singleplayer24", ""}, - {"multiplayer24", ""}, - {"dmalogo128", "dmalogo128m"}, - {"gtaLogo128", "gtaLogo128"}, - {"rockstarLogo128", "rockstarlogo128m"}, - {"gamespy256", "gamespy256a"}, - {"mouse", "mousetimera"}, - {"mousetimer", "mousetimera"}, - {"mp3logo", "mp3logoA"}, - {"downOFF", "buttonA"}, - {"downON", "buttonA"}, + {"wildstyle", "wildstyleA"}, + {"flash", "flashA"}, + {"kchat", "kchatA"}, + {"fever", "feverA"}, + {"vrock", "vrockA"}, + {"vcpr", "vcprA"}, + {"espantoso", "espantosoA"}, + {"emotion", "emotionA"}, + {"wave103", "wave103A"}, + {"mp3", "mp3A"}, + {"downOff", "buttonA"}, + {"downOn", "buttonA"}, {"upOff", "buttonA"}, - {"upON", "buttonA"}, - {"gta3logo256", "gta3logo256m"}, - { nil, nil } + {"upOn", "buttonA"}, +#ifdef GAMEPAD_MENU + {"fe_controller", "" }, + {"fe_arrows1", "" }, + {"fe_arrows2", "" }, + {"fe_arrows3", "" }, + {"fe_arrows4", "" }, +#endif }; #define MENU_X_RIGHT_ALIGNED(x) SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - (x)) @@ -289,31 +178,24 @@ const char* MenuFilenames[][2] = { #define MENU_Y(y) StretchY(y) #endif -#ifdef PS2_LIKE_MENU -#define PAGE_NAME_X MENU_X_RIGHT_ALIGNED -#else -#define PAGE_NAME_X SCREEN_SCALE_FROM_RIGHT +#ifdef XBOX_MESSAGE_SCREEN +bool CMenuManager::m_bDialogOpen = false; +uint32 CMenuManager::m_nDialogHideTimer = 0; +uint32 CMenuManager::m_nDialogHideTimerPauseMode = 0; +bool CMenuManager::m_bSaveWasSuccessful = false; +wchar* CMenuManager::m_pDialogText = nil; #endif -// Seperate func. in VC -#define ChangeScreen(screen, option, updateDelay, clearAlpha) \ - do { \ - m_nPrevScreen = m_nCurrScreen; \ - int newOpt = option; \ - SETUP_SCROLLING(screen) \ - m_nCurrScreen = screen; \ - m_nCurrOption = newOpt; \ - if(updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ - if(clearAlpha) \ - m_nMenuFadeAlpha = 0; \ - } while(0) - #define SET_FONT_FOR_MENU_HEADER \ - CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \ CFont::SetRightJustifyOn(); \ + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); \ CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetDropShadowPosition(0); + +#define SET_FONT_FOR_LIST_ITEM \ + CFont::SetRightJustifyOff(); \ + CFont::SetScale(MENU_X(LISTITEM_X_SCALE), MENU_Y(LISTITEM_Y_SCALE)); \ + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); #define RESET_FONT_FOR_NEW_PAGE \ CFont::SetBackgroundOff(); \ @@ -324,47 +206,35 @@ const char* MenuFilenames[][2] = { CFont::SetRightJustifyOff(); \ CFont::SetBackGroundOnlyTextOn(); \ CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); \ - CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); - -#define SET_FONT_FOR_HELPER_TEXT \ - CFont::SetCentreOn(); \ - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); \ - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - -#define SET_FONT_FOR_LIST_ITEM \ - CFont::SetRightJustifyOff(); \ - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); \ - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN)); // value must be between 0.0-1.0 -#define ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ +#define ProcessSlider(value, origY, increaseAction, decreaseAction, hoverEndX, onlyWhenHoveringRow) \ do { \ - lastActiveBarX = DisplaySlider(MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ + float y = origY MINUS_SCROLL_OFFSET; \ + lastActiveBarX = DisplaySlider(MENU_X_LEFT_ALIGNED(MENUSLIDER_X), MENU_Y(y), MENU_Y(MENUSLIDER_SMALLEST_BAR), MENU_Y(MENUSLIDER_BIGGEST_BAR), MENU_X(MENUSLIDER_UNK), value, MENU_X(3.0f)); \ if (i != m_nCurrOption || !itemsAreSelectable) \ break; \ \ - if (CheckHover(hoverStartX, lastActiveBarX - MENU_X(10.0f), MENU_Y(nextYToUse), MENU_Y(28.0f + nextYToUse))) \ + if (CheckHover(0, lastActiveBarX - MENU_X(3.0f), MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) { \ m_nHoverOption = decreaseAction; \ - \ - if (!CheckHover(MENU_X(10.0f) + lastActiveBarX, hoverEndX, MENU_Y(nextYToUse), MENU_Y(28.0f + nextYToUse))) \ break; \ - \ + } \ + if (!CheckHover(MENU_X(3.0f) + lastActiveBarX, hoverEndX, MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) { \ + m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ + break; \ + } \ m_nHoverOption = increaseAction; \ - if (m_nMousePosX < MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth)) \ + if (m_nMousePosX < MENU_X_LEFT_ALIGNED(MENUSLIDER_X)) \ + m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ + \ + if (onlyWhenHoveringRow && (m_nMousePosY < MENU_Y(y) || m_nMousePosY > MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) \ m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ } while(0) -#define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \ - do { \ - sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : \ - CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, INACTIVE_RADIO_COLOR.a)); \ - if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ - m_nHoverOption = hoverOpt; \ - } while (0) - // --- Functions not in the game/inlined starts -void +inline void CMenuManager::ScrollUpListByOne() { if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { @@ -378,7 +248,7 @@ CMenuManager::ScrollUpListByOne() } } -void +inline void CMenuManager::ScrollDownListByOne() { if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1) { @@ -394,13 +264,13 @@ CMenuManager::ScrollDownListByOne() } } -void +inline void CMenuManager::PageUpList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) { if (m_nFirstVisibleRowOnList > 0) { if(playSoundOnSuccess) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_OPTION_ON_SCREEN); m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1); @@ -412,13 +282,13 @@ CMenuManager::PageUpList(bool playSoundOnSuccess) } } -void +inline void CMenuManager::PageDownList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) { if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) { if(playSoundOnSuccess) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN, m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN); m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList); @@ -431,6 +301,7 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) } #ifdef CUSTOM_FRONTEND_OPTIONS +#define PLUS_LINE_HEIGHT_ON_SCREEN + (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->lineHeight : MENU_DEFAULT_LINE_HEIGHT) bool ScreenHasOption(int screen, const char* gxtKey) { for (int i = 0; i < NUM_MENUROWS; i++) { @@ -439,30 +310,21 @@ bool ScreenHasOption(int screen, const char* gxtKey) } return false; } -#endif -void -CMenuManager::ThingsToDoBeforeGoingBack() +inline void +CMenuManager::ThingsToDoBeforeLeavingPage() { if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); -#ifdef CUSTOM_FRONTEND_OPTIONS - } else if (ScreenHasOption(m_nCurrScreen, "FEA_3DH")) { -#else + } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { -#endif - if (m_nPrefsAudio3DProviderIndex != -1) + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); -#ifdef TIDY_UP_PBP + DMAudio.StopFrontEndTrack(); OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); -#endif -#ifdef CUSTOM_FRONTEND_OPTIONS } else if (ScreenHasOption(m_nCurrScreen, "FED_RES")) { -#else - } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { -#endif m_nDisplayVideoMode = m_nPrefsVideoMode; } @@ -470,10 +332,6 @@ CMenuManager::ThingsToDoBeforeGoingBack() CPlayerSkin::EndFrontendSkinEdit(); } - if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { - m_nTotalListRow = 0; - } - #ifdef SCROLLABLE_PAGES if (SCREEN_HAS_AUTO_SCROLLBAR) { m_nSelectedListRow = 0; @@ -482,7 +340,6 @@ CMenuManager::ThingsToDoBeforeGoingBack() } #endif -#ifdef CUSTOM_FRONTEND_OPTIONS CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; if (option.m_Action == MENUACTION_CFO_DYNAMIC) @@ -495,16 +352,13 @@ CMenuManager::ThingsToDoBeforeGoingBack() if (aScreens[m_nCurrScreen].returnPrevPageFunc) { aScreens[m_nCurrScreen].returnPrevPageFunc(); } -#endif } -int8 +inline int8 CMenuManager::GetPreviousPageOption() { -#ifndef CUSTOM_FRONTEND_OPTIONS - return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; -#else - int8 prevPage = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; + int8 prevPage = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage : + (m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_OPTIONS || m_nCurrScreen == MENUPAGE_EXIT ? MENUPAGE_START_MENU : aScreens[m_nCurrScreen].m_PreviousPage); if (prevPage == -1) // Game also does same return 0; @@ -521,271 +375,234 @@ CMenuManager::GetPreviousPageOption() // This shouldn't happen return 0; -#endif } -void -CMenuManager::ProcessList(bool &goBack, bool &optionSelected) +#else +#define PLUS_LINE_HEIGHT_ON_SCREEN + MENU_DEFAULT_LINE_HEIGHT +inline void +CMenuManager::ThingsToDoBeforeLeavingPage() { - if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { - m_nTotalListRow = m_nSkinsTotal; - } - if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - // GetNumOptionsCntrlConfigScreens would have been a better choice - m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25; - if (m_nSelectedListRow > m_nTotalListRow) - m_nSelectedListRow = m_nTotalListRow - 1; + switch (m_nCurrScreen) { + case MENUPAGE_SOUND_SETTINGS: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); + + DMAudio.StopFrontEndTrack(); + OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); + break; + case MENUPAGE_DISPLAY_SETTINGS: + m_nDisplayVideoMode = m_nPrefsVideoMode; + break; + case MENUPAGE_SKIN_SELECT: + if (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + + CPlayerSkin::EndFrontendSkinEdit(); + break; } -#ifndef TIDY_UP_PBP - if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - m_bShowMouse = 0; - optionSelected = true; +#ifdef SCROLLABLE_PAGES + if (SCREEN_HAS_AUTO_SCROLLBAR) { + m_nSelectedListRow = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0; } #endif - if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) { - if (m_nCurrExLayer == HOVEROPTION_LIST) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - m_bKeyChangeNotProcessed = true; - pControlEdit = &m_KeyPressedCode; - } - } else { - field_535 = false; - } +} - static uint32 lastTimeClickedScrollButton = 0; +inline int8 +CMenuManager::GetPreviousPageOption() +{ + return (!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry : + (m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry)))); +} +#endif - if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) { - m_bPressedPgUpOnList = false; - m_bPressedPgDnOnList = false; - m_bPressedUpOnList = false; - m_bPressedDownOnList = false; - m_bPressedScrollButton = false; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - } +// ------ Functions not in the game/inlined ends - if (CPad::GetPad(0)->GetTabJustDown()) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - m_bShowMouse = false; - switch (m_nCurrExLayer) { - case HOVEROPTION_BACK: - default: - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case HOVEROPTION_LIST: - m_nCurrExLayer = HOVEROPTION_USESKIN; - break; - case HOVEROPTION_USESKIN: - m_nCurrExLayer = HOVEROPTION_BACK; - } - if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { - m_nCurrExLayer = HOVEROPTION_BACK; - } - if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) { - m_nCurrExLayer = HOVEROPTION_BACK; - } - } +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +void DoRWStuffEndOfFrame(void); - bool pressed = false; - if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { - m_bShowMouse = false; - pressed = true; - } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { - m_bShowMouse = true; - pressed = true; - } +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + bMenuChangeOngoing = true; + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + m_nPrevScreen = m_nCurrScreen; + m_ShowEmptyBindingError = false; + ResetHelperText(); - // Up - if (pressed) { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedUpOnList) { - m_bPressedUpOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - ScrollUpListByOne(); - } - } else { - m_bPressedUpOnList = false; - } + ThingsToDoBeforeLeavingPage(); - pressed = false; - if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { - m_bShowMouse = false; - pressed = true; - } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { - m_bShowMouse = true; - pressed = true; - } + if (screen == -2) { + int oldScreen = aScreens[m_nCurrScreen].m_PreviousPage; + int oldOption = GetPreviousPageOption(); - // Down - if (pressed) { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedDownOnList) { - m_bPressedDownOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - ScrollDownListByOne(); - } + m_nCurrOption = oldOption; + m_nCurrScreen = oldScreen; + } else if (screen == 0) { + m_nCurrScreen = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu; + m_nCurrOption = 0; } else { - m_bPressedDownOnList = false; + m_nCurrOption = 0; + m_nCurrScreen = screen; } + SETUP_SCROLLING(m_nCurrScreen) + + if (hasNativeList(m_nPrevScreen)) + m_nTotalListRow = 0; - if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { - if (!CPad::GetPad(0)->GetPageUp()) { - m_bPressedPgUpOnList = false; - } else { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedPgUpOnList) { - m_bPressedPgUpOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - PageUpList(false); - } - } - if (!CPad::GetPad(0)->GetPageDown()) { - m_bPressedPgDnOnList = false; - } else { - m_nCurrExLayer = HOVEROPTION_LIST; - if (!m_bPressedPgDnOnList) { - m_bPressedPgDnOnList = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - PageDownList(false); - } - } - if (CPad::GetPad(0)->GetHome()) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { - m_nFirstVisibleRowOnList = 0; - } - m_nSelectedListRow = 0; - m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; - } - if (CPad::GetPad(0)->GetEnd()) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { - m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN; - } - m_nSelectedListRow = m_nTotalListRow - 1; - m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; - } - } + if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) + m_nCurrOption = 8; + m_nMenuFadeAlpha = 0; + m_nOptionHighlightTransitionBlend = 0; + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); +} -#ifndef TIDY_UP_PBP - if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) { - m_bShowMouse = false; - goBack = true; - } -#endif +CMenuManager::CMenuManager() +{ + m_StatsScrollSpeed = 150.0f; + m_StatsScrollDirection = 1; + m_PrefsSfxVolume = 49; + m_PrefsMusicVolume = 49; + m_PrefsRadioStation = 0; + m_PrefsStereoMono = 1; + m_PrefsBrightness = 256; + m_PrefsLOD = CRenderer::ms_lodDistScale; + m_KeyPressedCode = -1; + m_bFrontEnd_ReloadObrTxtGxt = false; + m_PrefsMP3BoostVolume = 0; + m_PrefsShowSubtitles = 0; + m_PrefsShowLegends = 1; +#ifdef ASPECT_RATIO_SCALE + m_PrefsUseWideScreen = AR_AUTO; +#else + m_PrefsUseWideScreen = 0; +#endif + m_PrefsVsync = 0; + m_PrefsVsyncDisp = 1; + m_PrefsFrameLimiter = 1; + m_PrefsLanguage = 0; + field_54 = 0; + m_PrefsAllowNastyGame = 1; + m_PrefsSpeakers = 0; + field_8 = 0; + m_PrefsUseVibration = 0; + m_PrefsShowHud = 1; + m_PrefsRadarMode = 0; + m_DisplayControllerOnFoot = false; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + pEditString = nil; + pControlEdit = nil; + DisplayComboButtonErrMsg = false; + m_PrefsDMA = 1; + OS_Language = LANG_ENGLISH; + m_ControlMethod = CONTROL_STANDARD; +#ifdef PC_PLAYER_CONTROLS + CCamera::m_bUseMouse3rdPerson = true; +#else + CCamera::m_bUseMouse3rdPerson = false; +#endif + m_lastWorking3DAudioProvider = 0; + m_nFirstVisibleRowOnList = 0; + m_nScrollbarTopMargin = 0.0f; + m_nSelectedListRow = 0; + m_nSkinsTotal = 0; + m_nPrefsAudio3DProviderIndex = AUDIO_PROVIDER_NOT_DETERMINED; + m_bGameNotLoaded = true; + m_nMousePosX = m_nMouseTempPosX; + m_nMousePosY = m_nMouseTempPosY; + m_nMouseOldPosX = m_nMousePosX; + m_nMouseOldPosY = m_nMousePosY; + m_bShowMouse = true; + m_nHoverOption = HOVEROPTION_NOT_HOVERING; - if (CPad::GetPad(0)->GetLeftMouseJustDown()) { - switch (m_nHoverOption) { - case HOVEROPTION_BACK: - goBack = true; - break; - case HOVEROPTION_PAGEUP: - PageUpList(true); - break; - case HOVEROPTION_PAGEDOWN: - PageDownList(true); - break; - case HOVEROPTION_USESKIN: - if (m_nSkinsTotal > 0) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_pSelectedSkin = m_pSkinListHead.nextSkin; - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - SaveSettings(); - } - } - } + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + m_bMenuActive = false; + m_bActivateSaveMenu = false; + m_bWantToLoad = false; + m_nMenuFadeAlpha = 0; + m_OnlySaveMenu = false; + m_fMapSize = MENU_Y(162.0f); // Y because of HOR+ + m_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f); + m_fMapCenterY = MENU_Y(225.0f); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); - if (CPad::GetPad(0)->GetLeftMouseJustDown()) { - switch (m_nHoverOption) { - case HOVEROPTION_OVER_SCROLL_UP: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; - break; - case HOVEROPTION_OVER_SCROLL_DOWN: - m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; - break; - case HOVEROPTION_LIST: - m_nHoverOption = HOVEROPTION_SKIN; - } - } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) - && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - } +#ifdef NO_ISLAND_LOADING + m_PrefsIslandLoading = ISLAND_LOADING_LOW; +#endif - if (!CPad::GetPad(0)->GetLeftMouse()) { - holdingScrollBar = false; - } else { - if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { - holdingScrollBar = true; - // TODO: This part is a bit hard to reverse. Not much code tho - assert(0 && "Holding scrollbar isn't done yet"); - } else { - switch (m_nHoverOption) { - case HOVEROPTION_OVER_SCROLL_UP: - case HOVEROPTION_CLICKED_SCROLL_UP: - if (!m_bPressedScrollButton) { - m_bPressedScrollButton = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - ScrollUpListByOne(); - } - break; - case HOVEROPTION_OVER_SCROLL_DOWN: - case HOVEROPTION_CLICKED_SCROLL_DOWN: - if (!m_bPressedScrollButton) { - m_bPressedScrollButton = true; - lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - ScrollDownListByOne(); - } - break; - default: - m_bPressedScrollButton = false; - } - } - } +#ifdef GAMEPAD_MENU + m_PrefsControllerType = CONTROLLER_XBOXONE; +#endif } -// ------ Functions not in the game/inlined ends void -CMenuManager::BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2) +CMenuManager::SetFrontEndRenderStates(void) { - if (!text) - return; + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); +} -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese() && stat2) - if (itsFloat) - sprintf(gString2, " %.2f/%.2f", *(float*)stat, *(float*)stat2); - else - sprintf(gString2, " %d/%d", *(int*)stat, *(int*)stat2); - else +void +CMenuManager::Initialise(void) +{ + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_AllowNavigation = false; + m_firstStartCounter = -50; // to start from black + m_nMenuFadeAlpha = 0; + m_nCurrOption = 0; + m_nOptionHighlightTransitionBlend = 0; + CentreMousePointer(); + m_bShowMouse = true; + m_fMapSize = MENU_Y(162.0f); // Y because of HOR+ + m_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f); + m_fMapCenterY = MENU_Y(225.0f); + CPad::StopPadsShaking(); +#ifdef MISSION_REPLAY + if (!m_OnlySaveMenu && m_nCurrScreen != MENUPAGE_MISSION_RETRY) +#else + if (!m_OnlySaveMenu) #endif - if (stat2) { - if (itsFloat) - sprintf(gString2, " %.2f %s %.2f", *(float*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(float*)stat2); - else - sprintf(gString2, " %d %s %d", *(int*)stat, UnicodeToAscii(TheText.Get("FEST_OO")), *(int*)stat2); - } else if (stat) { - if (itsFloat) - sprintf(gString2, " %.2f", *(float*)stat); - else - sprintf(gString2, " %d", *(int*)stat); + m_nCurrScreen = MENUPAGE_NONE; + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + DMAudio.Service(); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); +#ifdef FIX_BUGS + static bool firstTime = true; + if (firstTime) { + DMAudio.SetRadioInCar(m_PrefsRadioStation); + firstTime = false; } else - gString2[0] = '\0'; +#endif + m_PrefsRadioStation = DMAudio.GetRadioInCar(); + + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % (USERTRACK + 1); + } else if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > WAVE) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % (WAVE + 1); - UnicodeStrcpy(gUString, TheText.Get(text)); - AsciiToUnicode(gString2, gUString2); + CFileMgr::SetDir(""); + //CFileMgr::SetDir(""); + PcSaveHelper.PopulateSlotInfo(); + CTimer::StartUserPause(); } void @@ -842,26 +659,23 @@ CMenuManager::CheckCodesForControls(int typeOfControl) if(!escPressed && !invalidKey) #endif ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); + if (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) { if (typeOfControl == KEYBOARD) { ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD); ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, OPTIONAL_EXTRA); - } else { - if (typeOfControl == MOUSE) { - ControlsManager.DeleteMatchingActionInitiators(action, MouseButtonJustClicked, MOUSE); - } else if (typeOfControl == JOYSTICK) { - ControlsManager.DeleteMatchingActionInitiators(action, JoyButtonJustClicked, JOYSTICK); - } + } else if (typeOfControl == MOUSE) { + ControlsManager.DeleteMatchingActionInitiators(action, MouseButtonJustClicked, MOUSE); + } else if (typeOfControl == JOYSTICK) { + ControlsManager.DeleteMatchingActionInitiators(action, JoyButtonJustClicked, JOYSTICK); } + if (typeOfControl == KEYBOARD) { ControlsManager.SetControllerKeyAssociatedWithAction(action, *pControlEdit, typeToSave); - } else if (typeOfControl == MOUSE) { ControlsManager.SetControllerKeyAssociatedWithAction(action, MouseButtonJustClicked, typeToSave); - } else { - if (typeOfControl == JOYSTICK) { - ControlsManager.SetControllerKeyAssociatedWithAction(action, JoyButtonJustClicked, typeToSave); - } + } else if (typeOfControl == JOYSTICK) { + ControlsManager.SetControllerKeyAssociatedWithAction(action, JoyButtonJustClicked, typeToSave); } pControlEdit = nil; m_bWaitingForNewKeyBind = false; @@ -873,18 +687,6 @@ CMenuManager::CheckCodesForControls(int typeOfControl) SaveSettings(); #endif } - - if (escPressed) { - pControlEdit = nil; - m_bWaitingForNewKeyBind = false; - m_KeyPressedCode = -1; - m_bStartWaitingForKeyBind = false; -#ifdef LOAD_INI_SETTINGS - SaveINIControllerSettings(); -#else - SaveSettings(); -#endif - } } bool @@ -899,34 +701,51 @@ CMenuManager::CheckSliderMovement(int value) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_BRIGHTNESS: - m_PrefsBrightness += value * (512/MENUSLIDER_LOGICAL_BARS); - m_PrefsBrightness = Clamp(m_PrefsBrightness, 0, 511); +#ifdef FIX_BUGS + m_PrefsBrightness += value * (384 / MENUSLIDER_LOGICAL_BARS); +#else + m_PrefsBrightness += value * 24.19f; +#endif + m_PrefsBrightness = Clamp(m_PrefsBrightness, 0, 384); break; case MENUACTION_DRAWDIST: if(value > 0) - m_PrefsLOD += ((1.8f - 0.8f) / MENUSLIDER_LOGICAL_BARS); + m_PrefsLOD += ((1.8f - 0.925f) / MENUSLIDER_LOGICAL_BARS); else - m_PrefsLOD -= ((1.8f - 0.8f) / MENUSLIDER_LOGICAL_BARS); - m_PrefsLOD = Clamp(m_PrefsLOD, 0.8f, 1.8f); + m_PrefsLOD -= ((1.8f - 0.925f) / MENUSLIDER_LOGICAL_BARS); + m_PrefsLOD = Clamp(m_PrefsLOD, 0.925f, 1.8f); CRenderer::ms_lodDistScale = m_PrefsLOD; break; + + // I wonder the idea behind clamping those max to 65 case MENUACTION_MUSICVOLUME: - m_PrefsMusicVolume += value * (128/MENUSLIDER_LOGICAL_BARS); - m_PrefsMusicVolume = Clamp(m_PrefsMusicVolume, 0, 127); - DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_PrefsMusicVolume += value * (64 / MENUSLIDER_LOGICAL_BARS); + m_PrefsMusicVolume = Clamp(m_PrefsMusicVolume, 0, 65); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + } break; case MENUACTION_SFXVOLUME: - m_PrefsSfxVolume += value * (128/MENUSLIDER_LOGICAL_BARS); - m_PrefsSfxVolume = Clamp(m_PrefsSfxVolume, 0, 127); - DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_PrefsSfxVolume += value * (64 / MENUSLIDER_LOGICAL_BARS); + m_PrefsSfxVolume = Clamp(m_PrefsSfxVolume, 0, 65); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + } + break; + case MENUACTION_MP3VOLUMEBOOST: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + if (DMAudio.IsMP3RadioChannelAvailable()) { + m_PrefsMP3BoostVolume += value * (64 / MENUSLIDER_LOGICAL_BARS); + m_PrefsMP3BoostVolume = Clamp(m_PrefsMP3BoostVolume, 0, 65); + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + } + } break; case MENUACTION_MOUSESENS: TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // probably because diving it to 15 instead of 16(MENUSLIDER_LOGICAL_BARS) had more accurate steps TheCamera.m_fMouseAccelHorzntl = Clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); #ifdef FIX_BUGS TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; -#else - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; #endif break; #ifdef CUSTOM_FRONTEND_OPTIONS @@ -950,72 +769,110 @@ CMenuManager::CheckSliderMovement(int value) } void -CMenuManager::DisplayHelperText() +CMenuManager::DisplayHelperText(char *text) { + if (m_nMenuFadeAlpha != 255) + return; + // there was a unused static bool static uint32 LastFlash = 0; - int32 alpha; + int32 alpha = 255; - if (m_nHelperTextMsgId != 0 && m_nHelperTextMsgId != 1) { + CFont::SetRightJustifyOn(); + CFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(0); - // FIX: High fps bug -#ifndef FIX_BUGS + // We're using SCREEN_STRETCH_FROM_RIGHT, because we also stretch black borders + if (text) { + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(text)); + return; + } + + if (m_nHelperTextMsgId != 0 && m_nHelperTextMsgId != 1) { if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 10) { LastFlash = CTimer::GetTimeInMillisecondsPauseMode(); m_nHelperTextAlpha -= 2; } -#else - m_nHelperTextAlpha -= 2 * CTimer::GetLogicalFramesPassed(); -#endif + if (m_nHelperTextAlpha < 1) ResetHelperText(); alpha = m_nHelperTextAlpha > 255 ? 255 : m_nHelperTextAlpha; } - SET_FONT_FOR_HELPER_TEXT + CFont::SetColor(CRGBA(255, 255, 255, alpha)); // TODO: name this cases? switch (m_nHelperTextMsgId) { - case 0: - { - int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if (action != MENUACTION_CHANGEMENU && action != MENUACTION_KEYBOARDCTRLS && action != MENUACTION_RESTOREDEF) { - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_MIG")); - } - break; - } case 1: - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_APP")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_APP")); break; case 2: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_HRD")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_HRD")); break; case 3: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSO")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSO")); break; case 4: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(HELPER_TEXT_LEFT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSC")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_STS")); + break; + case 5: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get("FET_RSC")); break; default: + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NO) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MUSICVOLUME || + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SFXVOLUME) { + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_KEYBOARDCTRLS) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SCREENRES) { + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_bGameNotLoaded ? TheText.Get("FET_MIG") : TheText.Get("FEH_NA")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_AUDIOHW || + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SPEAKERCONF) { + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESTOREDEF) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MP3VOLUMEBOOST) { + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), + m_nCurrScreen != MENUPAGE_STATS ? TheText.Get("FET_MIG") : TheText.Get("FEH_SSA")); + break; } - CFont::SetRightJustifyOff(); } int -CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress) +CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress, float spacing) { CRGBA color; float maxBarHeight; int lastActiveBarX = 0; float curBarX = 0.0f; - float spacing = SCREEN_SCALE_X(10.0f); for (int i = 0; i < MENUSLIDER_BARS; i++) { curBarX = i * rectSize/MENUSLIDER_BARS + x; @@ -1042,82 +899,91 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR void CMenuManager::DoSettingsBeforeStartingAGame() { -#ifdef PC_PLAYER_CONTROLS - CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; -#endif +#ifdef LEGACY_MENU_OPTIONS if (m_PrefsVsyncDisp != m_PrefsVsync) m_PrefsVsync = m_PrefsVsyncDisp; - +#endif + DMAudio.DestroyAllGameCreatedEntities(); DMAudio.Service(); + m_bShutDownFrontEndRequested = true; m_bWantToRestart = true; - - ShutdownJustMenu(); - UnloadTextures(); DMAudio.SetEffectsFadeVol(0); DMAudio.SetMusicFadeVol(0); + for (int i = 0; i < NUM_RADIOS; i++) + CStats::FavoriteRadioStationList[i] = 0.0f; + + SwitchMenuOnAndOff(); DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); } void -CMenuManager::Draw() +CMenuManager::DrawStandardMenus(bool activeScreen) { + float nextYToUse = 0.0f; // III leftover, set but unused in VC + bool itemsAreSelectable = true; CFont::SetBackgroundOff(); CFont::SetPropOn(); CFont::SetCentreOff(); CFont::SetJustifyOn(); - CFont::SetBackGroundOnlyTextOn(); -#if GTA_VERSION >= GTA3_PC_11 && defined(DRAW_MENU_VERSION_TEXT) - CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); - CFont::SetWrapx(SCREEN_WIDTH); - CFont::SetRightJustifyWrap(0.0f); - strcpy(gString, "V1.1"); - AsciiToUnicode(gString, gUString); - CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); + CFont::SetBackGroundOnlyTextOff(); + +#ifdef CUSTOM_FRONTEND_OPTIONS + const int xMargin = aScreens[m_nCurrScreen].layout && aScreens[m_nCurrScreen].layout->xMargin != 0 ? aScreens[m_nCurrScreen].layout->xMargin : MENU_X_MARGIN; +#else + const int xMargin = MENU_X_MARGIN; +#endif + + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(xMargin)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(xMargin)); +#ifdef ASPECT_RATIO_SCALE + CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); +#else + CFont::SetCentreSize(SCREEN_WIDTH); #endif - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f)); switch (m_nCurrScreen) { + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(38.0f), MENU_Y(85.0f), + MENU_X_LEFT_ALIGNED(615.0f), MENU_Y(75.0f), + MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(320.0f), + MENU_X_LEFT_ALIGNED(605.0f), MENU_Y(330.0f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + break; + case MENUPAGE_SOUND_SETTINGS: + PrintRadioSelector(); + break; case MENUPAGE_STATS: PrintStats(); break; case MENUPAGE_BRIEFS: PrintBriefs(); break; -#ifdef MENU_MAP - case MENUPAGE_MAP: - PrintMap(); - break; -#endif } - // Header height isn't accounted, we will add that later. - float nextYToUse = 40.0f; - // Page name -#ifdef PS2_SAVE_DIALOG - if(!m_bRenderGameInMenu) -#endif if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - + SET_FONT_FOR_MENU_HEADER - CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - // Weird place to put that. - nextYToUse += 24.0f + 10.0f; + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); } - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y)); - CFont::SetRightJustifyOff(); - CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); - // Label wchar *str; if (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) { + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENULABEL_X_MARGIN)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENULABEL_X_MARGIN)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(BIGTEXT2_X_SCALE), MENU_Y(BIGTEXT2_Y_SCALE)); + CFont::SetRightJustifyOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + switch (m_nCurrScreen) { case MENUPAGE_LOAD_SLOT_CONFIRM: if (m_bGameNotLoaded) @@ -1125,8 +991,13 @@ CMenuManager::Draw() else str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); break; + case MENUPAGE_DELETE_SLOT_CONFIRM: + str = TheText.Get(aScreens[MENUPAGE_DELETE_SLOT_CONFIRM].m_aEntries[0].m_EntryName); + break; case MENUPAGE_SAVE_OVERWRITE_CONFIRM: - if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY) + if (Slots[m_nCurrSaveSlot] == SLOT_OK) + str = TheText.Get("FESZ_QO"); + else if (Slots[m_nCurrSaveSlot] == SLOT_CORRUPTED) str = TheText.Get("FESZ_QZ"); else str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); @@ -1142,735 +1013,591 @@ CMenuManager::Draw() break; } -#ifdef FIX_BUGS - // Label is wrapped from right by StretchX(40)px, but wrapped from left by 40px. And this is only place R* didn't use StretchX in here. - CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(MENUACTION_POS_Y), str); -#else - CFont::PrintString(MENU_X_MARGIN, MENUACTION_POS_Y, str); -#endif + CFont::PrintString(MENU_X_LEFT_ALIGNED(100.0f), MENU_Y(97.0f), str); + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(xMargin)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(xMargin)); } - // Not a bug, we just want HFoV+ on menu -#ifdef ASPECT_RATIO_SCALE - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)); -#else - CFont::SetCentreSize(SCREEN_WIDTH); -#endif - -#ifdef PS2_LIKE_MENU - bool itemsAreSelectable = !bottomBarActive; -#else - bool itemsAreSelectable = true; -#endif - int lineHeight; - int headerHeight; - int columnWidth; - switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_BRIEFS: - columnWidth = 320; - headerHeight = 240; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; -#ifdef FIX_BUGS - case MENUPAGE_CONTROLLER_SETTINGS: - columnWidth = 50; - headerHeight = -50; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = MEDIUMTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = MEDIUMTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; -#endif - case MENUPAGE_SOUND_SETTINGS: - case MENUPAGE_DISPLAY_SETTINGS: - case MENUPAGE_MULTIPLAYER_CREATE: - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_CONTROLLER_PC_OLD1: - case MENUPAGE_CONTROLLER_PC_OLD2: - case MENUPAGE_CONTROLLER_PC_OLD3: - case MENUPAGE_CONTROLLER_PC_OLD4: - case MENUPAGE_CONTROLLER_DEBUG: - case MENUPAGE_MOUSE_CONTROLS: - columnWidth = 50; - headerHeight = 0; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = MEDIUMTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = MEDIUMTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_CHOOSE_SAVE_SLOT: - columnWidth = 120; - headerHeight = 38; - lineHeight = 20; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - break; - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_SAVE_OVERWRITE_CONFIRM: - case MENUPAGE_EXIT: - columnWidth = 320; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_START_MENU: - columnWidth = 320; - headerHeight = 140; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; - case MENUPAGE_PAUSE_MENU: - columnWidth = 320; - headerHeight = 117; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - break; -#ifdef PS2_SAVE_DIALOG - case MENUPAGE_SAVE: - columnWidth = 180; - headerHeight = 60; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - break; -#endif - default: -#ifdef CUSTOM_FRONTEND_OPTIONS - CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout; - if (custom) { - columnWidth = custom->columnWidth; - headerHeight = custom->headerHeight; - lineHeight = custom->lineHeight; - CFont::SetFontStyle(FONT_LOCALE(custom->font)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = custom->fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = custom->fontScaleY)); - if (custom->alignment == FESCREEN_LEFT_ALIGN) { - CFont::SetCentreOff(); - CFont::SetRightJustifyOff(); - } else if (custom->alignment == FESCREEN_RIGHT_ALIGN) { - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - } else { - CFont::SetRightJustifyOff(); - CFont::SetCentreOn(); - } - } - if (!custom) -#endif - { - columnWidth = 320; - headerHeight = 40; - lineHeight = 24; - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); - CFont::SetCentreOn(); - } - break; - } - -#ifdef PS2_LIKE_MENU - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); -#endif - - switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_PC_OLD1: - case MENUPAGE_CONTROLLER_PC_OLD2: - case MENUPAGE_CONTROLLER_PC_OLD3: - case MENUPAGE_CONTROLLER_PC_OLD4: - case MENUPAGE_CONTROLLER_DEBUG: - if (m_bWaitingForNewKeyBind) - itemsAreSelectable = false; + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + if (m_bWaitingForNewKeyBind) + itemsAreSelectable = false; - DrawControllerScreenExtraText(nextYToUse - 8.0f, MENU_X_LEFT_ALIGNED(350), lineHeight); - break; - default: - break; + DrawControllerScreenExtraText(-8.0f, MENU_X_LEFT_ALIGNED(350), MENU_DEFAULT_LINE_HEIGHT); } - float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider - float smallestSliderBar = lineHeight * 0.1f; - bool foundTheHoveringItem = false; wchar unicodeTemp[64]; #ifdef ASPECT_RATIO_SCALE char asciiTemp[32]; #endif -#ifdef MENU_MAP - if (m_nCurrScreen == MENUPAGE_MAP) { - // Back button - wchar *backTx = TheText.Get("FEDS_TB"); - CFont::SetDropShadowPosition(1); - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::PrintString(MENU_X(60.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), backTx); - CFont::SetDropShadowPosition(0); - if (!CheckHover(MENU_X(30.0f), MENU_X(30.0f) + CFont::GetStringWidth(backTx), SCREEN_SCALE_FROM_BOTTOM(125.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f))) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_nCurrOption = m_nOptionMouseHovering = 0; - } else { - m_nHoverOption = HOVEROPTION_RANDOM_ITEM; - m_nCurrOption = m_nOptionMouseHovering = 1; - } - return; - } -#endif + bool weHaveLabel = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; + uint8 section = 0; // 0: highlight trapezoid 1: texts -#ifdef CUSTOM_FRONTEND_OPTIONS - // Thanks R*, for checking mouse hovering in Draw(). - static int lastSelectedOpt = m_nCurrOption; + while (section < 2) { #endif #ifdef SCROLLABLE_PAGES - int firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0; - for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) { + int firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0; + int scrollOffset = aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Y - aScreens[m_nCurrScreen].m_aEntries[0].m_Y; + for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) { #else - for (int i = 0; i < NUM_MENUROWS; ++i) { + for (int i = 0; i < NUM_MENUROWS; ++i) { #endif - + wchar* rightText = nil; + wchar* leftText; + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + CFont::SetDropShadowPosition(0); + } else { + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + } + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Align == MENUALIGN_LEFT) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + } else if (aScreens[m_nCurrScreen].m_aEntries[i].m_Align == MENUALIGN_RIGHT) { + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + } else { + CFont::SetRightJustifyOff(); + CFont::SetCentreOn(); + } + if (aScreens[m_nCurrScreen].m_aEntries[i].m_X == 0 && aScreens[m_nCurrScreen].m_aEntries[i].m_Y == 0) { + if (i == 0 || (i == 1 && weHaveLabel)) { #ifdef CUSTOM_FRONTEND_OPTIONS - bool isOptionDisabled = false; + aScreens[m_nCurrScreen].m_aEntries[i].m_X = (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->startX : MENU_DEFAULT_CONTENT_X); + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->startY : MENU_DEFAULT_CONTENT_Y); +#else + aScreens[m_nCurrScreen].m_aEntries[i].m_X = MENU_DEFAULT_CONTENT_X; + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = MENU_DEFAULT_CONTENT_Y; #endif - // Hide back button -#ifdef PS2_LIKE_MENU - if ((i == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[i+1].m_EntryName[0] == '\0') && strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEDS_TB") == 0) - break; + + } else { + aScreens[m_nCurrScreen].m_aEntries[i].m_X = aScreens[m_nCurrScreen].m_aEntries[i-1].m_X; + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = aScreens[m_nCurrScreen].m_aEntries[i-1].m_Y PLUS_LINE_HEIGHT_ON_SCREEN; + } + } +#ifdef CUSTOM_FRONTEND_OPTIONS + else if (aScreens[m_nCurrScreen].m_aEntries[i].m_Y == 0) { + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = aScreens[m_nCurrScreen].m_aEntries[i-1].m_Y PLUS_LINE_HEIGHT_ON_SCREEN; + } #endif - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { - wchar *rightText = nil; - wchar *leftText; - if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { - CFont::SetRightJustifyOff(); - leftText = GetNameOfSavedGame(i - 1); + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { - if (Slots[i] != SLOT_EMPTY) - rightText = GetSavedGameDateAndTime(i - 1); + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetRightJustifyOff(); - if (leftText[0] == '\0') { - sprintf(gString, "FEM_SL%d", i); - leftText = TheText.Get(gString); + leftText = nil; + if (Slots[i] == SLOT_OK) { + leftText = GetNameOfSavedGame(i); + rightText = GetSavedGameDateAndTime(i); + } + + if (!leftText || leftText[0] == '\0') { + sprintf(gString, "FEM_SL%d", i + 1); + leftText = TheText.Get(gString); + } + } else { + leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } - } else { - leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); - } - switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case MENUACTION_CHANGEMENU: { - switch (aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu) { - case MENUPAGE_MULTIPLAYER_MAP: - switch (m_SelectedMap) { - case 0: - rightText = TheText.Get("FEM_MA0"); - break; - case 1: - rightText = TheText.Get("FEM_MA1"); - break; - case 2: - rightText = TheText.Get("FEM_MA2"); - break; - case 3: - rightText = TheText.Get("FEM_MA3"); - break; - case 4: - rightText = TheText.Get("FEM_MA4"); - break; - case 5: - rightText = TheText.Get("FEM_MA5"); - break; - case 6: - rightText = TheText.Get("FEM_MA6"); - break; - case 7: - rightText = TheText.Get("FEM_MA7"); - break; - default: - break; - } + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEO_AUD") == 0) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + } + + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { +#ifdef GAMEPAD_MENU + case MENUACTION_CTRLVIBRATION: + if (m_PrefsUseVibration) + rightText = TheText.Get("FEM_ON"); + else + rightText = TheText.Get("FEM_OFF"); + break; + case MENUACTION_CTRLCONFIG: + switch (CPad::GetPad(0)->Mode) { + case 0: + rightText = TheText.Get("FEC_CF1"); break; - case MENUPAGE_MULTIPLAYER_MODE: - switch (m_SelectedGameType) { - case 0: - rightText = TheText.Get("FEN_TY0"); - break; - case 1: - rightText = TheText.Get("FEN_TY1"); - break; - case 2: - rightText = TheText.Get("FEN_TY2"); - break; - case 3: - rightText = TheText.Get("FEN_TY3"); - break; - case 4: - rightText = TheText.Get("FEN_TY4"); - break; - case 5: - rightText = TheText.Get("FEN_TY5"); - break; - case 6: - rightText = TheText.Get("FEN_TY6"); - break; - case 7: - rightText = TheText.Get("FEN_TY7"); - break; - default: - break; - } + case 1: + rightText = TheText.Get("FEC_CF2"); break; - default: + case 2: + rightText = TheText.Get("FEC_CF3"); break; - } - break; - } - case MENUACTION_CTRLVIBRATION: - if (m_PrefsUseVibration) - rightText = TheText.Get("FEM_ON"); - else - rightText = TheText.Get("FEM_OFF"); - break; - case MENUACTION_CTRLCONFIG: - switch (CPad::GetPad(0)->Mode) { - case 0: - rightText = TheText.Get("FEC_CF1"); + case 3: + rightText = TheText.Get("FEC_CF4"); + break; + } break; - case 1: - rightText = TheText.Get("FEC_CF2"); + // This one is still in enum and ProcessOnOffMenuOptions, but removed from other places + case MENUACTION_CTRLDISPLAY: + if (m_DisplayControllerOnFoot) + rightText = TheText.Get("FEC_ONF"); + else + rightText = TheText.Get("FEC_INC"); break; - case 2: - rightText = TheText.Get("FEC_CF3"); +#endif + case MENUACTION_FRAMESYNC: + rightText = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); break; - case 3: - rightText = TheText.Get("FEC_CF4"); + case MENUACTION_FRAMELIMIT: + rightText = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); break; - } - break; - case MENUACTION_CTRLDISPLAY: - if (m_DisplayControllerOnFoot) - rightText = TheText.Get("FEC_ONF"); - else - rightText = TheText.Get("FEC_INC"); - break; - case MENUACTION_FRAMESYNC: - rightText = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_FRAMELIMIT: - rightText = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_TRAILS: - rightText = TheText.Get(CMBlur::BlurOn ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_SUBTITLES: - rightText = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_WIDESCREEN: + case MENUACTION_TRAILS: + rightText = TheText.Get(CMBlur::BlurOn ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_SUBTITLES: + rightText = TheText.Get(m_PrefsShowSubtitles ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_WIDESCREEN: #ifndef ASPECT_RATIO_SCALE - rightText = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); + rightText = TheText.Get(m_PrefsUseWideScreen ? "FEM_ON" : "FEM_OFF"); #else - switch (m_PrefsUseWideScreen) { - case AR_AUTO: - rightText = TheText.Get("FEM_AUT"); + switch (m_PrefsUseWideScreen) { + case AR_AUTO: + rightText = TheText.Get("FEM_AUT"); + break; + case AR_4_3: + sprintf(asciiTemp, "4:3"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_5_4: + sprintf(asciiTemp, "5:4"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_16_10: + sprintf(asciiTemp, "16:10"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_16_9: + sprintf(asciiTemp, "16:9"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + case AR_21_9: + sprintf(asciiTemp, "21:9"); + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; + break; + } +#endif break; - case AR_4_3: - sprintf(asciiTemp, "4:3"); - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; + + case MENUACTION_MUSICVOLUME: + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + break; - case AR_5_4: - sprintf(asciiTemp, "5:4"); - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; + case MENUACTION_RADIO: + switch (m_PrefsRadioStation) { + case WILDSTYLE: + rightText = TheText.Get("FEA_FM0"); + break; + case FLASH_FM: + rightText = TheText.Get("FEA_FM1"); + break; + case KCHAT: + rightText = TheText.Get("FEA_FM2"); + break; + case FEVER: + rightText = TheText.Get("FEA_FM3"); + break; + case V_ROCK: + rightText = TheText.Get("FEA_FM4"); + break; + case VCPR: + rightText = TheText.Get("FEA_FM5"); + break; + case RADIO_ESPANTOSO: + rightText = TheText.Get("FEA_FM6"); + break; + case EMOTION: + rightText = TheText.Get("FEA_FM7"); + break; + case WAVE: + rightText = TheText.Get("FEA_FM8"); + break; + case USERTRACK: + rightText = TheText.Get("FEA_MP3"); + break; + } break; - case AR_16_10: - sprintf(asciiTemp, "16:10"); - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; + case MENUACTION_LEGENDS: + rightText = TheText.Get(m_PrefsShowLegends ? "FEM_ON" : "FEM_OFF"); break; - case AR_16_9: - sprintf(asciiTemp, "16:9"); - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; + case MENUACTION_RADARMODE: + switch (m_PrefsRadarMode) { + case 0: + rightText = TheText.Get("FED_RDM"); + break; + case 1: + rightText = TheText.Get("FED_RDB"); + break; + case 2: + rightText = TheText.Get("FEM_OFF"); + break; + } break; - case AR_21_9: - sprintf(asciiTemp, "21:9"); - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; + case MENUACTION_HUD: + rightText = TheText.Get(m_PrefsShowHud ? "FEM_ON" : "FEM_OFF"); + break; +#ifdef LEGACY_MENU_OPTIONS + case MENUACTION_SETDBGFLAG: + rightText = TheText.Get(CTheScripts::IsDebugOn() ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: + rightText = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_COLLISIONPOLYS: + rightText = TheText.Get(gbShowCollisionPolys ? "FEM_ON" : "FEM_OFF"); break; - } #endif - break; - case MENUACTION_RADIO: - if (m_PrefsRadioStation > USERTRACK) + case MENUACTION_SHOWHEADBOB: + rightText = TheText.Get(TheCamera.m_bHeadBob ? "FEM_ON" : "FEM_OFF"); + break; + case MENUACTION_INVVERT: + rightText = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_OFF" : "FEM_ON"); break; + case MENUACTION_SCREENRES: + AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp); + rightText = unicodeTemp; - sprintf(gString, "FEA_FM%d", m_PrefsRadioStation); - rightText = TheText.Get(gString); - break; - case MENUACTION_SETDBGFLAG: - rightText = TheText.Get(CTheScripts::IsDebugOn() ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: - rightText = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_PEDROADGROUPS: - rightText = TheText.Get(gbShowPedRoadGroups ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_CARROADGROUPS: - rightText = TheText.Get(gbShowCarRoadGroups ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_COLLISIONPOLYS: - rightText = TheText.Get(gbShowCollisionPolys ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_SHOWCULL: - rightText = TheText.Get(gbShowCullZoneDebugStuff ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_SHOWHEADBOB: - rightText = TheText.Get(TheCamera.m_bHeadBob ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_INVVERT: - rightText = TheText.Get(MousePointerStateHelper.bInvertVertically ? "FEM_OFF" : "FEM_ON"); - break; - case MENUACTION_SCREENRES: - AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp); - rightText = unicodeTemp; - break; - case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex == -1) - rightText = TheText.Get("FEA_NAH"); - else { - char *provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); - - if (!strcmp(strupr(provider), "DIRECTSOUND3D HARDWARE SUPPORT")) { - strcpy(provider, "DSOUND3D HARDWARE SUPPORT"); - } else if (!strcmp(strupr(provider), "DIRECTSOUND3D SOFTWARE EMULATION")) { - strcpy(provider, "DSOUND3D SOFTWARE EMULATION"); + if (!m_bGameNotLoaded) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } - AsciiToUnicode(provider, unicodeTemp); - rightText = unicodeTemp; + break; + case MENUACTION_AUDIOHW: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + else if (m_nPrefsAudio3DProviderIndex == -1) + rightText = TheText.Get("FEA_ADP"); + else { + char *rawProvider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); + AsciiToUnicode(rawProvider, unicodeTemp); + char *provider = UnicodeToAscii(unicodeTemp); // genius + strupr(provider); + if (!strcmp(provider, "DIRECTSOUND3D HARDWARE SUPPORT")) { + strcpy(provider, "DSOUND3D HARDWARE SUPPORT"); + } else if (!strcmp(provider, "DIRECTSOUND3D SOFTWARE EMULATION")) { + strcpy(provider, "DSOUND3D SOFTWARE EMULATION"); + } + AsciiToUnicode(provider, unicodeTemp); + rightText = unicodeTemp; + } + break; + case MENUACTION_SPEAKERCONF: { + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + else { + switch (m_PrefsSpeakers) { + case 0: + rightText = TheText.Get("FEA_2SP"); + break; + case 1: + rightText = TheText.Get("FEA_EAR"); + break; + case 2: + rightText = TheText.Get("FEA_4SP"); + break; + } + } + break; } - break; - case MENUACTION_SPEAKERCONF: { - if (m_nPrefsAudio3DProviderIndex == -1) - rightText = TheText.Get("FEA_NAH"); - else { - switch (m_PrefsSpeakers) { - case 0: - rightText = TheText.Get("FEA_2SP"); + case MENUACTION_CTRLMETHOD: { + switch (m_ControlMethod) { + case CONTROL_STANDARD: + leftText = TheText.Get("FET_STI"); break; - case 1: - rightText = TheText.Get("FEA_EAR"); - break; - case 2: - rightText = TheText.Get("FEA_4SP"); + case CONTROL_CLASSIC: + leftText = TheText.Get("FET_CTI"); break; } + break; } - break; - } - case MENUACTION_CTRLMETHOD: { - switch (m_ControlMethod) { - case 0: - leftText = TheText.Get("FET_SCN"); + case MENUACTION_DYNAMICACOUSTIC: + rightText = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); break; - case 1: - leftText = TheText.Get("FET_CCN"); + case MENUACTION_MOUSESTEER: + rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); + if (m_ControlMethod == CONTROL_CLASSIC) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + break; + case MENUACTION_MP3VOLUMEBOOST: + if (!DMAudio.IsMP3RadioChannelAvailable()) { + rightText = TheText.Get("FEA_NM3"); + } break; - } - break; - } - case MENUACTION_DYNAMICACOUSTIC: - rightText = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); - break; - case MENUACTION_MOUSESTEER: - rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); - break; #ifdef CUSTOM_FRONTEND_OPTIONS - case MENUACTION_CFO_DYNAMIC: - case MENUACTION_CFO_SELECT: - CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; - if (option.m_Action == MENUACTION_CFO_SELECT) { + case MENUACTION_CFO_DYNAMIC: + case MENUACTION_CFO_SELECT: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + + // To whom manipulate option.m_CFO->value of static options externally (like RestoreDef functions) + if (*(int8*)option.m_CFO->value != option.m_CFOSelect->lastSavedValue) + option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *(int8*)option.m_CFO->value; - isOptionDisabled = option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded; - if (option.m_CFOSelect->onlyApplyOnEnter){ - if (m_nCurrOption != i) { - if (option.m_CFOSelect->displayedValue != option.m_CFOSelect->lastSavedValue) - SetHelperText(3); // Restored original value + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = 0; - // If that was previously selected option, restore it to default value. - // if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) - option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *(int8*)option.m_CFO->value; + rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]); - } else { - if (option.m_CFOSelect->displayedValue != *(int8*)option.m_CFO->value) - SetHelperText(1); // Enter to apply - else if (m_nHelperTextMsgId == 1) - ResetHelperText(); // Applied + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (option.m_CFODynamic->drawFunc) { + bool isOptionDisabled = false; + rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i); + if (isOptionDisabled) + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } } + break; +#endif + } - // To whom manipulate option.m_CFO->value of select options externally (like RestoreDef functions) - if (*(int8*)option.m_CFO->value != option.m_CFOSelect->lastSavedValue) - option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *(int8*)option.m_CFO->value; + // Highlight trapezoid + if (activeScreen && i == m_nCurrOption && itemsAreSelectable && section == 0) { - if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) - option.m_CFOSelect->displayedValue = 0; + int leftXMax, rightXMin; - rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]); + // FIX: Let's don't scale those so GetStringWidth can give us unscaled width, which will be handy to other calculations below that's done without scaling in mind, + // and scaling will be done eventually. + // CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetScale(BIGTEXT_X_SCALE, BIGTEXT_Y_SCALE); + + wchar *curOptionName = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName); + float curOptionWidth = CFont::GetStringWidth(curOptionName, true); - } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { - if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) { - if(option.m_CFODynamic->buttonPressFunc) - option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); - } + if (CFont::Details.centre) { + leftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth / 2.f); + rightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth / 2.f + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); - if (option.m_CFODynamic->drawFunc) { - rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i); + } else if (!CFont::Details.rightJustify) { + leftXMax = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X; + rightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); + + } else { + leftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth); + rightXMin = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X; } - } - break; -#endif - } + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); - float nextItemY = headerHeight + nextYToUse; - float bitAboveNextItemY = nextItemY - 2.0f; - int nextYToCheck = bitAboveNextItemY; - - if (!foundTheHoveringItem) { -#ifdef SCROLLABLE_PAGES - for (int rowToCheck = firstOption + (aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Action == MENUACTION_LABEL); rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) { -#else - for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) { -#endif - if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) - break; - - // Hide back button -#ifdef PS2_LIKE_MENU - if ((rowToCheck == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[rowToCheck+1].m_EntryName[0] == '\0') && - strcmp(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName, "FEDS_TB") == 0) - break; + int action = aScreens[m_nCurrScreen].m_aEntries[i].m_Action; + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot; + if (rightText || action == MENUACTION_DRAWDIST || action == MENUACTION_BRIGHTNESS || action == MENUACTION_MUSICVOLUME || + action == MENUACTION_SFXVOLUME || action == MENUACTION_MP3VOLUMEBOOST || action == MENUACTION_MOUSESENS || + saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 +#ifdef CUSTOM_FRONTEND_OPTIONS + || action == MENUACTION_CFO_SLIDER #endif + ) { + rightXMin = 600; + leftXMax = 40; + } - int extraOffset = 0; - if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO) - extraOffset = MENURADIO_ICON_SCALE; - - // There were many unused codes in here to calculate how much space will texts gonna take. - - // FIX: nextYToCheck already starts with Y - 2, let's sync it with green bar bounds. -#ifdef FIX_BUGS - if (m_nMousePosY > MENU_Y(nextYToCheck) && -#else - if (m_nMousePosY > MENU_Y(nextYToCheck - 2) && -#endif - m_nMousePosY < MENU_Y((nextYToCheck + 2) + usableLineHeight)) { + int y = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Y MINUS_SCROLL_OFFSET; + int topYMax = y; + uint32 bottomYMin = y + MENU_DEFAULT_LINE_HEIGHT - 7; // Decreasing is not recommended. Because this actually is dependent to font scale, not line height. - static int oldOption = -99; - static int oldScreen = m_nCurrScreen; + // Actually bottomRight and bottomLeft should be exchanged here(although this is original code). + // So this shows us either R* didn't use same struct for menu BG and highlight, or they just kept fields as x1,y1 etc. Yikes. - m_nOptionMouseHovering = rowToCheck; - if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { - m_nCurrOption = rowToCheck; - m_bShowMouse = true; + if (m_nOptionHighlightTransitionBlend == 0) { + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) { + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR); } - if (oldOption != m_nCurrOption) { - if (oldScreen == m_nCurrScreen && m_bShowMouse) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - - oldOption = m_nCurrOption; - oldScreen = m_nCurrScreen; + menuOptionHighlight.SaveCurrentCoors(); + menuOptionHighlight.topLeft_x = leftXMax - 5 - CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.topLeft_y = topYMax - CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.topRight_x = rightXMin + 5 + CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.topRight_y = topYMax - CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.bottomLeft_x = rightXMin + 5 + CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.bottomLeft_y = bottomYMin + CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.bottomRight_x = leftXMax - 5 - CGeneral::GetRandomNumber() % 10; + menuOptionHighlight.bottomRight_y = bottomYMin + CGeneral::GetRandomNumber() % 7; + menuOptionHighlight.UpdateMultipliers(); + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + + } else if (m_nOptionHighlightTransitionBlend < 255) { + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) { + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR); + } + } else { + m_nOptionHighlightTransitionBlend = 255; + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) { + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y), + MENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR); } - if (oldScreen == m_nPrevScreen) - oldScreen = m_nCurrScreen; - - m_nHoverOption = HOVEROPTION_RANDOM_ITEM; - foundTheHoveringItem = true; - break; } - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - nextYToCheck += extraOffset + lineHeight; - } - } - // Green bar behind selected option -#ifdef PS2_SAVE_DIALOG - if (!m_bRenderGameInMenu) -#endif - if (i == m_nCurrOption && itemsAreSelectable) { -#ifdef PS2_LIKE_MENU - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(29.0f), MENU_Y(bitAboveNextItemY), - MENU_X_RIGHT_ALIGNED(29.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(SELECTION_HIGHLIGHTBG_COLOR.r, SELECTION_HIGHLIGHTBG_COLOR.g, SELECTION_HIGHLIGHTBG_COLOR.b, FadeIn(SELECTION_HIGHLIGHTBG_COLOR.a))); + static uint32 lastBlendChange = 0; + if (m_nOptionHighlightTransitionBlend <= 255) { + static uint32 blendChangeCounter = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastBlendChange > 20 + || blendChangeCounter > 20 + ) { + m_nOptionHighlightTransitionBlend += 50; + lastBlendChange = CTimer::GetTimeInMillisecondsPauseMode(); + blendChangeCounter = 0; + } +#ifdef FIX_BUGS + blendChangeCounter += CTimer::GetLogicalFramesPassed(); #else - // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background - CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), - SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), - CRGBA(SELECTION_HIGHLIGHTBG_COLOR.r, SELECTION_HIGHLIGHTBG_COLOR.g, SELECTION_HIGHLIGHTBG_COLOR.b, FadeIn(SELECTION_HIGHLIGHTBG_COLOR.a))); + ++blendChangeCounter; #endif - } - - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); + } + } - // Button and it's shadow - for(int textLayer = 0; textLayer < 2; textLayer++) { - if (!CFont::Details.centre) - CFont::SetRightJustifyOff(); + if (section == 1) { + if (leftText) { + CFont::PrintString(MENU_X_LEFT_ALIGNED(aScreens[m_nCurrScreen].m_aEntries[i].m_X), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y MINUS_SCROLL_OFFSET), leftText); + } - float itemY = MENU_Y(textLayer + nextItemY); - float itemX = MENU_X_LEFT_ALIGNED(textLayer + columnWidth); - CFont::PrintString(itemX, itemY, leftText); - if (rightText) { - if (!CFont::Details.centre) + if (rightText) { + CFont::SetCentreOff(); CFont::SetRightJustifyOn(); - - if(textLayer == 1) - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") && !m_bGameNotLoaded + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + } else { + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(DEFAULT_SCREEN_WIDTH - RIGHT_ALIGNED_TEXT_RIGHT_MARGIN(xMargin)), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y MINUS_SCROLL_OFFSET), rightText); + } + + if (m_nPrefsAudio3DProviderIndex == DMAudio.GetCurrent3DProviderIndex()) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) + ResetHelperText(); + } + if (m_nDisplayVideoMode == m_nPrefsVideoMode) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1) + ResetHelperText(); + } + if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH")) + SetHelperText(1); + } + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) + SetHelperText(1); + } + if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 #ifdef CUSTOM_FRONTEND_OPTIONS - || isOptionDisabled + && ScreenHasOption(m_nCurrScreen, "FEA_3DH") +#else + && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS #endif - ) - CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); - - CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); - } - if (i == m_nCurrOption && itemsAreSelectable){ - CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); - } else { - CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); - } - } + && m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { - if (m_nPrefsAudio3DProviderIndex == DMAudio.GetCurrent3DProviderIndex()) { - if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") && m_nHelperTextMsgId == 1) - ResetHelperText(); - } - if (m_nDisplayVideoMode == m_nPrefsVideoMode) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1) - ResetHelperText(); - } - if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH")) - SetHelperText(1); - } - if (m_nDisplayVideoMode != m_nPrefsVideoMode) { - if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES")) - SetHelperText(1); - } - if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 - // To make assigning built-in actions to new custom options possible. + m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); + SetHelperText(3); + } + } + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") != 0 #ifdef CUSTOM_FRONTEND_OPTIONS - && ScreenHasOption(m_nCurrScreen, "FEA_3DH") + && ScreenHasOption(m_nCurrScreen, "FED_RES")) { #else - && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS + && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { #endif - && m_nPrefsAudio3DProviderIndex != -1) { + m_nDisplayVideoMode = m_nPrefsVideoMode; + SetHelperText(3); + } + } - m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); - SetHelperText(3); - } - } - if (m_nDisplayVideoMode != m_nPrefsVideoMode) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") != 0 - // To make assigning built-in actions to new custom options possible. #ifdef CUSTOM_FRONTEND_OPTIONS - && ScreenHasOption(m_nCurrScreen, "FED_RES") +#define SLIDER_Y(pos) (aScreens[m_nCurrScreen].m_aEntries[i].m_Y - 5.f) #else - && m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS +#define SLIDER_Y(pos) pos #endif - ){ - m_nDisplayVideoMode = m_nPrefsVideoMode; - SetHelperText(3); - } - } - - // Sliders - int lastActiveBarX; - switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { - case MENUACTION_BRIGHTNESS: - ProcessSlider(m_PrefsBrightness / 512.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_DRAWDIST: - ProcessSlider((m_PrefsLOD - 0.8f) * 1.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_MUSICVOLUME: - ProcessSlider(m_PrefsMusicVolume / 128.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_SFXVOLUME: - ProcessSlider(m_PrefsSfxVolume / 128.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; - case MENUACTION_MOUSESENS: - ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); - break; + // Sliders + int lastActiveBarX; + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case MENUACTION_BRIGHTNESS: + ProcessSlider(m_PrefsBrightness / 384.0f, SLIDER_Y(70.0f), HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, SCREEN_WIDTH, true); + break; + case MENUACTION_DRAWDIST: + ProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, SLIDER_Y(99.0f), HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, SCREEN_WIDTH, true); + break; + case MENUACTION_MUSICVOLUME: + if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + ProcessSlider(m_PrefsMusicVolume / 64.0f, SLIDER_Y(70.0f), HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, SCREEN_WIDTH, true); + break; + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + ProcessSlider(m_PrefsSfxVolume / 64.0f, SLIDER_Y(99.0f), HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, SCREEN_WIDTH, true); + break; + case MENUACTION_MOUSESENS: + ProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, SLIDER_Y(170.0f), HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, SCREEN_WIDTH, false); + break; + case MENUACTION_MP3VOLUMEBOOST: + if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER && DMAudio.IsMP3RadioChannelAvailable()) + ProcessSlider(m_PrefsMP3BoostVolume / 64.f, SLIDER_Y(128.0f), HOVEROPTION_INCREASE_MP3BOOST, HOVEROPTION_DECREASE_MP3BOOST, SCREEN_WIDTH, true); + break; #ifdef CUSTOM_FRONTEND_OPTIONS - case MENUACTION_CFO_SLIDER: - CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; - ProcessSlider((*(float*)option.m_CFOSlider->value - option.m_CFOSlider->min) / (option.m_CFOSlider->max - option.m_CFOSlider->min), HOVEROPTION_INCREASE_CFO_SLIDER, HOVEROPTION_DECREASE_CFO_SLIDER, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); - break; + case MENUACTION_CFO_SLIDER: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i]; + ProcessSlider((*(float*)option.m_CFOSlider->value - option.m_CFOSlider->min) / (option.m_CFOSlider->max - option.m_CFOSlider->min), SLIDER_Y(0), HOVEROPTION_INCREASE_CFO_SLIDER, HOVEROPTION_DECREASE_CFO_SLIDER, SCREEN_WIDTH, true); + break; #endif - } - - // Needed after the bug fix in Font.cpp -#ifdef FIX_BUGS - if (!CFont::Details.centre) - CFont::SetRightJustifyOff(); + } + + // Not just unused, but also collides with the bug fix in Font.cpp. Yikes. +#ifndef FIX_BUGS + nextYToUse += MENU_DEFAULT_LINE_HEIGHT * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText); #endif - // 60.0 is silly - nextYToUse += lineHeight * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText); - - // Radio icons - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO1], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO2], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO5], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO7], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO8], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO3], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO4], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO6], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7); - ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO9], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); - - if (DMAudio.IsMP3RadioChannelAvailable()) - ProcessRadioIcon(m_aMenuSprites[MENUSPRITE_MP3LOGO], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); - - nextYToUse += 70.0f; + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { + nextYToUse += MENURADIO_SELECTOR_HEIGHT + 5.f; // unused + } + } } } + section++; } -#ifdef CUSTOM_FRONTEND_OPTIONS - lastSelectedOpt = m_nCurrOption; -#endif - #ifdef SCROLLABLE_PAGES - #define SCROLLBAR_BOTTOM_Y 125.0f // only for background, scrollbar's itself is calculated - #define SCROLLBAR_RIGHT_X 36.0f + #define SCROLLBAR_BOTTOM_Y 105.0f // only for background, scrollbar's itself is calculated + #define SCROLLBAR_RIGHT_X 26.0f #define SCROLLBAR_WIDTH 9.5f - #define SCROLLBAR_TOP_Y 64 + #define SCROLLBAR_TOP_Y 84 - if (SCREEN_HAS_AUTO_SCROLLBAR) { + if (activeScreen && SCREEN_HAS_AUTO_SCROLLBAR) { // Scrollbar background CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_Y), - MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_Y)), CRGBA(100, 100, 66, FadeIn(205))); + MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_Y)), CRGBA(30, 30, 30, FadeIn(150))); float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION); float scrollbarBottom, scrollbarTop; - scrollbarBottom = MENU_Y(SCROLLBAR_TOP_Y - 8 + m_nScrollbarTopMargin + scrollbarHeight); - scrollbarTop = MENU_Y(SCROLLBAR_TOP_Y + m_nScrollbarTopMargin); + scrollbarBottom = MENU_Y(SCROLLBAR_TOP_Y - 6 + m_nScrollbarTopMargin + scrollbarHeight); + scrollbarTop = MENU_Y(SCROLLBAR_TOP_Y + 2 + m_nScrollbarTopMargin); // Scrollbar shadow CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop, MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), @@ -1885,32 +1612,41 @@ CMenuManager::Draw() #endif switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_SETTINGS: - case MENUPAGE_SOUND_SETTINGS: - case MENUPAGE_DISPLAY_SETTINGS: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_CONTROLLER_PC: - case MENUPAGE_MOUSE_CONTROLS: - DisplayHelperText(); - break; +#ifdef GAMEPAD_MENU + case MENUPAGE_CONTROLLER_SETTINGS: + PrintController(); + break; +#endif + case MENUPAGE_STATS: + case MENUPAGE_CONTROLLER_PC: + case MENUPAGE_SOUND_SETTINGS: + case MENUPAGE_DISPLAY_SETTINGS: + case MENUPAGE_MOUSE_CONTROLS: + DisplayHelperText(nil); + break; + case MENUPAGE_OPTIONS: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LOADRADIO) + DisplayHelperText("FEA_NAH"); + break; #ifdef CUSTOM_FRONTEND_OPTIONS - default: - if (aScreens[m_nCurrScreen].layout) { - if (aScreens[m_nCurrScreen].layout->showLeftRightHelper) { - DisplayHelperText(); + default: + if (aScreens[m_nCurrScreen].layout) { + if (aScreens[m_nCurrScreen].layout->showLeftRightHelper) { + DisplayHelperText(nil); + } } - } - break; + break; #endif } - if (m_nCurrScreen == MENUPAGE_CONTROLLER_SETTINGS) - PrintController(); - else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT_OLD) { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(180), MENU_Y(98), MENU_X_LEFT_ALIGNED(230), MENU_Y(123)), CRGBA(255, 255, 255, FadeIn(255))); - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(181), MENU_Y(99), MENU_X_LEFT_ALIGNED(229), MENU_Y(122)), CRGBA(m_PrefsPlayerRed, m_PrefsPlayerGreen, m_PrefsPlayerBlue, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_DELETING_IN_PROGRESS) { + SmallMessageScreen("FEDL_WR"); } - +#ifndef XBOX_MESSAGE_SCREEN + else if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) { + SmallMessageScreen("FESZ_WR"); + } +#endif } int @@ -1918,19 +1654,21 @@ CMenuManager::GetNumOptionsCntrlConfigScreens(void) { int number = 0; switch (m_nCurrScreen) { +#ifdef LEGACY_MENU_OPTIONS case MENUPAGE_CONTROLLER_PC_OLD3: number = 2; break; case MENUPAGE_CONTROLLER_DEBUG: number = 4; break; +#endif case MENUPAGE_KEYBOARD_CONTROLS: switch (m_ControlMethod) { case CONTROL_STANDARD: - number = 25; + number = 27; break; case CONTROL_CLASSIC: - number = 30; + number = 32; break; } break; @@ -1958,12 +1696,11 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 break; } - // MENU_Y(rowHeight * 0.0f + yStart); for (int optionIdx = 0; optionIdx < numOptions; nextY = MENU_Y(++optionIdx * rowHeight + yStart)) { int nextX = xStart; int bindingsForThisOpt = 0; int contSetOrder = SETORDER_1; - CFont::SetColor(CRGBA(LIST_OPTION_COLOR.r, LIST_OPTION_COLOR.g, LIST_OPTION_COLOR.b, FadeIn(LIST_OPTION_COLOR.a))); + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); if (column == CONTSETUP_PED_COLUMN) { switch (optionIdx) { @@ -2001,10 +1738,10 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 case 11: case 12: case 16: - case 18: - case 19: case 20: case 21: + case 22: + case 23: controllerAction = -1; break; case 13: @@ -2019,34 +1756,40 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 case 17: controllerAction = PED_LOCK_TARGET; break; - case 22: + case 18: + controllerAction = PED_DUCK; + break; + case 19: + controllerAction = PED_ANSWER_PHONE; + break; + case 24: controllerAction = PED_LOOKBEHIND; break; - case 23: + case 25: if (m_ControlMethod == CONTROL_STANDARD) controllerAction = -1; else controllerAction = PED_1RST_PERSON_LOOK_LEFT; break; - case 24: + case 26: if (m_ControlMethod == CONTROL_STANDARD) controllerAction = -1; else controllerAction = PED_1RST_PERSON_LOOK_RIGHT; break; - case 25: + case 27: controllerAction = PED_1RST_PERSON_LOOK_UP; break; - case 26: + case 28: controllerAction = PED_1RST_PERSON_LOOK_DOWN; break; - case 27: + case 29: controllerAction = PED_CYCLE_TARGET_LEFT; break; - case 28: + case 30: controllerAction = PED_CYCLE_TARGET_RIGHT; break; - case 29: + case 31: controllerAction = PED_CENTER_CAMERA_BEHIND_PLAYER; break; default: @@ -2068,11 +1811,13 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 case 14: case 15: case 17: - case 25: - case 26: + case 18: + case 19: case 27: case 28: case 29: + case 30: + case 31: controllerAction = -1; break; case 3: @@ -2105,32 +1850,31 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 case 16: controllerAction = VEHICLE_HANDBRAKE; break; - case 18: + case 20: controllerAction = VEHICLE_TURRETLEFT; break; - case 19: + case 21: controllerAction = VEHICLE_TURRETRIGHT; break; - case 20: + case 22: controllerAction = VEHICLE_TURRETUP; break; - case 21: + case 23: controllerAction = VEHICLE_TURRETDOWN; break; - case 22: + case 24: controllerAction = -2; break; - case 23: + case 25: controllerAction = VEHICLE_LOOKLEFT; break; - case 24: + case 26: controllerAction = VEHICLE_LOOKRIGHT; break; default: break; } } - int bindingWhite = 155; // Highlight selected column(and make its text black) if (m_nSelectedListRow == optionIdx) { @@ -2139,49 +1883,31 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 if (column == CONTSETUP_PED_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_PED_COLUMN) { #ifdef FIX_BUGS - if (controllerAction == -1) { - CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); - } else { - CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); - } + CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); #else - if (controllerAction == -1) { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), - MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); - } else { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), - MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); - } + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY), + MENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); #endif - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - bindingWhite = 0; + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); } else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) { #ifdef FIX_BUGS - if (controllerAction == -1) { - CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); - } else { - CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), - MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); - } + CSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH), + MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); #else - if (controllerAction == -1) { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.r, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.g, CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_DISABLED_HIGHLIGHTBG_COLOR.a))); - } else { - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + 10)), CRGBA(CONTSETUP_HIGHLIGHTBG_COLOR.r, CONTSETUP_HIGHLIGHTBG_COLOR.g, CONTSETUP_HIGHLIGHTBG_COLOR.b, FadeIn(CONTSETUP_HIGHLIGHTBG_COLOR.a))); - } + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), + CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255))); #endif - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - bindingWhite = 0; + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); } } } // Print bindings, including seperator (-) between them - CFont::SetScale(MENU_X(0.25f), MENU_Y(SMALLESTTEXT_Y_SCALE)); + + CFont::SetScale(MENU_X(0.25f), MENU_Y(LISTITEM_Y_SCALE)); #ifdef FIX_BUGS for (; contSetOrder < MAX_SETORDERS && controllerAction >= 0; contSetOrder++) { #else @@ -2192,9 +1918,8 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 ++bindingsForThisOpt; if (bindingsForThisOpt > 1) { wchar *seperator = TheText.Get("FEC_IBT"); - CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(nextX, nextY, seperator); - CFont::SetColor(CRGBA(bindingWhite, bindingWhite, bindingWhite, FadeIn(255))); nextX += CFont::GetStringWidth(seperator, true) + bindingMargin; } CFont::PrintString(nextX, nextY, settingText); @@ -2207,23 +1932,27 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 } } if (controllerAction == -1) { - CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_NUS")); // not used + } else if (controllerAction == -2) { - CFont::SetColor(CRGBA(20, 20, 20, FadeIn(80))); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_CMP")); // combo: l+r + } else if (bindingsForThisOpt == 0) { + m_NoEmptyBinding = false; if (m_nSelectedListRow != optionIdx) { - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound + } else if (m_bWaitingForNewKeyBind) { if (column != m_nSelectedContSetupColumn) { - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound } } else { if (column != m_nSelectedContSetupColumn) { - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); } CFont::PrintString(nextX, nextY, TheText.Get("FEC_UNB")); // unbound } @@ -2247,34 +1976,26 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 lastWaitingTextFlash = CTimer::GetTimeInMillisecondsPauseMode(); } if (showWaitingText) { - CFont::SetColor(CRGBA(55, 55, 55, FadeIn(255))); + CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); CFont::PrintString(nextX, nextY, TheText.Get("FEC_QUE")); // "???" } - SET_FONT_FOR_HELPER_TEXT - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); - if (m_bKeyChangeNotProcessed) { - CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_CIG")); // BACKSPACE TO CLEAR - LMB,RETURN TO CHANGE - } else { - CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_RIG")); // SELECT A NEW CONTROL FOR THIS ACTION OR ESC TO CANCEL - } - + if (m_bKeyChangeNotProcessed) + DisplayHelperText("FET_CIG"); + else + DisplayHelperText("FET_RIG"); + SET_FONT_FOR_LIST_ITEM - if (!m_bKeyIsOK) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); m_bKeyIsOK = true; } else { - SET_FONT_FOR_HELPER_TEXT - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); - CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_CIG")); // BACKSPACE TO CLEAR - LMB,RETURN TO CHANGE + DisplayHelperText("FET_CIG"); SET_FONT_FOR_LIST_ITEM + m_bKeyIsOK = false; m_bKeyChangeNotProcessed = false; } } else if (optionIdx == m_nSelectedListRow) { - SET_FONT_FOR_HELPER_TEXT - CFont::SetColor(CRGBA(55, 55, 55, FadeIn(255))); - CFont::PrintString(MENU_X_LEFT_ALIGNED(275.0f), SCREEN_SCALE_FROM_BOTTOM(114.0f), TheText.Get("FET_EIG")); // CANNOT SET A CONTROL FOR THIS ACTION + DisplayHelperText("FET_EIG"); SET_FONT_FOR_LIST_ITEM } } @@ -2322,7 +2043,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig if (waitingTextVisible) { CFont::SetColor(CRGBA(255, 255, 0, FadeIn(255))); CFont::PrintString(nextX, MENU_Y(yStart), TheText.Get("FEC_QUE")); - CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); } } yStart += lineHeight; @@ -2352,22 +2073,25 @@ CMenuManager::DrawControllerSetupScreen() break; } RESET_FONT_FOR_NEW_PAGE - SET_FONT_FOR_MENU_HEADER - switch (m_ControlMethod) { - case CONTROL_STANDARD: - CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), - TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - break; - case CONTROL_CLASSIC: - CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), - TheText.Get("FET_CTI")); - break; - default: - break; - } - wchar *actionTexts[31]; + // Shadow + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + + if (m_ControlMethod == CONTROL_STANDARD) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_STI")); + else if (m_ControlMethod == CONTROL_CLASSIC) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_CTI")); + + // Real header + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + + if (m_ControlMethod == CONTROL_STANDARD) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_STI")); + else if (m_ControlMethod == CONTROL_CLASSIC) + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_CTI")); + + wchar *actionTexts[33]; actionTexts[0] = TheText.Get("FEC_FIR"); actionTexts[1] = TheText.Get("FEC_NWE"); actionTexts[2] = TheText.Get("FEC_PWE"); @@ -2386,32 +2110,34 @@ CMenuManager::DrawControllerSetupScreen() actionTexts[15] = TheText.Get("FEC_SPN"); actionTexts[16] = TheText.Get("FEC_HND"); actionTexts[17] = TheText.Get("FEC_TAR"); + actionTexts[18] = TheText.Get("FEC_CRO"); + actionTexts[19] = TheText.Get("FEC_ANS"); if (m_ControlMethod == CONTROL_CLASSIC) { - actionTexts[18] = TheText.Get("FEC_TFL"); - actionTexts[19] = TheText.Get("FEC_TFR"); - actionTexts[20] = TheText.Get("FEC_TFU"); - actionTexts[21] = TheText.Get("FEC_TFD"); - actionTexts[22] = TheText.Get("FEC_LBA"); - actionTexts[23] = TheText.Get("FEC_LOL"); - actionTexts[24] = TheText.Get("FEC_LOR"); - actionTexts[25] = TheText.Get("FEC_LUD"); - actionTexts[26] = TheText.Get("FEC_LDU"); - actionTexts[27] = TheText.Get("FEC_NTR"); - actionTexts[28] = TheText.Get("FEC_PTT"); - actionTexts[29] = TheText.Get("FEC_CEN"); - actionTexts[30] = nil; + actionTexts[20] = TheText.Get("FEC_TFL"); + actionTexts[21] = TheText.Get("FEC_TFR"); + actionTexts[22] = TheText.Get("FEC_TFU"); + actionTexts[23] = TheText.Get("FEC_TFD"); + actionTexts[24] = TheText.Get("FEC_LBA"); + actionTexts[25] = TheText.Get("FEC_LOL"); + actionTexts[26] = TheText.Get("FEC_LOR"); + actionTexts[27] = TheText.Get("FEC_LUD"); + actionTexts[28] = TheText.Get("FEC_LDU"); + actionTexts[29] = TheText.Get("FEC_NTR"); + actionTexts[30] = TheText.Get("FEC_PTT"); + actionTexts[31] = TheText.Get("FEC_CEN"); + actionTexts[32] = nil; } else { - actionTexts[18] = TheText.Get("FEC_TFL"); - actionTexts[19] = TheText.Get("FEC_TFR"); - actionTexts[20] = TheText.Get("FEC_TFU"); - actionTexts[21] = TheText.Get("FEC_TFD"); - actionTexts[22] = TheText.Get("FEC_LBA"); - actionTexts[23] = TheText.Get("FEC_LOL"); - actionTexts[24] = TheText.Get("FEC_LOR"); - actionTexts[25] = nil; + actionTexts[20] = TheText.Get("FEC_TFL"); + actionTexts[21] = TheText.Get("FEC_TFR"); + actionTexts[22] = TheText.Get("FEC_TFU"); + actionTexts[23] = TheText.Get("FEC_TFD"); + actionTexts[24] = TheText.Get("FEC_LBA"); + actionTexts[25] = TheText.Get("FEC_LOL"); + actionTexts[26] = TheText.Get("FEC_LOR"); + actionTexts[27] = nil; } - // Gray panel background + // Blue panel background CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT), MENU_Y(CONTSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(CONTSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); @@ -2425,16 +2151,18 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); CFont::SetRightJustifyOff(); - CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CAC")); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CFT")); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CCR")); + CFont::SetDropShadowPosition(0); SET_FONT_FOR_LIST_ITEM - + int yStart; if (m_ControlMethod == CONTROL_CLASSIC) - yStart = CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT + 1; + yStart = CONTSETUP_LIST_TOP + 18; else - yStart = CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT + 5; + yStart = CONTSETUP_LIST_TOP + 21; float optionYBottom = yStart + rowHeight; for (int i = 0; i < ARRAY_SIZE(actionTexts); ++i) { @@ -2442,49 +2170,42 @@ CMenuManager::DrawControllerSetupScreen() if (!actionText) break; - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && - m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { - - if (m_nMousePosY > MENU_Y(i * rowHeight + yStart) && m_nMousePosY < MENU_Y(i * rowHeight + optionYBottom)) { - if (m_nOptionMouseHovering != i && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + if (!m_bWaitingForNewKeyBind) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT - 10.0f) && + m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { - m_nOptionMouseHovering = i; - if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { - m_nCurrExLayer = HOVEROPTION_LIST; - m_nSelectedListRow = i; + if (m_nMousePosY > MENU_Y(i * rowHeight + yStart) && m_nMousePosY < MENU_Y(i * rowHeight + optionYBottom)) { + m_nOptionMouseHovering = i; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_nSelectedListRow = i; - // why different number for 3rd column hovering X?? this function is a mess + // why different number for 3rd column hovering X?? this function is a mess #ifdef FIX_BUGS - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) { #else - if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) { #endif - if (m_nSelectedContSetupColumn != CONTSETUP_PED_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - - m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; + m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; #ifdef FIX_BUGS - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) { #else - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) { #endif - if (m_nSelectedContSetupColumn != CONTSETUP_VEHICLE_COLUMN && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - - m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; + } } - } - // what?? - if (m_nHoverOption == HOVEROPTION_SKIN) { - if (i == m_nSelectedListRow) { + // what?? + if (m_nHoverOption == HOVEROPTION_SKIN) { + if (i == m_nSelectedListRow) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + } else m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - } - } else - m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } } } if (m_nSelectedListRow != i) @@ -2493,578 +2214,318 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); CFont::SetRightJustifyOff(); - if (m_PrefsLanguage == LANGUAGE_GERMAN && (i == 20 || i == 21)) - CFont::SetScale(MENU_X(0.32f), MENU_Y(SMALLESTTEXT_Y_SCALE)); + if (m_PrefsLanguage == LANGUAGE_GERMAN && (i == 20 || i == 21 || i == 22 || i == 23)) + CFont::SetScale(MENU_X(0.32f), MENU_Y(LISTITEM_Y_SCALE)); else - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); + CFont::SetScale(MENU_X(LISTITEM_X_SCALE), MENU_Y(LISTITEM_Y_SCALE)); CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(i * rowHeight + yStart), actionText); } DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), rowHeight, CONTSETUP_PED_COLUMN); DrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), rowHeight, CONTSETUP_VEHICLE_COLUMN); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); - if ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) - CFont::GetStringWidth(TheText.Get("FEDS_TB"), true) - && m_nMousePosX < MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM) - && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - CONTSETUP_BACK_HEIGHT)) || m_nCurrExLayer == HOVEROPTION_BACK) { - m_nHoverOption = HOVEROPTION_BACK; + if (!m_bWaitingForNewKeyBind) { + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); - } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT + 2.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) - && m_nMousePosY > MENU_Y(CONTSETUP_LIST_TOP + CONTSETUP_LIST_HEADER_HEIGHT) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM + 5.0f)) { - m_nHoverOption = HOVEROPTION_LIST; + if ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) - CFont::GetStringWidth(TheText.Get("FEDS_TB"), true) + && m_nMousePosX < MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM) + && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - CONTSETUP_BACK_HEIGHT)) || m_nCurrExLayer == HOVEROPTION_BACK) { + m_nHoverOption = HOVEROPTION_BACK; - } else { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT - 10.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH) + && m_nMousePosY > MENU_Y(CONTSETUP_LIST_TOP - 10.0f) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)) { + m_nHoverOption = HOVEROPTION_LIST; + + } else { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } } // Back button and it's shadow CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); CFont::SetRightJustifyOn(); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); - for (int i = 0; i < 2; i++) { - CFont::PrintString(MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT - 2.0f - i), - SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - 4.0f - i), TheText.Get("FEDS_TB")); - - if (m_nHoverOption == HOVEROPTION_BACK) - CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); - else - CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); - } + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT - 2.0f), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - 4.0f), TheText.Get("FEDS_TB")); } void CMenuManager::DrawFrontEnd() { CFont::SetAlphaFade(255.0f); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + SetFrontEndRenderStates(); + m_NoEmptyBinding = true; -#ifdef PS2_LIKE_MENU - #define setBbItem(a, b, c) strcpy(a.name, b); a.screenId = c; - if (m_nCurrScreen == MENUPAGE_NONE) { - if (m_bGameNotLoaded) { - if (bbTabCount != 6) { - setBbItem(bbNames[0], "FEB_SAV",MENUPAGE_NEW_GAME) - setBbItem(bbNames[1], "FEB_CON",MENUPAGE_CONTROLLER_PC) - setBbItem(bbNames[2], "FEB_AUD",MENUPAGE_SOUND_SETTINGS) - setBbItem(bbNames[3], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS) - setBbItem(bbNames[4], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS) - setBbItem(bbNames[5], "FESZ_QU",MENUPAGE_EXIT) - bbTabCount = 6; - } - } else { - if (bbTabCount != 8) { - setBbItem(bbNames[0], "FEB_STA",MENUPAGE_STATS) - setBbItem(bbNames[1], "FEB_SAV",MENUPAGE_NEW_GAME) - setBbItem(bbNames[2], "FEB_BRI",MENUPAGE_BRIEFS) - setBbItem(bbNames[3], "FEB_CON",MENUPAGE_CONTROLLER_PC) - setBbItem(bbNames[4], "FEB_AUD",MENUPAGE_SOUND_SETTINGS) - setBbItem(bbNames[5], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS) - setBbItem(bbNames[6], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS) - setBbItem(bbNames[7], "FESZ_QU",MENUPAGE_EXIT) - bbTabCount = 8; - } - } - m_nCurrScreen = bbNames[0].screenId; - bottomBarActive = true; - curBottomBarOption = 0; - } - #undef setBbItem -#else if (m_nCurrScreen == MENUPAGE_NONE) { if (m_bGameNotLoaded) { m_nCurrScreen = MENUPAGE_START_MENU; } else { m_nCurrScreen = MENUPAGE_PAUSE_MENU; } + SETUP_SCROLLING(m_nCurrScreen) } -#endif if (m_nCurrOption == 0 && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) m_nCurrOption = 1; -#ifdef PS2_SAVE_DIALOG - if(m_bRenderGameInMenu) - DrawFrontEndSaveZone(); - else -#endif - DrawFrontEndNormal(); + if (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255) + bMenuChangeOngoing = false; - PrintErrorMessage(); + DrawBackground(false); } -#ifdef PS2_SAVE_DIALOG void -CMenuManager::DrawFrontEndSaveZone() +CMenuManager::DrawBackground(bool transitionCall) { - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); - - // Not original dimensions, have been changed to fit PC screen & PC menu layout. - CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(30.0f), SCREEN_SCALE_FROM_BOTTOM(50.0f)), CRGBA(0, 0, 0, 175)); - - m_nMenuFadeAlpha = 255; - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - Draw(); - - CFont::DrawFonts(); - - // Draw mouse - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - if (m_bShowMouse) { - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - - CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f)); - CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f)); - - mouse.Translate(m_nMousePosX, m_nMousePosY); - shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - } - } -} -#endif + if (!m_bSpritesLoaded) + return; -#ifdef PS2_LIKE_MENU -void -CMenuManager::DrawFrontEndNormal() -{ - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + SetFrontEndRenderStates(); - if (!m_bGameNotLoaded) { - CSprite2d *bg = LoadSplash(nil); - bg->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(48, 48, 48, 255)); - } else { + if (m_firstStartCounter < 255) { CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - m_aFrontEndSprites[FE2_MAINPANEL_UL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), 0.0f, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255)); - m_aFrontEndSprites[FE2_MAINPANEL_UR].Draw(CRect(SCREEN_WIDTH / 2, 0.0f, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255)); - m_aFrontEndSprites[FE2_MAINPANEL_DL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), SCREEN_HEIGHT / 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - m_aFrontEndSprites[FE2_MAINPANEL_DR].Draw(CRect(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - eFrontendSprites currentSprite; - switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - case MENUPAGE_EXIT: - currentSprite = FE_ICONSTATS; - break; - case MENUPAGE_LANGUAGE_SETTINGS: - currentSprite = FE_ICONLANGUAGE; - break; - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - currentSprite = FE_ICONSAVE; - break; - case MENUPAGE_DISPLAY_SETTINGS: - currentSprite = FE_ICONDISPLAY; - break; - case MENUPAGE_SOUND_SETTINGS: - currentSprite = FE_ICONAUDIO; - break; - case MENUPAGE_CONTROLLER_PC: - case MENUPAGE_OPTIONS: - case MENUPAGE_CONTROLLER_SETTINGS: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - currentSprite = FE_ICONCONTROLS; - break; - default: - /*case MENUPAGE_NEW_GAME: */ - /*case MENUPAGE_BRIEFS: */ - currentSprite = FE_ICONBRIEF; - break; - } - - static float fadeAlpha = 0.0f; + if (m_nMenuFadeAlpha != 0) { - if (m_nMenuFadeAlpha < 255) { - m_nMenuFadeAlpha += 20 * CTimer::GetLogicalFramesPassed(); - } else { - // TODO: what is this? waiting mouse? - if(field_518 == 4){ - if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || - m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) + if (m_nMenuFadeAlpha < 255) { - field_518 = 2; - else - field_518 = 1; - } - } + menuBg.Translate(m_nMenuFadeAlpha); + SetFrontEndRenderStates(); + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_MAP) + PrintMap(); - m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); + // Left border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT, + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - switch (m_nCurrScreen) { - case MENUPAGE_SKIN_SELECT: - DrawPlayerSetupScreen(); - break; - case MENUPAGE_KEYBOARD_CONTROLS: - DrawControllerSetupScreen(); - break; - default: - Draw(); - break; - } + // Top border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); - // Positions/style from PS2 menu, credits to Fire_Head - /* Draw controller buttons */ - CFont::SetFontStyle(FONT_BANK); - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.35f), SCREEN_SCALE_Y(0.64f)); - CFont::SetPropOn(); - CFont::SetCentreOff(); - CFont::SetJustifyOn(); - CFont::SetRightJustifyOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); // 600.0f - CFont::SetColor(CRGBA(16, 16, 16, 255)); - switch (m_nCurrScreen) { + // Bottom border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255)); - // Page names overlaps buttons on those. - case MENUPAGE_MOUSE_CONTROLS: - case MENUPAGE_KEYBOARD_CONTROLS: - break; - - default: - { - CFont::PrintString(MENU_X_LEFT_ALIGNED(52.0f), MENU_Y(360.0f), TheText.Get("FEDS_SE")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(52.0f), MENU_Y(372.0f), TheText.Get("FEDS_BA")); - if (!m_bGameNotLoaded) - CFont::PrintString(MENU_X_LEFT_ALIGNED(52.0f), MENU_Y(384.0f), TheText.Get("FEDS_ST")); - - if (bottomBarActive) - CFont::PrintString(MENU_X_LEFT_ALIGNED(242.0f), MENU_Y(372.0f), TheText.Get("FEDS_AM")); // <>-CHANGE MENU - else if (m_nCurrScreen != MENUPAGE_STATS && m_nCurrScreen != MENUPAGE_BRIEFS) { - CFont::PrintString(MENU_X_LEFT_ALIGNED(242.0f), MENU_Y(360.0f + 3.5f), TheText.Get("FEA_UP")); // ; - CFont::PrintString(MENU_X_LEFT_ALIGNED(242.0f), MENU_Y(384.0f - 3.5f), TheText.Get("FEA_DO")); // = - CFont::PrintString(MENU_X_LEFT_ALIGNED(242.0f - 10.0f), MENU_Y(372.0f), TheText.Get("FEA_LE")); // < - CFont::PrintString(MENU_X_LEFT_ALIGNED(242.0f + 11.0f), MENU_Y(372.0f), TheText.Get("FEA_RI")); // > - CFont::PrintString(MENU_X_LEFT_ALIGNED(242.0f + 20.0f), MENU_Y(372.0f), TheText.Get("FEDSAS3")); // - CHANGE SELECTION - } - - break; - } - } - - #define optionWidth MENU_X(66.0f) - #define rawOptionHeight 22.0f - #define optionBottom SCREEN_SCALE_FROM_BOTTOM(20.0f) - #define optionTop SCREEN_SCALE_FROM_BOTTOM(20.0f + rawOptionHeight) - #define leftPadding MENU_X_LEFT_ALIGNED(90.0f) - wchar *str; - hoveredBottomBarOption = -1; - if (curBottomBarOption != -1) { - - // This active tab sprite is needlessly big - m_aFrontEndSprites[FE2_TABACTIVE].Draw(CRect(leftPadding - MENU_X(2.0f) + (optionWidth) * curBottomBarOption, optionTop, - leftPadding - MENU_X(5.0f) + optionWidth * (curBottomBarOption + 2), optionBottom + MENU_Y(rawOptionHeight - 9.0f)), - CRGBA(CRGBA(255, 255, 255, 255))); - - for (int i = 0; i < bbTabCount; i++) { - float xStart = leftPadding + optionWidth * i; - if (CheckHover(xStart, xStart + optionWidth, optionTop, optionBottom)) - hoveredBottomBarOption = i; - - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(0.35f), MENU_Y(0.7f)); - CFont::SetRightJustifyOff(); - if (hoveredBottomBarOption == i && hoveredBottomBarOption != curBottomBarOption) - CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, 255)); - else { - if(bottomBarActive || curBottomBarOption == i) - CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, 255)); - else - CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, 110)); - } - - str = TheText.Get(bbNames[i].name); - - CFont::PrintString(xStart + MENU_X(4.0f), SCREEN_SCALE_FROM_BOTTOM(39.0f), str); - - } - } - #undef optionBottom - #undef optionTop - #undef leftPadding - #undef optionWidth - #undef rawOptionHeight - - CFont::DrawFonts(); - - // Draw mouse - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - if (m_bShowMouse) { - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - - CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f)); - CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f)); - - mouse.Translate(m_nMousePosX, m_nMousePosY); - shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); + // Right border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255)); + } else { + m_nMenuFadeAlpha = 255; + m_firstStartCounter = 255; + m_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255))); + if (m_nCurrScreen == MENUPAGE_MAP) + PrintMap(); + + // Left border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT, + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Top border + CSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), + SCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255)); + + // Bottom border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255)); + + // Right border + CSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y), + SCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255)); } - } -} -#else -void -CMenuManager::DrawFrontEndNormal() -{ - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - - LoadSplash(nil); - - eMenuSprites previousSprite; - if (m_nMenuFadeAlpha < 255) { - switch (m_nPrevScreen) { + } else { + menuBg.SaveCurrentCoors(); + switch (m_nCurrScreen) { case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - previousSprite = MENUSPRITE_MAINMENU; - break; - case MENUPAGE_NEW_GAME: - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_EXIT: - previousSprite = MENUSPRITE_SINGLEPLAYER; + menuBg.topLeft_x = 70.0f; + menuBg.topLeft_y = 75.0f; + menuBg.topRight_x = 550.0f; + menuBg.topRight_y = 16.0f; + menuBg.bottomLeft_x = 74.0f; + menuBg.bottomLeft_y = 354.0f; + menuBg.bottomRight_x = 581.0f; + menuBg.bottomRight_y = 340.0f; break; - case MENUPAGE_MULTIPLAYER_MAIN: - previousSprite = MENUSPRITE_MULTIPLAYER; + case MENUPAGE_SOUND_SETTINGS: + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 438.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 410.0f; break; - case MENUPAGE_MULTIPLAYER_MAP: - case MENUPAGE_MULTIPLAYER_FIND_GAME: case MENUPAGE_SKIN_SELECT: case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - previousSprite = MENUSPRITE_FINDGAME; - break; - case MENUPAGE_MULTIPLAYER_CONNECTION: - case MENUPAGE_MULTIPLAYER_MODE: - previousSprite = MENUSPRITE_CONNECTION; - break; - case MENUPAGE_MULTIPLAYER_CREATE: - previousSprite = MENUSPRITE_HOSTGAME; + menuBg.topLeft_x = 14.0f; + menuBg.topLeft_y = 39.0f; + menuBg.topRight_x = 636.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 630.0f; + menuBg.bottomRight_y = 398.0f; break; - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - previousSprite = MENUSPRITE_PLAYERSET; + case MENUPAGE_BRIEFS: + case MENUPAGE_DISPLAY_SETTINGS: + case MENUPAGE_MAP: + case MENUPAGE_CHOOSE_LOAD_SLOT: + case MENUPAGE_CHOOSE_DELETE_SLOT: + case MENUPAGE_CHOOSE_SAVE_SLOT: + case MENUPAGE_MOUSE_CONTROLS: + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 398.0f; break; default: #ifdef CUSTOM_FRONTEND_OPTIONS - CCustomScreenLayout *custom = aScreens[m_nPrevScreen].layout; - if (custom) { - previousSprite = custom->sprite; + if (aScreens[m_nCurrScreen].layout && aScreens[m_nCurrScreen].layout->noInvasiveBorders) { + // Taken from the case above + menuBg.topLeft_x = 26.0f; + menuBg.topLeft_y = 59.0f; + menuBg.topRight_x = 629.0f; + menuBg.topRight_y = 29.0f; + menuBg.bottomLeft_x = 15.0f; + menuBg.bottomLeft_y = 426.0f; + menuBg.bottomRight_x = 610.0f; + menuBg.bottomRight_y = 398.0f; break; } - if (!custom) #endif - previousSprite = MENUSPRITE_MAINMENU; + menuBg.topLeft_x = CGeneral::GetRandomNumber() % 40 + 65; + menuBg.topLeft_y = CGeneral::GetRandomNumber() % 40 + 21; + menuBg.topRight_x = CGeneral::GetRandomNumber() % 40 + 568; + menuBg.topRight_y = CGeneral::GetRandomNumber() % 40 + 44; + menuBg.bottomLeft_x = CGeneral::GetRandomNumber() % 40 + 36; + menuBg.bottomLeft_y = CGeneral::GetRandomNumber() % 40 + 382; + menuBg.bottomRight_x = CGeneral::GetRandomNumber() % 40 + 593; + menuBg.bottomRight_y = CGeneral::GetRandomNumber() % 40 + 342; break; } - - if (m_nPrevScreen == m_nCurrScreen) - CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255 - m_nMenuFadeAlpha)); - else - m_aMenuSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha)); - } - - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - eMenuSprites currentSprite = MENUSPRITE_MAINMENU; // actually uninitialized - switch (m_nCurrScreen) { - case MENUPAGE_STATS: - case MENUPAGE_START_MENU: - case MENUPAGE_PAUSE_MENU: - currentSprite = MENUSPRITE_MAINMENU; - break; - case MENUPAGE_NEW_GAME: - case MENUPAGE_CHOOSE_LOAD_SLOT: - case MENUPAGE_CHOOSE_DELETE_SLOT: - case MENUPAGE_NEW_GAME_RELOAD: - case MENUPAGE_LOAD_SLOT_CONFIRM: - case MENUPAGE_DELETE_SLOT_CONFIRM: - case MENUPAGE_EXIT: - currentSprite = MENUSPRITE_SINGLEPLAYER; - break; - case MENUPAGE_MULTIPLAYER_MAIN: - currentSprite = MENUSPRITE_MULTIPLAYER; - break; - case MENUPAGE_MULTIPLAYER_MAP: - case MENUPAGE_MULTIPLAYER_FIND_GAME: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_KEYBOARD_CONTROLS: - case MENUPAGE_MOUSE_CONTROLS: - currentSprite = MENUSPRITE_FINDGAME; - break; - case MENUPAGE_MULTIPLAYER_CONNECTION: - case MENUPAGE_MULTIPLAYER_MODE: - currentSprite = MENUSPRITE_CONNECTION; - break; - case MENUPAGE_MULTIPLAYER_CREATE: - currentSprite = MENUSPRITE_HOSTGAME; - break; - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - currentSprite = MENUSPRITE_PLAYERSET; - break; -#ifdef CUSTOM_FRONTEND_OPTIONS - default: - CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout; - if (custom) { - previousSprite = custom->sprite; - } - break; -#endif + menuBg.UpdateMultipliers(); + if (m_firstStartCounter == 255) + m_nOptionHighlightTransitionBlend = 0; } - if (m_nMenuFadeAlpha < 255) { - - // Famous transparent menu bug -#ifdef FIX_BUGS - m_nMenuFadeAlpha += 20 * CTimer::GetLogicalFramesPassed(); -#else - static uint32 LastFade = 0; + static uint32 LastFade = 0; - if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ + if (m_nMenuFadeAlpha < 255) { + static uint8 forceFadeInCounter = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 30 + || forceFadeInCounter > 30 + ) { m_nMenuFadeAlpha += 20; + if (m_firstStartCounter < 255) { + m_firstStartCounter = Min(m_firstStartCounter + 20, 255); + } LastFade = CTimer::GetTimeInMillisecondsPauseMode(); - } +#ifdef FIX_BUGS + forceFadeInCounter = 0; #endif - - if (m_nMenuFadeAlpha > 255){ - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - } else { - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); } - } else { - m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); - // TODO: what is this? waiting mouse? - if(field_518 == 4){ - if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || - m_nHoverOption == HOVEROPTION_5 || m_nHoverOption == HOVEROPTION_6 || m_nHoverOption == HOVEROPTION_7) - - field_518 = 2; - else - field_518 = 1; - } - } - -#ifdef RED_DELETE_BACKGROUND - if (m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT || m_nCurrScreen == MENUPAGE_DELETE_SLOT_CONFIRM) { - CSprite2d::Draw2DPolygon(0.0f, 0.0f, - SCREEN_WIDTH, 0.0f, - 0.0f, SCREEN_HEIGHT, - SCREEN_WIDTH, SCREEN_HEIGHT, - CRGBA(150, 0, 0, 80)); - } +#ifdef FIX_BUGS + forceFadeInCounter += CTimer::GetLogicalFramesPassed(); +#else + forceFadeInCounter++; #endif + } else if (m_nMenuFadeAlpha > 255) + m_nMenuFadeAlpha = 255; - // GTA LOGO - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) { - if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - m_aMenuSprites[MENUSPRITE_GTA3LOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); - else - m_aMenuSprites[MENUSPRITE_GTALOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); + if (!transitionCall && m_firstStartCounter == 255) { + int actualAlpha = m_nMenuFadeAlpha; + if (actualAlpha < 255) { + int actualScreen = m_nCurrScreen; + SetFrontEndRenderStates(); + m_nCurrScreen = m_nPrevScreen; + m_nMenuFadeAlpha = 255 - m_nMenuFadeAlpha; + switch (m_nCurrScreen) { + case MENUPAGE_SKIN_SELECT: + DrawPlayerSetupScreen(false); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + DrawControllerSetupScreen(); + break; + case MENUPAGE_OUTRO: + DrawQuitGameScreen(); + break; + default: + DrawStandardMenus(false); + break; + } + m_nCurrScreen = actualScreen; + m_nMenuFadeAlpha = actualAlpha; + } } - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); switch (m_nCurrScreen) { case MENUPAGE_SKIN_SELECT: - DrawPlayerSetupScreen(); + DrawPlayerSetupScreen(true); break; case MENUPAGE_KEYBOARD_CONTROLS: DrawControllerSetupScreen(); break; + case MENUPAGE_OUTRO: + DrawQuitGameScreen(); + break; default: - Draw(); + DrawStandardMenus(true); break; } CFont::DrawFonts(); + SetFrontEndRenderStates(); - // Draw mouse - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - if (m_bShowMouse) { - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + if (m_nCurrScreen != MENUPAGE_OUTRO) + if (m_firstStartCounter == 255) { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); + } else { + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); + } - CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f)); - CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f)); + if (m_ShowEmptyBindingError) { + static uint32 lastBindingError = CTimer::GetTimeInMillisecondsPauseMode(); + static bool bindingErrorShown = false; + if (bindingErrorShown) { + lastBindingError = CTimer::GetTimeInMillisecondsPauseMode(); + bindingErrorShown = false; + } + SmallMessageScreen("FEC_ERI"); + CFont::DrawFonts(); + if (CTimer::GetTimeInMillisecondsPauseMode() - lastBindingError > 4000) { + m_ShowEmptyBindingError = false; + bindingErrorShown = true; + } + } + + if (m_bShowMouse) { + CRect mouse(0.0f, 0.0f, MENU_X(35.0f), MENU_Y(35.0f)); + CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(45.0f), MENU_Y(38.0f)); mouse.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY); - if(field_518 == 4){ - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); - }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); - } + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); } } -#endif void -CMenuManager::DrawPlayerSetupScreen() +CMenuManager::DrawPlayerSetupScreen(bool activeScreen) { RESET_FONT_FOR_NEW_PAGE - SET_FONT_FOR_MENU_HEADER - - CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); - // lstrcpy's changed with strcpy - if (!m_bSkinsEnumerated) { OutputDebugString("Enumerating skin filenames from skins..."); m_pSkinListHead.nextSkin = nil; @@ -3147,8 +2608,14 @@ CMenuManager::DrawPlayerSetupScreen() m_bSkinsEnumerated = true; } CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), - MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), - CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + + SET_FONT_FOR_MENU_HEADER + CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_PS")); + + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // Header (Skin - Date) if (m_nCurrExLayer == HOVEROPTION_LIST) { @@ -3156,7 +2623,8 @@ CMenuManager::DrawPlayerSetupScreen() } else { CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); CFont::SetRightJustifyOn(); CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_DAT")); @@ -3171,6 +2639,7 @@ CMenuManager::DrawPlayerSetupScreen() } CFont::SetRightJustifyOff(); CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get("FES_SKN")); + CFont::SetDropShadowPosition(0); // Skin list SET_FONT_FOR_LIST_ITEM @@ -3195,13 +2664,11 @@ CMenuManager::DrawPlayerSetupScreen() if (rowIdx == m_nSelectedListRow) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; if (m_nSkinsTotal > 0) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); } } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); m_nCurrExLayer = HOVEROPTION_LIST; m_nSelectedListRow = rowIdx; m_nHoverOption = HOVEROPTION_NOT_HOVERING; @@ -3244,7 +2711,7 @@ CMenuManager::DrawPlayerSetupScreen() ++rowIdx; m_pSelectedSkin = m_pSelectedSkin->nextSkin; } - // Scrollbar background + // Scrollbar background - it's unchanged since III and still yellowish... CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205))); @@ -3281,21 +2748,21 @@ CMenuManager::DrawPlayerSetupScreen() // 2 - leaves gap between button and scrollbar if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), CRGBA(255, 255, 255, FadeIn(255))); #endif } else { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), + m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), MENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), CRGBA(255, 255, 255, FadeIn(255))); #endif @@ -3303,27 +2770,28 @@ CMenuManager::DrawPlayerSetupScreen() if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), + m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), + m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), CRGBA(255, 255, 255, FadeIn(255))); #endif } else { #ifdef FIX_BUGS - m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), + m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), CRGBA(255, 255, 255, FadeIn(255))); #else - m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f), + m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f), MENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), CRGBA(255, 255, 255, FadeIn(255))); #endif } - CPlayerSkin::RenderFrontendSkinEdit(); + if (activeScreen) + CPlayerSkin::RenderFrontendSkinEdit(); // Big apply button if (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { @@ -3343,35 +2811,29 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f)); break; } - CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(120))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(120))); CFont::SetRightJustifyOff(); - CFont::PrintString(MENU_X_LEFT_ALIGNED(20.0f), MENU_Y(220.0f), TheText.Get("FET_APL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(24.0f), MENU_Y(220.0f), TheText.Get("FET_APP")); } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); if ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1) - CFont::GetStringWidth(TheText.Get("FEDS_TB"), true) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 26)) || m_nCurrExLayer == HOVEROPTION_BACK) { - if (m_nHoverOption != HOVEROPTION_BACK) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); m_nHoverOption = HOVEROPTION_BACK; - } else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0 && m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) + CFont::GetStringWidth(TheText.Get("FES_SET"), true) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 26)) || m_nCurrExLayer == HOVEROPTION_USESKIN) { - if (m_nHoverOption != HOVEROPTION_USESKIN) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); m_nHoverOption = HOVEROPTION_USESKIN; - } else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2) && m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_TOP) @@ -3426,86 +2888,46 @@ CMenuManager::DrawPlayerSetupScreen() } } CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); CFont::SetRightJustifyOn(); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // Back button - for (int i = 0; i < 2; i++) { - CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - i), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FEDS_TB")); - if (m_nHoverOption == HOVEROPTION_BACK) { - CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); - } else { - CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); - } - } + CFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5), TheText.Get("FEDS_TB")); CFont::SetRightJustifyOff(); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); - // Use skin button - for (int i = 0; i < 2; i++) { - CFont::PrintString(MENU_X_LEFT_ALIGNED(i + PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5 - i), TheText.Get("FES_SET")); - if (!strcmp(m_aSkinName, m_PrefsSkinFile)) { - CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); - } else if (m_nHoverOption == HOVEROPTION_USESKIN) { - CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255))); - } else { - CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); - } + if (!strcmp(m_aSkinName, m_PrefsSkinFile)) { + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } else { + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); } + // Use skin button + CFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5), TheText.Get("FES_SET")); + CFont::SetDropShadowPosition(0); } int CMenuManager::FadeIn(int alpha) { - if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS || - m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS || - m_nCurrScreen == MENUPAGE_DELETING) - return alpha; - return Min(m_nMenuFadeAlpha, alpha); } -void -CMenuManager::FilterOutColorMarkersFromString(wchar *str, CRGBA &newColor) -{ - int newIdx = 0; - wchar copy[256], *c; - UnicodeStrcpy(copy, str); - - for (c = copy; *c != '\0'; c++) { - if (*c == '~') { - c++; - switch (*c) { - case 'b': newColor = CRGBA(40, 40, 255, 255); break; - case 'g': newColor = CRGBA(40, 235, 40, 255); break; - // There is no case for "h", is that a mistake? - case 'l': newColor = CRGBA(0, 0, 0, 255); break; - case 'p': newColor = CRGBA(255, 0, 255, 255); break; - case 'r': newColor = CRGBA(255, 0, 0, 255); break; - case 'w': newColor = CRGBA(255, 255, 255, 255); break; - case 'y': newColor = CRGBA(255, 255, 0, 255); break; - } - while (*c != '~') c++; - } else { - str[newIdx++] = *c; - } - } - str[newIdx] = '\0'; -} - int CMenuManager::GetStartOptionsCntrlConfigScreens() { int number = 0; switch (m_nCurrScreen) { +#ifdef LEGACY_MENU_OPTIONS case MENUPAGE_CONTROLLER_PC_OLD3: number = 34; break; case MENUPAGE_CONTROLLER_DEBUG: number = 35; break; +#endif case MENUPAGE_KEYBOARD_CONTROLS: number = 0; break; @@ -3569,6 +2991,7 @@ CMenuManager::InitialiseChangedLanguageSettings() default: break; } + } } @@ -3578,182 +3001,92 @@ CMenuManager::LoadAllTextures() if (m_bSpritesLoaded) return; - CentreMousePointer(); - DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); - m_nCurrOption = 0; - -#ifdef FIX_BUGS - static bool firstTime = true; - if (firstTime) { - DMAudio.SetRadioInCar(m_PrefsRadioStation); - firstTime = false; - } else -#endif - m_PrefsRadioStation = DMAudio.GetRadioInCar(); - - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = CGeneral::GetRandomNumber() % (USERTRACK + 1); - } else if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = CGeneral::GetRandomNumber() % (CHATTERBOX + 1); - - CFileMgr::SetDir(""); - //CFileMgr::SetDir(""); + // First icon is hidden behind arrow + m_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE); CTimer::Stop(); + CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile CStreaming::ImGonnaUseStreamingMemory(); CGame::TidyUpMemory(false, true); CTxdStore::PushCurrentTxd(); - int frontendTxdSlot = CTxdStore::FindTxdSlot("frontend"); + int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1"); - if(frontendTxdSlot == -1) - frontendTxdSlot = CTxdStore::AddTxdSlot("frontend"); + if(frontendTxdSlot1 == -1) + frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1"); - printf("LOAD frontend\n"); - CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD"); - CTxdStore::AddRef(frontendTxdSlot); - CTxdStore::SetCurrentTxd(frontendTxdSlot); -#if GTA_VERSION < GTA3_PC_11 - CStreaming::IHaveUsedStreamingMemory(); - CTimer::Update(); -#endif + printf("LOAD frontend1\n"); + CTxdStore::LoadTxd(frontendTxdSlot1, "MODELS/FRONTEN1.TXD"); + CTxdStore::AddRef(frontendTxdSlot1); + CTxdStore::SetCurrentTxd(frontendTxdSlot1); - for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); i++) { + for (int i = 0; i < 3; i++) { m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } -#ifdef GAMEPAD_MENU - LoadController(m_PrefsControllerType); -#endif - - int menuTxdSlot = CTxdStore::FindTxdSlot("menu"); - - if (menuTxdSlot == -1) - menuTxdSlot = CTxdStore::AddTxdSlot("menu"); - - printf("LOAD sprite\n"); - CTxdStore::LoadTxd(menuTxdSlot, "MODELS/MENU.TXD"); - CTxdStore::AddRef(menuTxdSlot); - CTxdStore::SetCurrentTxd(menuTxdSlot); - - for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) { - m_aMenuSprites[i].SetTexture(MenuFilenames[i][0], MenuFilenames[i][1]); - m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); - } -#ifdef MENU_MAP - static bool menuOptionAdded = false; - for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) { - RwTexture *firstTile; - if (!menuOptionAdded && (firstTile = RwTextureRead(MapFilenames[i][0], MapFilenames[i][1]))) { - RwTextureDestroy(firstTile); - FrontendOptionSetCursor(MENUPAGE_PAUSE_MENU, 2, false); - FrontendOptionAddBuiltinAction("FEG_MAP", MENUACTION_CHANGEMENU, MENUPAGE_MAP, SAVESLOT_NONE); - menuOptionAdded = true; - } - m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]); - m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); - } - fMapSize = SCREEN_HEIGHT * 2.0f; - fMapCenterX = 0.0f; - fMapCenterY = 0.0f; -#endif -#if GTA_VERSION >= GTA3_PC_11 - CStreaming::IHaveUsedStreamingMemory(); - CTimer::Update(); -#endif - m_bSpritesLoaded = true; CTxdStore::PopCurrentTxd(); -} + CStreaming::IHaveUsedStreamingMemory(); -#ifdef GAMEPAD_MENU -const char* controllerTypesPaths[] = { - nil, - "MODELS/FRONTEND_DS3.TXD", - "MODELS/FRONTEND_DS4.TXD", - "MODELS/FRONTEND_X360.TXD", - "MODELS/FRONTEND_XONE.TXD", -}; + if (!m_OnlySaveMenu) { + CStreaming::MakeSpaceFor(692 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); -void -CMenuManager::LoadController(int8 type) -{ - switch (type) - { - case CONTROLLER_DUALSHOCK2: - case CONTROLLER_DUALSHOCK3: - case CONTROLLER_DUALSHOCK4: - CFont::LoadButtons("MODELS/PS3BTNS.TXD"); - break; - default: - CFont::LoadButtons("MODELS/X360BTNS.TXD"); - break; - } + int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2"); - // Unload current textures - for (int i = FE_CONTROLLER; i <= FE_ARROWS4; i++) - m_aFrontEndSprites[i].Delete(); + if (frontendTxdSlot2 == -1) + frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2"); - // Unload txd - int frontend_controller = CTxdStore::FindTxdSlot("frontend_controller"); - if (frontend_controller != -1) - CTxdStore::RemoveTxd(frontend_controller); + printf("LOAD frontend2\n"); + CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD"); + CTxdStore::AddRef(frontendTxdSlot2); + CTxdStore::SetCurrentTxd(frontendTxdSlot2); - // Find the new txd to load - bool bTxdMissing = true; - if (controllerTypesPaths[type]) - if (int file = CFileMgr::OpenFile(controllerTypesPaths[type])) { - CFileMgr::CloseFile(file); - bTxdMissing = false; +#ifdef GAMEPAD_MENU + for (int i = 3; i < MENUSPRITE_CONTROLLER; i++) { +#else + for (int i = 3; i < NUM_MENU_SPRITES; i++) { +#endif + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } - int txdSlot = -1; - - if (bTxdMissing) - // Not found, fall back to original textures - txdSlot = CTxdStore::FindTxdSlot("frontend"); - else { - // Found, load txd - txdSlot = frontend_controller; - if (txdSlot == -1) - txdSlot = CTxdStore::AddTxdSlot("frontend_controller"); - CTxdStore::LoadTxd(txdSlot, controllerTypesPaths[type]); - CTxdStore::AddRef(txdSlot); + CTxdStore::PopCurrentTxd(); +#ifdef GAMEPAD_MENU + LoadController(m_PrefsControllerType); +#endif + CStreaming::IHaveUsedStreamingMemory(); } - assert(txdSlot != -1); - // Load new textures - CTxdStore::SetCurrentTxd(txdSlot); - for (int i = FE_CONTROLLER; i <= FE_ARROWS4; i++) { - m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); - m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); - } + m_bSpritesLoaded = true; + CTimer::Update(); } -#endif // GAMEPAD_MENU void CMenuManager::LoadSettings() { CFileMgr::SetDirMyDocuments(); - int fileHandle = CFileMgr::OpenFile("gta3.set", "r"); + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "r"); int32 prevLang = m_PrefsLanguage; -#if GTA_VERSION >= GTA3_PC_11 - CMBlur::BlurOn = (_dwOperatingSystemVersion != OS_WIN98); -#else - CMBlur::BlurOn = true; -#endif MousePointerStateHelper.bInvertVertically = true; + CMBlur::BlurOn = false; // 50 is silly - char Ver[50]; + char headerText[50]; + int someVersion = 0; + bool fileIsValid = true; if (fileHandle) { - CFileMgr::Read(fileHandle, Ver, 29); + CFileMgr::Read(fileHandle, headerText, 29); - if (strncmp(Ver, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1)) { + if (strncmp(headerText, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1) == 0) { + fileIsValid = false; + } else { CFileMgr::Seek(fileHandle, 0, 0); + CFileMgr::Read(fileHandle, (char*)&someVersion, sizeof(someVersion)); + } + if (fileIsValid && someVersion >= 3) { ControlsManager.LoadSettings(fileHandle); #ifdef IMPROVED_VIDEOMODE CFileMgr::Read(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth)); @@ -3778,30 +3111,36 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, gString, 4); CFileMgr::Read(fileHandle, gString, 4); CFileMgr::Read(fileHandle, gString, 1); +#ifdef LEGACY_MENU_OPTIONS + CFileMgr::Read(fileHandle, (char*)&m_PrefsVsyncDisp, 1); + CFileMgr::Read(fileHandle, (char*)&CMBlur::BlurOn, 1); +#else CFileMgr::Read(fileHandle, gString, 1); CFileMgr::Read(fileHandle, gString, 1); +#endif CFileMgr::Read(fileHandle, (char*)&TheCamera.m_bHeadBob, 1); CFileMgr::Read(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4); - CFileMgr::Read(fileHandle, (char*)&TheCamera.m_fMouseAccelVertical, 4); CFileMgr::Read(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1); CFileMgr::Read(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsSfxVolume, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsMusicVolume, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsRadioStation, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsSpeakers, 1); CFileMgr::Read(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsDMA, 1); - CFileMgr::Read(fileHandle, (char*)&m_PrefsBrightness, 1); - CFileMgr::Read(fileHandle, (char*)&m_PrefsLOD, 4); + CFileMgr::Read(fileHandle, (char*)&m_PrefsBrightness, 2); + CFileMgr::Read(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD)); CFileMgr::Read(fileHandle, (char*)&m_PrefsShowSubtitles, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsUseWideScreen, 1); - CFileMgr::Read(fileHandle, (char*)&m_PrefsVsyncDisp, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsFrameLimiter, 1); CFileMgr::Read(fileHandle, (char*)&m_nDisplayVideoMode, 1); - CFileMgr::Read(fileHandle, (char*)&CMBlur::BlurOn, 1); CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowLegends, 1); } } @@ -3812,26 +3151,33 @@ CMenuManager::LoadSettings() if (LoadINISettings()) { LoadINIControllerSettings(); } - // if no re3.ini, create it, or update it with new values + // if no reVC.ini, create it, or update it with new values SaveINISettings(); SaveINIControllerSettings(); #endif +#ifdef FIX_BUGS + TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; +#endif +#ifdef PC_PLAYER_CONTROLS + CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; +#endif +#ifdef LEGACY_MENU_OPTIONS m_PrefsVsync = m_PrefsVsyncDisp; +#endif CRenderer::ms_lodDistScale = m_PrefsLOD; - if (m_nPrefsAudio3DProviderIndex == -1) + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = -2; + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; + if (m_PrefsLanguage == prevLang) m_bLanguageLoaded = false; else { m_bLanguageLoaded = true; - // Already called in InitialiseChangedLanguageSettings - /* TheText.Unload(); TheText.Load(); - */ m_bFrontEnd_ReloadObrTxtGxt = true; InitialiseChangedLanguageSettings(); @@ -3862,11 +3208,17 @@ CMenuManager::SaveSettings() { #ifndef LOAD_INI_SETTINGS static char RubbishString[48] = "stuffmorestuffevenmorestuff etc"; +#ifdef BIND_VEHICLE_FIREWEAPON + static int SomeVersion = 4; +#else + static int SomeVersion = 3; +#endif CFileMgr::SetDirMyDocuments(); - int fileHandle = CFileMgr::OpenFile("gta3.set", "w+"); + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "w+"); if (fileHandle) { + CFileMgr::Write(fileHandle, (char*)&SomeVersion, sizeof(SomeVersion)); ControlsManager.SaveSettings(fileHandle); #ifdef IMPROVED_VIDEOMODE CFileMgr::Write(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth)); @@ -3881,45 +3233,50 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, RubbishString, 4); CFileMgr::Write(fileHandle, RubbishString, 4); CFileMgr::Write(fileHandle, RubbishString, 1); +#ifdef LEGACY_MENU_OPTIONS + CFileMgr::Write(fileHandle, (char*)&m_PrefsVsyncDisp, 1); + CFileMgr::Write(fileHandle, (char*)&CMBlur::BlurOn, 1); +#else CFileMgr::Write(fileHandle, RubbishString, 1); CFileMgr::Write(fileHandle, RubbishString, 1); +#endif CFileMgr::Write(fileHandle, (char*)&TheCamera.m_bHeadBob, 1); CFileMgr::Write(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4); - CFileMgr::Write(fileHandle, (char*)&TheCamera.m_fMouseAccelVertical, 4); CFileMgr::Write(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1); CFileMgr::Write(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsSfxVolume, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsMusicVolume, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsRadioStation, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsSpeakers, 1); CFileMgr::Write(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsDMA, 1); - CFileMgr::Write(fileHandle, (char*)&m_PrefsBrightness, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsBrightness, 2); CFileMgr::Write(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD)); CFileMgr::Write(fileHandle, (char*)&m_PrefsShowSubtitles, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsUseWideScreen, 1); - CFileMgr::Write(fileHandle, (char*)&m_PrefsVsyncDisp, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsFrameLimiter, 1); CFileMgr::Write(fileHandle, (char*)&m_nPrefsVideoMode, 1); - CFileMgr::Write(fileHandle, (char*)&CMBlur::BlurOn, 1); CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowLegends, 1); } + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; CFileMgr::CloseFile(fileHandle); CFileMgr::SetDir(""); - + #else + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; SaveINISettings(); #endif } -bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); -void DoRWStuffEndOfFrame(void); - void -CMenuManager::MessageScreen(const char *text) +CMenuManager::MessageScreen(const char *text, bool blackBg) { CSprite2d *splash = LoadSplash(nil); if (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)) @@ -3929,54 +3286,58 @@ CMenuManager::MessageScreen(const char *text) CSprite2d::InitPerFrame(); CFont::InitPerFrame(); DefinedState(); + // CRGBA unused(255, 255, 255, 255); + if (blackBg) { + CSprite2d::DrawRect(CRect(0, SCREEN_HEIGHT, SCREEN_WIDTH, 0), CRGBA(0, 0, 0, 255)); + } - RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); - splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); + m_nMenuFadeAlpha = 255; + SmallMessageScreen(text); + CFont::DrawFonts(); + DoRWStuffEndOfFrame(); +} +void +CMenuManager::SmallMessageScreen(const char* text) +{ CFont::SetBackgroundOff(); CFont::SetPropOn(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // unused - CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // unused - CSprite2d::DrawRect(CRect(StretchX(120.0f), StretchY(150.0f), SCREEN_WIDTH - StretchX(120.0f), SCREEN_HEIGHT - StretchY(220.0f)), CRGBA(50, 50, 50, 210)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); + CSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(95.0f), SCREEN_SCALE_FROM_BOTTOM(165.0f), SCREEN_STRETCH_FROM_RIGHT(95.0f), SCREEN_SCALE_Y(115.0f)), CRGBA(50, 50, 50, FadeIn(210))); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetCentreSize(SCREEN_SCALE_X(430.0f)); CFont::SetCentreOn(); - CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, 255)); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE)); - CFont::PrintString(StretchX(320.0f), StretchY(170.0f), TheText.Get(text)); - CFont::DrawFonts(); - DoRWStuffEndOfFrame(); -} + + int numOfLines = CFont::GetNumberLines(SCREEN_WIDTH / 2.f, SCREEN_SCALE_Y(135.f), TheText.Get(text)); + float y; + if (numOfLines > 1) + y = SCREEN_SCALE_Y(192.f) - numOfLines * SCREEN_SCALE_Y(8.f); + else + y = SCREEN_SCALE_Y(182.f); -void -CMenuManager::PickNewPlayerColour() -{ - m_PrefsPlayerRed = 0; - m_PrefsPlayerGreen = 0; - m_PrefsPlayerBlue = 0; - while (true) { - int sum = m_PrefsPlayerRed + m_PrefsPlayerGreen + m_PrefsPlayerBlue; - if (sum >= 100 && sum <= 650) - break; - m_PrefsPlayerRed = CGeneral::GetRandomNumber(); - m_PrefsPlayerGreen = CGeneral::GetRandomNumber(); - m_PrefsPlayerBlue = CGeneral::GetRandomNumber(); - } + CFont::PrintString(SCREEN_WIDTH / 2.f, y, TheText.Get(text)); } void CMenuManager::PrintBriefs() { - CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(80.0f)); + CFont::SetDropShadowPosition(0); - float nextY = BRIEFS_TOP_MARGIN; - CRGBA newColor; + float nextY = BRIEFS_BOTTOM_MARGIN; for (int i = 4; i >= 0; i--) { + if (nextY < BRIEFS_TOP_MARGIN) + break; + tPreviousBrief &brief = CMessages::PreviousBriefs[i]; if (brief.m_pText) { CMessages::InsertNumberInString(brief.m_pText, @@ -3985,347 +3346,987 @@ CMenuManager::PrintBriefs() brief.m_nNumber[4], brief.m_nNumber[5], gUString); CMessages::InsertStringInString(gUString, brief.m_pString); CMessages::InsertPlayerControlKeysInString(gUString); - newColor = TEXT_COLOR; - FilterOutColorMarkersFromString(gUString, newColor); - if (newColor != TEXT_COLOR) { - newColor.r /= 2; - newColor.g /= 2; - newColor.b /= 2; - } - -#ifdef PS2_LIKE_MENU - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetDropShadowPosition(1); -#endif + CFont::FilterOutTokensFromString(gUString); -#if defined(FIX_BUGS) || defined(PS2_LIKE_MENU) - newColor.a = FadeIn(255); - CFont::SetColor(newColor); -#endif - CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString); - nextY += MENU_Y(BRIEFS_LINE_HEIGHT); + nextY -= CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString) * BRIEFS_LINE_HEIGHT + BRIEFS_LINE_SPACING; + CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), MENU_Y(nextY), gUString); } } - -#ifdef PS2_LIKE_MENU - CFont::SetDropShadowPosition(0); -#endif } -// Not sure about name. Not to be confused with CPad::PrintErrorMessage void -CMenuManager::PrintErrorMessage() +CMenuManager::PrintStats() { - if (!CPad::bDisplayNoControllerMessage && !CPad::bObsoleteControllerMessage) - return; +#ifdef SECUROM + static uint8 statsPirateCheck = 0; +#endif + static float scrollY = 0; - CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(140.0f), SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f)), CRGBA(64, 16, 16, 224)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetBackgroundOff(); + int rowNum = CStats::ConstructStatLine(99999); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(142.0f), + MENU_X_LEFT_ALIGNED(543.0f), MENU_Y(142.f), + MENU_X_LEFT_ALIGNED(107.0f), MENU_Y(316.f), + MENU_X_LEFT_ALIGNED(531.f), MENU_Y(299.f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a))); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); CFont::SetPropOn(); - CFont::SetCentreOff(); - CFont::SetJustifyOn(); - CFont::SetRightJustifyOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(MENU_X_MARGIN)); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(180.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); -#else - CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(40.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT")); -#endif - CFont::DrawFonts(); -} + CFont::SetDropShadowPosition(0); -void -CMenuManager::PrintStats() -{ - int rowNum = ConstructStatLine(99999); -#if GTA_VERSION >= GTA3_PC_11 - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); +#ifdef SECUROM + if (statsPirateCheck == 0) + // if not pirated game + // statsPirateCheck = 46; + // else + statsPirateCheck = 45; #endif - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why - float nextYChange, y, alphaMult; - // Scroll stats with mouse -#ifdef SCROLLABLE_STATS_PAGE - static float scrollY = 0; - static uint32 lastChange = m_nScreenChangeDelayTimer; - if (CPad::GetPad(0)->GetLeftMouse()) { - scrollY += (m_nMouseOldPosY - m_nMousePosY); - lastChange = CTimer::GetTimeInMillisecondsPauseMode(); - } else { - scrollY += MENU_Y(STATS_SLIDE_Y_PER_SECOND) / 1000.0f * (CTimer::GetTimeInMillisecondsPauseMode() - lastChange); - lastChange = CTimer::GetTimeInMillisecondsPauseMode(); + if (m_PrefsLanguage == LANGUAGE_AMERICAN) + CFont::SetScale(MENU_X(0.43f), MENU_Y(0.75f)); + else + CFont::SetScale(MENU_X(0.37f), MENU_Y(0.75f)); + + static uint32 lastCheck = 0; + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastCheck > 40) { + + if (m_StatsScrollSpeed > 0.f) { + if (m_StatsScrollDirection == 0) + scrollY -= MENU_Y(100.f) / m_StatsScrollSpeed; + else + scrollY += MENU_Y(100.f) / m_StatsScrollSpeed; + } + lastCheck = CTimer::GetTimeInMillisecondsPauseMode(); } -#else - // MENU_Y(30.0f) per second - float scrollY = MENU_Y(STATS_SLIDE_Y_PER_SECOND) * (CTimer::GetTimeInMillisecondsPauseMode() - m_nScreenChangeDelayTimer) / 1000.0f; + +#ifdef SECUROM + if (statsPirateCheck == 45) + return; #endif + float nextYChange, y, alpha; + + float totalHeight = (rowNum + 7) * STATS_ROW_HEIGHT; for (int row = 0; row < rowNum; ++row) { - // Put just got hidden text at the top back to the bottom, in circular fashion - for (y = MENU_Y(STATS_ROW_HEIGHT - 1) * row + SCREEN_HEIGHT - scrollY; MENU_Y(STATS_PUT_BACK_TO_BOTTOM_Y) > y; y += nextYChange) { - nextYChange = (MENU_Y(STATS_ROW_HEIGHT) + rowNum) * MENU_Y(STATS_ROW_HEIGHT - 1); + // Put faded away text at the top back to the bottom, in circular fashion + for (y = MENU_Y(STATS_ROW_HEIGHT) * row + MENU_Y(100.f) - scrollY; MENU_Y(STATS_FADING_AREA_LENGTH) > y; y += nextYChange) { + nextYChange = MENU_Y(totalHeight); } + // Put faded away text at the bottom back to the top + while (SCREEN_SCALE_FROM_BOTTOM(STATS_FADING_AREA_LENGTH) < y) { + y -= MENU_Y(totalHeight); + } + alpha = 0.f; + // If it's still on screen - if (y > 0.0f && SCREEN_HEIGHT > y) { - ConstructStatLine(row); + if (y > MENU_Y(STATS_VISIBLE_START_Y) && y < MENU_Y(STATS_VISIBLE_END_Y)) { + CStats::ConstructStatLine(row); - // But about to dim from top - if (y - MENU_Y(STATS_BOTTOM_MARGIN) < MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH)) { - if ((y - MENU_Y(STATS_BOTTOM_MARGIN)) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH) < 0.0f) - alphaMult = 0.0f; - else - alphaMult = (y - MENU_Y(STATS_BOTTOM_MARGIN)) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); + // But about to dim from bottom + if (y < MENU_Y(STATS_BOTTOM_Y)) { + if (y > MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH)) + alpha = (MENU_Y(STATS_BOTTOM_Y) - y) * 5.f; + } - // About to dim from bottom - } else if (y > SCREEN_SCALE_FROM_BOTTOM(STATS_TOP_DIMMING_AREA_LENGTH) - MENU_Y(STATS_BOTTOM_DIMMING_AREA_LENGTH)) { - if ((SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH) < 0.0f) - alphaMult = 0.0f; - else - alphaMult = (SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); - } else - alphaMult = 1.0f; + // About to dim from top + if (y > MENU_Y(STATS_TOP_Y)) { + if (y < MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH)) + alpha = (y - MENU_Y(STATS_TOP_Y)) * 5.f; + } + + // Content + if (y >= MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH) && y <= MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH)) + alpha = 255.0f; - CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255.0f * alphaMult))); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(Min(255.f, alpha)))); CFont::SetRightJustifyOff(); - CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_X_MARGIN), y - MENU_Y(STATS_BOTTOM_MARGIN - STATS_TOP_MARGIN), gUString); + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_LEFT_MARGIN), y, gUString); CFont::SetRightJustifyOn(); - CFont::PrintString(MENU_X_RIGHT_ALIGNED(STATS_ROW_X_MARGIN), y - MENU_Y(STATS_BOTTOM_MARGIN - STATS_TOP_MARGIN), gUString2); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(STATS_ROW_RIGHT_MARGIN), y, gUString2); } } - // Game doesn't do that, but it's better - float nextX = MENU_X_LEFT_ALIGNED(STATS_RATING_X); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetCentreOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(0.65f), MENU_Y(1.05f)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X), MENU_Y(STATS_RATING_Y_1), TheText.Get("CRIMRA")); - CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + CFont::SetCentreOff(); CFont::SetRightJustifyOff(); - CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), TheText.Get("CRIMRA")); -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese()) - nextX += MENU_X(10.0f) + CFont::GetStringWidth_Jap(TheText.Get("CRIMRA")); - else -#endif - nextX += MENU_X(10.0f) + CFont::GetStringWidth(TheText.Get("CRIMRA"), true); - UnicodeStrcpy(gUString, CStats::FindCriminalRatingString()); - CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), gUString); -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese()) - nextX += MENU_X(6.0f) + CFont::GetStringWidth_Jap(gUString); - else -#endif - nextX += MENU_X(6.0f) + CFont::GetStringWidth(gUString, true); - sprintf(gString, "%d", CStats::FindCriminalRatingNumber()); + + // FIX: Game does that in a weird way, alignment and spacing is now ok + + sprintf(gString, "(%d)", CStats::FindCriminalRatingNumber()); AsciiToUnicode(gString, gUString); - CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), gUString); - // ::Draw already does that. - /* - SET_FONT_FOR_MENU_HEADER - CFont::PrintString(PAGE_NAME_X(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - */ - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); + UnicodeStrcpy(gUString2, CStats::FindCriminalRatingString()); + UnicodeStrcat(gUString2, gUString); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); +#ifndef FIX_BUGS + CFont::SetScale(MENU_X(0.5f), MENU_Y(0.9f)); +#else + CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); +#endif + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetDropShadowPosition(0); + + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X) - CFont::GetStringWidth(gUString2, true) / 2.f, MENU_Y(STATS_RATING_Y_2), gUString2); } void CMenuManager::Process(void) { - m_bMenuStateChanged = false; +#ifdef XBOX_MESSAGE_SCREEN + ProcessDialogTimer(); +#endif - if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0) + if (TheCamera.GetScreenFadeStatus() != FADE_0) return; - m_bWantToRestart = false; InitialiseChangedLanguageSettings(); - // Just a hack by R* to not make game continuously resume/pause. But we it seems we can live with it. - if (CPad::GetPad(0)->GetEscapeJustDown()) - RequestFrontEndStartUp(); + if (m_bMenuActive) { + UserInput(); + ProcessFileActions(); + DMAudio.Service(); +#ifdef USE_TEXTURE_POOL + // TODO +#endif + } SwitchMenuOnAndOff(); +} - // Be able to re-open menu correctly. - if (m_bMenuActive) { +#ifdef MAP_ENHANCEMENTS +#define ZOOM(x, y, in) \ + do { \ + if(m_fMapSize >= MENU_Y(1000.0f) && in) \ + break; \ + float z2 = in? 1.1f : 1.f/1.1f; \ + m_fMapCenterX += (x - m_fMapCenterX) * (1.0f - z2); \ + m_fMapCenterY += (y - m_fMapCenterY) * (1.0f - z2); \ + \ + if (m_fMapSize <= MENU_Y(MAP_MIN_SIZE) && !in) \ + break; \ + \ + m_fMapSize *= z2; \ + m_fMapCenterX = Clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); \ + m_fMapCenterY = Clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); \ + } while(0) - // Load frontend textures. - LoadAllTextures(); +#endif + +// Handles Map, Audio and Stats +void +CMenuManager::AdditionalOptionInput(bool &goBack) +{ + switch (m_nCurrScreen) { + case MENUPAGE_MAP: + { + static uint32 lastMapTick = 0; - // Set save/delete game pages. - if (m_nCurrScreen == MENUPAGE_DELETING) { - bool SlotPopulated = false; + // FIX: All those macros were hardcoded values originally. - if (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) { - PcSaveHelper.PopulateSlotInfo(); - SlotPopulated = true; +#ifndef MAP_ENHANCEMENTS + if (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + m_fMapSize = Min(MENU_Y(1000.0f), m_fMapSize + MENU_Y(15.f)); + } } + if (CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustUp() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (m_fMapSize > MENU_Y(MAP_MIN_SIZE)) { + if (m_fMapCenterY > SCREEN_HEIGHT/2) + m_fMapCenterY -= (m_fMapCenterY - SCREEN_HEIGHT/2) / ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) * 1/15.f); - if (SlotPopulated) - ChangeScreen(MENUPAGE_DELETE_SUCCESS, 0, true, false); - else - SaveLoadFileError_SetUpErrorScreen(); - } - if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) { - int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); - PcSaveHelper.PopulateSlotInfo(); - if (SaveSlot) - ChangeScreen(MENUPAGE_SAVE_SUCCESSFUL, 0, true, false); - else - SaveLoadFileError_SetUpErrorScreen(); - } - if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS) { -#ifdef MISSION_REPLAY - if (doingMissionRetry) { - RetryMission(2, 0); - m_nCurrSaveSlot = SLOT_COUNT; - doingMissionRetry = false; + if (m_fMapCenterY < SCREEN_HEIGHT/2) + m_fMapCenterY += (SCREEN_HEIGHT/2 - m_fMapCenterY) / ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) * 1/15.f); + + if (m_fMapCenterX > SCREEN_WIDTH/2) + m_fMapCenterX -= (m_fMapCenterX - SCREEN_WIDTH/2) / ((m_fMapSize - MENU_X(MAP_MIN_SIZE)) * 1/15.f); + + if (m_fMapCenterX < SCREEN_WIDTH/2) + m_fMapCenterX += (SCREEN_WIDTH/2 - m_fMapCenterX) / ((m_fMapSize - MENU_X(MAP_MIN_SIZE)) * 1/15.f); + + m_fMapSize = Max(MENU_Y(MAP_MIN_SIZE), m_fMapSize - MENU_Y(15.f)); + m_fMapCenterX = Clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); + m_fMapCenterY = Clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); + } else { + m_fMapSize = MENU_Y(MAP_MIN_SIZE); + } + } + } +#else + // Adding marker + if (m_nMenuFadeAlpha == 255) { + if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + if (mapCrosshair.y > m_fMapCenterY - m_fMapSize && mapCrosshair.y < m_fMapCenterY + m_fMapSize && + mapCrosshair.x > m_fMapCenterX - m_fMapSize && mapCrosshair.x < m_fMapCenterX + m_fMapSize) { + + // Don't ask me the meanings, I don't know. Found them by trying + float diffX = m_fMapCenterX - m_fMapSize, diffY = m_fMapCenterY - m_fMapSize; + float x = ((mapCrosshair.x - diffX) / (m_fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT); + float y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapCrosshair.y - diffY) / (m_fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE); + CRadar::ToggleTargetMarker(x, y); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + } + } + } + + if (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { + if (CPad::GetPad(0)->GetMouseWheelDown() && m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE)) + ZOOM(mapCrosshair.x, mapCrosshair.y, false); + else + ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false); + + } else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { + if (CPad::GetPad(0)->GetMouseWheelUp()) + ZOOM(mapCrosshair.x, mapCrosshair.y, true); + else + ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); } + + static bool justResetPointer = false; + if (CPad::GetPad(0)->GetLeftMouse()) { + if (!justResetPointer) { + m_fMapCenterX += m_nMousePosX - m_nMouseOldPosX; + m_fMapCenterY += m_nMousePosY - m_nMouseOldPosY; + m_fMapCenterX = Clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); + m_fMapCenterY = Clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); + } + justResetPointer = false; + + } else +#undef ZOOM #endif - if (CheckSlotDataValid(m_nCurrSaveSlot)) { -#ifdef USE_DEBUG_SCRIPT_LOADER - scriptToLoad = 0; + + { + // This is else block of GetLeftMouse() if MAP_ENHANCEMENTS defined, so all of GetLeftMouse() conditions below being rendered useless. + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosY < m_nMouseOldPosY || CPad::GetPad(0)->GetUp() || + CPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetAnalogueUpDown() < 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) + SCREEN_HEIGHT/2 > m_fMapCenterY) + m_fMapCenterY += MENU_Y(15.f); + m_bShowMouse = false; + } + } + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosY > m_nMouseOldPosY || CPad::GetPad(0)->GetDown() || + CPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetAnalogueUpDown() > 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)) < m_fMapCenterY) + m_fMapCenterY -= MENU_Y(15.f); + m_bShowMouse = false; + } + } + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosX < m_nMouseOldPosX || CPad::GetPad(0)->GetLeft() || + CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetAnalogueLeftRight() < 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE) && m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2 > m_fMapCenterX) + m_fMapCenterX += MENU_X(15.f); + m_bShowMouse = false; + } + } + + if (CPad::GetPad(0)->GetLeftMouseJustUp()) { + // The coordinates in aScreens->MENUPAGE_MAP. + if (m_nMousePosX > MENU_X_LEFT_ALIGNED(60.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(140.0f)) { + if (m_nMousePosY > MENU_Y(375.0f) && m_nMousePosY < MENU_Y(400.0f)) { + m_nHoverOption = HOVEROPTION_RANDOM_ITEM; + goBack = true; + } + } + } + + if (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosX > m_nMouseOldPosX || CPad::GetPad(0)->GetRight() || + CPad::GetPad(0)->GetDPadRight() || CPad::GetPad(0)->GetAnalogueLeftRight() > 0) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) { + if (m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE) && SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)) < m_fMapCenterX) + m_fMapCenterX -= MENU_X(15.f); + m_bShowMouse = false; + } + } + } + + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) + lastMapTick = CTimer::GetTimeInMillisecondsPauseMode(); + +#ifndef MAP_ENHANCEMENTS + if (CPad::GetPad(0)->GetLeftMouseJustUp()) + CentreMousePointer(); #endif -#ifdef PC_PLAYER_CONTROLS - TheCamera.m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; + + if (CPad::GetPad(0)->GetLeftMouse()) { + if (m_nMousePosX < SCREEN_STRETCH_X(20.0f) || m_nMousePosX > SCREEN_STRETCH_X(620.0f) || m_nMousePosY < SCREEN_STRETCH_Y(20.0f) || m_nMousePosY > SCREEN_STRETCH_Y(428.0f)) { +#ifdef MAP_ENHANCEMENTS + justResetPointer = true; #endif - if (m_PrefsVsyncDisp != m_PrefsVsync) - m_PrefsVsync = m_PrefsVsyncDisp; - DMAudio.Service(); - m_bWantToRestart = true; - RequestFrontEndShutDown(); - m_bWantToLoad = true; - b_FoundRecentSavedGameWantToLoad = true; - DMAudio.SetEffectsFadeVol(0); - DMAudio.SetMusicFadeVol(0); - DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); - } else - SaveLoadFileError_SetUpErrorScreen(); - } + CentreMousePointer(); + } + } + if (!CPad::GetPad(0)->GetLeftMouse() && !m_bShowMouse && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) { + m_bShowMouse = true; + } - ProcessButtonPresses(); + static bool pressedL = false; - // Set binding keys. - if (pEditString && CPad::EditString(pEditString, 0) == nil) { - if (*pEditString == 0) - strcpy(pEditString, "NoName"); - pEditString = nil; - SaveSettings(); + if (!CPad::GetPad(0)->GetChar('L') && !CPad::GetPad(0)->GetChar('l')) { + pressedL = false; + } + + if (!pressedL) { + if (CPad::GetPad(0)->GetChar('L') || CPad::GetPad(0)->GetChar('l')) { + m_PrefsShowLegends = !m_PrefsShowLegends; + pressedL = true; + } + } + break; } + case MENUPAGE_SOUND_SETTINGS: + if (CheckHover(MENU_X_LEFT_ALIGNED(177.f), MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y - 13.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT - 8.f))) { + m_nHoverOption = HOVEROPTION_PREV_RADIO; + } - if (m_bWaitingForNewKeyBind) { - if (m_bStartWaitingForKeyBind) - m_bStartWaitingForKeyBind = false; - else { - pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); - JoyButtonJustClicked = false; - MouseButtonJustClicked = false; - - if (CPad::GetPad(0)->GetLeftMouseJustDown()) - MouseButtonJustClicked = rsMOUSELEFTBUTTON; - else if (CPad::GetPad(0)->GetRightMouseJustUp()) - MouseButtonJustClicked = rsMOUSERIGHTBUTTON; - else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) - MouseButtonJustClicked = rsMOUSMIDDLEBUTTON; - else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) - MouseButtonJustClicked = rsMOUSEWHEELUPBUTTON; - else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) - MouseButtonJustClicked = rsMOUSEWHEELDOWNBUTTON; - else if (CPad::GetPad(0)->GetMouseX1JustUp()) - MouseButtonJustClicked = rsMOUSEX1BUTTON; - else if (CPad::GetPad(0)->GetMouseX2JustUp()) - MouseButtonJustClicked = rsMOUSEX2BUTTON; - - JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); - - int32 TypeOfControl = KEYBOARD; - if (JoyButtonJustClicked) - TypeOfControl = JOYSTICK; - if (MouseButtonJustClicked) - TypeOfControl = MOUSE; - if (*pControlEdit != rsNULL) - TypeOfControl = KEYBOARD; - - if (!m_bKeyIsOK) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - pControlEdit = nil; - m_bWaitingForNewKeyBind = false; - m_KeyPressedCode = -1; - m_bStartWaitingForKeyBind = false; - } else if (!m_bKeyChangeNotProcessed) { - if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) - CheckCodesForControls(TypeOfControl); - - field_535 = true; - } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - for (int i = 0; i < 4; i++) - ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); - m_bKeyIsOK = false; - m_bKeyChangeNotProcessed = false; - pControlEdit = nil; - m_bWaitingForNewKeyBind = false; - m_KeyPressedCode = -1; - m_bStartWaitingForKeyBind = false; + if (CheckHover(MENU_X_LEFT_ALIGNED(422.f), MENU_X_LEFT_ALIGNED(491.f), MENU_Y(MENURADIO_SELECTOR_START_Y - 13.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT - 8.f))) { + m_nHoverOption = HOVEROPTION_NEXT_RADIO; + } + break; + case MENUPAGE_STATS: + { + if (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustUp() || CPad::GetPad(0)->GetUp() || + CPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetAnalogueUpDown() < 0) { + + m_StatsScrollSpeed = 20.0f; + m_StatsScrollDirection = 0; + + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustUp() || CPad::GetPad(0)->GetDown() || + CPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetAnalogueUpDown() > 0) { + + m_StatsScrollSpeed = 20.0f; + m_StatsScrollDirection = 1; + + } else if (CPad::GetPad(0)->GetChar(' ')) { + m_StatsScrollSpeed = 0.0f; + } else + m_StatsScrollSpeed = 150.0f; + + static bool pressedS = false; + + if (!CPad::GetPad(0)->GetChar('S') && !CPad::GetPad(0)->GetChar('s')) { + pressedS = false; + } + + if (!pressedS) { + if (CPad::GetPad(0)->GetChar('S') || CPad::GetPad(0)->GetChar('s')) { + ExportStats(); + m_nHelperTextMsgId = 4; + m_nHelperTextAlpha = 300; + pressedS = true; } } + break; } + } +} - if ((m_nCurrScreen == MENUPAGE_NO_MEMORY_CARD || m_nCurrScreen == MENUPAGE_PS2_LOAD_FAILED) && CTimer::GetTimeInMillisecondsPauseMode() > field_558) { - m_nCurrScreen = m_nPrevScreen; - m_nCurrOption = 0; +// Not original name +void +CMenuManager::ExportStats() +{ + char date[10]; + CFileMgr::SetDirMyDocuments(); + _strdate(date); + wchar *lastMission = TheText.Get(CStats::LastMissionPassedName[0] == '\0' ? "ITBEG" : CStats::LastMissionPassedName); + FILE *txtFile = fopen("stats.txt", "w"); + + if (txtFile) { + int statLines = CStats::ConstructStatLine(99999); + fprintf(txtFile, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); + fprintf(txtFile, "\t\t\tGTA VICE CITY %s\n", UnicodeToAscii(TheText.Get("FEH_STA"))); + fprintf(txtFile, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n\n"); + fprintf(txtFile, "%s: ", UnicodeToAscii(TheText.Get("FES_CMI"))); + fprintf(txtFile, "%s\n", UnicodeToAscii(lastMission)); + fprintf(txtFile, "%s: ", UnicodeToAscii(TheText.Get("FES_DAT"))); + fprintf(txtFile, "%s\n\n\n", date); + fprintf(txtFile, "%s ", UnicodeToAscii(TheText.Get("CRIMRA"))); + UnicodeStrcpy(gUString, CStats::FindCriminalRatingString()); + fprintf(txtFile, "%s (%d)\n\n\n", UnicodeToAscii(gUString), CStats::FindCriminalRatingNumber()); + for (int i = 0; i < statLines; ++i) { + CStats::ConstructStatLine(i); + char *statKey = UnicodeToAscii(gUString); + if (statKey[0] != '\0') + fprintf(txtFile, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n%s\n", statKey); + + char *statValue = UnicodeToAscii(gUString2); + for (int j = 0; statValue[j] != '\0'; ++j) { + if (statValue[j] == '_') + statValue[j] = '\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation + } + if (statValue) + fprintf(txtFile, "%s\n\n", statValue); } + fprintf(txtFile, "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n"); + } + fclose(txtFile); + FILE *htmlFile = fopen("stats.html", "w"); + if (htmlFile) { + int statLines = CStats::ConstructStatLine(99999); + fprintf(htmlFile, "<title>Grand Theft Auto Vice City Stats</title>\n"); + fprintf(htmlFile, "<body bgcolor=\"#FF00CC\" leftmargin=\"10\" topmargin=\"10\" marginwidth=\"10\" marginheight=\"10\">\n"); + fprintf(htmlFile, "<table width=\"560\" align=\"center\" border=\"0\" cellpadding=\"5\" cellspacing=\"0\">\n"); + fprintf(htmlFile, "<tr align=\"center\" valign=\"top\"> \n"); + fprintf(htmlFile, "<td height=\"59\" colspan=\"2\" bgcolor=\"#FFCCFF\"><div align=\"center\"><font color=\"#FF00CC\" size=\"3\" " + "face=\"Arial, \n"); + fprintf(htmlFile, "Helvetica, sans-serif\">-------------------------------------------------------------------------</font><font \n"); + fprintf(htmlFile, "size=\"3\" face=\"Arial, Helvetica, sans-serif\"><br>\n"); + fprintf(htmlFile, "<strong><font color=\"#000000\">GRAND THEFT AUTO VICE CITY "); + fprintf(htmlFile, "%s</font></strong><br><font\n", UnicodeToAscii(TheText.Get("FEH_STA"))); + fprintf(htmlFile, "color=\"#FF00CC\">-------------------------------------------------------------------------</font></font></div></td> </tr>\n"); + fprintf(htmlFile, "<tr align=\"left\" valign=\"top\" bgcolor=\"#FFFFFF\"> <td height=\"22\" colspan=\"2\"> </td> </tr>\n"); + fprintf(htmlFile, "<tr align=\"left\" valign=\"top\" bgcolor=\"#FFFFFF\"> \n"); + fprintf(htmlFile, + "<td height=\"40\" colspan=\"2\"> <p><font color=\"#00CC00\" size=\"2\" face=\"Arial, Helvetica, sans-serif\">" + "<strong><font color=\"#009900\" size=\"1\">%s: \n", UnicodeToAscii(TheText.Get("FES_DAT"))); + fprintf(htmlFile, "%s</font><br> %s: </strong>", date, UnicodeToAscii(TheText.Get("FES_CMI"))); + fprintf(htmlFile, "%s<strong><br></strong> </font></p></td></tr>\n", UnicodeToAscii(lastMission)); + fprintf(htmlFile, "<tr align=\"left\" valign=\"top\" bgcolor=\"#CCCCCC\"> <td height=\"5\" colspan=\"2\"></td> </tr> <tr align=\"" + "left\" valign=\"top\" bgcolor=\"#FFFFFF\"> \n"); + fprintf(htmlFile, "<td height=\"10\" colspan=\"2\"></td> </tr> <tr align=\"left\" valign=\"top\" bgcolor=\"#FFFFFF\"> \n"); + fprintf(htmlFile, "<td height=\"20\" colspan=\"2\"><font color=\"#FF00CC\" size=\"2\" face=\"Arial, Helvetica, sans-serif\"><str" + "ong>%s</strong>\n", UnicodeToAscii(TheText.Get("CRIMRA"))); + + UnicodeStrcpy(gUString, CStats::FindCriminalRatingString()); + char *statKey = UnicodeToAscii(gUString); + int rating = CStats::FindCriminalRatingNumber(); + fprintf(htmlFile, "%s (%d)</font></td> </tr> <tr align=\"left\" valign=\"top\" bgcolor=\"#FFFFFF\"><td height=\"10\" colspan=\"" + "2\"></td> </tr>\n", statKey, rating); + + for (int k = 0; k < statLines; ++k) { + CStats::ConstructStatLine(k); + statKey = UnicodeToAscii(gUString); + if (statKey[0] != '\0') + fprintf(htmlFile, "</font></strong></div></td> </tr> <tr align=\"left\" valign=\"top\" bgcolor=\"#FFFFFF\"> <td height=\"10" + "\" colspan=\"2\"></td> </tr>\n"); + + fprintf(htmlFile, "<tr align=\"left\" valign=\"top\"><td width=\"500\" height=\"22\" bgcolor=\"#FFCCFF\"><font color=\"#FF00CC" + "\" size=\"2\" face=\"Arial, Helvetica, sans-serif\"><strong>\n"); + + if (statKey[0] != '\0') + fprintf(htmlFile, "%s", statKey); + else + fprintf(htmlFile, " "); + + fprintf(htmlFile, "</strong></font></td> <td width=\"500\" align=\"right\" valign=\"middle\" bgcolor=\"#FFCCFF\"> <div align=\"" + "right\"><strong><font color=\"#FF00CC\">\n"); - // Reset pad shaking. - if (TimeToStopPadShaking && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode()) { - CPad::StopPadsShaking(); - TimeToStopPadShaking = 0; + char *statValue = UnicodeToAscii(gUString2); + for (int l = 0; statValue[l] != '\0'; ++l) { + if (statValue[l] == '_') + statValue[l] = '\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation + } + if (statValue) + fprintf(htmlFile, "%s", statValue); + else + fprintf(htmlFile, " "); } + fprintf(htmlFile, "</font></strong></div></td> </tr> <tr align=\"left\" valign=\"top\" bgcolor=\"#FFFFFF\"> <td height=\"10\" c" + "olspan=\"2\"></td> </tr>\n"); + fprintf(htmlFile, "</table><br><table width=\"560\" border=\"0\" align=\"center\" cellspacing=\"0\" cellpadding=\"5\"><tr align" + "=\"center\" valign=\"middle\" bgcolor=\"#FFCCFF\">"); + fprintf(htmlFile, "<td><font color=\"#000000\" size=\"2\" face=\"Arial, Helvetica, sans-serif\"><a href=\"http://www.rockstargam" + "es.com/vicecity\">rockstargames.com/vicecity</a></font></td>\n"); + fprintf(htmlFile, "<td><font color=\"#000000\" size=\"2\" face=\"Arial, Helvetica, sans-serif\"><a href=\"http://www.rockstargam" + "es.com\">rockstargames.com</a></font></td>\n"); + fprintf(htmlFile, "<td><font color=\"#000000\" size=\"2\" face=\"Arial, Helvetica, sans-serif\"> <a href=\"http://www.rocks" + "tarnorth.com\">rockstarnorth.com</a></font></td></tr>\n"); + fprintf(htmlFile, "</table>\n</body>\n"); + } + fclose(htmlFile); + CFileMgr::SetDir(""); +} +// Original name is unknown +void +CMenuManager::PrintRadioSelector(void) +{ + static uint32 lastRadioChange = 0; + + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(418.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(228.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(428.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y), CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(180))); + + int rightMostSprite, rightMostStation; + if (DMAudio.IsMP3RadioChannelAvailable()) { + rightMostSprite = MENUSPRITE_MP3; + rightMostStation = USERTRACK; } else { - UnloadTextures(); - m_bRenderGameInMenu = false; - // byte_5F33E4 = 1; // unused - ChangeScreen(MENUPAGE_NONE, 0, false, false); - pEditString = nil; - m_bWaitingForNewKeyBind = false; + rightMostSprite = MENUSPRITE_WAVE; + rightMostStation = WAVE; + } + #ifdef THIS_IS_STUPID + + // First radio + if (m_ScrollRadioBy == 1) { + if (m_PrefsRadioStation == 1) { + m_aFrontEndSprites[rightMostSprite].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if ( m_PrefsRadioStation == 0) { + m_aFrontEndSprites[rightMostSprite - 1].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE - 2].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + } + + // Second + if (m_PrefsRadioStation == 0) { + m_aFrontEndSprites[rightMostSprite].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE - 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), + MENU_Y(MENURADIO_ICON_SIZE), CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Third (middle) + int prevStation = m_PrefsRadioStation - 1; + if (prevStation == rightMostStation) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if ( prevStation == rightMostStation - 1) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Fifth + if (m_ScrollRadioBy == -1) { + int prevStation = m_PrefsRadioStation - 1; + if (prevStation == rightMostStation) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 4].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if (prevStation == rightMostStation - 1) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else if ( prevStation == rightMostStation - 2) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE + 2].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + } + + // Fourth + if (m_ScrollRadioBy == 0) { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2 - 10.f), MENU_Y(MENURADIO_ICON_Y - 10.f), MENU_X(MENURADIO_ICON_SIZE) + MENU_X(20.f), MENU_Y(MENURADIO_ICON_SIZE) + MENU_Y(20.f), + CRGBA(255, 255, 255, FadeIn(255))); + } else { + if (m_PrefsRadioStation - 1 == rightMostStation) { + m_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + } +#else + int first = ((m_PrefsRadioStation - 2) + rightMostStation + 1) % (rightMostStation + 1); + int second = ((m_PrefsRadioStation - 1) + rightMostStation + 1) % (rightMostStation + 1); + int third = ((m_PrefsRadioStation) + rightMostStation + 1) % (rightMostStation + 1); + int fourth = ((m_PrefsRadioStation + 1) + rightMostStation + 1) % (rightMostStation + 1); + int fifth = ((m_PrefsRadioStation + 2) + rightMostStation + 1) % (rightMostStation + 1); + + // First one is only drawn on transition to next + if (m_ScrollRadioBy == 1) { + m_aFrontEndSprites[first + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } + + // Second + m_aFrontEndSprites[second + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + + // Fourth + m_aFrontEndSprites[fourth + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + + // Fifth one is only drawn on transition to prev. + if (m_ScrollRadioBy == -1) { + m_aFrontEndSprites[fifth + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); } - if (!m_bWantToRestart) { - if (m_bGameNotLoaded) - DMAudio.Service(); + // Middle one(third) is colored differently depending on if it's in transition. + // If not in transition then this icon indicates selected radio, and should be on top of all icons. thus drawn last + if (m_ScrollRadioBy != 0) { + m_aFrontEndSprites[third + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE), + CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a))); + } else { + m_aFrontEndSprites[third + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2 - 10.f), MENU_Y(MENURADIO_ICON_Y - 10.f), MENU_X(MENURADIO_ICON_SIZE) + MENU_X(20.f), MENU_Y(MENURADIO_ICON_SIZE) + MENU_Y(20.f), + CRGBA(255, 255, 255, FadeIn(255))); + } +#endif + + static bool radioChangeRequested = false; + static uint32 lastScrollCheck = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastScrollCheck > 17) { + if (m_ScrollRadioBy == 1) { + if (m_LeftMostRadioX > MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE)) { + m_LeftMostRadioX -= MENU_X(6.f); + } else { + m_ScrollRadioBy = 0; + lastRadioChange = CTimer::GetTimeInMillisecondsPauseMode(); + radioChangeRequested = true; + } + } + if (m_ScrollRadioBy == -1) { + if (m_LeftMostRadioX < MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE)) { + m_LeftMostRadioX += MENU_X(6.f); + } else { + m_ScrollRadioBy = 0; + lastRadioChange = CTimer::GetTimeInMillisecondsPauseMode(); + radioChangeRequested = true; + } + } + lastScrollCheck = CTimer::GetTimeInMillisecondsPauseMode(); + } + // Background behind arrows + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(228.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(168.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + MENU_X_LEFT_ALIGNED(178.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(255))); + + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(478.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(418.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT), + MENU_X_LEFT_ALIGNED(488.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + MENU_X_LEFT_ALIGNED(428.f), MENU_Y(MENURADIO_SELECTOR_START_Y), + CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(255))); + + // Arrows and their shadows + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(216.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 48.f), MENU_X_LEFT_ALIGNED(196.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), MENU_X_LEFT_ALIGNED(216.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 22.f), MENU_X_LEFT_ALIGNED(196.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), CRGBA(0, 0, 0, FadeIn(255))); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(213.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 45.f), MENU_X_LEFT_ALIGNED(193.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), MENU_X_LEFT_ALIGNED(213.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 19.f), MENU_X_LEFT_ALIGNED(193.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), CRGBA(97, 194, 247, FadeIn(255))); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(440.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 48.f), MENU_X_LEFT_ALIGNED(460.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), MENU_X_LEFT_ALIGNED(440.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 22.f), MENU_X_LEFT_ALIGNED(460.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), CRGBA(0, 0, 0, FadeIn(255))); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(443.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 45.f), MENU_X_LEFT_ALIGNED(463.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), MENU_X_LEFT_ALIGNED(443.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 19.f), MENU_X_LEFT_ALIGNED(463.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), CRGBA(97, 194, 247, FadeIn(255))); + if (radioChangeRequested) { + if (CTimer::GetTimeInMillisecondsPauseMode() - lastRadioChange > 50) { + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); + OutputDebugString("FRONTEND RADIO STATION CHANGED"); + lastRadioChange = CTimer::GetTimeInMillisecondsPauseMode(); + radioChangeRequested = false; + } } } +// Original name is unknown void -CMenuManager::ProcessButtonPresses(void) +CMenuManager::ProcessList(bool &optionSelected, bool &goBack) { - if (pEditString || pControlEdit) + if (m_bWaitingForNewKeyBind) return; + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { + m_nTotalListRow = m_nSkinsTotal; + } + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + // GetNumOptionsCntrlConfigScreens would have been a better choice + m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 32 : 27; + if (m_nSelectedListRow > m_nTotalListRow) + m_nSelectedListRow = m_nTotalListRow - 1; + } + + if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { + m_bShowMouse = 0; + optionSelected = true; + } + if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_159) { + if (m_nCurrExLayer == HOVEROPTION_LIST) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + m_bKeyChangeNotProcessed = true; + pControlEdit = &m_KeyPressedCode; + } + } else { + field_159 = false; + } + + static uint32 lastTimeClickedScrollButton = 0; + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) { + m_bPressedPgUpOnList = false; + m_bPressedPgDnOnList = false; + m_bPressedUpOnList = false; + m_bPressedDownOnList = false; + m_bPressedScrollButton = false; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + } + + if (CPad::GetPad(0)->GetTabJustDown()) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + m_bShowMouse = false; + switch (m_nCurrExLayer) { + case HOVEROPTION_BACK: + default: + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case HOVEROPTION_LIST: + m_nCurrExLayer = HOVEROPTION_USESKIN; + break; + case HOVEROPTION_USESKIN: + m_nCurrExLayer = HOVEROPTION_BACK; + } + if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) { + m_nCurrExLayer = HOVEROPTION_BACK; + } + if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) { + m_nCurrExLayer = HOVEROPTION_BACK; + } + } + + bool pressed = false; + if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + m_bShowMouse = false; + pressed = true; + } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) { + m_bShowMouse = true; + pressed = true; + } + + // Up + if (pressed) { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedUpOnList) { + m_bPressedUpOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + ScrollUpListByOne(); + } + } else { + m_bPressedUpOnList = false; + } + + pressed = false; + if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { + m_bShowMouse = false; + pressed = true; + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + m_bShowMouse = true; + pressed = true; + } + + // Down + if (pressed) { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedDownOnList) { + m_bPressedDownOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + ScrollDownListByOne(); + } + } else { + m_bPressedDownOnList = false; + } + + if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { + if (!CPad::GetPad(0)->GetPageUp()) { + m_bPressedPgUpOnList = false; + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedPgUpOnList) { + m_bPressedPgUpOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + PageUpList(false); + } + } + if (!CPad::GetPad(0)->GetPageDown()) { + m_bPressedPgDnOnList = false; + } else { + m_nCurrExLayer = HOVEROPTION_LIST; + if (!m_bPressedPgDnOnList) { + m_bPressedPgDnOnList = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + PageDownList(false); + } + } + if (CPad::GetPad(0)->GetHome()) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nFirstVisibleRowOnList = 0; + } + m_nSelectedListRow = 0; + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } + if (CPad::GetPad(0)->GetEnd()) { + m_nCurrExLayer = HOVEROPTION_LIST; + m_bShowMouse = false; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) { + m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN; + } + m_nSelectedListRow = m_nTotalListRow - 1; + m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; + } + } + + if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) { + m_bShowMouse = false; + goBack = true; + } + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + switch (m_nHoverOption) { + case HOVEROPTION_BACK: + goBack = true; + break; + case HOVEROPTION_PAGEUP: + PageUpList(true); + break; + case HOVEROPTION_PAGEDOWN: + PageDownList(true); + break; + case HOVEROPTION_USESKIN: + if (m_nSkinsTotal > 0) { + m_pSelectedSkin = m_pSkinListHead.nextSkin; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + SaveSettings(); + } + } + } + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) { + switch (m_nHoverOption) { + case HOVEROPTION_OVER_SCROLL_UP: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP; + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN; + break; + case HOVEROPTION_LIST: + m_nHoverOption = HOVEROPTION_SKIN; + } + } else if ((CPad::GetPad(0)->GetLeftMouseJustUp()) + && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) { + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + } + + if (!CPad::GetPad(0)->GetLeftMouse()) { + holdingScrollBar = false; + } else { + if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) { + holdingScrollBar = true; + // TODO: This part is a bit hard to reverse. Not much code tho + assert(0 && "Holding scrollbar isn't done yet"); + } else { + switch (m_nHoverOption) { + case HOVEROPTION_OVER_SCROLL_UP: + case HOVEROPTION_CLICKED_SCROLL_UP: + if (!m_bPressedScrollButton) { + m_bPressedScrollButton = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + ScrollUpListByOne(); + } + break; + case HOVEROPTION_OVER_SCROLL_DOWN: + case HOVEROPTION_CLICKED_SCROLL_DOWN: + if (!m_bPressedScrollButton) { + m_bPressedScrollButton = true; + lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); + ScrollDownListByOne(); + } + break; + default: + m_bPressedScrollButton = false; + } + } + } +} + +void +CMenuManager::UserInput(void) +{ bool goBack = false; bool optionSelected = false; bool goUp = false; bool goDown = false; -#ifdef TIDY_UP_PBP - bool assumeIncrease = false; + int8 changeValueBy; + + if (!m_AllowNavigation && m_firstStartCounter == 255) + m_AllowNavigation = true; + if (!m_bShowMouse && m_nCurrScreen != MENUPAGE_MAP && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) { + m_bShowMouse = true; + } + + static int oldOption = -99; + oldOption = m_nCurrOption; +#ifdef SCROLLABLE_PAGES + int firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0; + int scrollOffset = aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Y - aScreens[m_nCurrScreen].m_aEntries[0].m_Y; + for (int rowToCheck = firstOption; rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) { +#else + for (int rowToCheck = 0; rowToCheck < NUM_MENUROWS; ++rowToCheck) { #endif + if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING || + aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_LABEL) + continue; -#ifdef USE_DEBUG_SCRIPT_LOADER - if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_NEW_GAME_RELOAD) { - if (CPad::GetPad(0)->GetChar('R')) { - scriptToLoad = 1; - DoSettingsBeforeStartingAGame(); - return; + // unused: CFont::GetStringWidth(TheText.Get(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName), true); + // So they also wanted the compare X, but they abandoned the idea later on + + if (m_nMousePosY > MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y MINUS_SCROLL_OFFSET) && + m_nMousePosY < MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y MINUS_SCROLL_OFFSET PLUS_LINE_HEIGHT_ON_SCREEN)) { + static int oldScreen = m_nCurrScreen; + + m_nOptionMouseHovering = rowToCheck; + if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { + m_nCurrOption = rowToCheck; + m_bShowMouse = true; + } + + int action = aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action; + if (action != MENUACTION_BRIGHTNESS && action != MENUACTION_DRAWDIST && action != MENUACTION_MUSICVOLUME + && action != MENUACTION_SFXVOLUME && action != MENUACTION_MOUSESENS && action != MENUACTION_MP3VOLUMEBOOST +#ifdef CUSTOM_FRONTEND_OPTIONS + && action != MENUACTION_CFO_SLIDER +#endif + ) + m_nHoverOption = HOVEROPTION_RANDOM_ITEM; + + break; } - if (CPad::GetPad(0)->GetChar('D')) { - scriptToLoad = 2; - DoSettingsBeforeStartingAGame(); - return; + if (m_bShowMouse && m_nMenuFadeAlpha == 255) { + m_nOptionMouseHovering = oldOption; + m_nCurrOption = oldOption; } } -#endif - if (!m_bShowMouse && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) { - m_bShowMouse = true; + if (m_bShowMouse) { + if (oldOption != m_nCurrOption) { + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LABEL) { + ++m_nCurrOption; + ++m_nOptionMouseHovering; + } + m_nOptionHighlightTransitionBlend = 0; + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + } } m_nMouseOldPosX = m_nMousePosX; @@ -4338,33 +4339,25 @@ CMenuManager::ProcessButtonPresses(void) if (m_nMousePosY < 0) m_nMousePosY = 0; if (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT; + changeValueBy = 0; if (hasNativeList(m_nCurrScreen)) { - // Not split to seperate function in III as in VC, but we need it for scrollable pages :) - ProcessList(goBack, optionSelected); - - } else if (isPlainTextScreen(m_nCurrScreen)) { -#ifndef TIDY_UP_PBP - if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) { - optionSelected = true; - } - if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustUp()) { - if (m_nCurrScreen != MENUPAGE_START_MENU) { - goBack = true; - } - } -#endif + ProcessList(optionSelected, goBack); } else { - if (CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { + AdditionalOptionInput(goBack); + + if (m_AllowNavigation && + (CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown())) { m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); goDown = true; - } else if (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + m_nOptionHighlightTransitionBlend = 0; + + } else if (m_AllowNavigation && + (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown())) { m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); goUp = true; + m_nOptionHighlightTransitionBlend = 0; } -#ifndef TIDY_UP_PBP if ((m_nCurrOption == 0) && (m_nCurrScreen == MENUPAGE_PAUSE_MENU)) { if (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) { m_bShowMouse = false; @@ -4376,245 +4369,43 @@ CMenuManager::ProcessButtonPresses(void) optionSelected = true; } } -#endif - if (CPad::GetPad(0)->GetLeftMouseJustUp()) { -#ifndef TIDY_UP_PBP - if (((m_nCurrOption == 0) && (m_nCurrScreen == MENUPAGE_PAUSE_MENU)) && -#else - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESUME && -#endif - (m_nHoverOption == HOVEROPTION_RANDOM_ITEM)) { - m_nCurrOption = m_nOptionMouseHovering; + if (CPad::GetPad(0)->GetLeftMouseJustUp() && m_nCurrScreen != MENUPAGE_MAP) { + if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM) optionSelected = true; - } - } else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { -#ifdef TIDY_UP_PBP - if (m_nHoverOption >= HOVEROPTION_RADIO_0 && m_nHoverOption <= HOVEROPTION_RADIO_9) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = m_nHoverOption - HOVEROPTION_RADIO_0; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - } else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM - && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESUME) { - m_nCurrOption = m_nOptionMouseHovering; - optionSelected = true; - } -#else - switch (m_nHoverOption) { - case HOVEROPTION_RADIO_0: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = HEAD_RADIO; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_1: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = DOUBLE_CLEF; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_2: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = JAH_RADIO; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_3: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = RISE_FM; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_4: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = LIPS_106; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_5: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = GAME_FM; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_6: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = MSX_FM; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_7: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = FLASHBACK; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_8: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = CHATTERBOX; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RADIO_9: - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - m_PrefsRadioStation = USERTRACK; - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); - break; - case HOVEROPTION_RANDOM_ITEM: - if (((m_nCurrOption != 0) || (m_nCurrScreen != MENUPAGE_PAUSE_MENU)) { - m_nCurrOption = m_nOptionMouseHovering; - optionSelected = true; - } - break; - } -#endif + else if (m_nHoverOption == HOVEROPTION_NEXT_RADIO) + ChangeRadioStation(1); + else if (m_nHoverOption == HOVEROPTION_PREV_RADIO) + ChangeRadioStation(-1); } if (CPad::GetPad(0)->GetLeftMouse()) { -#ifndef TIDY_UP_PBP switch (m_nHoverOption) { case HOVEROPTION_INCREASE_BRIGHTNESS: - m_PrefsBrightness = m_PrefsBrightness + (512 / MENUSLIDER_LOGICAL_BARS); - if (m_PrefsBrightness < 0) { - m_PrefsBrightness = 0; - } - if (510 < m_PrefsBrightness) { - m_PrefsBrightness = 511; - } - SaveSettings(); - break; - case HOVEROPTION_DECREASE_BRIGHTNESS: - m_PrefsBrightness = m_PrefsBrightness - (512 / MENUSLIDER_LOGICAL_BARS); - if (m_PrefsBrightness < 0) { - m_PrefsBrightness = 0; - } - if (510 < m_PrefsBrightness) { - m_PrefsBrightness = 511; - } - SaveSettings(); - break; + case HOVEROPTION_INCREASE_MP3BOOST: case HOVEROPTION_INCREASE_DRAWDIST: - m_PrefsLOD = m_PrefsLOD + (1.0f / MENUSLIDER_LOGICAL_BARS); - m_PrefsLOD = min(1.8f, m_PrefsLOD); - CRenderer::ms_lodDistScale = m_PrefsLOD; - SaveSettings(); - break; - case HOVEROPTION_DECREASE_DRAWDIST: - m_PrefsLOD = m_PrefsLOD - (1.0f / MENUSLIDER_LOGICAL_BARS); - m_PrefsLOD = max(0.8f, m_PrefsLOD); - CRenderer::ms_lodDistScale = m_PrefsLOD; - SaveSettings(); - break; case HOVEROPTION_INCREASE_MUSICVOLUME: - m_PrefsMusicVolume = m_PrefsMusicVolume + (128 / MENUSLIDER_LOGICAL_BARS); - m_PrefsMusicVolume = Clamp(m_PrefsMusicVolume, 0, 127); - DMAudio.SetMusicMasterVolume(uchar)(m_PrefsMusicVolume); - SaveSettings(); - break; - case HOVEROPTION_DECREASE_MUSICVOLUME: - m_PrefsMusicVolume = m_PrefsMusicVolume - (128 / MENUSLIDER_LOGICAL_BARS); - if (m_PrefsMusicVolume < 0) { - m_PrefsMusicVolume = 0; - } - if (126 < m_PrefsMusicVolume) { - m_PrefsMusicVolume = 127; - } - DMAudio.SetMusicMasterVolume(uchar)(m_PrefsMusicVolume); - SaveSettings(); - break; case HOVEROPTION_INCREASE_SFXVOLUME: - m_PrefsSFXVolume = m_PrefsSFXVolume + (128 / MENUSLIDER_LOGICAL_BARS); - if (m_PrefsSFXVolume < 0) { - m_PrefsSFXVolume = 0; - } - if (126 < m_PrefsSFXVolume) { - m_PrefsSFXVolume = 127; - } - DMAudio.SetEffectsMasterVolume(uchar)(m_PrefsSFXVolume); - SaveSettings(); - break; - case HOVEROPTION_DECREASE_SFXVOLUME: - m_PrefsSFXVolume = m_PrefsSFXVolume - (128 / MENUSLIDER_LOGICAL_BARS); - if (m_PrefsSFXVolume < 0) { - m_PrefsSFXVolume = 0; - } - if (126 < m_PrefsSFXVolume) { - m_PrefsSFXVolume = 127; - } - DMAudio.SetEffectsMasterVolume(uchar)(m_PrefsSFXVolume); - SaveSettings(); - break; case HOVEROPTION_INCREASE_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl += 1.0f/200.0f/15.0f; // probably because diving it to 15 instead of 16(MENUSLIDER_LOGICAL_BARS) had more accurate steps - TheCamera.m_fMouseAccelHorzntl = Clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); -#ifdef FIX_BUGS - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; -#else - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; +#ifdef CUSTOM_FRONTEND_OPTIONS + case HOVEROPTION_INCREASE_CFO_SLIDER: #endif - SaveSettings(); + CheckSliderMovement(1); break; + case HOVEROPTION_DECREASE_BRIGHTNESS: + case HOVEROPTION_DECREASE_MP3BOOST: + case HOVEROPTION_DECREASE_DRAWDIST: + case HOVEROPTION_DECREASE_MUSICVOLUME: + case HOVEROPTION_DECREASE_SFXVOLUME: case HOVEROPTION_DECREASE_MOUSESENS: - TheCamera.m_fMouseAccelHorzntl -= 1.0f/200.0f/15.0f; // probably because diving it to 15 instead of 16(MENUSLIDER_LOGICAL_BARS) had more accurate steps - TheCamera.m_fMouseAccelHorzntl = Clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); -#ifdef FIX_BUGS - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f; -#else - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; -#endif - SaveSettings(); - break; - } -#else - switch (m_nHoverOption) { - case HOVEROPTION_INCREASE_BRIGHTNESS: - case HOVEROPTION_INCREASE_DRAWDIST: - case HOVEROPTION_INCREASE_MUSICVOLUME: - case HOVEROPTION_INCREASE_SFXVOLUME: - case HOVEROPTION_INCREASE_MOUSESENS: -#ifdef CUSTOM_FRONTEND_OPTIONS - case HOVEROPTION_INCREASE_CFO_SLIDER: -#endif - CheckSliderMovement(1); - break; - case HOVEROPTION_DECREASE_BRIGHTNESS: - case HOVEROPTION_DECREASE_DRAWDIST: - case HOVEROPTION_DECREASE_MUSICVOLUME: - case HOVEROPTION_DECREASE_SFXVOLUME: - case HOVEROPTION_DECREASE_MOUSESENS: #ifdef CUSTOM_FRONTEND_OPTIONS - case HOVEROPTION_DECREASE_CFO_SLIDER: + case HOVEROPTION_DECREASE_CFO_SLIDER: #endif - CheckSliderMovement(-1); - break; + CheckSliderMovement(-1); + break; } -#endif } - + #ifdef SCROLLABLE_PAGES if (m_nTotalListRow > MAX_VISIBLE_OPTION) { bool temp = false; @@ -4628,40 +4419,36 @@ CMenuManager::ProcessButtonPresses(void) goUp = false; goDown = false; m_nCurrOption = m_nSelectedListRow; + + if (oldOption != m_nCurrOption) + m_nOptionHighlightTransitionBlend = 0; } // Prevent sound on scroll. Mouse wheel is now belongs to us! if (!(m_nTotalListRow > MAX_VISIBLE_OPTION && (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()))) #endif - if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp() || CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp() || CPad::GetPad(0)->GetAnaloguePadLeftJustUp() || CPad::GetPad(0)->GetAnaloguePadRightJustUp() || CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()) { int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if (option == MENUACTION_BRIGHTNESS || option == MENUACTION_DRAWDIST + if (option == MENUACTION_BRIGHTNESS #ifdef CUSTOM_FRONTEND_OPTIONS || option == MENUACTION_CFO_SLIDER #endif ) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); else if (option == MENUACTION_SFXVOLUME) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_AUDIO_TEST, 0); - else if (option == MENUACTION_MOUSESENS) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + else if (option == MENUACTION_DRAWDIST || option == MENUACTION_MOUSESENS) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); } - -#ifndef TIDY_UP_PBP - if (CPad::GetPad(0)->GetBackJustDown()) { - if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU) { - m_bShowMouse = false; - goBack = true; - } - } - - if (CPad::GetPad(0)->GetEscapeJustDown()) { - if (m_nCurrScreen != MENUPAGE_START_MENU) { + if (CPad::GetPad(0)->GetBackJustDown() || CPad::GetPad(0)->GetEscapeJustDown()) { + if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU && m_nCurrScreen != MENUPAGE_CHOOSE_SAVE_SLOT + && m_nCurrScreen != MENUPAGE_SAVE_CHEAT_WARNING && m_nCurrScreen != MENUPAGE_SAVING_IN_PROGRESS + && m_nCurrScreen != MENUPAGE_DELETING_IN_PROGRESS && m_nCurrScreen != MENUPAGE_OUTRO) + { m_bShowMouse = false; goBack = true; } @@ -4670,92 +4457,193 @@ CMenuManager::ProcessButtonPresses(void) if (((goDown) || (goUp)) || (optionSelected)) { goBack = false; } -#endif + } - // Centralized enter/back (except some conditions) -#ifdef TIDY_UP_PBP - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESUME) { - if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || - (isPlainTextScreen(m_nCurrScreen) && CPad::GetPad(0)->GetLeftMouseJustDown())) { + int curAction = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; + if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetPedWalkLeftRight() < 0 || CPad::GetPad(0)->GetDPadLeft()) { + static uint32 lastSliderDecrease = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderDecrease > 150) { + if (curAction == MENUACTION_BRIGHTNESS || curAction == MENUACTION_MUSICVOLUME || + curAction == MENUACTION_SFXVOLUME || curAction == MENUACTION_RADIO || + curAction == MENUACTION_DRAWDIST || curAction == MENUACTION_MOUSESENS || + curAction == MENUACTION_MP3VOLUMEBOOST +#ifdef CUSTOM_FRONTEND_OPTIONS + || curAction == MENUACTION_CFO_SLIDER +#endif + ) + changeValueBy = -1; - if (!isPlainTextScreen(m_nCurrScreen)) - m_bShowMouse = false; + lastSliderDecrease = CTimer::GetTimeInMillisecondsPauseMode(); + } + } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { + static uint32 lastSliderIncrease = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) { + if (curAction == MENUACTION_BRIGHTNESS || curAction == MENUACTION_MUSICVOLUME || + curAction == MENUACTION_SFXVOLUME || curAction == MENUACTION_RADIO || + curAction == MENUACTION_DRAWDIST || curAction == MENUACTION_MOUSESENS || + curAction == MENUACTION_MP3VOLUMEBOOST +#ifdef CUSTOM_FRONTEND_OPTIONS + || curAction == MENUACTION_CFO_SLIDER +#endif + ) + changeValueBy = 1; + lastSliderIncrease = CTimer::GetTimeInMillisecondsPauseMode(); + } + } - optionSelected = true; +#ifdef SCROLLABLE_PAGES + if (!SCREEN_HAS_AUTO_SCROLLBAR) +#endif + { + if (CPad::GetPad(0)->GetMouseWheelUpJustDown()) { + changeValueBy = 1; + } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) { + changeValueBy = -1; } - } else { - if (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) { + } + + if (m_AllowNavigation) { + if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) { m_bShowMouse = false; - optionSelected = true; + changeValueBy = 1; } } - if (!goDown && !goUp && !optionSelected) { - if (m_nCurrScreen != MENUPAGE_START_MENU) { - if (isPlainTextScreen(m_nCurrScreen)) { - if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustUp()) { - goBack = true; - } - } else { - if (CPad::GetPad(0)->GetEscapeJustDown() || (m_nCurrScreen != MENUPAGE_PAUSE_MENU && CPad::GetPad(0)->GetBackJustDown())) { - m_bShowMouse = false; - goBack = true; - } + if (m_AllowNavigation) { + if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) { + m_bShowMouse = false; + changeValueBy = -1; + } + } + if (changeValueBy != 0) { + if ((m_nCurrScreen == MENUPAGE_SOUND_SETTINGS || m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS || m_nCurrScreen == MENUPAGE_CONTROLLER_PC || m_nCurrScreen == MENUPAGE_MOUSE_CONTROLS) + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_NOTHING + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_LABEL + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_YES + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_NO + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_CHANGEMENU + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_KEYBOARDCTRLS + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_GOBACK + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESTOREDEF + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_DRAWDIST + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_MOUSESENS + && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_MP3VOLUMEBOOST) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + } + } + ProcessUserInput(goDown, goUp, optionSelected, goBack, changeValueBy); +#ifdef CUSTOM_FRONTEND_OPTIONS + if (aScreens[m_nCurrScreen].m_aEntries[oldOption].m_Action < MENUACTION_NOTHING) { // CFO check + CMenuScreenCustom::CMenuEntry &oldEntry = aScreens[m_nCurrScreen].m_aEntries[oldOption]; + if (m_nCurrOption != oldOption) { + if (oldEntry.m_Action == MENUACTION_CFO_DYNAMIC) + if(oldEntry.m_CFODynamic->buttonPressFunc) + oldEntry.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (oldEntry.m_Action == MENUACTION_CFO_SELECT && oldEntry.m_CFOSelect->onlyApplyOnEnter) { + if (oldEntry.m_CFOSelect->displayedValue != oldEntry.m_CFOSelect->lastSavedValue) + SetHelperText(3); // Restored original value + + oldEntry.m_CFOSelect->displayedValue = oldEntry.m_CFOSelect->lastSavedValue = *(int8*)oldEntry.m_CFO->value; } + } else if (oldEntry.m_Action == MENUACTION_CFO_SELECT && oldEntry.m_CFOSelect->onlyApplyOnEnter) { + if (oldEntry.m_CFOSelect->displayedValue != *(int8*)oldEntry.m_CFO->value) + SetHelperText(1); // Enter to apply + else if (m_nHelperTextMsgId == 1) + ResetHelperText(); // Applied } } #endif +} -#ifdef PS2_LIKE_MENU - if (CPad::GetPad(0)->GetLeftMouseJustDown() && hoveredBottomBarOption != -1) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - bottomBarActive = false; - curBottomBarOption = hoveredBottomBarOption; - ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, false); - if (bbNames[curBottomBarOption].screenId == MENUPAGE_SOUND_SETTINGS) - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); +void +CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, uint8 goBack, int8 changeAmount) +{ + if (m_nCurrScreen == MENUPAGE_OUTRO) return; - } else if (bottomBarActive) { - if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - bottomBarActive = false; - if (bbNames[curBottomBarOption].screenId == MENUPAGE_SOUND_SETTINGS) - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); + if (m_bWaitingForNewKeyBind) { + if (m_bStartWaitingForKeyBind) + m_bStartWaitingForKeyBind = false; + else { + pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); + JoyButtonJustClicked = false; + MouseButtonJustClicked = false; + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) + MouseButtonJustClicked = rsMOUSELEFTBUTTON; + else if (CPad::GetPad(0)->GetRightMouseJustUp()) + MouseButtonJustClicked = rsMOUSERIGHTBUTTON; + else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) + MouseButtonJustClicked = rsMOUSMIDDLEBUTTON; + else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) + MouseButtonJustClicked = rsMOUSEWHEELUPBUTTON; + else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) + MouseButtonJustClicked = rsMOUSEWHEELDOWNBUTTON; + else if (CPad::GetPad(0)->GetMouseX1JustUp()) + MouseButtonJustClicked = rsMOUSEX1BUTTON; + else if (CPad::GetPad(0)->GetMouseX2JustUp()) + MouseButtonJustClicked = rsMOUSEX2BUTTON; + + JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); + + int32 TypeOfControl = KEYBOARD; + if (JoyButtonJustClicked) + TypeOfControl = JOYSTICK; + if (MouseButtonJustClicked) + TypeOfControl = MOUSE; + if (*pControlEdit != rsNULL) + TypeOfControl = KEYBOARD; + + if (!m_bKeyIsOK) { + pControlEdit = nil; + m_bWaitingForNewKeyBind = false; + m_KeyPressedCode = -1; + m_bStartWaitingForKeyBind = false; + } else if (!m_bKeyChangeNotProcessed) { + if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) + CheckCodesForControls(TypeOfControl); - return; - } else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown() - || CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { + field_159 = true; + } else { + for (int i = 0; i < 4; i++) + ControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i); + m_bKeyIsOK = false; + m_bKeyChangeNotProcessed = false; + } + } + } - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - curBottomBarOption = ((curBottomBarOption + bbTabCount) - 1) % bbTabCount; - ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); - return; - } else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown() - || CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { + if (pEditString || pControlEdit) + return; - m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - curBottomBarOption = ((curBottomBarOption + bbTabCount) + 1) % bbTabCount; - ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); +#ifdef USE_DEBUG_SCRIPT_LOADER + if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_NEW_GAME_RELOAD) { + if (CPad::GetPad(0)->GetChar('R')) { + scriptToLoad = 1; + DoSettingsBeforeStartingAGame(); return; } - optionSelected = false; - goDown = false; - goUp = false; } #endif - int prevOption = m_nCurrOption; - if (goDown && (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME)) { + int oldOption = m_nCurrOption; + if (goDown) { + if (m_nCurrScreen != MENUPAGE_MAP) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + m_nCurrOption++; if (m_nCurrOption == NUM_MENUROWS || (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NOTHING)) { m_nCurrOption = 0; } + if (oldOption != m_nCurrOption) + m_nOptionHighlightTransitionBlend = 0; } - if (goUp && (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME)) { + if (goUp) { + if (m_nCurrScreen != MENUPAGE_MAP) + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0); + if (m_nCurrOption == (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL)) { while (m_nCurrOption != NUM_MENUROWS - 1 && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption + 1].m_Action != MENUACTION_NOTHING) { @@ -4764,634 +4652,418 @@ CMenuManager::ProcessButtonPresses(void) } else { m_nCurrOption--; } + if (oldOption != m_nCurrOption) + m_nOptionHighlightTransitionBlend = 0; } - // Hide back button -#ifdef PS2_LIKE_MENU - if ((goUp || goDown) && m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME && strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB") == 0) - m_nCurrOption = goUp ? m_nCurrOption - 1 : (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL); -#endif - - if (optionSelected) { - int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if ((option == MENUACTION_CHANGEMENU) || (option == MENUACTION_POPULATESLOTS_CHANGEMENU)) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB") != 0 && - strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FESZ_CA") != 0) { - - if (m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT) { - if (Slots[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot - 1] == SLOT_EMPTY) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - else - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - } else - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); - } else { - // This is duplicate, back button already processed below -#ifndef TIDY_UP_PBP - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_EXIT, 0); - if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); - } -#endif - } - } else if (option == MENUACTION_CHECKSAVE) { - if (Slots[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot - 1] == SLOT_EMPTY) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - } else { - if (m_nCurrScreen != MENUPAGE_NEW_GAME_RELOAD) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - } - } - } else if (option != MENUACTION_CHANGEMENU && option != MENUACTION_BRIGHTNESS && option != MENUACTION_DRAWDIST - && option != MENUACTION_MUSICVOLUME && option != MENUACTION_SFXVOLUME - && option != MENUACTION_CHECKSAVE && option != MENUACTION_UNK24 - && option != MENUACTION_MOUSESENS && option != MENUACTION_SCREENRES -#ifdef CUSTOM_FRONTEND_OPTIONS - && option != MENUACTION_CFO_SLIDER -#endif - ) - { - - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - } - - if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) || (m_nCurrScreen == MENUPAGE_SKIN_SELECT)) { + if (optionSelected && m_nMenuFadeAlpha == 255) { + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { + DoSettingsBeforeStartingAGame(); + } else if (hasNativeList(m_nCurrScreen)) { switch (m_nCurrExLayer) { - default: - goBack = true; - break; - case HOVEROPTION_LIST: - if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - } - if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { - strcpy(m_PrefsSkinFile, m_aSkinName); - CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); - m_nCurrExLayer = HOVEROPTION_BACK; - SaveSettings(); - } - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - break; - case HOVEROPTION_USESKIN: - m_nHoverOption = HOVEROPTION_NOT_HOVERING; + case HOVEROPTION_LIST: + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + } + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); m_nCurrExLayer = HOVEROPTION_BACK; SaveSettings(); - break; + } + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + break; + case HOVEROPTION_USESKIN: + m_nHoverOption = HOVEROPTION_NOT_HOVERING; + strcpy(m_PrefsSkinFile, m_aSkinName); + CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); + m_nCurrExLayer = HOVEROPTION_BACK; + SaveSettings(); + break; + case HOVEROPTION_BACK: + default: + goBack = true; + break; } - } else if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) { - DoSettingsBeforeStartingAGame(); -/* } else if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - // .. either empty or there was some outer if. :shrug: pointless anyway, keyboard_controls is handled in first if. -*/ - } else if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { if (m_nSkinsTotal > 0) { m_pSelectedSkin = m_pSkinListHead.nextSkin; strcpy(m_PrefsSkinFile, m_aSkinName); CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); SaveSettings(); - } else { -#ifndef TIDY_UP_PBP - ChangeScreen(!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0], - GetPreviousPageOption(), true, true); -#else - goBack = true; -#endif } - } else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { - option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - switch (option) { - case MENUACTION_RADIO: -#ifdef TIDY_UP_PBP - assumeIncrease = true; -#else - ++m_PrefsRadioStation; - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; - } else if (m_PrefsRadioStation > CHATTERBOX) { - m_PrefsRadioStation = USERTRACK; - } - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); -#endif - break; - case MENUACTION_LANG_ENG: - m_PrefsLanguage = LANGUAGE_AMERICAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_FRE: - m_PrefsLanguage = LANGUAGE_FRENCH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_GER: - m_PrefsLanguage = LANGUAGE_GERMAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_ITA: - m_PrefsLanguage = LANGUAGE_ITALIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_SPA: - m_PrefsLanguage = LANGUAGE_SPANISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_POPULATESLOTS_CHANGEMENU: - PcSaveHelper.PopulateSlotInfo(); - - // fall through - case MENUACTION_CHANGEMENU: - { - bool changeMenu = true; - int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; - - // This should be unused. - if (saveSlot >= 2 && saveSlot <= 9) { - m_nCurrSaveSlot = saveSlot - 2; - switch (m_nCurrScreen) { - case MENUPAGE_CHOOSE_LOAD_SLOT: - if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY) - changeMenu = false; - - break; - case MENUPAGE_CHOOSE_DELETE_SLOT: - if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY) - changeMenu = false; + } - break; + int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; +#ifdef FIX_BUGS + int currScreen = m_nCurrScreen; + int currOption = m_nCurrOption; +#endif + switch (option) { + case MENUACTION_CHANGEMENU: + case MENUACTION_YES: + case MENUACTION_NO: + SwitchToNewScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu); + break; + case MENUACTION_RADIO: + ChangeRadioStation(1); + break; + case MENUACTION_LANG_ENG: + m_PrefsLanguage = LANGUAGE_AMERICAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_FRE: + m_PrefsLanguage = LANGUAGE_FRENCH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_GER: + m_PrefsLanguage = LANGUAGE_GERMAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_ITA: + m_PrefsLanguage = LANGUAGE_ITALIAN; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_LANG_SPA: + m_PrefsLanguage = LANGUAGE_SPANISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; + case MENUACTION_CHECKSAVE: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + if (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8) { + m_nCurrSaveSlot = saveSlot - SAVESLOT_1; + if (Slots[m_nCurrSaveSlot] != SLOT_EMPTY && Slots[m_nCurrSaveSlot] != SLOT_CORRUPTED) { + if (m_nCurrScreen == MENUPAGE_CHOOSE_LOAD_SLOT) { + SwitchToNewScreen(MENUPAGE_LOAD_SLOT_CONFIRM); + } else if (m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT) { + SwitchToNewScreen(MENUPAGE_DELETE_SLOT_CONFIRM); } } - if (changeMenu) { - if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB") == 0) { -#ifndef TIDY_UP_PBP - ResetHelperText(); - ChangeScreen(!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0], - GetPreviousPageOption(), true, true); -#else - goBack = true; - break; + } + break; + } + case MENUACTION_NEWGAME: + DoSettingsBeforeStartingAGame(); + break; +#ifdef LEGACY_MENU_OPTIONS + case MENUACTION_RELOADIDE: + CFileLoader::ReloadObjectTypes("GTA3.IDE"); + break; #endif - } else { - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } - break; + case MENUACTION_RESUME_FROM_SAVEZONE: + RequestFrontEndShutDown(); + break; + case MENUACTION_LOADRADIO: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + SwitchToNewScreen(MENUPAGE_SOUND_SETTINGS); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); + OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); } - case MENUACTION_CHECKSAVE: - { - int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + break; +#ifdef MISSION_REPLAY + case MENUACTION_REJECT_RETRY: + doingMissionRetry = false; + AllowMissionReplay = 0; + RequestFrontEndShutDown(); + break; + case MENUACTION_UNK114: + doingMissionRetry = false; + RequestFrontEndShutDown(); + RetryMission(2, 0); + return; +#endif + case MENUACTION_SAVEGAME: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; - if (saveSlot >= 2 && saveSlot <= 9) { - m_nCurrSaveSlot = saveSlot - 2; - if (Slots[m_nCurrSaveSlot + 1] != SLOT_EMPTY && Slots[m_nCurrSaveSlot + 1] != SLOT_CORRUPTED) { - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } - break; + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = m_nCurrOption; + SwitchToNewScreen(MENUPAGE_SAVE_OVERWRITE_CONFIRM); + } + break; + } + case MENUACTION_RADARMODE: + if (++m_PrefsRadarMode > 2) + m_PrefsRadarMode = 0; + SaveSettings(); + break; + case MENUACTION_GOBACK: + goBack = true; + break; + case MENUACTION_KEYBOARDCTRLS: + SwitchToNewScreen(MENUPAGE_KEYBOARD_CONTROLS); + m_nSelectedListRow = 0; + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case MENUACTION_GETKEY: + m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; + m_bKeyIsOK = true; + m_bWaitingForNewKeyBind = true; + m_bStartWaitingForKeyBind = true; + pControlEdit = &m_KeyPressedCode; + break; + case MENUACTION_CANCELGAME: + DMAudio.Service(); + SwitchToNewScreen(MENUPAGE_OUTRO); + break; + case MENUACTION_RESUME: +#ifdef LEGACY_MENU_OPTIONS + if (m_PrefsVsyncDisp != m_PrefsVsync) { + m_PrefsVsync = m_PrefsVsyncDisp; } - case MENUACTION_NEWGAME: - DoSettingsBeforeStartingAGame(); - break; - case MENUACTION_RELOADIDE: - CFileLoader::ReloadObjectTypes("GTA3.IDE"); - break; - case MENUACTION_RELOADIPL: - CGame::ReloadIPLs(); - break; - case MENUACTION_SHOWCULL: - gbShowCullZoneDebugStuff = !gbShowCullZoneDebugStuff; - break; - case MENUACTION_MEMCARDSAVECONFIRM: - return; - case MENUACTION_RESUME_FROM_SAVEZONE: - RequestFrontEndShutDown(); - break; - case MENUACTION_MPMAP_LIBERTY: - case MENUACTION_MPMAP_REDLIGHT: - case MENUACTION_MPMAP_CHINATOWN: - case MENUACTION_MPMAP_TOWER: - case MENUACTION_MPMAP_SEWER: - case MENUACTION_MPMAP_INDUSTPARK: - case MENUACTION_MPMAP_DOCKS: - case MENUACTION_MPMAP_STAUNTON: - m_SelectedMap = option - MENUACTION_MPMAP_LIBERTY; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_MPMAP_DEATHMATCH1: - case MENUACTION_MPMAP_DEATHMATCH2: - case MENUACTION_MPMAP_TEAMDEATH1: - case MENUACTION_MPMAP_TEAMDEATH2: - case MENUACTION_MPMAP_STASH: - case MENUACTION_MPMAP_CAPTURE: - case MENUACTION_MPMAP_RATRACE: - case MENUACTION_MPMAP_DOMINATION: - m_SelectedGameType = option - MENUACTION_MPMAP_DEATHMATCH1; - SaveSettings(); - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - break; - case MENUACTION_KEYBOARDCTRLS: - ChangeScreen(MENUPAGE_KEYBOARD_CONTROLS, 0, true, true); - m_nSelectedListRow = 0; - m_nCurrExLayer = HOVEROPTION_LIST; - break; - case MENUACTION_GETKEY: - m_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption; - m_bKeyIsOK = true; - m_bWaitingForNewKeyBind = true; - m_bStartWaitingForKeyBind = true; - pControlEdit = &m_KeyPressedCode; - break; - case MENUACTION_CANCELGAME: - DMAudio.Service(); - RsEventHandler(rsQUITAPP, nil); - break; - case MENUACTION_RESUME: -#ifndef TIDY_UP_PBP - if (m_PrefsVsyncDisp != m_PrefsVsync) { - m_PrefsVsync = m_PrefsVsyncDisp; - } - RequestFrontEndShutDown(); -#else - goBack = true; #endif - break; - case MENUACTION_DONTCANCEL: - ChangeScreen(!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0], - GetPreviousPageOption(), true, true); - break; - case MENUACTION_SCREENRES: - if (m_nDisplayVideoMode != m_nPrefsVideoMode) { - m_nPrefsVideoMode = m_nDisplayVideoMode; - _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); - SaveSettings(); - } - break; - case MENUACTION_AUDIOHW: - { - int selectedProvider = m_nPrefsAudio3DProviderIndex; - if (selectedProvider != -1) { - m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); - if (selectedProvider == m_nPrefsAudio3DProviderIndex) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SetHelperText(0); - } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - SetHelperText(4); - } - SaveSettings(); - } - break; + RequestFrontEndShutDown(); + break; + case MENUACTION_DONTCANCEL: + SwitchToNewScreen(-2); + break; + case MENUACTION_SCREENRES: + if (m_nDisplayVideoMode != m_nPrefsVideoMode) { + m_nPrefsVideoMode = m_nDisplayVideoMode; + _psSelectScreenVM(m_nPrefsVideoMode); + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.Service(); + CentreMousePointer(); + m_bShowMouse = true; + m_nCurrOption = 5; // TODO(Miami): Because selected option is resetted after res. change. We'll need to revisit that. + m_nOptionHighlightTransitionBlend = 0; + SaveSettings(); } - case MENUACTION_SPEAKERCONF: -#ifndef TIDY_UP_PBP - if (m_nPrefsAudio3DProviderIndex != -1) { - if (--m_PrefsSpeakers < 0) - m_PrefsSpeakers = 2; - DMAudio.SetSpeakerConfig(m_PrefsSpeakers); - SaveSettings(); + break; + case MENUACTION_AUDIOHW: + { + int selectedProvider = m_nPrefsAudio3DProviderIndex; + if (selectedProvider != NO_AUDIO_PROVIDER) { + if (selectedProvider == -1) + selectedProvider = m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); + + m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + if (selectedProvider != m_nPrefsAudio3DProviderIndex) { + SetHelperText(5); } -#else - assumeIncrease = true; -#endif - break; - case MENUACTION_PLAYERSETUP: - CPlayerSkin::BeginFrontendSkinEdit(); - ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); - m_nCurrExLayer = HOVEROPTION_LIST; - m_bSkinsEnumerated = false; - break; - case MENUACTION_RESTOREDEF: - if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - m_PrefsSfxVolume = 102; - m_PrefsSpeakers = 0; - m_PrefsMusicVolume = 102; - m_PrefsStereoMono = 0; - m_PrefsRadioStation = HEAD_RADIO; - DMAudio.SetMusicMasterVolume(102); - DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - SaveSettings(); - } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { - m_PrefsFrameLimiter = true; - m_PrefsBrightness = 256; - m_PrefsVsyncDisp = true; - m_PrefsLOD = 1.2f; - m_PrefsVsync = true; - CRenderer::ms_lodDistScale = 1.2f; + SaveSettings(); + } + break; + } + case MENUACTION_SPEAKERCONF: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + if (--m_PrefsSpeakers < 0) + m_PrefsSpeakers = 2; + DMAudio.SetSpeakerConfig(m_PrefsSpeakers); + SaveSettings(); + } + break; + case MENUACTION_PLAYERSETUP: + CPlayerSkin::BeginFrontendSkinEdit(); + SwitchToNewScreen(MENUPAGE_SKIN_SELECT); + m_bSkinsEnumerated = false; + m_nCurrExLayer = HOVEROPTION_LIST; + break; + case MENUACTION_RESTOREDEF: + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { + m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); + DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + m_PrefsSfxVolume = 49; + m_PrefsMusicVolume = 49; + m_PrefsRadioStation = EMOTION; + m_PrefsMP3BoostVolume = 0; + m_PrefsStereoMono = 1; + m_PrefsSpeakers = 0; + DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); + DMAudio.SetRadioInCar(m_PrefsRadioStation); + DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); + SaveSettings(); + } else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) { + m_PrefsBrightness = 256; + m_PrefsLOD = 1.2f; +#ifdef LEGACY_MENU_OPTIONS + m_PrefsVsync = true; +#endif + CRenderer::ms_lodDistScale = m_PrefsLOD; + m_PrefsShowSubtitles = false; #ifdef ASPECT_RATIO_SCALE - m_PrefsUseWideScreen = AR_AUTO; -#else - m_PrefsUseWideScreen = false; -#endif - m_PrefsShowSubtitles = true; - m_nDisplayVideoMode = m_nPrefsVideoMode; -#if GTA_VERSION >= GTA3_PC_11 - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } + m_PrefsUseWideScreen = AR_AUTO; #else - CMBlur::BlurOn = true; + m_PrefsUseWideScreen = false; #endif + m_PrefsShowLegends = true; + m_PrefsVsyncDisp = true; + m_PrefsFrameLimiter = true; + m_PrefsRadarMode = 0; + m_PrefsShowHud = true; + m_nDisplayVideoMode = m_nPrefsVideoMode; + CMBlur::BlurOn = false; #ifdef CUSTOM_FRONTEND_OPTIONS - extern void RestoreDefGraphics(int8); - extern void RestoreDefDisplay(int8); + extern void RestoreDefGraphics(int8); + extern void RestoreDefDisplay(int8); - RestoreDefGraphics(FEOPTION_ACTION_SELECT); - RestoreDefDisplay(FEOPTION_ACTION_SELECT); + RestoreDefGraphics(FEOPTION_ACTION_SELECT); + RestoreDefDisplay(FEOPTION_ACTION_SELECT); #endif - SaveSettings(); - } else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { - ControlsManager.MakeControllerActionsBlank(); - ControlsManager.InitDefaultControlConfiguration(); - ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); + SaveSettings(); + } else if (m_nCurrScreen == MENUPAGE_CONTROLLER_PC) { + ControlsManager.MakeControllerActionsBlank(); + ControlsManager.InitDefaultControlConfiguration(); + ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); #if !defined RW_GL3 - if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { - DIDEVCAPS devCaps; - devCaps.dwSize = sizeof(DIDEVCAPS); - PSGLOBAL(joy1)->GetCapabilities(&devCaps); - ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); - } + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { + DIDEVCAPS devCaps; + devCaps.dwSize = sizeof(DIDEVCAPS); + PSGLOBAL(joy1)->GetCapabilities(&devCaps); + ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); + } #else - if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { - int count; - glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); - ControlsManager.InitDefaultControlConfigJoyPad(count); - } + if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + ControlsManager.InitDefaultControlConfigJoyPad(count); + } #endif - m_ControlMethod = CONTROL_STANDARD; + MousePointerStateHelper.bInvertVertically = true; + TheCamera.m_bHeadBob = false; #ifdef FIX_BUGS - MousePointerStateHelper.bInvertVertically = true; - TheCamera.m_fMouseAccelVertical = 0.003f; -#else - MousePointerStateHelper.bInvertVertically = false; -#endif - TheCamera.m_fMouseAccelHorzntl = 0.0025f; - CVehicle::m_bDisableMouseSteering = true; - TheCamera.m_bHeadBob = false; - SaveSettings(); -#ifdef LOAD_INI_SETTINGS - SaveINIControllerSettings(); + TheCamera.m_fMouseAccelVertical = 0.003f; #endif - } - SetHelperText(2); - break; - case MENUACTION_CTRLMETHOD: -#ifndef TIDY_UP_PBP - if (m_ControlMethod == CONTROL_CLASSIC) { - CCamera::m_bUseMouse3rdPerson = true; - m_ControlMethod = CONTROL_STANDARD; - } else { - CCamera::m_bUseMouse3rdPerson = false; - m_ControlMethod = CONTROL_CLASSIC; - } - SaveSettings(); + TheCamera.m_fMouseAccelHorzntl = 0.0025f; + CVehicle::m_bDisableMouseSteering = true; + m_ControlMethod = CONTROL_STANDARD; +#ifdef PC_PLAYER_CONTROLS + TheCamera.m_bUseMouse3rdPerson = true; #else - assumeIncrease = true; + TheCamera.m_bUseMouse3rdPerson = false; #endif - break; - case MENUACTION_LOADRADIO: - ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); - break; -#ifdef MISSION_REPLAY - case MENUACTION_REJECT_RETRY: - doingMissionRetry = false; - AllowMissionReplay = 0; - RequestFrontEndShutDown(); - break; - case MENUACTION_UNK114: - doingMissionRetry = false; - RequestFrontEndShutDown(); - RetryMission(2, 0); - return; + SaveSettings(); +#ifdef LOAD_INI_SETTINGS + SaveINIControllerSettings(); #endif + } + SetHelperText(2); + break; + case MENUACTION_CTRLMETHOD: + if (m_ControlMethod == CONTROL_CLASSIC) { + CCamera::m_bUseMouse3rdPerson = true; + m_ControlMethod = CONTROL_STANDARD; + } else { + CCamera::m_bUseMouse3rdPerson = false; + m_ControlMethod = CONTROL_CLASSIC; + } + SaveSettings(); + break; #ifdef CUSTOM_FRONTEND_OPTIONS - case MENUACTION_CFO_SELECT: - case MENUACTION_CFO_DYNAMIC: - CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; - if (option.m_Action == MENUACTION_CFO_SELECT) { - if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) + case MENUACTION_CFO_SELECT: + case MENUACTION_CFO_DYNAMIC: + CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption]; + if (option.m_Action == MENUACTION_CFO_SELECT) { + if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) break; - if (!option.m_CFOSelect->onlyApplyOnEnter) { - option.m_CFOSelect->displayedValue++; - if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) - option.m_CFOSelect->displayedValue = 0; - } - int8 oldValue = *(int8*)option.m_CFO->value; - - *(int8*)option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; - - // Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO - // if (option.m_CFOSelect->save) - SaveSettings(); + if (!option.m_CFOSelect->onlyApplyOnEnter) { + option.m_CFOSelect->displayedValue++; + if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0) + option.m_CFOSelect->displayedValue = 0; + } + int8 oldValue = *(int8*)option.m_CFO->value; - if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc) - option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); + *(int8*)option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue; - } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { - if (option.m_CFODynamic->buttonPressFunc) - option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT); - } + // Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO + // if (option.m_CFOSelect->save) + SaveSettings(); - break; -#endif - } - } - ProcessOnOffMenuOptions(); - } + if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc) + option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); - if (goBack) { - ResetHelperText(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_BACK, 0); -#ifdef PS2_LIKE_MENU - if (m_nCurrScreen == MENUPAGE_PAUSE_MENU || bottomBarActive) { -#else - if (m_nCurrScreen == MENUPAGE_PAUSE_MENU) { -#endif - if (!m_bGameNotLoaded && !m_bMenuStateChanged) { - if (m_PrefsVsyncDisp != m_PrefsVsync) { - m_PrefsVsync = m_PrefsVsyncDisp; + } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) { + if (option.m_CFODynamic->buttonPressFunc) + option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT); } - RequestFrontEndShutDown(); - } - // We're already resuming, we don't need further processing. -#if defined(FIX_BUGS) || defined(PS2_LIKE_MENU) - return; -#endif - } -#ifdef PS2_SAVE_DIALOG - else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT || m_nCurrScreen == MENUPAGE_SAVE) { -#else - else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) { + break; #endif - RequestFrontEndShutDown(); - } - // It's now in ThingsToDoBeforeGoingBack() -#ifndef TIDY_UP_PBP - else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); } -#endif - - int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; - int oldOption = GetPreviousPageOption(); - - if (oldScreen != -1) { - ThingsToDoBeforeGoingBack(); - -#ifdef PS2_LIKE_MENU - if (!bottomBarActive && - (oldScreen == MENUPAGE_NONE || oldScreen == MENUPAGE_OPTIONS)) { - bottomBarActive = true; - } else -#endif - { - ChangeScreen(oldScreen, oldOption, true, true); - } - - // We will go back for sure at this point, why process other things?! + ProcessOnOffMenuOptions(); + if (!goBack) { #ifdef FIX_BUGS - return; -#endif - } - } - -#ifdef PS2_LIKE_MENU - if (bottomBarActive) - return; -#endif - - int changeValueBy = 0; - bool decrease = false; -#ifdef TIDY_UP_PBP - bool increase = assumeIncrease; + int saveSlot = aScreens[currScreen].m_aEntries[currOption].m_SaveSlot; + if (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 && Slots[currOption] != SLOT_OK) #else - bool increase = false; + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + if (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 && Slots[m_nCurrOption] != SLOT_OK) #endif - if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetPedWalkLeftRight() < 0 || CPad::GetPad(0)->GetDPadLeft()) { - static uint32 lastSliderDecrease = 0; - if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderDecrease > 150) { - CheckSliderMovement(-1); - lastSliderDecrease = CTimer::GetTimeInMillisecondsPauseMode(); - } - } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) { - static uint32 lastSliderIncrease = 0; - if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) { - CheckSliderMovement(1); - lastSliderIncrease = CTimer::GetTimeInMillisecondsPauseMode(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + else + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); } } - if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) { - m_bShowMouse = false; - increase = true; - } else if ( -#ifdef SCROLLABLE_PAGES - !SCREEN_HAS_AUTO_SCROLLBAR && -#endif - CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { - increase = true; - CheckSliderMovement(1); - m_bShowMouse = true; - } - - if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) { - m_bShowMouse = false; - decrease = true; - } else if ( -#ifdef SCROLLABLE_PAGES - !SCREEN_HAS_AUTO_SCROLLBAR && -#endif - CPad::GetPad(0)->GetMouseWheelDownJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) { - decrease = true; - CheckSliderMovement(-1); - m_bShowMouse = true; + if (goBack) { + if (m_NoEmptyBinding) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_BACK, 0); + SwitchToNewScreen(-2); + if (hasNativeList(m_nCurrScreen)) { + m_nTotalListRow = 0; + } + } else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); + m_ShowEmptyBindingError = true; + } } - if (increase) - changeValueBy++; - else if (decrease) - changeValueBy--; - - if (changeValueBy != 0) { + if (changeAmount != 0) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { -#ifdef FIX_BUGS +#ifdef GAMEPAD_MENU case MENUACTION_CTRLCONFIG: - CPad::GetPad(0)->Mode += changeValueBy; + CPad::GetPad(0)->Mode += changeAmount; if (CPad::GetPad(0)->Mode > 3) CPad::GetPad(0)->Mode = 0; else if (CPad::GetPad(0)->Mode < 0) CPad::GetPad(0)->Mode = 3; SaveSettings(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); break; #endif case MENUACTION_RADIO: - m_PrefsRadioStation += changeValueBy; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = USERTRACK; - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; - } else { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = CHATTERBOX; - if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = HEAD_RADIO; - } - SaveSettings(); - DMAudio.SetRadioInCar(m_PrefsRadioStation); - DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, TRUE); - OutputDebugString("FRONTEND RADIO STATION CHANGED"); + ChangeRadioStation(changeAmount); + break; + case MENUACTION_RADARMODE: + m_PrefsRadarMode += changeAmount; + if (m_PrefsRadarMode < 0) + m_PrefsRadarMode = 2; + if (m_PrefsRadarMode > 2) + m_PrefsRadarMode = 0; break; #ifdef ASPECT_RATIO_SCALE case MENUACTION_WIDESCREEN: - if (changeValueBy > 0) { + if (changeAmount > 0) { m_PrefsUseWideScreen++; - if (m_PrefsUseWideScreen > AR_MAX-1) + if (m_PrefsUseWideScreen > AR_MAX - 1) m_PrefsUseWideScreen = 0; } else { m_PrefsUseWideScreen--; if (m_PrefsUseWideScreen < 0) - m_PrefsUseWideScreen = AR_MAX-1; + m_PrefsUseWideScreen = AR_MAX - 1; } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; #endif case MENUACTION_SCREENRES: if (m_bGameNotLoaded) { RwChar** videoMods = _psGetVideoModeList(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - if (changeValueBy > 0) { + if (changeAmount > 0) { do { ++m_nDisplayVideoMode; @@ -5409,25 +5081,49 @@ CMenuManager::ProcessButtonPresses(void) } break; case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex != -1) { - m_nPrefsAudio3DProviderIndex += changeValueBy; - m_nPrefsAudio3DProviderIndex = Clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_nPrefsAudio3DProviderIndex += changeAmount; + + bool checkIfForbidden = true; + while (checkIfForbidden) { + checkIfForbidden = false; + + if (m_nPrefsAudio3DProviderIndex < -1) + m_nPrefsAudio3DProviderIndex = DMAudio.GetNum3DProvidersAvailable() - 1; + else if (m_nPrefsAudio3DProviderIndex > DMAudio.GetNum3DProvidersAvailable() - 1) + m_nPrefsAudio3DProviderIndex = -1; + + // what a retarded move... + if (m_nPrefsAudio3DProviderIndex != -1) { + char* provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex); + strupr(provider); + if (!strcmp(provider, "MILES FAST 2D POSITIONAL AUDIO")) { + m_nPrefsAudio3DProviderIndex += changeAmount; + checkIfForbidden = true; + + } else if (!strcmp(provider, "AUREAL A3D 2.0 (TM)")) { + m_nPrefsAudio3DProviderIndex += changeAmount; + checkIfForbidden = true; + + } else if (!strcmp(provider, "AUREAL A3D INTERACTIVE (TM)")) { + m_nPrefsAudio3DProviderIndex += changeAmount; + checkIfForbidden = true; + } + } + } } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); break; case MENUACTION_SPEAKERCONF: - if (m_nPrefsAudio3DProviderIndex != -1) { - m_PrefsSpeakers -= changeValueBy; + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + m_PrefsSpeakers -= changeAmount; m_PrefsSpeakers = Clamp(m_PrefsSpeakers, 0, 2); DMAudio.SetSpeakerConfig(m_PrefsSpeakers); SaveSettings(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } break; case MENUACTION_CTRLMETHOD: m_ControlMethod = !m_ControlMethod; CCamera::m_bUseMouse3rdPerson = !m_ControlMethod; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; #ifdef CUSTOM_FRONTEND_OPTIONS @@ -5438,7 +5134,7 @@ CMenuManager::ProcessButtonPresses(void) if (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded) break; - if (changeValueBy > 0) { + if (changeAmount > 0) { option.m_CFOSelect->displayedValue++; if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts) option.m_CFOSelect->displayedValue = 0; @@ -5460,21 +5156,19 @@ CMenuManager::ProcessButtonPresses(void) option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue); } } else if (option.m_Action == MENUACTION_CFO_DYNAMIC && option.m_CFODynamic->buttonPressFunc) { - option.m_CFODynamic->buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); + option.m_CFODynamic->buttonPressFunc(changeAmount > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - break; #endif } + CheckSliderMovement(changeAmount); ProcessOnOffMenuOptions(); if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { - if (changeValueBy < 1) { + if (changeAmount < 1) { m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; } else { m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); } } } @@ -5483,106 +5177,81 @@ void CMenuManager::ProcessOnOffMenuOptions() { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { +#ifdef GAMEPAD_MENU case MENUACTION_CTRLVIBRATION: m_PrefsUseVibration = !m_PrefsUseVibration; - if (m_PrefsUseVibration) { CPad::GetPad(0)->StartShake(350, 150); TimeToStopPadShaking = CTimer::GetTimeInMillisecondsPauseMode() + 500; } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); -#ifdef FIX_BUGS SaveSettings(); -#endif // !FIX_BUGS break; -#ifndef FIX_BUGS - case MENUACTION_CTRLCONFIG: - CPad::GetPad(0)->Mode++; - if (CPad::GetPad(0)->Mode > 3) - CPad::GetPad(0)->Mode = 0; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); +#endif + case MENUACTION_INVERTPADY: + CPad::bInvertLook4Pad = !CPad::bInvertLook4Pad; + SaveSettings(); // FIX: Why don't SaveSettings? Because of it's an hidden option? :( break; -#endif // !FIX_BUGS case MENUACTION_CTRLDISPLAY: m_DisplayControllerOnFoot = !m_DisplayControllerOnFoot; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); break; case MENUACTION_FRAMESYNC: m_PrefsVsyncDisp = !m_PrefsVsyncDisp; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SaveSettings(); + SaveSettings(); // FIX: Again... This makes me very unhappy break; case MENUACTION_FRAMELIMIT: m_PrefsFrameLimiter = !m_PrefsFrameLimiter; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; case MENUACTION_TRAILS: CMBlur::BlurOn = !CMBlur::BlurOn; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); - if (CMBlur::BlurOn) - CMBlur::MotionBlurOpen(Scene.camera); - else - CMBlur::MotionBlurClose(); break; case MENUACTION_SUBTITLES: m_PrefsShowSubtitles = !m_PrefsShowSubtitles; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; #ifndef ASPECT_RATIO_SCALE case MENUACTION_WIDESCREEN: m_PrefsUseWideScreen = !m_PrefsUseWideScreen; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; #endif + case MENUACTION_LEGENDS: + m_PrefsShowLegends = !m_PrefsShowLegends; + break; + case MENUACTION_HUD: + m_PrefsShowHud = !m_PrefsShowHud; + SaveSettings(); + break; +#ifdef LEGACY_MENU_OPTIONS case MENUACTION_SETDBGFLAG: CTheScripts::InvertDebugFlag(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); break; case MENUACTION_SWITCHBIGWHITEDEBUGLIGHT: gbBigWhiteDebugLightSwitchedOn = !gbBigWhiteDebugLightSwitchedOn; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - break; - case MENUACTION_PEDROADGROUPS: - gbShowPedRoadGroups = !gbShowPedRoadGroups; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - break; - case MENUACTION_CARROADGROUPS: - gbShowCarRoadGroups = !gbShowCarRoadGroups; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); break; case MENUACTION_COLLISIONPOLYS: gbShowCollisionPolys = !gbShowCollisionPolys; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - break; - case MENUACTION_MP_PLAYERCOLOR: - PickNewPlayerColour(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SaveSettings(); break; +#endif case MENUACTION_SHOWHEADBOB: TheCamera.m_bHeadBob = !TheCamera.m_bHeadBob; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; case MENUACTION_INVVERT: MousePointerStateHelper.bInvertVertically = !MousePointerStateHelper.bInvertVertically; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; case MENUACTION_DYNAMICACOUSTIC: m_PrefsDMA = !m_PrefsDMA; DMAudio.SetDynamicAcousticModelingStatus(m_PrefsDMA); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; case MENUACTION_MOUSESTEER: - CVehicle::m_bDisableMouseSteering = !CVehicle::m_bDisableMouseSteering; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SaveSettings(); + if (m_ControlMethod == CONTROL_STANDARD) { + CVehicle::m_bDisableMouseSteering = !CVehicle::m_bDisableMouseSteering; + SaveSettings(); + } break; } } @@ -5591,7 +5260,6 @@ void CMenuManager::RequestFrontEndShutDown() { m_bShutDownFrontEndRequested = true; - DMAudio.ChangeMusicMode(MUSICMODE_GAME); } void @@ -5608,49 +5276,12 @@ CMenuManager::ResetHelperText() } void -CMenuManager::SaveLoadFileError_SetUpErrorScreen() -{ - switch (PcSaveHelper.nErrorCode) { - case SAVESTATUS_ERR_SAVE_CREATE: - case SAVESTATUS_ERR_SAVE_WRITE: - case SAVESTATUS_ERR_SAVE_CLOSE: - ChangeScreen(MENUPAGE_SAVE_FAILED, 0, true, false); - break; - case SAVESTATUS_ERR_LOAD_OPEN: - case SAVESTATUS_ERR_LOAD_READ: - case SAVESTATUS_ERR_LOAD_CLOSE: - ChangeScreen(MENUPAGE_LOAD_FAILED, 0, true, false); - break; - case SAVESTATUS_ERR_DATA_INVALID: - ChangeScreen(MENUPAGE_LOAD_FAILED_2, 0, true, false); - break; - case SAVESTATUS_DELETEFAILED8: - case SAVESTATUS_DELETEFAILED9: - case SAVESTATUS_DELETEFAILED10: - ChangeScreen(MENUPAGE_DELETE_FAILED, 0, true, false); - break; - default: break; - } -} - -void CMenuManager::SetHelperText(int text) { m_nHelperTextMsgId = text; m_nHelperTextAlpha = 300; } -void -CMenuManager::ShutdownJustMenu() -{ - // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions. -#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE) - glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_DISABLED); -#endif - m_bMenuActive = false; - CTimer::EndUserPause(); -} - float CMenuManager::StretchX(float x) { @@ -5670,128 +5301,416 @@ float CMenuManager::StretchY(float y) return SCREEN_STRETCH_Y(y); } +#ifdef XBOX_MESSAGE_SCREEN +void +CMenuManager::CloseDialog(void) +{ + // We don't have this on PC GXT :shrug: + static wchar* gameSaved = AllocUnicode("Game saved successfully!"); + + if (m_bSaveWasSuccessful && DialogTextCmp("FESZ_WR")) { + m_bSaveWasSuccessful = false; // i don't know where XBOX resets that + m_pDialogText = gameSaved; + SetDialogTimer(1000); + ProcessDialogTimer(); + } else { + ToggleDialog(false); + } + +} + +void +CMenuManager::ProcessDialogTimer(void) +{ + if (!m_bDialogOpen || m_nDialogHideTimer == 0) + return; + + // Also XBOX has unified time source for in-game/menu, but we don't have that + if (m_bMenuActive && CTimer::GetTimeInMilliseconds() > m_nDialogHideTimer || !m_bMenuActive && CTimer::GetTimeInMillisecondsPauseMode() > m_nDialogHideTimerPauseMode) { + + // This is originally activePage.funcs->closePage() + CloseDialog(); + } +} + +void +CMenuManager::SetDialogTimer(uint32 timer) +{ + // XBOX iterates some page list(actives?) and then sets timer variable of specified page to specified value. We only have dialog right now. + // Also XBOX has unified time source for in-game/menu, but we don't have that, thus 2 timer variables... + + m_nDialogHideTimer = CTimer::GetTimeInMilliseconds() + timer; + m_nDialogHideTimerPauseMode = CTimer::GetTimeInMillisecondsPauseMode() + timer; +} + +void +CMenuManager::SetDialogText(const char* key) +{ + // There are many things going around here, idk why + m_pDialogText = TheText.Get(key); +} + +bool +CMenuManager::DialogTextCmp(const char* key) +{ + wchar *value = TheText.Get(key); + wchar *i = m_pDialogText; + for (; *i != '\0' && *value != '\0'; i++, value++) { + if (*i != *value) + return false; + } + return *i == '\0' && *value == '\0'; +} + +void +CMenuManager::ToggleDialog(bool toggle) +{ + // This originally calls some mysterious function on enable and close CB on disable, along with decreasing some counter. Which is no use for dialog + + // XBOX doesn't do that + if (toggle) + m_nDialogHideTimer = 0; + + m_bDialogOpen = toggle; +} + +void +DrawDialogBg(float offset, uint8 alpha) +{ + CSprite2d::Draw2DPolygon(SCALE_AND_CENTER_X(84.f + offset), MENU_Y(126.f + offset), + SCALE_AND_CENTER_X(512.f + offset), MENU_Y(109.f + offset), + SCALE_AND_CENTER_X(100.f + offset), MENU_Y(303.f + offset), + SCALE_AND_CENTER_X(474.f + offset), MENU_Y(311.f + offset), CRGBA(107, 193, 236, alpha)); + CSprite2d::Draw2DPolygon(SCALE_AND_CENTER_X(523.f + offset), MENU_Y(108.f + offset), + SCALE_AND_CENTER_X(542.f + offset), MENU_Y(107.f + offset), + SCALE_AND_CENTER_X(485.f + offset), MENU_Y(310.f + offset), + SCALE_AND_CENTER_X(516.f + offset), MENU_Y(311.f + offset), CRGBA(107, 193, 236, alpha)); +} + +void +CMenuManager::DrawOverlays(void) +{ + // This is stripped to show only Dialog box, XBOX does much more in here. + + if (!m_bDialogOpen) + return; + + DefinedState(); + + CSprite2d::DrawRect(CRect(0, SCREEN_HEIGHT, SCREEN_WIDTH, 0), CRGBA(0, 0, 0, 160)); + + // Ofc this is not hardcoded like that on Xbox, it should be a texture + DrawDialogBg(20.f, 160); // shadow + DrawDialogBg(0.f, 255); + + CFont::SetBackgroundOff(); + CFont::SetPropOn(); + CFont::SetJustifyOn(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetCentreSize(SCREEN_SCALE_X(380.0f)); + CFont::SetCentreOn(); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, 255)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + // Both of those are 0.9 on Xbox, which is ofcouse wrong... + CFont::SetScale(SCREEN_SCALE_X(BIGTEXT_X_SCALE), SCREEN_SCALE_Y(BIGTEXT_Y_SCALE)); + + int x = SCREEN_WIDTH / 2.f - SCREEN_SCALE_X(30.0f); + int y = SCREEN_HEIGHT / 2.f - SCREEN_SCALE_Y(30.0f); + int numOfLines = CFont::GetNumberLines(x, y, m_pDialogText); + CFont::PrintString(x, y - SCREEN_SCALE_Y(numOfLines / 2.f), m_pDialogText); + CFont::DrawFonts(); +} +#endif + +void +CMenuManager::ProcessFileActions() +{ + switch (m_nCurrScreen) { + case MENUPAGE_LOADING_IN_PROGRESS: +#ifdef MISSION_REPLAY + if (MissionSkipLevel) { + if (gGameState != GS_PLAYING_GAME) + DoSettingsBeforeStartingAGame(); + RequestFrontEndShutDown(); + break; + } + if (doingMissionRetry) { + RetryMission(2, 0); + m_nCurrSaveSlot = SLOT_COUNT; + doingMissionRetry = false; + } +#endif + if (CheckSlotDataValid(m_nCurrSaveSlot)) { +#ifdef USE_DEBUG_SCRIPT_LOADER + scriptToLoad = 0; +#endif + +#ifdef XBOX_MESSAGE_SCREEN + SetDialogText("FELD_WR"); + ToggleDialog(true); +#else + if (!m_bGameNotLoaded) + MessageScreen("FELD_WR", true); +#endif + DoSettingsBeforeStartingAGame(); + m_bWantToLoad = true; + } else + SwitchToNewScreen(MENUPAGE_NEW_GAME); + + break; + case MENUPAGE_DELETING_IN_PROGRESS: + { + static bool waitedForScreen = false; + + if (waitedForScreen) { + bool SlotPopulated = false; + if (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) { + PcSaveHelper.PopulateSlotInfo(); + SlotPopulated = true; + } + + if (SlotPopulated) { + SwitchToNewScreen(MENUPAGE_DELETE_SUCCESSFUL); + } else { + SwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING); + strncpy(aScreens[m_nCurrScreen].m_ScreenName, "FES_DEL", 8); + strncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, "FES_DEE", 8); + } + waitedForScreen = false; + } else if (m_nMenuFadeAlpha >= 255) + waitedForScreen = true; + + break; + } + case MENUPAGE_SAVING_IN_PROGRESS: + { +#ifdef XBOX_MESSAGE_SCREEN + if (m_bDialogOpen && DialogTextCmp("FESZ_WR")) { + uint32 startTime = CTimer::GetTimeInMillisecondsPauseMode(); + int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); + PcSaveHelper.PopulateSlotInfo(); + + // Original code, but we don't want redundant saving text if it doesn't +#if 0 + CTimer::Update(); // not on Xbox, who updates it? + + // it compensates the lag to show saving text always one second... how cute + int dialogDur = Max(1, startTime - CTimer::GetTimeInMillisecondsPauseMode() + 1000); +#else + int dialogDur = 1; +#endif + + if (SaveSlot) { + // error. PC code + ToggleDialog(false); + SwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING); + strncpy(aScreens[m_nCurrScreen].m_ScreenName, "FET_SG", 8); + strncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, "FES_CMP", 8); + + } else { + m_bSaveWasSuccessful = true; + SetDialogTimer(dialogDur); + ProcessDialogTimer(); + RequestFrontEndShutDown(); + } + + } else { + SetDialogText("FESZ_WR"); + ToggleDialog(true); + } +#else + static bool waitedForScreen = false; + + if (waitedForScreen) { + int8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot); + PcSaveHelper.PopulateSlotInfo(); + if (SaveSlot) { + SwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING); + strncpy(aScreens[m_nCurrScreen].m_ScreenName, "FET_SG", 8); + strncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, "FES_CMP", 8); + } else + SwitchToNewScreen(MENUPAGE_SAVE_SUCCESSFUL); + + waitedForScreen = false; + } else if (m_nMenuFadeAlpha >= 255) + waitedForScreen = true; +#endif + break; + } + } +} + void CMenuManager::SwitchMenuOnAndOff() { - bool menuWasActive = GetIsMenuActive(); + if (!TheCamera.m_WideScreenOn) { - // Reminder: You need REGISTER_START_BUTTON defined to make it work. - if (CPad::GetPad(0)->GetStartJustDown() -#ifdef FIX_BUGS - && !m_bGameNotLoaded + // Reminder: You need REGISTER_START_BUTTON defined to make it work. + if ((CPad::GetPad(0)->GetStartJustDown() || CPad::GetPad(0)->GetEscapeJustDown()) + && (!m_bMenuActive || m_nCurrScreen == MENUPAGE_PAUSE_MENU || m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT || m_nCurrScreen == MENUPAGE_SAVE_CHEAT_WARNING) + || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested +#ifdef REGISTER_START_BUTTON + || CPad::GetPad(0)->GetStartJustDown() && !m_bGameNotLoaded #endif - || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { + ) { - m_bMenuActive = !m_bMenuActive; -#ifdef FIX_BUGS - CPad::StopPadsShaking(); + if (m_nCurrScreen != MENUPAGE_LOADING_IN_PROGRESS +#ifdef XBOX_MESSAGE_SCREEN + && m_nCurrScreen != MENUPAGE_SAVING_IN_PROGRESS #endif + ) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + } - if (m_bShutDownFrontEndRequested) - m_bMenuActive = false; - if (m_bStartUpFrontEndRequested) - m_bMenuActive = true; + if (m_bShutDownFrontEndRequested) + m_bMenuActive = false; + else if (m_bStartUpFrontEndRequested) + m_bMenuActive = true; + else + m_bMenuActive = !m_bMenuActive; - if (m_bMenuActive) { - CTimer::StartUserPause(); - } else { -#ifdef PS2_LIKE_MENU - bottomBarActive = false; + if (m_bMenuActive) { + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } + Initialise(); + LoadAllTextures(); +#ifdef FIX_BUGS + CPad::StopPadsShaking(); #endif + } else { +#ifdef EXTENDED_COLOURFILTER + // we always expect CPostFX to be open + CMBlur::BlurOn = true; +#endif + if (CMBlur::BlurOn) + CMBlur::MotionBlurOpen(Scene.camera); + else + CMBlur::MotionBlurClose(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(true); + } + + m_StatsScrollSpeed = 150.0f; #ifdef FIX_BUGS - ThingsToDoBeforeGoingBack(); + ThingsToDoBeforeLeavingPage(); #endif - ShutdownJustMenu(); - SaveSettings(); + SaveSettings(); #ifdef LOAD_INI_SETTINGS - SaveINIControllerSettings(); + SaveINIControllerSettings(); #endif - m_bStartUpFrontEndRequested = false; - pControlEdit = nil; - m_bShutDownFrontEndRequested = false; - DisplayComboButtonErrMsg = false; + pControlEdit = nil; + pEditString = nil; + DisplayComboButtonErrMsg = false; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + m_bWaitingForNewKeyBind = false; #ifdef REGISTER_START_BUTTON - int16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start, - start3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start; + int16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start, + start3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start; #endif - CPad::GetPad(0)->Clear(false); - CPad::GetPad(1)->Clear(false); + CPad::GetPad(0)->Clear(false); + CPad::GetPad(1)->Clear(false); #ifdef REGISTER_START_BUTTON - CPad::GetPad(0)->PCTempJoyState.Start = start1; - CPad::GetPad(0)->PCTempKeyState.Start = start2; - CPad::GetPad(0)->OldState.Start = start3; - CPad::GetPad(0)->NewState.Start = start4; -#endif - m_nCurrScreen = MENUPAGE_NONE; + CPad::GetPad(0)->PCTempJoyState.Start = start1; + CPad::GetPad(0)->PCTempKeyState.Start = start2; + CPad::GetPad(0)->OldState.Start = start3; + CPad::GetPad(0)->NewState.Start = start4; +#endif + UnloadTextures(); + CTimer::EndUserPause(); + CTimer::Update(); + m_OnlySaveMenu = false; + } } } // Just entered the save/safe zone - if (m_bSaveMenuActive && !m_bQuitGameNoCD) { - m_bSaveMenuActive = false; + if (m_bActivateSaveMenu) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_bActivateSaveMenu = false; m_bMenuActive = true; - CTimer::StartUserPause(); -#ifdef PS2_SAVE_DIALOG - m_nCurrScreen = MENUPAGE_SAVE; - m_bRenderGameInMenu = true; -#else - m_nCurrScreen = MENUPAGE_CHOOSE_SAVE_SLOT; -#endif - PcSaveHelper.PopulateSlotInfo(); - m_nCurrOption = 0; - } -/* // PS2 leftover - if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) - { - DMAudio.StopFrontEndTrack(); - OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); - gMusicPlaying = 0; - } -*/ - if (m_bMenuActive != menuWasActive) { - m_bMenuStateChanged = true; - - // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions. -#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE) - glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, m_bMenuActive && m_nPrefsWindowed ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED); -#endif + m_OnlySaveMenu = true; + + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } + + Initialise(); + LoadAllTextures(); + + if (CPad::bHasPlayerCheated) { + m_nCurrScreen = MENUPAGE_SAVE_CHEAT_WARNING; + m_nCurrOption = 0; + } else { + m_nCurrScreen = MENUPAGE_CHOOSE_SAVE_SLOT; + m_nCurrOption = 8; + } } m_bStartUpFrontEndRequested = false; m_bShutDownFrontEndRequested = false; + +#ifdef GAMEPAD_MENU + // Reset pad shaking. + if (TimeToStopPadShaking && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode()) { + CPad::StopPadsShaking(); + TimeToStopPadShaking = 0; + } +#endif } void CMenuManager::UnloadTextures() { - if (!m_bSpritesLoaded) - return; + if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) + DMAudio.StopFrontEndTrack(); - printf("REMOVE frontend\n"); - for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i) - m_aFrontEndSprites[i].Delete(); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); + if (m_bSpritesLoaded) { + printf("REMOVE frontend\n"); + int frontend = CTxdStore::FindTxdSlot("frontend1"); + for (int i = 0; i < 3; ++i) + m_aFrontEndSprites[i].Delete(); - int frontend = CTxdStore::FindTxdSlot("frontend"); - CTxdStore::RemoveTxd(frontend); + CTxdStore::RemoveTxd(frontend); -#ifdef GAMEPAD_MENU - int frontend_controllerTxdSlot = CTxdStore::FindTxdSlot("frontend_controller"); - if (frontend_controllerTxdSlot != -1) - CTxdStore::RemoveTxd(frontend_controllerTxdSlot); -#endif + if (!m_OnlySaveMenu) { + int frontend2 = CTxdStore::FindTxdSlot("frontend2"); + for (int i = 3; i < NUM_MENU_SPRITES; ++i) + m_aFrontEndSprites[i].Delete(); - printf("REMOVE menu textures\n"); - for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i) - m_aMenuSprites[i].Delete(); -#ifdef MENU_MAP - for (int i = 0; i < ARRAY_SIZE(MapFilenames); ++i) - m_aMapSprites[i].Delete(); + CTxdStore::RemoveTxd(frontend2); + +#ifdef GAMEPAD_MENU + // Unload controller txd + int frontend_controller = CTxdStore::FindTxdSlot("frontend_controller"); + if (frontend_controller != -1) + CTxdStore::RemoveTxd(frontend_controller); #endif - int menu = CTxdStore::FindTxdSlot("menu"); - CTxdStore::RemoveTxd(menu); + } - m_bSpritesLoaded = false; + m_bSpritesLoaded = false; + } + m_OnlySaveMenu = false; + CUserDisplay::PlaceName.ProcessAfterFrontEndShutDown(); } void @@ -5800,13 +5719,6 @@ CMenuManager::WaitForUserCD() CSprite2d *splash; char *splashscreen = nil; -#if (!(defined RANDOMSPLASH) && GTA_VERSION < GTA3_PC_11) - if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - splashscreen = "mainsc2"; - else - splashscreen = "mainsc1"; -#endif - splash = LoadSplash(splashscreen); if (RsGlobal.quit) @@ -5814,7 +5726,7 @@ CMenuManager::WaitForUserCD() HandleExit(); CPad::UpdatePads(); - MessageScreen("NO_PCCD"); + MessageScreen("NO_PCCD", true); if (CPad::GetPad(0)->GetEscapeJustDown()) { m_bQuitGameNoCD = true; @@ -5822,15 +5734,244 @@ CMenuManager::WaitForUserCD() } } +void +CMenuManager::DrawQuitGameScreen(void) +{ + static int32 exitSignalTimer = 0; + +#ifdef FIX_BUGS + int alpha = Clamp(m_nMenuFadeAlpha, 0, 255); +#else + int alpha = m_nMenuFadeAlpha; +#endif + +#ifndef MUCH_SHORTER_OUTRO_SCREEN + static uint32 lastTickIncrease = 0; + if (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - lastTickIncrease > 10) { + exitSignalTimer++; + lastTickIncrease = CTimer::GetTimeInMillisecondsPauseMode(); + } +#else + static uint32 firstTick = CTimer::GetTimeInMillisecondsPauseMode(); + if (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - firstTick > 750) { + exitSignalTimer = 150; + } +#endif + static CSprite2d *splash = nil; + + if (splash == nil) + splash = LoadSplash("OUTRO"); + + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(28.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255 - alpha)); + + // Or we can see menu background from sides +#ifdef ASPECT_RATIO_SCALE + CSprite2d::DrawRect(CRect(0, 0, MENU_X_LEFT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha)); + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(0.f), 0, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha)); +#endif + + splash->Draw(CRect(MENU_X_LEFT_ALIGNED(0.f), 0, MENU_X_RIGHT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(255, 255, 255, alpha)); + if (alpha == 255 && exitSignalTimer == 150) + RsEventHandler(rsQUITAPP, nil); + + m_bShowMouse = false; + m_AllowNavigation = false; +} + +void +CMenuManager::PrintMap(void) +{ + m_bMenuMapActive = true; + CRadar::InitFrontEndMap(); + + // Because m_fMapSize is half of the map length(hence * 2), and map consists of 3x3 tiles(hence / 3). + float halfTile = m_fMapSize * 2.f / 3.f / 2.f; + + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - m_fMapSize, + m_fMapCenterX - halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - m_fMapSize, + m_fMapCenterX + halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { + m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - m_fMapSize, + m_fMapCenterX + m_fMapSize, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - halfTile, + m_fMapCenterX - halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - halfTile, + m_fMapCenterX + halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - halfTile, + m_fMapCenterX + m_fMapSize, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY + halfTile, + m_fMapCenterX - halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY + halfTile, + m_fMapCenterX + halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + } + + if (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) { + m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY + halfTile, + m_fMapCenterX + m_fMapSize, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255))); + } + + CRadar::DrawBlips(); + if (m_PrefsShowLegends) { + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(40.0f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(84.0f)); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetCentreOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(SCREEN_SCALE_X(0.65f), SCREEN_SCALE_Y(0.95f)); + + int secondColumnStart = (CRadar::MapLegendCounter - 1) / 2; + int boxBottom = MENU_Y(100.0f); + + // + 3, because we want 19*3 px padding + for (int i = 0; i < secondColumnStart + 3; i++) { + boxBottom += MENU_Y(19.f); + } + + CSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(95.0f), MENU_Y(100.0f), MENU_X_LEFT_ALIGNED(555.f), boxBottom), + CRGBA(0, 0, 0, FadeIn(190))); + + CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(102.0f), TheText.Get("FE_MLG")); + CFont::SetRightJustifyOff(); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + if (m_PrefsLanguage == LANGUAGE_AMERICAN) + CFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.55f)); + else + CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.55f)); + + CFont::SetColor(CRGBA(225, 225, 225, FadeIn(255))); + CFont::SetDropShadowPosition(0); + + int y = MENU_Y(127.0f); + int x = MENU_X_LEFT_ALIGNED(160.0f); + + for (int16 i = 0; i < CRadar::MapLegendCounter; i++) { + CRadar::DrawLegend(x, y, CRadar::MapLegendList[i]); + + if (i == secondColumnStart) { + x = MENU_X_LEFT_ALIGNED(350.0f); + y = MENU_Y(127.0f); + } else { + y += MENU_Y(19.0f); + } + } + } + +#ifdef MAP_ENHANCEMENTS + if (m_nMenuFadeAlpha != 255 && !m_bShowMouse) { + mapCrosshair.x = SCREEN_WIDTH / 2; + mapCrosshair.y = SCREEN_HEIGHT / 2; + } else if (m_bShowMouse) { + mapCrosshair.x = m_nMousePosX; + mapCrosshair.y = m_nMousePosY; + } + + CSprite2d::DrawRect(CRect(mapCrosshair.x - MENU_X(1.0f), 0.0f, + mapCrosshair.x + MENU_X(1.0f), SCREEN_HEIGHT), + CRGBA(0, 0, 0, 150)); + CSprite2d::DrawRect(CRect(0.0f, mapCrosshair.y + MENU_X(1.0f), + SCREEN_WIDTH, mapCrosshair.y - MENU_X(1.0f)), + CRGBA(0, 0, 0, 150)); + +#endif + m_bMenuMapActive = false; + + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN)); + DisplayHelperText("FEH_MPH"); +} + +void +CMenuManager::ChangeRadioStation(int8 increaseBy) +{ + if (m_ScrollRadioBy != 0) + return; + + m_PrefsRadioStation += increaseBy; + m_ScrollRadioBy = increaseBy; + if (m_ScrollRadioBy == 1) { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + m_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X); + } else { + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0); + m_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - (2 * MENURADIO_ICON_SIZE)); + } + + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < WILDSTYLE) + m_PrefsRadioStation = USERTRACK; + if (m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = WILDSTYLE; + } else { + if (m_PrefsRadioStation < WILDSTYLE) + m_PrefsRadioStation = WAVE; + if (m_PrefsRadioStation > WAVE) + m_PrefsRadioStation = WILDSTYLE; + } + DMAudio.StopFrontEndTrack(); + DMAudio.PlayFrontEndSound(SOUND_RADIO_CHANGE, 0); +} + +#if 0 +uint8 CMenuManager::GetNumberOfMenuOptions() +{ + uint8 Rows = -1; + for (int i = 0; i < NUM_MENUROWS; i++) { + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_NOTHING) + break; + + ++Rows; + } + return Rows; +} +#endif + #ifdef GAMEPAD_MENU +const char* controllerTypesPaths[] = { + "MODELS/FRONTEND_DS2.TXD", + "MODELS/FRONTEND_DS3.TXD", + "MODELS/FRONTEND_DS4.TXD", + "MODELS/FRONTEND_X360.TXD", + "MODELS/FRONTEND_XONE.TXD", +}; + void CMenuManager::PrintController(void) { + // Don't print anything if controller texture is missing + if (!m_aFrontEndSprites[MENUSPRITE_CONTROLLER].m_pTexture) return; + const float scale = 0.9f; const float CONTROLLER_SIZE_X = 235.2f; const float CONTROLLER_SIZE_Y = 175.2f; const float CONTROLLER_POS_X = (DEFAULT_SCREEN_WIDTH - CONTROLLER_SIZE_X) / 2.0f; - const float CONTROLLER_POS_Y = 160.0f; + const float CONTROLLER_POS_Y = 220.0f; float centerX = CONTROLLER_POS_X + CONTROLLER_SIZE_X / 2; float centerY = CONTROLLER_POS_Y + CONTROLLER_SIZE_Y / 2; @@ -5838,46 +5979,46 @@ CMenuManager::PrintController(void) #define X(f) ((f)*scale + centerX) #define Y(f) ((f)*scale + centerY) - m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X((CONTROLLER_SIZE_X + 4.8f) * scale), MENU_Y((CONTROLLER_SIZE_Y + 4.8f) * scale), CRGBA(0, 0, 0, 255)); - m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); if (m_DisplayControllerOnFoot) { - if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400) - m_aFrontEndSprites[FE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255)); + if ((int)CTimer::GetTimeInMillisecondsPauseMode() & 0x400) + m_aFrontEndSprites[MENUSPRITE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); else - m_aFrontEndSprites[FE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255)); - } else { - if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400) - m_aFrontEndSprites[FE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); + } + else { + if ((int)CTimer::GetTimeInMillisecondsPauseMode() & 0x400) + m_aFrontEndSprites[MENUSPRITE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); else - m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255))); } - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * scale), MENU_Y(SMALLESTTEXT_Y_SCALE * scale)); // X + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.9f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.9f)); // X - // CFont::SetColor(CRGBA(128, 128, 128, FadeIn(255))); CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetDropShadowPosition(1); - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); + CFont::SetDropShadowPosition(0); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::SetWrapx(SCREEN_WIDTH); - float TEXT_L2_X = 50.0f + CONTROLLER_POS_X - centerX, TEXT_L2_Y = -14.0f + CONTROLLER_POS_Y - centerY; - float TEXT_L1_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_L1_Y = 25.0f + CONTROLLER_POS_Y - centerY, TEXT_L1_Y_VEH = 3.0f + TEXT_L1_Y; - float TEXT_DPAD_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_DPAD_Y = 65.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L2_X = 85.0f + CONTROLLER_POS_X - centerX, TEXT_L2_Y = -14.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L1_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_L1_Y = 27.0f + CONTROLLER_POS_Y - centerY, TEXT_L1_Y_VEH = 3.0f + TEXT_L1_Y; + float TEXT_DPAD_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_DPAD_Y = 67.0f + CONTROLLER_POS_Y - centerY; float TEXT_LSTICK_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_LSTICK_Y = 97.0f + CONTROLLER_POS_Y - centerY; - float TEXT_SELECT_X = 103.0f + CONTROLLER_POS_X - centerX, TEXT_SELECT_Y = 141.0f + CONTROLLER_POS_Y - centerY; + float TEXT_SELECT_X = 170.0f + CONTROLLER_POS_X - centerX, TEXT_SELECT_Y = 141.0f + CONTROLLER_POS_Y - centerY; float TEXT_START_X = 130.0f + CONTROLLER_POS_X - centerX, TEXT_START_Y = 128.0f + CONTROLLER_POS_Y - centerY; - float TEXT_R2_X = 184.0F + CONTROLLER_POS_X - centerX, TEXT_R2_Y = -14.0f + CONTROLLER_POS_Y - centerY; - float TEXT_R1_X = 238.0f + CONTROLLER_POS_X - centerX, TEXT_R1_Y = 25.0f + CONTROLLER_POS_Y - centerY; - - float TEXT_SQUARE_X = 144.0f + CONTROLLER_POS_X - centerX, TEXT_SQUARE_Y = 18.0f + CONTROLLER_POS_Y - centerY; - float TEXT_TRIANGLE_X = 238.0f + CONTROLLER_POS_X - centerX, TEXT_TRIANGLE_Y = 52.0f + CONTROLLER_POS_Y - centerY; - float TEXT_CIRCLE_X = 238.0f + CONTROLLER_POS_X - centerX, TEXT_CIRCLE_Y = 65.0f + CONTROLLER_POS_Y - centerY; - float TEXT_CROSS_X = 238.0f + CONTROLLER_POS_X - centerX, TEXT_CROSS_Y = 78.0f + CONTROLLER_POS_Y - centerY; - float TEXT_RSTICK_X = 238.0f + CONTROLLER_POS_X - centerX, TEXT_RSTICK_Y = 94.0f + CONTROLLER_POS_Y - centerY; - float TEXT_R3_X = 238.0f + CONTROLLER_POS_X - centerX, TEXT_R3_Y = 109.0f + CONTROLLER_POS_Y - centerY; - float TEXT_L3_X = 84.0f + CONTROLLER_POS_X - centerX, TEXT_L3_Y = 162.0f + CONTROLLER_POS_Y - centerY; - float TEXT_L2R2_X = 74.0f + CONTROLLER_POS_X - centerX, TEXT_L2R2_Y = -6.0f + CONTROLLER_POS_Y - centerY; + float TEXT_R2_X = 164.0f + CONTROLLER_POS_X - centerX, TEXT_R2_Y = -14.0f + CONTROLLER_POS_Y - centerY; + float TEXT_R1_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_R1_Y = 27.0f + CONTROLLER_POS_Y - centerY; + + float TEXT_SQUARE_X = 147.0f + CONTROLLER_POS_X - centerX, TEXT_SQUARE_Y = 30.0f + CONTROLLER_POS_Y - centerY; + float TEXT_TRIANGLE_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_TRIANGLE_Y = 55.0f + CONTROLLER_POS_Y - centerY; + float TEXT_CIRCLE_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_CIRCLE_Y = 67.0f + CONTROLLER_POS_Y - centerY; + float TEXT_CROSS_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_CROSS_Y = 80.0f + CONTROLLER_POS_Y - centerY; + float TEXT_RSTICK_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_RSTICK_Y = 97.0f + CONTROLLER_POS_Y - centerY; + float TEXT_R3_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_R3_Y = 110.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L3_X = 94.0f + CONTROLLER_POS_X - centerX, TEXT_L3_Y = 162.0f + CONTROLLER_POS_Y - centerY; + float TEXT_L2R2_X = 120.0f + CONTROLLER_POS_X - centerX, TEXT_L2R2_Y = -4.0f + CONTROLLER_POS_Y - centerY; switch (m_PrefsControllerType) { @@ -5890,7 +6031,7 @@ CMenuManager::PrintController(void) TEXT_CROSS_Y -= 1.0f; TEXT_RSTICK_Y -= 4.0f; TEXT_R3_Y -= 4.0f; - TEXT_DPAD_Y -= 1.0f; + TEXT_DPAD_Y -= 2.0f; TEXT_LSTICK_Y -= 6.0f; TEXT_L3_X -= 2.0f; break; @@ -5906,7 +6047,7 @@ CMenuManager::PrintController(void) TEXT_RSTICK_Y += 1.0f; TEXT_R3_Y += 1.0f; TEXT_DPAD_Y += 29.0f; - TEXT_LSTICK_Y -= 22.0f; + TEXT_LSTICK_Y -= 20.0f; TEXT_L3_X -= 36.0f; TEXT_L2R2_Y += 5.0f; TEXT_SELECT_X += 4.0f; @@ -5923,7 +6064,7 @@ CMenuManager::PrintController(void) TEXT_RSTICK_Y += 4.0f; TEXT_R3_Y += 4.0f; TEXT_DPAD_Y += 30.0f; - TEXT_LSTICK_Y -= 21.0f; + TEXT_LSTICK_Y -= 19.0f; TEXT_L3_X -= 36.0f; TEXT_L2R2_Y += 5.0f; TEXT_SELECT_X += 3.0f; @@ -5932,854 +6073,632 @@ CMenuManager::PrintController(void) if (m_DisplayControllerOnFoot) { switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + case 0: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); + break; + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + case 1: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + default: + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X - 50)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_NA")); break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_TAR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_ATT")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + } + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); break; default: - return; - } - } else { - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2R2_X)), MENU_Y(Y(TEXT_L2R2_Y)), TheText.Get("FEC_LB")); - switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + case 2: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_RS3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HOR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + default: + CFont::SetRightJustifyWrap(0); break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_CAW")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_BRA")); + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; break; default: - return; + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ATT")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + case 3: + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_L2_X -= 45.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85)); + break; + default: + CFont::SetRightJustifyWrap(0); + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL")); + CFont::SetRightJustifyWrap(0); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_TAR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_CR3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + case LANGUAGE_SPANISH: + TEXT_R2_X += 30.0f; + CFont::SetJustifyOff(); + CFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR")); + CFont::SetJustifyOn(); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_ATT")); + CFont::SetRightJustifyOn(); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_LOF")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3")); + break; + default: + return; } } - - CFont::SetDropShadowPosition(0); // X - -#undef X -#undef Y -} -#else -void -CMenuManager::PrintController(void) -{ - // FIX: Originally this function doesn't have StretchX/Y, everything had constant pixel size (due to screen was abandoned early?) - // Also texts and their alignment were very bad, so I tried to make them readable (commented out the original code, and marked the ones I added with X) - - m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(240.0f), MENU_Y(180.0f), CRGBA(0, 0, 0, 255)); - m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - if (m_DisplayControllerOnFoot) { - if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400) - m_aFrontEndSprites[FE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - else - m_aFrontEndSprites[FE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - } else { - if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400) - m_aFrontEndSprites[FE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - else - m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); - } - - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // X - - // CFont::SetScale(0.4f, 0.4f); - CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); // X - - // CFont::SetColor(CRGBA(128, 128, 128, FadeIn(255))); - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // X - CFont::SetDropShadowPosition(1); // X - CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255))); // X - - if (m_DisplayControllerOnFoot) { + else { + CFont::SetCentreOn(); + switch (m_PrefsLanguage) + { + case LANGUAGE_ITALIAN: + if (m_PrefsControllerType != CONTROLLER_XBOX360) + break; + case LANGUAGE_FRENCH: + case LANGUAGE_GERMAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + break; + default: + break; + } + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(0.0f)), MENU_Y(Y(TEXT_L2R2_Y)), TheText.Get("FEC_LB")); + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.9f), MENU_Y(SMALLESTTEXT_Y_SCALE* scale * 0.9f)); switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + case 0: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SELECT_X -= 5.0f; break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_ENV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_MOV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_CWL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_MOV")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_CWR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_TAR")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_JUM")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_LOF")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_RUN")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_ATT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_FPC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_LB3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_R3")); + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X += 3.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + case LANGUAGE_GERMAN: + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 18.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + } break; default: - return; - } - } else { - switch (CPad::GetPad(0)->Mode) { - case 0: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 5.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_GERMAN: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 10.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE* scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 15.0f; + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100)); + break; + } break; - case 1: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + } + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); + break; + case 1: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HOR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_NA")); + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; break; - case 2: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_VES")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_RS3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_HOR")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_BRA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_ACC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_TUC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_SM3")); + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 12.0f; break; - case 3: - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(146.0f), TheText.Get("FEC_LL")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(185.0f), TheText.Get("FEC_HAB")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(225.0f), TheText.Get("FEC_TUC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(156.0f), MENU_Y(257.0f), TheText.Get("FEC_VES")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(263.0f), MENU_Y(301.0f), TheText.Get("FEC_HO3")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(290.0f), MENU_Y(288.0f), TheText.Get("FEC_CAM")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(344.0f), MENU_Y(146.0f), TheText.Get("FEC_PAU")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(185.0f), TheText.Get("FEC_LB")); - CFont::SetRightJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(304.0f), MENU_Y(178.0f), TheText.Get("FEC_LR")); - CFont::SetJustifyOn(); // X - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(212.0f), TheText.Get("FEC_CAW")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(225.0f), TheText.Get("FEC_SMT")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(238.0f), TheText.Get("FEC_EXV")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(254.0f), TheText.Get("FEC_RSC")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(269.0f), TheText.Get("FEC_NA")); - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(282.0f), TheText.Get("FEC_ACC")); - // FIX: Coordinates of this line is undefined in PC... - CFont::PrintString(MENU_X_LEFT_ALIGNED(398.0f), MENU_Y(304.0f), TheText.Get("FEC_BRA")); + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_RSC")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X += 3.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + case LANGUAGE_GERMAN: + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 18.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + } break; default: - return; + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 5.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_GERMAN: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 10.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 15.0f; + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100)); + break; + } + break; + } + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); + break; + case 2: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_RS3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SELECT_X -= 5.0f; + break; + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HOR")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3")); + CFont::SetRightJustifyOn(); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X += 3.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + case LANGUAGE_GERMAN: + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 18.0f; + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90)); + break; + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + } + break; + default: + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 5.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_GERMAN: + TEXT_SQUARE_X -= 15.0f; + TEXT_SQUARE_Y += 10.0f; + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60)); + break; + case LANGUAGE_SPANISH: + TEXT_SQUARE_X += 15.0f; + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + default: + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100)); + break; + } + break; + } + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA")); + break; + case 3: + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HAB")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_TUC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES")); + CFont::SetRightJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3")); + switch (m_PrefsLanguage) + { + case LANGUAGE_FRENCH: + TEXT_SELECT_X -= 5.0f; + break; + case LANGUAGE_GERMAN: + TEXT_SELECT_X += 20.0f; + break; + case LANGUAGE_SPANISH: + TEXT_SELECT_X += 15.0f; + break; + default: + break; + } + CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_CAW")); + CFont::SetJustifyOn(); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RSC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_NA")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_ACC")); + CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_BRA")); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0); + switch (m_PrefsControllerType) + { + case CONTROLLER_XBOXONE: + case CONTROLLER_XBOX360: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); + break; + default: + switch (m_PrefsLanguage) + { + case LANGUAGE_GERMAN: + TEXT_SQUARE_X += 5.0f; + case LANGUAGE_FRENCH: + case LANGUAGE_ITALIAN: + CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f)); + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); + break; + default: + CFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X + 16.0f)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT")); + break; + } + break; + } + break; + default: + return; } } CFont::SetDropShadowPosition(0); // X + +#undef X +#undef Y } -#endif -#ifdef MENU_MAP - -#define ZOOM(x, y, in) \ - do { \ - if(fMapSize > SCREEN_HEIGHT * 3.0f && in) \ - break; \ - float z2 = in? 1.1f : 1.f/1.1f; \ - fMapCenterX += (x - fMapCenterX) * (1.0f - z2); \ - fMapCenterY += (y - fMapCenterY) * (1.0f - z2); \ - \ - if (fMapSize < SCREEN_HEIGHT / 2 && !in) \ - break; \ - \ - fMapSize *= z2; \ - } while(0) \ void -CMenuManager::PrintMap(void) +CMenuManager::LoadController(int8 type) { - CFont::SetJustifyOn(); - bMenuMapActive = true; - CRadar::InitFrontEndMap(); - - if (m_nMenuFadeAlpha < 255 && fMapCenterX == 0.f && fMapCenterY == 0.f) { - // Just entered. We need to do these transformations in here, because Radar knows whether map is active or not - CVector2D radarSpacePlayer; - CVector2D screenSpacePlayer; - CRadar::TransformRealWorldPointToRadarSpace(radarSpacePlayer, CVector2D(FindPlayerCoors())); - CRadar::TransformRadarPointToScreenSpace(screenSpacePlayer, radarSpacePlayer); - fMapCenterX = (-screenSpacePlayer.x) + SCREEN_WIDTH / 2; - fMapCenterY = (-screenSpacePlayer.y) + SCREEN_HEIGHT / 2; - } - - // Because fMapSize is half of the map length, and map consists of 3x3 tiles. - float halfTile = fMapSize / 3.0f; - - // Darken background a bit - CSprite2d::DrawRect(CRect(0, 0, - SCREEN_WIDTH, SCREEN_HEIGHT), - CRGBA(0, 0, 0, FadeIn(128))); - - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - - if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aMapSprites[MAPTOP1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize, - fMapCenterX - halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aMapSprites[MAPTOP2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize, - fMapCenterX + halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { - m_aMapSprites[MAPTOP3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize, - fMapCenterX + fMapSize, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aMapSprites[MAPMID1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile, - fMapCenterX - halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aMapSprites[MAPMID2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile, - fMapCenterX + halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { - m_aMapSprites[MAPMID3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile, - fMapCenterX + fMapSize, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aMapSprites[MAPBOT1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile, - fMapCenterX - halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aMapSprites[MAPBOT2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile, - fMapCenterX + halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); - } - - if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { - m_aMapSprites[MAPBOT3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile, - fMapCenterX + fMapSize, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); - } - - CRadar::DrawBlips(); - static CVector2D mapCrosshair; - - if (m_nMenuFadeAlpha != 255 && !m_bShowMouse) { - mapCrosshair.x = SCREEN_WIDTH / 2; - mapCrosshair.y = SCREEN_HEIGHT / 2; - } else if (m_bShowMouse) { - mapCrosshair.x = m_nMousePosX; - mapCrosshair.y = m_nMousePosY; - } - - CSprite2d::DrawRect(CRect(mapCrosshair.x - MENU_X(1.0f), 0.0f, - mapCrosshair.x + MENU_X(1.0f), SCREEN_HEIGHT), - CRGBA(0, 0, 0, 150)); - CSprite2d::DrawRect(CRect(0.0f, mapCrosshair.y + MENU_X(1.0f), - SCREEN_WIDTH, mapCrosshair.y - MENU_X(1.0f)), - CRGBA(0, 0, 0, 150)); - - // Adding marker - if (m_nMenuFadeAlpha >= 255) { - if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - if (mapCrosshair.y > fMapCenterY - fMapSize && mapCrosshair.y < fMapCenterY + fMapSize && - mapCrosshair.x > fMapCenterX - fMapSize && mapCrosshair.x < fMapCenterX + fMapSize) { - - float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize; - float x = ((mapCrosshair.x - diffX) / (fMapSize * 2)) * 4000.0f - 2000.0f; - float y = 2000.0f - ((mapCrosshair.y - diffY) / (fMapSize * 2)) * 4000.0f; - CRadar::ToggleTargetMarker(x, y); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - } - } - } - - if (CPad::GetPad(0)->GetLeftMouse()) { - fMapCenterX += m_nMousePosX - m_nMouseOldPosX; - fMapCenterY += m_nMousePosY - m_nMouseOldPosY; - } else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { - fMapCenterX += 15.0f; - } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { - fMapCenterX -= 15.0f; - } else if (CPad::GetPad(0)->GetLeftStickX()) { - fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; - } - - if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetDPadUp()) { - fMapCenterY += 15.0f; - } else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { - fMapCenterY -= 15.0f; - } else if (CPad::GetPad(0)->GetLeftStickY()) { - fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; - } - - if (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { - if (CPad::GetPad(0)->GetMouseWheelDown()) - ZOOM(mapCrosshair.x, mapCrosshair.y, false); - else - ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false); - } else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) { - if (CPad::GetPad(0)->GetMouseWheelUp()) - ZOOM(mapCrosshair.x, mapCrosshair.y, true); - else - ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); + switch (type) + { + case CONTROLLER_DUALSHOCK2: + case CONTROLLER_DUALSHOCK3: + case CONTROLLER_DUALSHOCK4: + CFont::LoadButtons("MODELS/PS3BTNS.TXD"); + break; + default: + CFont::LoadButtons("MODELS/X360BTNS.TXD"); + break; } - - if (fMapCenterX - fMapSize > SCREEN_WIDTH / 2) - fMapCenterX = fMapSize + SCREEN_WIDTH / 2; - - if (fMapCenterX + fMapSize < SCREEN_WIDTH / 2) - fMapCenterX = SCREEN_WIDTH / 2 - fMapSize; - - if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) - fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; - - fMapCenterY = Min(fMapCenterY, fMapSize); // To not show beyond north border - - bMenuMapActive = false; - - CSprite2d::DrawRect(CRect(MENU_X(14.0f), SCREEN_STRETCH_FROM_BOTTOM(95.0f), - SCREEN_STRETCH_FROM_RIGHT(11.0f), SCREEN_STRETCH_FROM_BOTTOM(59.0f)), - CRGBA(235, 170, 50, 255)); - - CFont::SetScale(MENU_X(0.4f), MENU_Y(0.7f)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); - CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); - - float nextX = MENU_X(30.0f), nextY = 95.0f; - wchar *text; -#ifdef MORE_LANGUAGES -#define TEXT_PIECE(key,extraSpace) \ - text = TheText.Get(key);\ - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), text);\ - if (CFont::IsJapanese())\ - nextX += CFont::GetStringWidth_Jap(text) + MENU_X(extraSpace);\ - else\ - nextX += CFont::GetStringWidth(text, true) + MENU_X(extraSpace); -#else -#define TEXT_PIECE(key,extraSpace) \ - text = TheText.Get(key); CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), text); nextX += CFont::GetStringWidth(text, true) + MENU_X(extraSpace); -#endif - - TEXT_PIECE("FEC_MWF", 3.0f); - TEXT_PIECE("FEC_PGU", 1.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - TEXT_PIECE("FEC_ZIN", 20.0f); - TEXT_PIECE("FEC_MWB", 3.0f); - TEXT_PIECE("FEC_PGD", 1.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), TheText.Get("FEC_ZOT")); nextX = MENU_X(30.0f); nextY -= 11.0f; - TEXT_PIECE("FEC_UPA", 2.0f); - TEXT_PIECE("FEC_DWA", 2.0f); - TEXT_PIECE("FEC_LFA", 2.0f); - TEXT_PIECE("FEC_RFA", 2.0f); - TEXT_PIECE("FEC_MSL", 1.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), TheText.Get("FEC_MOV")); nextX = MENU_X(30.0f); nextY -= 11.0f; - TEXT_PIECE("FEC_MSR", 2.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), TheText.Get("FEM_TWP")); -#undef TEXT_PIECE -} - -#undef ZOOM -#endif - -// rowIdx 99999 returns total numbers of rows. otherwise it returns 0. -int -CMenuManager::ConstructStatLine(int rowIdx) -{ -#define int_STAT_IS_FLOAT false -#define float_STAT_IS_FLOAT true -#define STAT_LINE_1(varType, left, right1) \ - do { \ - if(counter == rowIdx){ \ - varType a = right1; \ - BuildStatLine(left, &a, varType##_STAT_IS_FLOAT, nil); \ - return 0; \ - } counter++; \ - } while(0) -#define STAT_LINE_2(varType, left, right1, right2) \ - do { \ - if(counter == rowIdx){ \ - varType a = right1; \ - varType b = right2; \ - BuildStatLine(left, &a, varType##_STAT_IS_FLOAT, &b); \ - return 0; \ - } counter++; \ - } while(0) - -#define TEXT_ON_LEFT_GXT(name) \ - do { \ - if(counter == rowIdx){ \ - BuildStatLine(name, nil, false, nil); \ - return 0; \ - } counter++; \ - } while(0) - -#define TEXT_ON_RIGHT(text) \ - do { \ - if(counter == rowIdx){ \ - gUString[0] = '\0'; \ - UnicodeStrcpy(gUString2, text); \ - return 0; \ - } counter++; \ - } while(0) - - // Like TEXT_ON_LEFT_GXT, but counter wasn't initialized yet I think - if (rowIdx == 0) { - BuildStatLine("PL_STAT", nil, false, nil); - return 0; - } + // Unload current textures + for (int i = MENUSPRITE_CONTROLLER; i <= MENUSPRITE_ARROWS4; i++) + m_aFrontEndSprites[i].Delete(); - int percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : - CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1)); - percentCompleted = Min(percentCompleted, 100); + // Unload txd + int frontend_controller = CTxdStore::FindTxdSlot("frontend_controller"); + if (frontend_controller != -1) + CTxdStore::RemoveTxd(frontend_controller); - switch (rowIdx) { - // 0 is the heading text above - case 1: { - BuildStatLine("PER_COM", &percentCompleted, false, nil); - return 0; - } - case 2: { - BuildStatLine("NMISON", &CStats::MissionsGiven, false, nil); - return 0; - } - case 3: { - BuildStatLine("FEST_MP", &CStats::MissionsPassed, false, &CStats::TotalNumberMissions); - return 0; + // Find the new txd to load + bool bTxdMissing = true; + if (controllerTypesPaths[type]) + if (int file = CFileMgr::OpenFile(controllerTypesPaths[type])) { + CFileMgr::CloseFile(file); + bTxdMissing = false; } - } - int counter = 4; - - if (CGame::nastyGame) - STAT_LINE_2(int, "FEST_RP", CStats::NumberKillFrenziesPassed, CStats::TotalNumberKillFrenzies); - - CPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus]; - - // Hidden packages shouldn't be shown with percent -#ifdef FIX_BUGS - STAT_LINE_2(int, "PERPIC", player.m_nCollectedPackages, player.m_nTotalPackages); -#else - float packagesPercent = 0.0f; - if (player.m_nTotalPackages != 0) - packagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; - - STAT_LINE_2(int, "PERPIC", packagesPercent, 100); -#endif - STAT_LINE_2(int, "NOUNIF", CStats::NumberOfUniqueJumpsFound, CStats::TotalNumberOfUniqueJumps); - STAT_LINE_1(int, "DAYSPS", CStats::DaysPassed); - if (CGame::nastyGame) { - STAT_LINE_1(int, "PE_WAST", CStats::PeopleKilledByPlayer); - STAT_LINE_1(int, "PE_WSOT", CStats::PeopleKilledByOthers); - } - STAT_LINE_1(int, "CAR_EXP", CStats::CarsExploded); - STAT_LINE_1(int, "TM_BUST", CStats::TimesArrested); - STAT_LINE_1(int, "TM_DED", CStats::TimesDied); - STAT_LINE_1(int, "GNG_WST", CStats::PedsKilledOfThisType[PEDTYPE_GANG9] + CStats::PedsKilledOfThisType[PEDTYPE_GANG8] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2] - + CStats::PedsKilledOfThisType[PEDTYPE_GANG1]); - STAT_LINE_1(int, "DED_CRI", CStats::PedsKilledOfThisType[PEDTYPE_CRIMINAL]); - STAT_LINE_1(int, "HEL_DST", CStats::HelisDestroyed); - STAT_LINE_1(int, "KGS_EXP", CStats::KgsOfExplosivesUsed); - STAT_LINE_1(int, "ACCURA", (CStats::InstantHitsFiredByPlayer == 0 ? 0 : - CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer)); - - if (CStats::ElBurroTime > 0) { - STAT_LINE_1(int, "ELBURRO", CStats::ElBurroTime); - } - if (CStats::Record4x4One > 0) { - STAT_LINE_1(int, "FEST_R1", CStats::Record4x4One); - } - if (CStats::Record4x4Two > 0) { - STAT_LINE_1(int, "FEST_R2", CStats::Record4x4Two); - } - if (CStats::Record4x4Three > 0) { - STAT_LINE_1(int, "FEST_R3", CStats::Record4x4Three); - } - if (CStats::Record4x4Mayhem > 0) { - STAT_LINE_1(int, "FEST_RM", CStats::Record4x4Mayhem); - } - if (CStats::LongestFlightInDodo > 0) { - STAT_LINE_1(int, "FEST_LF", CStats::LongestFlightInDodo); - } - if (CStats::TimeTakenDefuseMission > 0) { - STAT_LINE_1(int, "FEST_BD", CStats::TimeTakenDefuseMission); - } - STAT_LINE_1(int, "CAR_CRU", CStats::CarsCrushed); - if (CStats::HighestScores[0] > 0) { - TEXT_ON_LEFT_GXT("FEST_BB"); - STAT_LINE_1(int, "FEST_H0", CStats::HighestScores[0]); - } - if (CStats::HighestScores[4] + CStats::HighestScores[3] + CStats::HighestScores[2] + CStats::HighestScores[1] > 0) { - TEXT_ON_LEFT_GXT("FEST_GC"); - } - if (CStats::HighestScores[1] > 0) { - STAT_LINE_1(int, "FEST_H1", CStats::HighestScores[1]); - } - if (CStats::HighestScores[2] > 0) { - STAT_LINE_1(int, "FEST_H2", CStats::HighestScores[2]); - } - if (CStats::HighestScores[3] > 0) { - STAT_LINE_1(int, "FEST_H3", CStats::HighestScores[3]); - } - if (CStats::HighestScores[4] > 0) { - STAT_LINE_1(int, "FEST_H4", CStats::HighestScores[4]); - } + int txdSlot = -1; - switch (m_PrefsLanguage) { - case LANGUAGE_AMERICAN: -#ifndef USE_MEASUREMENTS_IN_METERS - STAT_LINE_1(float, "FEST_DF", CStats::DistanceTravelledOnFoot * MILES_IN_METER); - STAT_LINE_1(float, "FEST_DC", CStats::DistanceTravelledInVehicle * MILES_IN_METER); - STAT_LINE_1(int, "MMRAIN", CStats::mmRain); - STAT_LINE_1(float, "MXCARD", CStats::MaximumJumpDistance * FEET_IN_METER); - STAT_LINE_1(float, "MXCARJ", CStats::MaximumJumpHeight * FEET_IN_METER); - break; -#endif - case LANGUAGE_FRENCH: - case LANGUAGE_GERMAN: - case LANGUAGE_ITALIAN: - case LANGUAGE_SPANISH: -#ifdef MORE_LANGUAGES - case LANGUAGE_POLISH: - case LANGUAGE_RUSSIAN: - case LANGUAGE_JAPANESE: -#endif - STAT_LINE_1(float, "FESTDFM", CStats::DistanceTravelledOnFoot); - STAT_LINE_1(float, "FESTDCM", CStats::DistanceTravelledInVehicle); - STAT_LINE_1(int, "MMRAIN", CStats::mmRain); - STAT_LINE_1(float, "MXCARDM", CStats::MaximumJumpDistance); - STAT_LINE_1(float, "MXCARJM", CStats::MaximumJumpHeight); - break; - default: - break; + if (bTxdMissing) + // Not found, fall back to original textures + txdSlot = CTxdStore::FindTxdSlot("frontend2"); + else { + // Found, load txd + txdSlot = frontend_controller; + if (txdSlot == -1) + txdSlot = CTxdStore::AddTxdSlot("frontend_controller"); + CTxdStore::LoadTxd(txdSlot, controllerTypesPaths[type]); + CTxdStore::AddRef(txdSlot); } - STAT_LINE_1(int, "MXFLIP", CStats::MaximumJumpFlips); - STAT_LINE_1(int, "MXJUMP", CStats::MaximumJumpSpins); - TEXT_ON_LEFT_GXT("BSTSTU"); - - switch (CStats::BestStuntJump) { - case 1: - TEXT_ON_RIGHT(TheText.Get("INSTUN")); - break; - case 2: - TEXT_ON_RIGHT(TheText.Get("PRINST")); - break; - case 3: - TEXT_ON_RIGHT(TheText.Get("DBINST")); - break; - case 4: - TEXT_ON_RIGHT(TheText.Get("DBPINS")); - break; - case 5: - TEXT_ON_RIGHT(TheText.Get("TRINST")); - break; - case 6: - TEXT_ON_RIGHT(TheText.Get("PRTRST")); - break; - case 7: - TEXT_ON_RIGHT(TheText.Get("QUINST")); - break; - case 8: - TEXT_ON_RIGHT(TheText.Get("PQUINS")); - break; - default: - TEXT_ON_RIGHT(TheText.Get("NOSTUC")); - break; + assert(txdSlot != -1); + // Load new textures + CTxdStore::SetCurrentTxd(txdSlot); + for (int i = MENUSPRITE_CONTROLLER; i <= MENUSPRITE_ARROWS4; i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); } - - STAT_LINE_1(int, "PASDRO", CStats::PassengersDroppedOffWithTaxi); - STAT_LINE_1(int, "MONTAX", CStats::MoneyMadeWithTaxi); - STAT_LINE_1(int, "FEST_LS", CStats::LivesSavedWithAmbulance); - STAT_LINE_1(int, "FEST_HA", CStats::HighestLevelAmbulanceMission); - STAT_LINE_1(int, "FEST_CC", CStats::CriminalsCaught); - STAT_LINE_1(int, "FEST_FE", CStats::FiresExtinguished); - STAT_LINE_1(int, "DAYPLC", CTimer::GetTimeInMilliseconds() + 100); - return counter; - -#undef STAT_LINE_1 -#undef STAT_LINE_2 -#undef TEXT_ON_LEFT_GXT -#undef TEXT_ON_RIGHT -#undef int_STAT_IS_FLOAT -#undef float_STAT_IS_FLOAT } +#endif // GAMEPAD_MENU #undef GetBackJustUp #undef GetBackJustDown -#undef ChangeScreen - -#endif diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 32e5ef9d..858d3fd9 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -4,44 +4,60 @@ #else #include "Sprite2d.h" +#include "Timer.h" -#ifdef PS2_LIKE_MENU -#define MENUHEADER_POS_X 50.0f -#define MENUHEADER_POS_Y 75.0f -#define MENUHEADER_HEIGHT 1.3f -#else -#define MENUHEADER_POS_X 35.0f -#define MENUHEADER_POS_Y 93.0f -#define MENUHEADER_HEIGHT 1.6f -#endif -#define MENUHEADER_WIDTH 0.84f +#define MENUHEADER_POS_X 10.0f +#define MENUHEADER_POS_Y 10.0f +#define MENUHEADER_HEIGHT 2.0f +#define MENUHEADER_WIDTH 1.0f -#define MENU_X_MARGIN 40.0f -#define MENUACTION_POS_Y 60.0f -#define MENUACTION_SCALE_MULT 0.9f +#define MENU_X_MARGIN 10.0f -#define MENURADIO_ICON_SCALE 60.0f - -#define MENUSLIDER_X 256.0f -#define MENUSLIDER_UNK 256.0f +#define MENUACTION_SCALE_MULT 0.9f #define MENUSLIDER_BARS 16 #define MENUSLIDER_LOGICAL_BARS MENUSLIDER_BARS -#define BIGTEXT_X_SCALE 0.75f // For FONT_HEADING -#define BIGTEXT_Y_SCALE 0.9f -#define MEDIUMTEXT_X_SCALE 0.55f // For FONT_HEADING -#define MEDIUMTEXT_Y_SCALE 0.8f -#define SMALLTEXT_X_SCALE 0.45f // used for FONT_HEADING and FONT_BANK, but looks off for HEADING -#define SMALLTEXT_Y_SCALE 0.7f -#define SMALLESTTEXT_X_SCALE 0.4f // used for both FONT_HEADING and FONT_BANK -#define SMALLESTTEXT_Y_SCALE 0.6f - -#define HELPER_TEXT_LEFT_MARGIN 320.0f -#define HELPER_TEXT_BOTTOM_MARGIN 120.0f - -#define PLAYERSETUP_LIST_TOP 28.0f -#define PLAYERSETUP_LIST_BOTTOM 125.0f +#define MENULABEL_X_MARGIN 80.0f +#define MENULABEL_POS_X 100.0f +#define MENULABEL_POS_Y 97.0f + +#define MENU_DEFAULT_CONTENT_X 320 +#define MENU_DEFAULT_CONTENT_Y 100 +#define MENU_DEFAULT_LINE_HEIGHT 29 + +#define RIGHT_ALIGNED_TEXT_RIGHT_MARGIN(xMargin) (xMargin + 30.0f) + +#define MENURADIO_ICON_FIRST_X 238.f +#define MENURADIO_ICON_Y 288.0f +#define MENURADIO_ICON_SIZE 60.0f +#define MENURADIO_SELECTOR_START_Y 285.f // other options should leave room on the screen +#define MENURADIO_SELECTOR_HEIGHT 65.f + +#define MENUSLIDER_X 500.0f +#define MENUSLIDER_UNK 100.0f +#define MENUSLIDER_SMALLEST_BAR 8.0f +#define MENUSLIDER_BIGGEST_BAR 25.0f + +#define BIGTEXT2_X_SCALE 0.6f // For FONT_STANDARD +#define BIGTEXT2_Y_SCALE 1.2f +#define BIGTEXT_X_SCALE 0.6f // For FONT_HEADING +#define BIGTEXT_Y_SCALE 1.0f +#define MEDIUMTEXT_X_SCALE 0.48f // For FONT_STANDARD +#define MEDIUMTEXT_Y_SCALE 1.0f +#define SMALLTEXT_X_SCALE 0.42f // For FONT_STANDARD +#define SMALLTEXT_Y_SCALE 0.9f +#define SMALLESTTEXT_X_SCALE 0.3f // For FONT_STANDARD +#define SMALLESTTEXT_Y_SCALE 0.7f + +#define LISTITEM_X_SCALE 0.4f // Only unproportional and commonly used scale for FONT_STANDARD +#define LISTITEM_Y_SCALE 0.6f + +#define HELPER_TEXT_RIGHT_MARGIN MENU_X_MARGIN +#define HELPER_TEXT_BOTTOM_MARGIN 18.f + +#define PLAYERSETUP_LIST_TOP 58.0f +#define PLAYERSETUP_LIST_BOTTOM 95.0f #define PLAYERSETUP_LIST_LEFT 200.0f #define PLAYERSETUP_LIST_RIGHT 36.0f #ifdef FIX_BUGS // See the scrollbar button drawing code @@ -53,96 +69,84 @@ #define PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION 64 #define PLAYERSETUP_SKIN_COLUMN_LEFT 220.0f #define PLAYERSETUP_DATE_COLUMN_RIGHT 56.0f -#define PLAYERSETUP_LIST_BODY_TOP 47 +#define PLAYERSETUP_LIST_BODY_TOP 77 #define PLAYERSETUP_ROW_HEIGHT 9 -#define STATS_SLIDE_Y_PER_SECOND 30.0f -#define STATS_ROW_HEIGHT 20.0f -#define STATS_ROW_X_MARGIN 50.0f -#define STATS_BOTTOM_MARGIN 135.0f -#define STATS_TOP_MARGIN 40.0f -#define STATS_TOP_DIMMING_AREA_LENGTH (93.0f - STATS_TOP_MARGIN) -#define STATS_BOTTOM_DIMMING_AREA_LENGTH 55.0f -#define STATS_PUT_BACK_TO_BOTTOM_Y 50.0f -#define STATS_RATING_X 24.0f -#define STATS_RATING_Y 20.0f - -#define BRIEFS_TOP_MARGIN 40.0f -#define BRIEFS_LINE_X 50.0f -#define BRIEFS_LINE_HEIGHT 60.0f +#define STATS_ROW_HEIGHT 17.0f +#define STATS_ROW_LEFT_MARGIN 110.0f +#define STATS_ROW_RIGHT_MARGIN 113.0f +#define STATS_TOP_Y 135.0f // Just faded in +#define STATS_BOTTOM_Y 300.0f // Starts to fade out after that +#define STATS_FADING_AREA_LENGTH 50.0f +#define STATS_VISIBLE_START_Y (STATS_TOP_Y - 10.f) +#define STATS_VISIBLE_END_Y (STATS_BOTTOM_Y + 21.f) +#define STATS_RATING_X 320.0f +#define STATS_RATING_Y_1 85.0f +#define STATS_RATING_Y_2 110.0f + +#define BRIEFS_TOP_MARGIN 140.0f +#define BRIEFS_BOTTOM_MARGIN 280.0f +#define BRIEFS_LINE_X 100.0f +#define BRIEFS_LINE_HEIGHT 20.0f +#define BRIEFS_LINE_SPACING 10.0f #define CONTSETUP_STANDARD_ROW_HEIGHT 10.7f #define CONTSETUP_CLASSIC_ROW_HEIGHT 9.0f #define CONTSETUP_BOUND_HIGHLIGHT_HEIGHT 10 #define CONTSETUP_BOUND_COLUMN_WIDTH 190.0f -#define CONTSETUP_LIST_HEADER_HEIGHT 20.0f -#define CONTSETUP_LIST_TOP 28.0f +#define CONTSETUP_LIST_TOP 58.0f #define CONTSETUP_LIST_RIGHT 18.0f -#define CONTSETUP_LIST_BOTTOM 120.0f -#define CONTSETUP_LIST_LEFT 18.0f +#define CONTSETUP_LIST_BOTTOM 78.0f +#define CONTSETUP_LIST_LEFT 30.0f #define CONTSETUP_COLUMN_1_X 40.0f #define CONTSETUP_COLUMN_2_X 210.0f #define CONTSETUP_COLUMN_3_X (CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH + 10.0f) #define CONTSETUP_BACK_RIGHT 35.0f -#define CONTSETUP_BACK_BOTTOM 122.0f +#define CONTSETUP_BACK_BOTTOM 82.0f #define CONTSETUP_BACK_HEIGHT 25.0f -enum eFrontendSprites +enum { - FE2_MAINPANEL_UL, - FE2_MAINPANEL_UR, - FE2_MAINPANEL_DL, - FE2_MAINPANEL_DR, - FE2_MAINPANEL_DR2, - FE2_TABACTIVE, - FE_ICONBRIEF, - FE_ICONSTATS, - FE_ICONCONTROLS, - FE_ICONSAVE, - FE_ICONAUDIO, - FE_ICONDISPLAY, - FE_ICONLANGUAGE, - FE_CONTROLLER, - FE_CONTROLLERSH, - FE_ARROWS1, - FE_ARROWS2, - FE_ARROWS3, - FE_ARROWS4, - FE_RADIO1, - FE_RADIO2, - FE_RADIO3, - FE_RADIO4, - FE_RADIO5, - FE_RADIO6, - FE_RADIO7, - FE_RADIO8, - FE_RADIO9, - - NUM_FE_SPRITES + MENUALIGN_LEFT = 1, + MENUALIGN_RIGHT, + MENUALIGN_CENTER, }; enum eMenuSprites { - MENUSPRITE_CONNECTION, - MENUSPRITE_FINDGAME, - MENUSPRITE_HOSTGAME, - MENUSPRITE_MAINMENU, - MENUSPRITE_PLAYERSET, - MENUSPRITE_SINGLEPLAYER, - MENUSPRITE_MULTIPLAYER, - MENUSPRITE_DMALOGO, - MENUSPRITE_GTALOGO, - MENUSPRITE_RSTARLOGO, - MENUSPRITE_GAMESPY, + MENUSPRITE_BACKGROUND, + MENUSPRITE_VCLOGO, MENUSPRITE_MOUSE, - MENUSPRITE_MOUSET, - MENUSPRITE_MP3LOGO, + MENUSPRITE_MAPTOP01, + MENUSPRITE_MAPTOP02, + MENUSPRITE_MAPTOP03, + MENUSPRITE_MAPMID01, + MENUSPRITE_MAPMID02, + MENUSPRITE_MAPMID03, + MENUSPRITE_MAPBOT01, + MENUSPRITE_MAPBOT02, + MENUSPRITE_MAPBOT03, + MENUSPRITE_WILDSTYLE, + MENUSPRITE_FLASH, + MENUSPRITE_KCHAT, + MENUSPRITE_FEVER, + MENUSPRITE_VROCK, + MENUSPRITE_VCPR, + MENUSPRITE_ESPANTOSO, + MENUSPRITE_EMOTION, + MENUSPRITE_WAVE, + MENUSPRITE_MP3, MENUSPRITE_DOWNOFF, MENUSPRITE_DOWNON, MENUSPRITE_UPOFF, MENUSPRITE_UPON, - MENUSPRITE_GTA3LOGO, - MENUSPRITE_UNUSED, +#ifdef GAMEPAD_MENU + MENUSPRITE_CONTROLLER, + MENUSPRITE_ARROWS1, + MENUSPRITE_ARROWS2, + MENUSPRITE_ARROWS3, + MENUSPRITE_ARROWS4, +#endif NUM_MENU_SPRITES }; @@ -158,102 +162,72 @@ enum eSaveSlot SAVESLOT_6, SAVESLOT_7, SAVESLOT_8, - SAVESLOT_LABEL = 36, -}; - -#ifdef MENU_MAP -enum MapSprites -{ - MAPMID1, - MAPMID2, - MAPMID3, - MAPBOT1, - MAPBOT2, - MAPBOT3, - MAPTOP1, - MAPTOP2, - MAPTOP3, - NUM_MAP_SPRITES + SAVESLOT_LABEL = 36 }; -#endif enum eMenuScreen { MENUPAGE_DISABLED = -1, - MENUPAGE_NONE = 0, - MENUPAGE_STATS = 1, - MENUPAGE_NEW_GAME = 2, - MENUPAGE_BRIEFS = 3, - MENUPAGE_CONTROLLER_SETTINGS = 4, - MENUPAGE_SOUND_SETTINGS = 5, - MENUPAGE_DISPLAY_SETTINGS = 6, - MENUPAGE_LANGUAGE_SETTINGS = 7, + MENUPAGE_STATS = 0, + MENUPAGE_NEW_GAME = 1, + MENUPAGE_BRIEFS = 2, + MENUPAGE_SOUND_SETTINGS = 3, + MENUPAGE_DISPLAY_SETTINGS = 4, + MENUPAGE_LANGUAGE_SETTINGS = 5, + MENUPAGE_MAP = 6, + MENUPAGE_NEW_GAME_RELOAD = 7, MENUPAGE_CHOOSE_LOAD_SLOT = 8, MENUPAGE_CHOOSE_DELETE_SLOT = 9, - MENUPAGE_NEW_GAME_RELOAD = 10, - MENUPAGE_LOAD_SLOT_CONFIRM = 11, - MENUPAGE_DELETE_SLOT_CONFIRM = 12, - MENUPAGE_NO_MEMORY_CARD = 13, // hud adjustment page in mobile - MENUPAGE_LOADING_IN_PROGRESS = 14, - MENUPAGE_DELETING_IN_PROGRESS = 15, - MENUPAGE_PS2_LOAD_FAILED = 16, - MENUPAGE_DELETE_FAILED = 17, - MENUPAGE_DEBUG_MENU = 18, - MENUPAGE_MEMORY_CARD_DEBUG = 19, - MENUPAGE_MEMORY_CARD_TEST = 20, - MENUPAGE_MULTIPLAYER_MAIN = 21, - MENUPAGE_PS2_SAVE_FAILED = 22, - MENUPAGE_PS2_SAVE_FAILED_2 = 23, - MENUPAGE_SAVE = 24, - MENUPAGE_NO_MEMORY_CARD_2 = 25, - MENUPAGE_CHOOSE_SAVE_SLOT = 26, - MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27, - MENUPAGE_MULTIPLAYER_MAP = 28, - MENUPAGE_MULTIPLAYER_CONNECTION = 29, - MENUPAGE_MULTIPLAYER_FIND_GAME = 30, - MENUPAGE_MULTIPLAYER_MODE = 31, - MENUPAGE_MULTIPLAYER_CREATE = 32, - MENUPAGE_MULTIPLAYER_START = 33, - MENUPAGE_SKIN_SELECT_OLD = 34, - MENUPAGE_CONTROLLER_PC = 35, - MENUPAGE_CONTROLLER_PC_OLD1 = 36, - MENUPAGE_CONTROLLER_PC_OLD2 = 37, - MENUPAGE_CONTROLLER_PC_OLD3 = 38, - MENUPAGE_CONTROLLER_PC_OLD4 = 39, - MENUPAGE_CONTROLLER_DEBUG = 40, - MENUPAGE_OPTIONS = 41, - MENUPAGE_EXIT = 42, - MENUPAGE_SAVING_IN_PROGRESS = 43, - MENUPAGE_SAVE_SUCCESSFUL = 44, - MENUPAGE_DELETING = 45, - MENUPAGE_DELETE_SUCCESS = 46, - MENUPAGE_SAVE_FAILED = 47, - MENUPAGE_LOAD_FAILED = 48, - MENUPAGE_LOAD_FAILED_2 = 49, - MENUPAGE_FILTER_GAME = 50, - MENUPAGE_START_MENU = 51, - MENUPAGE_PAUSE_MENU = 52, - MENUPAGE_CHOOSE_MODE = 53, - MENUPAGE_SKIN_SELECT = 54, - MENUPAGE_KEYBOARD_CONTROLS = 55, - MENUPAGE_MOUSE_CONTROLS = 56, - MENUPAGE_MISSION_RETRY = 57, + MENUPAGE_LOAD_SLOT_CONFIRM = 10, + MENUPAGE_DELETE_SLOT_CONFIRM = 11, + MENUPAGE_LOADING_IN_PROGRESS = 12, + MENUPAGE_DELETING_IN_PROGRESS = 13, + MENUPAGE_DELETE_SUCCESSFUL = 14, + MENUPAGE_CHOOSE_SAVE_SLOT = 15, + MENUPAGE_SAVE_OVERWRITE_CONFIRM = 16, + MENUPAGE_SAVING_IN_PROGRESS = 17, + MENUPAGE_SAVE_SUCCESSFUL = 18, + MENUPAGE_SAVE_CUSTOM_WARNING = 19, + MENUPAGE_SAVE_CHEAT_WARNING = 20, + MENUPAGE_SKIN_SELECT = 21, + MENUPAGE_SAVE_UNUSED = 22, + MENUPAGE_SAVE_FAILED = 23, + MENUPAGE_SAVE_FAILED_2 = 24, + MENUPAGE_LOAD_FAILED = 25, + MENUPAGE_CONTROLLER_PC = 26, + MENUPAGE_OPTIONS = 27, + MENUPAGE_EXIT = 28, + MENUPAGE_START_MENU = 29, + MENUPAGE_KEYBOARD_CONTROLS = 30, + MENUPAGE_MOUSE_CONTROLS = 31, + MENUPAGE_PAUSE_MENU = 32, + MENUPAGE_NONE = 33, // Then chooses main menu or pause menu +#ifdef GAMEPAD_MENU + MENUPAGE_CONTROLLER_SETTINGS, +#endif +#ifdef LEGACY_MENU_OPTIONS + MENUPAGE_DEBUG_MENU, + MENUPAGE_CONTROLLER_PC_OLD1, + MENUPAGE_CONTROLLER_PC_OLD2, + MENUPAGE_CONTROLLER_PC_OLD3, + MENUPAGE_CONTROLLER_PC_OLD4, + MENUPAGE_CONTROLLER_DEBUG, +#endif #ifdef CUSTOM_FRONTEND_OPTIONS -#ifdef MENU_MAP - MENUPAGE_MAP = 58, -#endif #ifdef GRAPHICS_MENU_OPTIONS MENUPAGE_GRAPHICS_SETTINGS, #endif #ifdef DETECT_JOYSTICK_MENU MENUPAGE_DETECT_JOYSTICK, #endif - #endif - MENUPAGE_UNK, // originally 58. Custom screens are inserted above, because last screen in CMenuScreens should always be empty to make CFO work - MENUPAGES +#ifdef MISSION_REPLAY + MENUPAGE_MISSION_RETRY, +#endif + MENUPAGE_OUTRO, // Originally 34, but CFO needs last screen to be empty to count number of menu pages + MENUPAGES }; enum eMenuAction @@ -265,9 +239,10 @@ enum eMenuAction #endif MENUACTION_NOTHING, MENUACTION_LABEL, + MENUACTION_YES, + MENUACTION_NO, MENUACTION_CHANGEMENU, - MENUACTION_CTRLVIBRATION, - MENUACTION_CTRLCONFIG, + MENUACTION_INVERTPADY, MENUACTION_CTRLDISPLAY, MENUACTION_FRAMESYNC, MENUACTION_FRAMELIMIT, @@ -275,10 +250,8 @@ enum eMenuAction MENUACTION_SUBTITLES, MENUACTION_WIDESCREEN, MENUACTION_BRIGHTNESS, - MENUACTION_DRAWDIST, MENUACTION_MUSICVOLUME, MENUACTION_SFXVOLUME, - MENUACTION_UNK15, MENUACTION_RADIO, MENUACTION_LANG_ENG, MENUACTION_LANG_FRE, @@ -287,74 +260,24 @@ enum eMenuAction MENUACTION_LANG_SPA, MENUACTION_POPULATESLOTS_CHANGEMENU, MENUACTION_CHECKSAVE, - MENUACTION_UNK24, MENUACTION_NEWGAME, + MENUACTION_RESUME_FROM_SAVEZONE, MENUACTION_RELOADIDE, - MENUACTION_RELOADIPL, MENUACTION_SETDBGFLAG, + MENUACTION_LOADRADIO, + MENUACTION_SAVEGAME, MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, - MENUACTION_PEDROADGROUPS, - MENUACTION_CARROADGROUPS, MENUACTION_COLLISIONPOLYS, - MENUACTION_REGMEMCARD1, - MENUACTION_TESTFORMATMEMCARD1, - MENUACTION_TESTUNFORMATMEMCARD1, - MENUACTION_CREATEROOTDIR, - MENUACTION_CREATELOADICONS, - MENUACTION_FILLWITHGUFF, - MENUACTION_SAVEONLYTHEGAME, - MENUACTION_SAVEGAME, - MENUACTION_SAVEGAMEUNDERGTA, - MENUACTION_CREATECOPYPROTECTED, - MENUACTION_TESTSAVE, - MENUACTION_TESTLOAD, - MENUACTION_TESTDELETE, - MENUACTION_PARSEHEAP, - MENUACTION_SHOWCULL, - MENUACTION_MEMCARDSAVECONFIRM, - MENUACTION_RESUME_FROM_SAVEZONE, - MENUACTION_UNK50, - MENUACTION_DEBUGSTREAM, - MENUACTION_MPMAP_LIBERTY, - MENUACTION_MPMAP_REDLIGHT, - MENUACTION_MPMAP_CHINATOWN, - MENUACTION_MPMAP_TOWER, - MENUACTION_MPMAP_SEWER, - MENUACTION_MPMAP_INDUSTPARK, - MENUACTION_MPMAP_DOCKS, - MENUACTION_MPMAP_STAUNTON, - MENUACTION_MPMAP_DEATHMATCH1, - MENUACTION_MPMAP_DEATHMATCH2, - MENUACTION_MPMAP_TEAMDEATH1, - MENUACTION_MPMAP_TEAMDEATH2, - MENUACTION_MPMAP_STASH, - MENUACTION_MPMAP_CAPTURE, - MENUACTION_MPMAP_RATRACE, - MENUACTION_MPMAP_DOMINATION, - MENUACTION_STARTMP, - MENUACTION_UNK69, - MENUACTION_UNK70, - MENUACTION_FINDMP, + MENUACTION_LEGENDS, + MENUACTION_RADARMODE, + MENUACTION_HUD, + MENUACTION_GOBACK, MENUACTION_KEYBOARDCTRLS, - MENUACTION_UNK73, - MENUACTION_INITMP, - MENUACTION_MP_PLAYERCOLOR, - MENUACTION_MP_PLAYERNAME, - MENUACTION_MP_GAMENAME, MENUACTION_GETKEY, MENUACTION_SHOWHEADBOB, - MENUACTION_UNK80, + MENUACTION_UNK38, // MENUACTION_PARSEHEAP? MENUACTION_DEBUGSTREAM? MENUACTION_MEMCARDSAVECONFIRM? MENUACTION_INVVERT, MENUACTION_CANCELGAME, - MENUACTION_MP_PLAYERNUMBER, - MENUACTION_MOUSESENS, - MENUACTION_CHECKMPGAMES, - MENUACTION_CHECKMPPING, - MENUACTION_MP_SERVER, - MENUACTION_MP_MAP, - MENUACTION_MP_GAMETYPE, - MENUACTION_MP_LAN, - MENUACTION_MP_INTERNET, MENUACTION_RESUME, MENUACTION_DONTCANCEL, MENUACTION_SCREENRES, @@ -364,24 +287,18 @@ enum eMenuAction MENUACTION_RESTOREDEF, MENUACTION_CTRLMETHOD, MENUACTION_DYNAMICACOUSTIC, - MENUACTION_LOADRADIO, MENUACTION_MOUSESTEER, - MENUACTION_UNK103, - MENUACTION_UNK104, - MENUACTION_UNK105, - MENUACTION_UNK106, - MENUACTION_UNK107, - MENUACTION_UNK108, - MENUACTION_UNK109, - MENUACTION_UNK110, - MENUACTION_UNK111, - MENUACTION_UNK112, + MENUACTION_DRAWDIST, + MENUACTION_MOUSESENS, + MENUACTION_MP3VOLUMEBOOST, +#ifdef GAMEPAD_MENU + MENUACTION_CTRLVIBRATION, + MENUACTION_CTRLCONFIG, +#endif +#ifdef MISSION_REPLAY MENUACTION_REJECT_RETRY, - MENUACTION_UNK114, -//#ifdef ANISOTROPIC_FILTERING -// MENUACTION_MIPMAPS, -// MENUACTION_TEXTURE_FILTERING, -//#endif + MENUACTION_UNK114 +#endif }; enum eCheckHover @@ -408,16 +325,8 @@ enum eCheckHover HOVEROPTION_LIST, // also layer in controller setup and skin menu HOVEROPTION_SKIN, HOVEROPTION_USESKIN, // also layer in controller setup and skin menu - HOVEROPTION_RADIO_0, - HOVEROPTION_RADIO_1, - HOVEROPTION_RADIO_2, - HOVEROPTION_RADIO_3, - HOVEROPTION_RADIO_4, - HOVEROPTION_RADIO_5, - HOVEROPTION_RADIO_6, - HOVEROPTION_RADIO_7, - HOVEROPTION_RADIO_8, - HOVEROPTION_RADIO_9, + HOVEROPTION_NEXT_RADIO, + HOVEROPTION_PREV_RADIO, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, HOVEROPTION_INCREASE_DRAWDIST, @@ -428,6 +337,8 @@ enum eCheckHover HOVEROPTION_DECREASE_SFXVOLUME, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, + HOVEROPTION_INCREASE_MP3BOOST, + HOVEROPTION_DECREASE_MP3BOOST, #ifdef CUSTOM_FRONTEND_OPTIONS HOVEROPTION_INCREASE_CFO_SLIDER, HOVEROPTION_DECREASE_CFO_SLIDER, @@ -437,7 +348,11 @@ enum eCheckHover enum { +#if defined LEGACY_MENU_OPTIONS || defined CUSTOM_FRONTEND_OPTIONS NUM_MENUROWS = 18, +#else + NUM_MENUROWS = 12, +#endif }; enum eControlMethod @@ -450,7 +365,7 @@ enum eControlMethod enum ControllerSetupColumn { CONTSETUP_PED_COLUMN = 0, - CONTSETUP_VEHICLE_COLUMN = 14, + CONTSETUP_VEHICLE_COLUMN = 16, }; struct tSkinInfo @@ -472,9 +387,8 @@ struct BottomBarOption struct CMenuScreen { char m_ScreenName[8]; - int32 unk; // 2 on MENUPAGE_MULTIPLAYER_START, 1 on everywhere else, 0 on unused. - int32 m_PreviousPage[2]; // eMenuScreen - int32 m_ParentEntry[2]; // row + int32 m_PreviousPage; // eMenuScreen + int32 m_ParentEntry; // row struct CMenuEntry { @@ -482,21 +396,21 @@ struct CMenuScreen char m_EntryName[8]; int32 m_SaveSlot; // eSaveSlot int32 m_TargetMenu; // eMenuScreen + uint16 m_X; + uint16 m_Y; + uint8 m_Align; } m_aEntries[NUM_MENUROWS]; }; extern CMenuScreen aScreens[MENUPAGES]; #else #include "frontendoption.h" struct CCustomScreenLayout { - eMenuSprites sprite; - int columnWidth; - int headerHeight; - int lineHeight; - int8 font; - int8 alignment; + int startX; // not used at all if first entry has X and Y values + int startY; // not used at all if first entry has X and Y values + int lineHeight; // used to determine next entry's Y coordinate, if it has 0-0 as coordinates bool showLeftRightHelper; - float fontScaleX; - float fontScaleY; + bool noInvasiveBorders; // not needed on pages already handled by game + int xMargin; // useful for two part texts - 0/empty = MENU_X_MARGIN }; struct CCFO @@ -568,7 +482,7 @@ struct CCFODynamic : CCFO struct CMenuScreenCustom { char m_ScreenName[8]; - int32 m_PreviousPage[2]; // eMenuScreen + int32 m_PreviousPage; // eMenuScreen CCustomScreenLayout *layout; ReturnPrevPageFunc returnPrevPageFunc; @@ -586,74 +500,203 @@ struct CMenuScreenCustom int32 m_SaveSlot; // eSaveSlot int32 m_TargetMenu; // eMenuScreen }; + uint16 m_X; + uint16 m_Y; + uint8 m_Align; } m_aEntries[NUM_MENUROWS]; }; extern CMenuScreenCustom aScreens[MENUPAGES]; #endif +struct MenuTrapezoid +{ + float topLeft_x; + float topLeft_y; + float topRight_x; + float topRight_y; + float bottomLeft_x; + float bottomLeft_y; + float bottomRight_x; + float bottomRight_y; + float old_topRight_x; + float old_topRight_y; + float old_topLeft_x; + float old_topLeft_y; + float old_bottomLeft_x; + float old_bottomLeft_y; + float old_bottomRight_x; + float old_bottomRight_y; + float mult_topRight_x; + float mult_topRight_y; + float mult_topLeft_x; + float mult_topLeft_y; + float mult_bottomLeft_x; + float mult_bottomLeft_y; + float mult_bottomRight_x; + float mult_bottomRight_y; + + MenuTrapezoid(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { + topLeft_x = x1; + topLeft_y = y1; + topRight_x = x2; + topRight_y = y2; + bottomLeft_x = x3; + bottomLeft_y = y3; + bottomRight_x = x4; + bottomRight_y = y4; + }; + + void SaveCurrentCoors() { + old_topLeft_x = topLeft_x; + old_topLeft_y = topLeft_y; + old_topRight_x = topRight_x; + old_topRight_y = topRight_y; + old_bottomLeft_x = bottomLeft_x; + old_bottomLeft_y = bottomLeft_y; + old_bottomRight_x = bottomRight_x; + old_bottomRight_y = bottomRight_y; + } + + void Translate(int delta) { + bottomRight_x = delta * mult_bottomRight_x + old_bottomRight_x; + bottomRight_y = delta * mult_bottomRight_y + old_bottomRight_y; + bottomLeft_x = delta * mult_bottomLeft_x + old_bottomLeft_x; + bottomLeft_y = delta * mult_bottomLeft_y + old_bottomLeft_y; + topRight_x = delta * mult_topRight_x + old_topRight_x; + topRight_y = delta * mult_topRight_y + old_topRight_y; + topLeft_x = delta * mult_topLeft_x + old_topLeft_x; + topLeft_y = delta * mult_topLeft_y + old_topLeft_y; + } + + void UpdateMultipliers() { + mult_bottomRight_x = (bottomRight_x - old_bottomRight_x) / 255.0f; + mult_bottomRight_y = (bottomRight_y - old_bottomRight_y) / 255.0f; + mult_bottomLeft_x = (bottomLeft_x - old_bottomLeft_x) / 255.0f; + mult_bottomLeft_y = (bottomLeft_y - old_bottomLeft_y) / 255.0f; + mult_topRight_x = (topRight_x - old_topRight_x) / 255.0f; + mult_topRight_y = (topRight_y - old_topRight_y) / 255.0f; + mult_topLeft_x = (topLeft_x - old_topLeft_x) / 255.0f; + mult_topLeft_y = (topLeft_y - old_topLeft_y) / 255.0f; + } +}; + class CMenuManager { public: - int32 m_nPrefsVideoMode; - int32 m_nDisplayVideoMode; + int8 m_StatsScrollDirection; + float m_StatsScrollSpeed; + uint8 field_8; + bool m_PrefsUseVibration; + bool m_PrefsShowHud; + int32 m_PrefsRadarMode; + bool m_DisplayControllerOnFoot; + bool m_bShutDownFrontEndRequested; + bool m_bStartUpFrontEndRequested; + int32 m_KeyPressedCode; + int32 m_PrefsBrightness; + float m_PrefsLOD; + int8 m_PrefsShowSubtitles; + int8 m_PrefsShowLegends; + int8 m_PrefsUseWideScreen; + int8 m_PrefsVsync; + int8 m_PrefsVsyncDisp; + int8 m_PrefsFrameLimiter; int8 m_nPrefsAudio3DProviderIndex; - bool m_bKeyChangeNotProcessed; - char m_aSkinName[256]; - int32 m_nHelperTextMsgId; - bool m_bLanguageLoaded; + int8 m_PrefsSpeakers; + int8 m_PrefsDMA; + int8 m_PrefsSfxVolume; + int8 m_PrefsMusicVolume; + int8 m_PrefsRadioStation; + uint8 m_PrefsStereoMono; // unused except restore settings + int32 m_nCurrOption; + bool m_bQuitGameNoCD; + bool m_bMenuMapActive; + bool m_AllowNavigation; + uint8 field_37; bool m_bMenuActive; - bool m_bMenuStateChanged; - bool m_bWaitingForNewKeyBind; bool m_bWantToRestart; bool m_bFirstTime; - bool m_bGameNotLoaded; - int32 m_nMousePosX; - int32 m_nMousePosY; + bool m_bActivateSaveMenu; + bool m_bWantToLoad; + float m_fMapSize; + float m_fMapCenterX; + float m_fMapCenterY; + uint32 OS_Language; + int32 m_PrefsLanguage; + int32 field_54; + int8 m_bLanguageLoaded; + uint8 m_PrefsAllowNastyGame; + int8 m_PrefsMP3BoostVolume; + int8 m_ControlMethod; + int32 m_nPrefsVideoMode; + int32 m_nDisplayVideoMode; int32 m_nMouseTempPosX; int32 m_nMouseTempPosY; - bool m_bShowMouse; - tSkinInfo m_pSkinListHead; - tSkinInfo *m_pSelectedSkin; - int32 m_nFirstVisibleRowOnList; - float m_nScrollbarTopMargin; - int32 m_nTotalListRow; - int32 m_nSkinsTotal; - char _unk0[4]; - int32 m_nSelectedListRow; - bool m_bSkinsEnumerated; - bool m_bQuitGameNoCD; - bool m_bRenderGameInMenu; - bool m_bSaveMenuActive; - bool m_bWantToLoad; - char field_455; - bool m_bStartWaitingForKeyBind; + bool m_bGameNotLoaded; + int8 m_lastWorking3DAudioProvider; + bool m_bFrontEnd_ReloadObrTxtGxt; + int32 *pEditString; + uint8 field_74[4]; + int32 *pControlEdit; + bool m_OnlySaveMenu; + int32 m_firstStartCounter; + CSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES]; bool m_bSpritesLoaded; - CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES]; - CSprite2d m_aMenuSprites[NUM_MENU_SPRITES]; - int32 field_518; + int32 m_LeftMostRadioX; + int32 m_ScrollRadioBy; + int32 m_nCurrScreen; + int32 m_nPrevScreen; + int32 m_nCurrSaveSlot; + uint32 m_LastScreenSwitch; int32 m_nMenuFadeAlpha; + int32 m_nOptionHighlightTransitionBlend; + bool bMenuChangeOngoing; + int32 MouseButtonJustClicked; + int32 JoyButtonJustClicked; + bool DisplayComboButtonErrMsg; + bool m_NoEmptyBinding; + bool m_ShowEmptyBindingError; + int32 m_nHelperTextAlpha; bool m_bPressedPgUpOnList; bool m_bPressedPgDnOnList; bool m_bPressedUpOnList; bool m_bPressedDownOnList; bool m_bPressedScrollButton; - int32 m_CurrCntrlAction; - char _unk1[4]; - int32 m_nSelectedContSetupColumn; - bool m_bKeyIsOK; - bool field_535; - int8 m_nCurrExLayer; - int32 m_nHelperTextAlpha; + uint8 field_129; + uint8 field_12A; + uint8 field_12B; + int32 m_nMousePosX; + int32 m_nMousePosY; int32 m_nMouseOldPosX; int32 m_nMouseOldPosY; int32 m_nHoverOption; - int32 m_nCurrScreen; - int32 m_nCurrOption; + bool m_bShowMouse; int32 m_nOptionMouseHovering; - int32 m_nPrevScreen; - uint32 field_558; - int32 m_nCurrSaveSlot; - int32 m_nScreenChangeDelayTimer; + bool m_bStartWaitingForKeyBind; + bool m_bWaitingForNewKeyBind; + bool m_bKeyChangeNotProcessed; + int32 m_CurrCntrlAction; + uint8 field_150; + uint8 field_151; + uint8 field_152; + uint8 field_153; + int32 m_nSelectedContSetupColumn; + bool m_bKeyIsOK; + bool field_159; + uint8 m_nCurrExLayer; + char m_PrefsSkinFile[256]; + char m_aSkinName[256]; + uint8 field_35B; + int32 m_nHelperTextMsgId; + tSkinInfo m_pSkinListHead; + tSkinInfo *m_pSelectedSkin; + int32 m_nFirstVisibleRowOnList; + float m_nScrollbarTopMargin; + int32 m_nTotalListRow; + int32 m_nSkinsTotal; + uint8 field_67C[4]; + int32 m_nSelectedListRow; + bool m_bSkinsEnumerated; #ifdef IMPROVED_VIDEOMODE int32 m_nPrefsWidth; @@ -664,10 +707,22 @@ public: int32 m_nSelectedScreenMode; #endif #ifdef MULTISAMPLING - static int8 m_nPrefsMSAALevel; - static int8 m_nDisplayMSAALevel; + int8 m_nPrefsMSAALevel; + int8 m_nDisplayMSAALevel; #endif +#ifdef GAMEPAD_MENU + enum + { + CONTROLLER_DUALSHOCK2 = 0, + CONTROLLER_DUALSHOCK3, + CONTROLLER_DUALSHOCK4, + CONTROLLER_XBOX360, + CONTROLLER_XBOXONE, + }; + + int8 m_PrefsControllerType; +#endif enum LANGUAGE { LANGUAGE_AMERICAN, @@ -681,42 +736,8 @@ public: LANGUAGE_JAPANESE, #endif }; -public: bool GetIsMenuActive() {return !!m_bMenuActive;} -public: - static int32 OS_Language; - static int8 m_PrefsUseVibration; - static int8 m_DisplayControllerOnFoot; - static int8 m_PrefsUseWideScreen; - static int8 m_PrefsRadioStation; - static int8 m_PrefsVsync; - static int8 m_PrefsVsyncDisp; - static int8 m_PrefsFrameLimiter; - static int8 m_PrefsShowSubtitles; - static int8 m_PrefsSpeakers; - static int32 m_ControlMethod; - static int8 m_PrefsDMA; - static int32 m_PrefsLanguage; - static int32 m_PrefsBrightness; - static float m_PrefsLOD; - static int8 m_bFrontEnd_ReloadObrTxtGxt; - static int32 m_PrefsMusicVolume; - static int32 m_PrefsSfxVolume; - static char m_PrefsSkinFile[256]; - static int32 m_KeyPressedCode; - - static bool m_bStartUpFrontEndRequested; - static bool m_bShutDownFrontEndRequested; - static bool m_PrefsAllowNastyGame; - - static uint8 m_PrefsStereoMono; - static int32 m_SelectedMap; - static int32 m_SelectedGameType; - static uint8 m_PrefsPlayerRed; - static uint8 m_PrefsPlayerGreen; - static uint8 m_PrefsPlayerBlue; - #ifdef CUTSCENE_BORDERS_SWITCH static bool m_PrefsCutsceneBorders; #endif @@ -726,14 +747,8 @@ public: static bool m_PrefsDisableTutorials; #endif // !MASTER -#ifdef MENU_MAP - static bool bMenuMapActive; - static float fMapSize; - static float fMapCenterY; - static float fMapCenterX; - static CSprite2d m_aMapSprites[NUM_MAP_SPRITES]; - void PrintMap(); -#endif + CMenuManager(void); + ~CMenuManager(void) { UnloadTextures(); } #ifdef NO_ISLAND_LOADING enum @@ -743,94 +758,99 @@ public: ISLAND_LOADING_HIGH }; - static int8 m_PrefsIslandLoading; + int8 m_PrefsIslandLoading; - #define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p) - #define ISLAND_LOADING_ISNT(p) if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_##p) + #define ISLAND_LOADING_IS(p) if (FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p) + #define ISLAND_LOADING_ISNT(p) if (FrontEndMenuManager.m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_##p) #else #define ISLAND_LOADING_IS(p) #define ISLAND_LOADING_ISNT(p) #endif -#ifdef GAMEPAD_MENU - enum - { - CONTROLLER_DUALSHOCK2 = 0, - CONTROLLER_DUALSHOCK3, - CONTROLLER_DUALSHOCK4, - CONTROLLER_XBOX360, - CONTROLLER_XBOXONE, - }; - - static int8 m_PrefsControllerType; +#ifdef XBOX_MESSAGE_SCREEN + static uint32 m_nDialogHideTimer; + static uint32 m_nDialogHideTimerPauseMode; + static bool m_bDialogOpen; + static wchar *m_pDialogText; + static bool m_bSaveWasSuccessful; + + static void SetDialogText(const char*); + static bool DialogTextCmp(const char*); + static void ToggleDialog(bool); + static void SetDialogTimer(uint32); + void ProcessDialogTimer(void); + void DrawOverlays(void); + void CloseDialog(void); #endif -public: - static void BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2); + void Initialise(); + void PrintMap(); + void SetFrontEndRenderStates(); static void CentreMousePointer(); void CheckCodesForControls(int); bool CheckHover(int x1, int x2, int y1, int y2); void CheckSliderMovement(int); - int CostructStatLine(int); - void DisplayHelperText(); - int DisplaySlider(float, float, float, float, float, float); + void DisplayHelperText(char*); + int DisplaySlider(float, float, float, float, float, float, float); void DoSettingsBeforeStartingAGame(); - void Draw(); + void DrawStandardMenus(bool); void DrawControllerBound(int32, int32, int32, int8); void DrawControllerScreenExtraText(int, int, int); void DrawControllerSetupScreen(); + void DrawQuitGameScreen(); void DrawFrontEnd(); - void DrawFrontEndNormal(); -#ifdef PS2_SAVE_DIALOG - void DrawFrontEndSaveZone(); -#endif - void DrawPlayerSetupScreen(); + void DrawBackground(bool transitionCall); + void DrawPlayerSetupScreen(bool); int FadeIn(int alpha); - void FilterOutColorMarkersFromString(wchar*, CRGBA &); int GetStartOptionsCntrlConfigScreens(); - static void InitialiseChangedLanguageSettings(); + void InitialiseChangedLanguageSettings(); void LoadAllTextures(); void LoadSettings(); - void MessageScreen(const char *); - void PickNewPlayerColour(); + void MessageScreen(const char *str, bool); + void SmallMessageScreen(const char *str); void PrintBriefs(); static void PrintErrorMessage(); void PrintStats(); void Process(); - void ProcessButtonPresses(); + void ProcessList(bool &optionSelected, bool &goBack); + void UserInput(); + void ProcessUserInput(uint8, uint8, uint8, uint8, int8); + void ChangeRadioStation(int8); + void ProcessFileActions(); void ProcessOnOffMenuOptions(); - static void RequestFrontEndShutDown(); - static void RequestFrontEndStartUp(); + void RequestFrontEndShutDown(); + void RequestFrontEndStartUp(); void ResetHelperText(); - void SaveLoadFileError_SetUpErrorScreen(); void SaveSettings(); void SetHelperText(int text); - void ShutdownJustMenu(); float StretchX(float); float StretchY(float); void SwitchMenuOnAndOff(); void UnloadTextures(); void WaitForUserCD(); - void PrintController(); int GetNumOptionsCntrlConfigScreens(); - int ConstructStatLine(int); + void SwitchToNewScreen(int8); + void AdditionalOptionInput(bool &goBack); + void ExportStats(void); + void PrintRadioSelector(void); - // Those are either inlined in game, not in function yet, or I can't believe that they're not inlined. - // Names were made up by me. - void ThingsToDoBeforeGoingBack(); + // New (not in function or inlined in the game) + void ThingsToDoBeforeLeavingPage(); void ScrollUpListByOne(); void ScrollDownListByOne(); void PageUpList(bool); void PageDownList(bool); int8 GetPreviousPageOption(); - void ProcessList(bool &goBack, bool &optionSelected); + + // uint8 GetNumberOfMenuOptions(); #ifdef GAMEPAD_MENU void LoadController(int8 type); + void PrintController(void); #endif }; #ifndef IMPROVED_VIDEOMODE -VALIDATE_SIZE(CMenuManager, 0x564); +VALIDATE_SIZE(CMenuManager, 0x688); #endif extern CMenuManager FrontEndMenuManager; diff --git a/src/core/Frontend_PS2.cpp b/src/core/Frontend_PS2.cpp index 1da15fbb..fa238031 100644 --- a/src/core/Frontend_PS2.cpp +++ b/src/core/Frontend_PS2.cpp @@ -203,6 +203,10 @@ static const char* FrontendFilenames[][2] = {"fe_radio9", "" }, }; +#ifdef CUTSCENE_BORDERS_SWITCH +bool CMenuManager::m_PrefsCutsceneBorders = true; +#endif + int32 CMenuManager::m_PrefsSfxVolume = 102; int32 CMenuManager::m_PrefsMusicVolume = 102; int32 CMenuManager::m_PrefsBrightness = 256; @@ -1178,30 +1182,9 @@ CMenuManager::InitialiseMenuContents(void) STAT_LINE("KGS_EXP", &CStats::KgsOfExplosivesUsed, 0, nil); - nTemp = (CStats::InstantHitsFiredByPlayer == 0 ? 0 : CStats::InstantHitsHitByPlayer * 100.0f / CStats::InstantHitsFiredByPlayer); - STAT_LINE("ACCURA", &nTemp, 0, nil); - - if (CStats::ElBurroTime > 0) - STAT_LINE("ELBURRO", &CStats::ElBurroTime, 0, nil); - - if (CStats::Record4x4One > 0) - STAT_LINE("FEST_R1", &CStats::Record4x4One, 0, nil); - - if (CStats::Record4x4Two > 0) - STAT_LINE("FEST_R2", &CStats::Record4x4Two, 0, nil); - - if (CStats::Record4x4Three > 0) - STAT_LINE("FEST_R3", &CStats::Record4x4Three, 0, nil); - - if (CStats::Record4x4Mayhem > 0) - STAT_LINE("FEST_RM", &CStats::Record4x4Mayhem, 0, nil); - if (CStats::LongestFlightInDodo > 0) STAT_LINE("FEST_LF", &CStats::LongestFlightInDodo, 0, nil); - if (CStats::TimeTakenDefuseMission > 0) - STAT_LINE("FEST_BD", &CStats::TimeTakenDefuseMission, 0, nil); - STAT_LINE("CAR_CRU", &CStats::CarsCrushed, 0, nil); if (CStats::HighestScores[0] > 0) @@ -1230,7 +1213,11 @@ CMenuManager::InitialiseMenuContents(void) STAT_LINE("FEST_H4", &CStats::HighestScores[4], 0, nil); STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, 0, nil); - STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, 0, nil); + STAT_LINE("FESTDCM", &CStats::DistanceTravelledByCar, 0, nil); + STAT_LINE("DISTBIM", &CStats::DistanceTravelledByBike, 0, nil); + STAT_LINE("DISTBOM", &CStats::DistanceTravelledByBoat, 0, nil); + STAT_LINE("DISTGOM", &CStats::DistanceTravelledByGolfCart, 0, nil); + STAT_LINE("DISTHEM", &CStats::DistanceTravelledByHelicoptor, 0, nil); STAT_LINE("MMRAIN", &CStats::mmRain, 0, nil); nTemp = (int32)CStats::MaximumJumpDistance; STAT_LINE("MXCARDM", &nTemp, 0, nil); diff --git a/src/core/Frontend_PS2.h b/src/core/Frontend_PS2.h index 4bab7df9..6311d821 100644 --- a/src/core/Frontend_PS2.h +++ b/src/core/Frontend_PS2.h @@ -161,8 +161,10 @@ public: static CONTRCONFIG m_PrefsControllerConfig; static bool m_PrefsUseVibration; -#define ISLAND_LOADING_IS(p) -#define ISLAND_LOADING_ISNT(p) +#ifdef CUTSCENE_BORDERS_SWITCH + static bool m_PrefsCutsceneBorders; +#endif + #ifdef GTA_PC bool m_bQuitGameNoCD; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index b3dd1eda..3a8cdb06 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -41,6 +41,7 @@ #include "MBlur.h" #include "Messages.h" #include "MemoryCard.h" +#include "MemoryHeap.h" #include "Pad.h" #include "Particle.h" #include "ParticleObject.h" @@ -62,6 +63,7 @@ #include "Script.h" #include "Shadows.h" #include "Skidmarks.h" +#include "SetPieces.h" #include "SpecialFX.h" #include "Stats.h" #include "Streaming.h" @@ -81,17 +83,21 @@ #include "World.h" #include "ZoneCull.h" #include "Zones.h" +#include "Occlusion.h" #include "debugmenu.h" +#include "Ropes.h" +#include "WindModifiers.h" +#include "WaterCreatures.h" #include "postfx.h" #include "custompipes.h" #include "screendroplets.h" -#include "crossplatform.h" -#include "MemoryHeap.h" +#include "VarConsole.h" #ifdef USE_TEXTURE_POOL #include "TexturePools.h" #endif eLevelName CGame::currLevel; +int32 CGame::currArea; bool CGame::bDemoMode = true; bool CGame::nastyGame = true; bool CGame::frenchGame; @@ -103,15 +109,24 @@ char CGame::aDatFile[32]; bool CGame::russianGame = false; bool CGame::japaneseGame = false; #endif +#ifndef MASTER +CVector CGame::PlayerCoords; +bool8 CGame::VarUpdatePlayerCoords; +#endif int gameTxdSlot; +#ifdef SECUROM +uint8 gameProcessPirateCheck = 0; +#endif bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); void DoRWStuffEndOfFrame(void); #ifdef PS2_MENU void MessageScreen(char *msg) { + //TODO: stretch_screen + CRect rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); CRGBA color(255, 255, 255, 255); @@ -123,32 +138,20 @@ void MessageScreen(char *msg) CSprite2d *splash = LoadSplash(NULL); splash->Draw(rect, color, color, color, color); -#ifdef FIX_BUGS - splash->DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(110.0f), SCREEN_WIDTH-SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(300.0f)), CRGBA(50, 50, 50, 192)); -#else - splash->DrawRect(CRect(20.0f, 110.0f, SCREEN_WIDTH-20.0f, 300.0f), CRGBA(50, 50, 50, 192)); -#endif + splash->DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(110.0f), SCREEN_SCALE_X(620.0f), SCREEN_SCALE_Y(300.0f)), CRGBA(50, 50, 50, 192)); + CFont::SetFontStyle(FONT_BANK); CFont::SetBackgroundOff(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190)); -#ifdef FIX_BUGS + CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); -#else - CFont::SetScale(1.0f, 1.0f); -#endif CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 190)); // 450.0f + CFont::SetCentreSize(SCREEN_SCALE_X(450.0f)); CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 255, 255)); CFont::SetDropColor(CRGBA(32, 32, 32, 255)); CFont::SetDropShadowPosition(3); - CFont::SetBackGroundOnlyTextOff(); CFont::SetPropOn(); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_WIDTH/2, SCREEN_SCALE_Y(130.0f), TheText.Get(msg)); -#else - CFont::PrintString(SCREEN_WIDTH/2, 130.0f, TheText.Get(msg)); -#endif + CFont::PrintString(SCREEN_SCALE_X(320.0f), SCREEN_SCALE_Y(130.0f), TheText.Get(msg)); CFont::DrawFonts(); DoRWStuffEndOfFrame(); @@ -160,7 +163,11 @@ CGame::InitialiseOnceBeforeRW(void) { CFileMgr::Initialise(); CdStreamInit(MAX_CDCHANNELS); - ValidateVersion(); + debug("size of matrix %d\n", sizeof(CMatrix)); + debug("size of placeable %d\n", sizeof(CPlaceable)); + debug("size of entity %d\n", sizeof(CEntity)); + debug("size of building %d\n", sizeof(CBuilding)); + debug("size of dummy %d\n", sizeof(CDummy)); #ifdef EXTENDED_COLOURFILTER CPostFX::InitOnce(); #endif @@ -184,16 +191,13 @@ void ReplaceAtomicPipeCallback(); bool CGame::InitialiseRenderWare(void) { + ValidateVersion(); #ifdef USE_TEXTURE_POOL _TexturePoolsInitialise(); #endif -#if GTA_VERSION > GTA3_PS2_160 - CTxdStore::Initialise(); // in GameInit on ps2 - CVisibilityPlugins::Initialise(); // in plugin attach on ps2 -#endif - - //InitialiseScene(Scene); // PS2 only, only clears Scene.camera + CTxdStore::Initialise(); + CVisibilityPlugins::Initialise(); #ifdef GTA_PS2 RpSkySelectTrueTSClipper(TRUE); @@ -213,7 +217,7 @@ CGame::InitialiseRenderWare(void) return (false); } - RwCameraSetFarClipPlane(Scene.camera, 2000.0f); // 250.0f on PS2 but who cares + RwCameraSetFarClipPlane(Scene.camera, 2000.0f); RwCameraSetNearClipPlane(Scene.camera, 0.9f); CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO); @@ -237,11 +241,7 @@ CGame::InitialiseRenderWare(void) RpWorldAddCamera(Scene.world, Scene.camera); LightsCreate(Scene.world); -#if GTA_VERSION > GTA3_PS2_160 - CreateDebugFont(); // in GameInit on PS2 -#else - RwImageSetPath("textures"); -#endif + CreateDebugFont(); #ifdef LIBRW #ifdef PS2_MATFX @@ -253,7 +253,7 @@ CGame::InitialiseRenderWare(void) rw::MatFX::envMapUseMatColor = false; rw::MatFX::envMapFlipU = false; #endif - rw::RGBA envcol = { 128, 128, 128, 255 }; + rw::RGBA envcol = { 64, 64, 64, 255 }; rw::MatFX::envMapColor = envcol; #else #ifdef PS2_MATFX @@ -264,17 +264,12 @@ CGame::InitialiseRenderWare(void) #endif // PS2_ALPHA_TEST #endif // LIBRW - -#if GTA_VERSION > GTA3_PS2_160 - // in GameInit on PS2 PUSH_MEMID(MEMID_TEXTURES); CFont::Initialise(); CHud::Initialise(); - POP_MEMID(); - // TODO: define CPlayerSkin::Initialise(); -#endif - + POP_MEMID(); + #ifdef EXTENDED_PIPELINES CustomPipes::CustomPipeInit(); // need Scene.world for this #endif @@ -285,7 +280,6 @@ CGame::InitialiseRenderWare(void) return (true); } -// missing altogether on PS2 void CGame::ShutdownRenderWare(void) { #ifdef SCREEN_DROPLETS @@ -295,7 +289,6 @@ void CGame::ShutdownRenderWare(void) CustomPipes::CustomPipeShutdown(); #endif - CMBlur::MotionBlurClose(); DestroySplashScreen(); CHud::Shutdown(); CFont::Shutdown(); @@ -303,7 +296,6 @@ void CGame::ShutdownRenderWare(void) for ( int32 i = 0; i < NUMPLAYERS; i++ ) CWorld::Players[i].DeletePlayerSkin(); - // TODO: define CPlayerSkin::Shutdown(); DestroyDebugFont(); @@ -326,64 +318,41 @@ void CGame::ShutdownRenderWare(void) #endif } -// missing altogether on PS2 bool CGame::InitialiseOnceAfterRW(void) { -#if GTA_VERSION > GTA3_PS2_160 TheText.Load(); - DMAudio.Initialise(); // before TheGame() on PS2 CTimer::Initialise(); CTempColModels::Initialise(); mod_HandlingManager.Initialise(); CSurfaceTable::Initialise("DATA\\SURFACE.DAT"); CPedStats::Initialise(); CTimeCycle::Initialise(); +#ifdef GTA_PS2 + LoadingScreen("Loading the Game", "Initialising audio", GetRandomSplashScreen()); +#endif + DMAudio.Initialise(); #ifndef GTA_PS2 if ( DMAudio.GetNum3DProvidersAvailable() == 0 ) - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1; - - if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -99 || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) { - CMenuManager::m_PrefsSpeakers = 0; - int32 i; - for (i = 0; i < DMAudio.GetNum3DProvidersAvailable(); i++) { - wchar buff[64]; - -#ifdef AUDIO_OAL - extern int defaultProvider; - if (defaultProvider >= 0 && defaultProvider < DMAudio.GetNum3DProvidersAvailable()) - break; -#endif - char *name = DMAudio.Get3DProviderName(i); - AsciiToUnicode(name, buff); - char *providername = UnicodeToAscii(buff); - strupr(providername); -#if defined(AUDIO_MSS) - if (strcmp(providername, "MILES FAST 2D POSITIONAL AUDIO") == 0) - break; -#elif defined(AUDIO_OAL) - if (strcmp(providername, "OPENAL SOFT") == 0) - break; -#endif - } + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = NO_AUDIO_PROVIDER; - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = i; + if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == AUDIO_PROVIDER_NOT_DETERMINED || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) + { + FrontEndMenuManager.m_PrefsSpeakers = 0; + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); } DMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); - DMAudio.SetSpeakerConfig(CMenuManager::m_PrefsSpeakers); - DMAudio.SetDynamicAcousticModelingStatus(CMenuManager::m_PrefsDMA); - DMAudio.SetMusicMasterVolume(CMenuManager::m_PrefsMusicVolume); - DMAudio.SetEffectsMasterVolume(CMenuManager::m_PrefsSfxVolume); + DMAudio.SetSpeakerConfig(FrontEndMenuManager.m_PrefsSpeakers); + DMAudio.SetDynamicAcousticModelingStatus(FrontEndMenuManager.m_PrefsDMA); + DMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume); DMAudio.SetEffectsFadeVol(127); DMAudio.SetMusicFadeVol(127); #endif - CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); -#endif return true; } -// missing altogether on PS2 void CGame::FinalShutdown(void) { @@ -392,31 +361,29 @@ CGame::FinalShutdown(void) CdStreamShutdown(); } -#if GTA_VERSION <= GTA3_PS2_160 -bool CGame::Initialise(void) -#else bool CGame::Initialise(const char* datFile) -#endif { + ResetLoadingScreenBar(); + strcpy(aDatFile, datFile); + #ifdef GTA_PS2 // TODO: upload VU0 collision code here #endif -#if GTA_VERSION > GTA3_PS2_160 - ResetLoadingScreenBar(); - strcpy(aDatFile, datFile); - CPools::Initialise(); // done in CWorld on PS2 -#endif + CPools::Initialise(); #ifndef GTA_PS2 #ifdef PED_CAR_DENSITY_SLIDERS - // Load density values from gta3.ini only if our re3.ini have them 1.f - if (CIniFile::PedNumberMultiplier == 1.f && CIniFile::CarNumberMultiplier == 1.f) + // Load density values from gta3.ini only if our reVC.ini have them 0.6f + if (CIniFile::PedNumberMultiplier == 0.6f && CIniFile::CarNumberMultiplier == 0.6f) #endif CIniFile::LoadIniFile(); #endif - - currLevel = LEVEL_INDUSTRIAL; +#ifdef USE_TEXTURE_POOL + _TexturePoolsUnknown(false); +#endif + currLevel = LEVEL_BEACH; + currArea = AREA_MAIN_MAP; PUSH_MEMID(MEMID_TEXTURES); LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen()); @@ -448,18 +415,16 @@ bool CGame::Initialise(const char* datFile) CDebug::DebugInitTextBuffer(); ThePaths.Init(); ThePaths.AllocatePathFindInfoMem(4500); + CScriptPaths::Init(); CWeather::Init(); CCullZones::Init(); + COcclusion::Init(); CCollision::Init(); -#ifdef PS2_MENU // TODO: is this the right define? - TheText.Load(); -#endif + CSetPieces::Init(); CTheZones::Init(); CUserDisplay::Init(); CMessages::Init(); -#if GTA_VERSION > GTA3_PS2_160 CMessages::ClearAllMessagesDisplayedByGame(); -#endif CRecordDataForGame::Init(); CRestart::Initialise(); @@ -467,22 +432,10 @@ bool CGame::Initialise(const char* datFile) CWorld::Initialise(); POP_MEMID(); -#if GTA_VERSION <= GTA3_PS2_160 - mod_HandlingManager.Initialise(); - CSurfaceTable::Initialise("DATA\\SURFACE.DAT"); - CTempColModels::Initialise(); -#endif - PUSH_MEMID(MEMID_TEXTURES); CParticle::Initialise(); POP_MEMID(); -#if GTA_VERSION <= GTA3_PS2_160 - gStartX = -180.0f; - gStartY = 180.0f; - gStartZ = 14.0f; -#endif - PUSH_MEMID(MEMID_ANIMATION); CAnimManager::Initialise(); CCutsceneMgr::Initialise(); @@ -493,13 +446,8 @@ bool CGame::Initialise(const char* datFile) POP_MEMID(); PUSH_MEMID(MEMID_DEF_MODELS); -#if GTA_VERSION > GTA3_PS2_160 InitModelIndices(); -#endif CModelInfo::Initialise(); - -#if GTA_VERSION > GTA3_PS2_160 - // probably moved before LoadLevel for multiplayer maps? CPickups::Init(); CTheCarGenerators::Init(); @@ -507,55 +455,42 @@ bool CGame::Initialise(const char* datFile) CFileLoader::LoadLevel("DATA\\DEFAULT.DAT"); CFileLoader::LoadLevel(datFile); -#else - CPedStats::Initialise(); // InitialiseOnceAfterRW - - CFileLoader::LoadLevel("GTA3.DAT"); -#endif + LoadingScreen("Loading the Game", "Add Particles", nil); CWorld::AddParticles(); CVehicleModelInfo::LoadVehicleColours(); CVehicleModelInfo::LoadEnvironmentMaps(); CTheZones::PostZoneCreation(); POP_MEMID(); -#if GTA_VERSION <= GTA3_PS2_160 - TestModelIndices(); -#endif - LoadingScreen("Loading the Game", "Setup paths", GetRandomSplashScreen()); + LoadingScreen("Loading the Game", "Setup paths", nil); ThePaths.PreparePathData(); -#if GTA_VERSION > GTA3_PS2_160 for (int i = 0; i < NUMPLAYERS; i++) CWorld::Players[i].Clear(); CWorld::Players[0].LoadPlayerSkin(); TestModelIndices(); -#endif LoadingScreen("Loading the Game", "Setup water", nil); CWaterLevel::Initialise("DATA\\WATER.DAT"); -#if GTA_VERSION <= GTA3_PS2_160 - CTimeCycle::Initialise(); // InitialiseOnceAfterRW -#else TheConsole.Init(); -#endif CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; LoadingScreen("Loading the Game", "Setup streaming", nil); - CStreaming::Init(); CStreaming::LoadInitialVehicles(); CStreaming::LoadInitialPeds(); CStreaming::RequestBigBuildings(LEVEL_GENERIC); CStreaming::LoadAllRequestedModels(false); -#if GTA_VERSION > GTA3_PS2_160 + CStreaming::RemoveIslandsNotUsed(currLevel); printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d -#endif LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen()); PUSH_MEMID(MEMID_ANIMATION); CAnimManager::LoadAnimFiles(); POP_MEMID(); + CStreaming::LoadInitialWeapons(); + CStreaming::LoadAllRequestedModels(0); CPed::Initialise(); CRouteNode::Initialise(); CEventList::Initialise(); @@ -576,11 +511,6 @@ bool CGame::Initialise(const char* datFile) LoadingScreen("Loading the Game", "Setup game variables", nil); CPopulation::Initialise(); -#if GTA_VERSION <= GTA3_PS2_160 - for (int i = 0; i < NUMPLAYERS; i++) - CWorld::Players[i].Clear(); -// CWorld::Players[0].LoadPlayerSkin(); // TODO: use a define for this -#endif CWorld::PlayerInFocus = 0; CCoronas::Init(); CShadows::Init(); @@ -600,47 +530,24 @@ bool CGame::Initialise(const char* datFile) POP_MEMID(); LoadingScreen("Loading the Game", "Setup game variables", nil); -#if GTA_VERSION <= GTA3_PS2_160 - CTimer::Initialise(); -#endif CClock::Initialise(1000); -#if GTA_VERSION <= GTA3_PS2_160 - CTheCarGenerators::Init(); -#endif CHeli::InitHelis(); CCranes::InitCranes(); CMovingThings::Init(); CDarkel::Init(); CStats::Init(); -#if GTA_VERSION <= GTA3_PS2_160 - CPickups::Init(); -#endif CPacManPickups::Init(); -#if GTA_VERSION <= GTA3_PS2_160 - CGarages::Init(); -#endif CRubbish::Init(); CClouds::Init(); -#if GTA_VERSION <= GTA3_PS2_160 - CRemote::Init(); -#endif CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CBridge::Init(); -#if GTA_VERSION > GTA3_PS2_160 CGarages::Init(); -#endif LoadingScreen("Loading the Game", "Position dynamic objects", nil); - CWorld::RepositionCertainDynamicObjects(); -#if GTA_VERSION <= GTA3_PS2_160 - CCullZones::ResolveVisibilities(); -#endif - LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); -#if GTA_VERSION > GTA3_PS2_160 - CCullZones::ResolveVisibilities(); -#endif + CTrain::InitTrains(); CPlane::InitPlanes(); CCredits::Init(); @@ -658,27 +565,44 @@ bool CGame::Initialise(const char* datFile) } LoadingScreen("Loading the Game", "Load scene", nil); - CModelInfo::RemoveColModelsFromOtherLevels(currLevel); CCollision::ms_collisionInMemory = currLevel; for (int i = 0; i < MAX_PADS; i++) CPad::GetPad(i)->Clear(true); +#ifdef USE_TEXTURE_POOL + _TexturePoolsUnknown(true); +#endif + +#ifndef MASTER + PlayerCoords = FindPlayerCoors(); + VarConsole.Add("X PLAYER COORD", &PlayerCoords.x, 10.0f, -10000.0f, 10000.0f, true); + VarConsole.Add("Y PLAYER COORD", &PlayerCoords.y, 10.0f, -10000.0f, 10000.0f, true); + VarConsole.Add("Z PLAYER COORD", &PlayerCoords.z, 10.0f, -10000.0f, 10000.0f, true); + VarConsole.Add("UPDATE PLAYER COORD", &VarUpdatePlayerCoords, true); +#endif + + + DMAudio.SetStartingTrackPositions(TRUE); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); return true; } bool CGame::ShutDown(void) { +#ifdef USE_TEXTURE_POOL + _TexturePoolsUnknown(false); +#endif CReplay::FinishPlayback(); + CReplay::EmptyReplayBuffer(); CPlane::Shutdown(); CTrain::Shutdown(); + CScriptPaths::Shutdown(); + CWaterCreatures::RemoveAll(); CSpecialFX::Shutdown(); -#if GTA_VERSION > GTA3_PS2_160 CGarages::Shutdown(); -#endif CMovingThings::Shutdown(); gPhoneInfo.Shutdown(); CWeapon::ShutdownWeapons(); CPedType::Shutdown(); - CMBlur::MotionBlurClose(); for (int32 i = 0; i < NUMPLAYERS; i++) { @@ -712,11 +636,14 @@ bool CGame::ShutDown(void) CSkidmarks::Shutdown(); CWeaponEffects::Shutdown(); CParticle::Shutdown(); -#if GTA_VERSION > GTA3_PS2_160 CPools::ShutDown(); -#endif + CHud::ReInitialise(); CTxdStore::RemoveTxdSlot(gameTxdSlot); + CMBlur::MotionBlurClose(); CdStreamRemoveImages(); +#ifdef USE_TEXTURE_POOL + _TexturePoolsFinalShutdown(); +#endif return true; } @@ -738,17 +665,15 @@ void CGame::ReInitGameObjectVariables(void) CWorld::bDoingCarCollisions = false; CHud::ReInitialise(); CRadar::Initialise(); -#if GTA_VERSION <= GTA3_PS2_160 - gStartX = -180.0f; - gStartY = 180.0f; - gStartZ = 14.0f; -#endif CCarCtrl::ReInit(); CTimeCycle::Initialise(); CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; CStreaming::RequestBigBuildings(LEVEL_GENERIC); + CStreaming::RemoveIslandsNotUsed(LEVEL_BEACH); + CStreaming::RemoveIslandsNotUsed(LEVEL_MAINLAND); CStreaming::LoadAllRequestedModels(false); + currArea = AREA_MAIN_MAP; CPed::Initialise(); CEventList::Initialise(); #ifdef SCREEN_DROPLETS @@ -761,10 +686,6 @@ void CGame::ReInitGameObjectVariables(void) CWorld::Players[i].Clear(); CWorld::PlayerInFocus = 0; -#if GTA_VERSION <= GTA3_PS2_160 - CWeaponEffects::Init(); - CSkidmarks::Init(); -#endif CAntennas::Init(); CGlass::Init(); gPhoneInfo.Initialise(); @@ -784,14 +705,11 @@ void CGame::ReInitGameObjectVariables(void) CPickups::Init(); CPacManPickups::Init(); CGarages::Init(); -#if GTA_VERSION <= GTA3_PS2_160 - CClouds::Init(); - CRemote::Init(); -#endif CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); + CScriptPaths::Init(); CParticle::ReloadConfig(); - CCullZones::ResolveVisibilities(); #ifdef PS2_MENU if ( !TheMemoryCard.m_bWantToLoad ) @@ -813,31 +731,18 @@ void CGame::ReInitGameObjectVariables(void) void CGame::ReloadIPLs(void) { - CTimer::Stop(); - CWorld::RemoveStaticObjects(); - ThePaths.Init(); - CCullZones::Init(); - CFileLoader::ReloadPaths("GTA3.IDE"); - CFileLoader::LoadScene("INDUST.IPL"); - CFileLoader::LoadScene("COMMER.IPL"); - CFileLoader::LoadScene("SUBURBAN.IPL"); - CFileLoader::LoadScene("CULL.IPL"); - ThePaths.PreparePathData(); - CTrafficLights::ScanForLightsOnMap(); - CRoadBlocks::Init(); - CCranes::InitCranes(); - CGarages::Init(); - CWorld::RepositionCertainDynamicObjects(); - CCullZones::ResolveVisibilities(); - CRenderer::SortBIGBuildings(); - CTimer::Update(); + // Empty and unused } void CGame::ShutDownForRestart(void) { +#ifdef USE_TEXTURE_POOL + _TexturePoolsUnknown(false); +#endif CReplay::FinishPlayback(); CReplay::EmptyReplayBuffer(); DMAudio.DestroyAllGameCreatedEntities(); + CMovingThings::Shutdown(); for (int i = 0; i < NUMPLAYERS; i++) CWorld::Players[i].Clear(); @@ -846,19 +751,16 @@ void CGame::ShutDownForRestart(void) CTheScripts::UndoBuildingSwaps(); CTheScripts::UndoEntityInvisibilitySettings(); CWorld::ClearForRestart(); + CGameLogic::ClearShortCut(); CTimer::Shutdown(); - CStreaming::FlushRequestList(); - CStreaming::DeleteAllRwObjects(); - CStreaming::RemoveAllUnusedModels(); - CStreaming::ms_disableStreaming = false; + CStreaming::ReInit(); CRadar::RemoveRadarSections(); FrontEndMenuManager.UnloadTextures(); - CParticleObject::RemoveAllParticleObjects(); -#if GTA_VERSION >= GTA3_PS2_160 + CParticleObject::RemoveAllExpireableParticleObjects(); + CWaterCreatures::RemoveAll(); + CSetPieces::Init(); CPedType::Shutdown(); CSpecialFX::Shutdown(); -#endif - TidyUpMemory(true, false); } void CGame::InitialiseWhenRestarting(void) @@ -869,116 +771,38 @@ void CGame::InitialiseWhenRestarting(void) CTimer::Initialise(); CSprite2d::SetRecipNearClip(); -#ifdef PS2_MENU - if ( TheMemoryCard.b_FoundRecentSavedGameWantToLoad == true || TheMemoryCard.m_bWantToLoad == false ) + if (b_FoundRecentSavedGameWantToLoad || FrontEndMenuManager.m_bWantToLoad) { - if ( TheMemoryCard.m_bWantToLoad == true ) - MessageScreen("MCLOAD"); // Loading Data. Please do not remove the Memory Card (PS2) in MEMORY CARD slot 1, reset or switch off the console. - else - MessageScreen("RESTART"); // Starting new game - } + LoadSplash("splash1"); +#ifndef XBOX_MESSAGE_SCREEN + if (FrontEndMenuManager.m_bWantToLoad) + FrontEndMenuManager.MessageScreen("FELD_WR", true); #endif - -#ifdef PS2_MENU - TheMemoryCard.b_FoundRecentSavedGameWantToLoad = false; -#else + } + b_FoundRecentSavedGameWantToLoad = false; -#endif TheCamera.Init(); -#ifdef PS2_MENU - if ( TheMemoryCard.m_bWantToLoad == true ) - { - TheMemoryCard.RestoreForStartLoad(); - CStreaming::LoadScene(TheCamera.GetPosition()); - } -#else if ( FrontEndMenuManager.m_bWantToLoad == true ) { +#ifdef XBOX_MESSAGE_SCREEN + FrontEndMenuManager.SetDialogTimer(1000); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 0); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + FrontEndMenuManager.DrawOverlays(); + DoRWStuffEndOfFrame(); +#endif RestoreForStartLoad(); - CStreaming::LoadScene(TheCamera.GetPosition()); } -#endif ReInitGameObjectVariables(); -#ifdef PS2_MENU - if ( TheMemoryCard.m_bWantToLoad == true ) - { - if ( TheMemoryCard.LoadSavedGame() == CMemoryCard::RES_SUCCESS ) - { - for ( int32 i = 0; i < 35; i++ ) - { - MessageScreen("FESZ_LS"); // Load Successful. - } - - DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); - CTrain::InitTrains(); - CPlane::InitPlanes(); - } - else - { - for ( int32 i = 0; i < 50; i++ ) - { - DoRWStuffStartOfFrame(50, 50, 50, 0, 0, 0, 255); - - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - DefinedState(); - - CSprite2d *splash = LoadSplash(NULL); - splash->Draw(rect, color, color, color, color); -#ifdef FIX_BUGS - splash->DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(110.0f), SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_Y(300.0f)), CRGBA(50, 50, 50, 192)); -#else - splash->DrawRect(CRect(20.0f, 110.0f, SCREEN_WIDTH-20.0f, 300.0f), CRGBA(50, 50, 50, 192)); -#endif - - CFont::SetBackgroundOff(); -#ifdef ASPECT_RATIO_SCALE - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // because SCREEN_SCALE_FROM_RIGHT(x) != SCREEN_SCALE_X(640-x) -#else - CFont::SetWrapx(SCREEN_SCALE_X(480.0f)); -#endif - CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); - CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(480.0f)); - CFont::SetJustifyOff(); - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetDropColor(CRGBA(32, 32, 32, 255)); - CFont::SetDropShadowPosition(3); - CFont::SetPropOn(); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_WIDTH/2, SCREEN_SCALE_Y(130.0f), TheText.Get("MC_LDFL")); // Load Failed! - CFont::PrintString(SCREEN_WIDTH/2, SCREEN_SCALE_Y(170.0f), TheText.Get("FES_NOC")); // No Memory Card (PS2) in MEMORY CARD slot 1. - CFont::PrintString(SCREEN_WIDTH/2, SCREEN_SCALE_Y(240.0f), TheText.Get("MC_NWRE")); // Now Restarting Game. -#else - CFont::PrintString(SCREEN_WIDTH/2, 130.0f, TheText.Get("MC_LDFL")); // Load Failed! - CFont::PrintString(SCREEN_WIDTH/2, 170.0f, TheText.Get("FES_NOC")); // No Memory Card (PS2) in MEMORY CARD slot 1. - CFont::PrintString(SCREEN_WIDTH/2, 240.0f, TheText.Get("MC_NWRE")); // Now Restarting Game. -#endif - CFont::DrawFonts(); - - DoRWStuffEndOfFrame(); - } - - ShutDownForRestart(); - CTimer::Stop(); - CTimer::Initialise(); - TheMemoryCard.m_bWantToLoad = false; - ReInitGameObjectVariables(); - currLevel = LEVEL_INDUSTRIAL; - CCollision::SortOutCollisionAfterLoad(); - - FrontEndMenuManager.SetSoundLevelsForMusicMenu(); - FrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame(); - } - } -#else if ( FrontEndMenuManager.m_bWantToLoad == true ) { + FrontEndMenuManager.m_bWantToLoad = false; + InitRadioStationPositionList(); if ( GenericLoad() == true ) { DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); @@ -990,23 +814,29 @@ void CGame::InitialiseWhenRestarting(void) for ( int32 i = 0; i < 50; i++ ) { HandleExit(); - FrontEndMenuManager.MessageScreen("FED_LFL"); // Loading save game has failed. The game will restart now. + FrontEndMenuManager.MessageScreen("FED_LFL", true); // Loading save game has failed. The game will restart now. } + TheCamera.SetFadeColour(0, 0, 0); ShutDownForRestart(); CTimer::Stop(); CTimer::Initialise(); FrontEndMenuManager.m_bWantToLoad = false; ReInitGameObjectVariables(); - currLevel = LEVEL_INDUSTRIAL; + currLevel = LEVEL_GENERIC; CCollision::SortOutCollisionAfterLoad(); } - } +#ifdef XBOX_MESSAGE_SCREEN + FrontEndMenuManager.ProcessDialogTimer(); #endif + } CTimer::Update(); DMAudio.ChangeMusicMode(MUSICMODE_GAME); +#ifdef USE_TEXTURE_POOL + _TexturePoolsUnknown(true); +#endif } void CGame::Process(void) @@ -1015,23 +845,35 @@ void CGame::Process(void) #ifdef USE_CUSTOM_ALLOCATOR ProcessTidyUpMemory(); #endif - TheCamera.SetMotionBlurAlpha(0); - if (TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_SNIPER || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) - TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE); #ifdef DEBUGMENU DebugMenuProcess(); #endif CCutsceneMgr::Update(); - PUSH_MEMID(MEMID_FRONTEND); if (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused()) FrontEndMenuManager.Process(); - POP_MEMID(); + CTheZones::Update(); +#ifdef SECUROM + if (CTimer::GetTimeInMilliseconds() >= (35 * 60 * 1000) && gameProcessPirateCheck == 0){ + // if game not pirated + // gameProcessPirateCheck = 1; + // else + gameProcessPirateCheck = 2; + } +#endif + uint32 startTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); CStreaming::Update(); + uint32 processTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond() - startTime; + CWindModifiers::Number = 0; if (!CTimer::GetIsPaused()) { - CTheZones::Update(); +#ifndef MASTER + if (VarUpdatePlayerCoords) { + FindPlayerPed()->Teleport(PlayerCoords); + VarUpdatePlayerCoords = false; + } +#endif CSprite2d::SetRecipNearClip(); CSprite2d::InitPerFrame(); CFont::InitPerFrame(); @@ -1046,6 +888,7 @@ void CGame::Process(void) POP_MEMID(); CCollision::Update(); + CScriptPaths::Update(); CTrain::UpdateTrains(); CPlane::UpdatePlanes(); CHeli::UpdateHelis(); @@ -1056,10 +899,23 @@ void CGame::Process(void) #ifdef GTA_SCENE_EDIT CSceneEdit::Update(); #endif + CSetPieces::Update(); CEventList::Update(); CParticle::Update(); gFireManager.Update(); - CPopulation::Update(); + + // Otherwise even on 30 fps most probably you won't see any peds around Ocean View Hospital +#if defined FIX_BUGS && !defined SQUEEZE_PERFORMANCE + if (processTime > 2) { +#else + if (processTime >= 2) { +#endif + CPopulation::Update(false); + } else { + uint32 startTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); + CPopulation::Update(true); + processTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond() - startTime; + } CWeapon::UpdateWeapons(); if (!CCutsceneMgr::IsRunning()) CTheCarGenerators::Process(); @@ -1081,6 +937,7 @@ void CGame::Process(void) CGarages::Update(); CRubbish::Update(); CSpecialFX::Update(); + CRopes::Update(); CTimeCycle::Update(); if (CReplay::ShouldStandardCameraBeProcessed()) TheCamera.Process(); @@ -1096,9 +953,11 @@ void CGame::Process(void) if (!CReplay::IsPlayingBack()) { PUSH_MEMID(MEMID_CARS); - CCarCtrl::GenerateRandomCars(); + if (processTime < 2) + CCarCtrl::GenerateRandomCars(); CRoadBlocks::GenerateRoadBlocks(); CCarCtrl::RemoveDistantCars(); + CCarCtrl::RemoveCarsIfThePoolGetsFull(); POP_MEMID(); } } @@ -1109,15 +968,17 @@ void CGame::Process(void) #ifdef USE_CUSTOM_ALLOCATOR +// TODO(MIAMI) + int32 gNumMemMoved; bool -MoveMem(void **ptr) +MoveMem(void** ptr) { - if(*ptr){ + if (*ptr) { gNumMemMoved++; - void *newPtr = gMainHeap.MoveMemory(*ptr); - if(*ptr != newPtr){ + void* newPtr = gMainHeap.MoveMemory(*ptr); + if (*ptr != newPtr) { *ptr = newPtr; return true; } @@ -1147,21 +1008,21 @@ struct DMAGIFUpload }; // This is very scary. it depends on the exact memory layout of the DMA chains and whatnot -RwTexture * -MoveTextureMemoryCB(RwTexture *texture, void *pData) +RwTexture* +MoveTextureMemoryCB(RwTexture* texture, void* pData) { #ifdef GTA_PS2 - bool *pRet = (bool*)pData; - RwRaster *raster = RwTextureGetRaster(texture); - _SkyRasterExt *rasterExt = RASTEREXTFROMRASTER(raster); - if(raster->originalPixels == nil || // the raw data - raster->cpPixels == raster->originalPixels || // old format, can't handle it - rasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0) + bool* pRet = (bool*)pData; + RwRaster* raster = RwTextureGetRaster(texture); + _SkyRasterExt* rasterExt = RASTEREXTFROMRASTER(raster); + if (raster->originalPixels == nil || // the raw data + raster->cpPixels == raster->originalPixels || // old format, can't handle it + rasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0) return texture; // this is the allocated pointer we will move - SkyDataPrefix *prefix = (SkyDataPrefix*)raster->originalPixels; - DMAGIFUpload *uploads = (DMAGIFUpload*)(prefix+1); + SkyDataPrefix* prefix = (SkyDataPrefix*)raster->originalPixels; + DMAGIFUpload* uploads = (DMAGIFUpload*)(prefix + 1); // We have 4qw for each upload, // i.e. for each buffer width of mip levels, @@ -1178,24 +1039,24 @@ MoveTextureMemoryCB(RwTexture *texture, void *pData) uintptr dataDiff, upload1Diff, upload2Diff, pixelDiff, paletteDiff; dataDiff = prefix->data - (uintptr)raster->originalPixels; upload1Diff = uploads[0].tag2_addr - (uintptr)raster->originalPixels; - if(raster->palette) + if (raster->palette) upload2Diff = uploads[1].tag2_addr - (uintptr)raster->originalPixels; pixelDiff = (uintptr)raster->cpPixels - (uintptr)raster->originalPixels; - if(raster->palette) + if (raster->palette) paletteDiff = (uintptr)raster->palette - (uintptr)raster->originalPixels; - uint8 *newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels); - if(newptr != raster->originalPixels){ + uint8* newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels); + if (newptr != raster->originalPixels) { // adjust everything prefix->data = (uintptr)newptr + dataDiff; uploads[0].tag2_addr = (uintptr)newptr + upload1Diff; - if(raster->palette) + if (raster->palette) uploads[1].tag2_addr = (uintptr)newptr + upload2Diff; raster->originalPixels = newptr; raster->cpPixels = newptr + pixelDiff; - if(raster->palette) + if (raster->palette) raster->palette = newptr + paletteDiff; - if(pRet){ + if (pRet) { *pRet = true; return nil; } @@ -1207,42 +1068,42 @@ MoveTextureMemoryCB(RwTexture *texture, void *pData) } bool -MoveAtomicMemory(RpAtomic *atomic, bool onlyOne) +MoveAtomicMemory(RpAtomic* atomic, bool onlyOne) { - RpGeometry *geo = RpAtomicGetGeometry(atomic); + RpGeometry* geo = RpAtomicGetGeometry(atomic); #if THIS_IS_COMPATIBLE_WITH_GTA3_RW31 - if(MoveMem((void**)&geo->triangles) && onlyOne) + if (MoveMem((void**)&geo->triangles) && onlyOne) return true; - if(MoveMem((void**)&geo->matList.materials) && onlyOne) + if (MoveMem((void**)&geo->matList.materials) && onlyOne) return true; - if(MoveMem((void**)&geo->preLitLum) && onlyOne) + if (MoveMem((void**)&geo->preLitLum) && onlyOne) return true; - if(MoveMem((void**)&geo->texCoords[0]) && onlyOne) + if (MoveMem((void**)&geo->texCoords[0]) && onlyOne) return true; - if(MoveMem((void**)&geo->texCoords[1]) && onlyOne) + if (MoveMem((void**)&geo->texCoords[1]) && onlyOne) return true; // verts and normals of morph target are allocated together int vertDiff; - if(geo->morphTarget->normals) + if (geo->morphTarget->normals) vertDiff = geo->morphTarget->normals - geo->morphTarget->verts; - if(MoveMem((void**)&geo->morphTarget->verts)){ - if(geo->morphTarget->normals) + if (MoveMem((void**)&geo->morphTarget->verts)) { + if (geo->morphTarget->normals) geo->morphTarget->normals = geo->morphTarget->verts + vertDiff; - if(onlyOne) + if (onlyOne) return true; } - RpMeshHeader *oldmesh = geo->mesh; - if(MoveMem((void**)&geo->mesh)){ + RpMeshHeader* oldmesh = geo->mesh; + if (MoveMem((void**)&geo->mesh)) { // index pointers are allocated together with meshes, // have to relocate those too - RpMesh *mesh = (RpMesh*)(geo->mesh+1); + RpMesh* mesh = (RpMesh*)(geo->mesh + 1); uintptr reloc = (uintptr)geo->mesh - (uintptr)oldmesh; - for(int i = 0; i < geo->mesh->numMeshes; i++) + for (int i = 0; i < geo->mesh->numMeshes; i++) mesh[i].indices = (RxVertexIndex*)((uintptr)mesh[i].indices + reloc); - if(onlyOne) + if (onlyOne) return true; } #else @@ -1252,37 +1113,37 @@ MoveAtomicMemory(RpAtomic *atomic, bool onlyOne) } bool -MoveColModelMemory(CColModel &colModel, bool onlyOne) +MoveColModelMemory(CColModel& colModel, bool onlyOne) { #if GTA_VERSION >= GTA3_PS2_160 // hm...should probably only do this if ownsCollisionVolumes // but it doesn't exist on PS2... - if(!colModel.ownsCollisionVolumes) + if (!colModel.ownsCollisionVolumes) return false; #endif - if(MoveMem((void**)&colModel.spheres) && onlyOne) + if (MoveMem((void**)&colModel.spheres) && onlyOne) return true; - if(MoveMem((void**)&colModel.lines) && onlyOne) + if (MoveMem((void**)&colModel.lines) && onlyOne) return true; - if(MoveMem((void**)&colModel.boxes) && onlyOne) + if (MoveMem((void**)&colModel.boxes) && onlyOne) return true; - if(MoveMem((void**)&colModel.vertices) && onlyOne) + if (MoveMem((void**)&colModel.vertices) && onlyOne) return true; - if(MoveMem((void**)&colModel.triangles) && onlyOne) + if (MoveMem((void**)&colModel.triangles) && onlyOne) return true; - if(MoveMem((void**)&colModel.trianglePlanes) && onlyOne) + if (MoveMem((void**)&colModel.trianglePlanes) && onlyOne) return true; return false; } RpAtomic* -MoveAtomicMemoryCB(RpAtomic *atomic, void *pData) +MoveAtomicMemoryCB(RpAtomic* atomic, void* pData) { - bool *pRet = (bool*)pData; - if(pRet == nil) + bool* pRet = (bool*)pData; + if (pRet == nil) MoveAtomicMemory(atomic, false); - else if(MoveAtomicMemory(atomic, true)){ + else if (MoveAtomicMemory(atomic, true)) { *pRet = true; return nil; } @@ -1290,34 +1151,35 @@ MoveAtomicMemoryCB(RpAtomic *atomic, void *pData) } bool -TidyUpModelInfo(CBaseModelInfo *modelInfo, bool onlyone) +TidyUpModelInfo(CBaseModelInfo* modelInfo, bool onlyone) { - if(modelInfo->GetColModel() && modelInfo->DoesOwnColModel()) - if(MoveColModelMemory(*modelInfo->GetColModel(), onlyone)) + if (modelInfo->GetColModel() && modelInfo->DoesOwnColModel()) + if (MoveColModelMemory(*modelInfo->GetColModel(), onlyone)) return true; - RwObject *rwobj = modelInfo->GetRwObject(); - if(RwObjectGetType(rwobj) == rpATOMIC) - if(MoveAtomicMemory((RpAtomic*)rwobj, onlyone)) + RwObject* rwobj = modelInfo->GetRwObject(); + if (RwObjectGetType(rwobj) == rpATOMIC) + if (MoveAtomicMemory((RpAtomic*)rwobj, onlyone)) return true; - if(RwObjectGetType(rwobj) == rpCLUMP){ + if (RwObjectGetType(rwobj) == rpCLUMP) { bool ret = false; - if(onlyone) + if (onlyone) RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, &ret); else RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, nil); - if(ret) + if (ret) return true; } - if(modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel) - if(MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone)) + if (modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel) + if (MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone)) return true; return false; } #endif + void CGame::DrasticTidyUpMemory(bool flushDraw) { #ifdef USE_CUSTOM_ALLOCATOR @@ -1325,32 +1187,32 @@ void CGame::DrasticTidyUpMemory(bool flushDraw) TidyUpMemory(true, flushDraw); - if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){ + if (gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro) { CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); TidyUpMemory(true, flushDraw); } - if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){ + if (gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro) { CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC); TidyUpMemory(true, flushDraw); removedCol = true; } - if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){ + if (gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro) { CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL); CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL); CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN); TidyUpMemory(true, flushDraw); } - if(removedCol){ + if (removedCol) { // different on PS2 CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory); } - if(!playingIntro) + if (!playingIntro) CStreaming::RequestBigBuildings(currLevel); CStreaming::LoadAllRequestedModels(true); @@ -1362,49 +1224,49 @@ void CGame::TidyUpMemory(bool moveTextures, bool flushDraw) #ifdef USE_CUSTOM_ALLOCATOR printf("Largest free block before tidy %d\n", gMainHeap.GetLargestFreeBlock()); - if(moveTextures){ - if(flushDraw){ + if (moveTextures) { + if (flushDraw) { #ifdef GTA_PS2 - for(int i = 0; i < sweMaxFlips+1; i++){ + for (int i = 0; i < sweMaxFlips + 1; i++) { #else - for(int i = 0; i < 5; i++){ // probably more than needed + for (int i = 0; i < 5; i++) { // probably more than needed #endif RwCameraBeginUpdate(Scene.camera); RwCameraEndUpdate(Scene.camera); RwCameraShowRaster(Scene.camera, nil, 0); } - } + } int fontSlot = CTxdStore::FindTxdSlot("fonts"); - for(int i = 0; i < TXDSTORESIZE; i++){ - if(i == fontSlot || - CTxdStore::GetSlot(i) == nil) + for (int i = 0; i < TXDSTORESIZE; i++) { + if (i == fontSlot || + CTxdStore::GetSlot(i) == nil) continue; - RwTexDictionary *txd = CTxdStore::GetSlot(i)->texDict; - if(txd) + RwTexDictionary* txd = CTxdStore::GetSlot(i)->texDict; + if (txd) RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, nil); } - } + } // animations - for(int i = 0; i < NUMANIMATIONS; i++){ - CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(i); - if(anim == nil) + for (int i = 0; i < NUMANIMATIONS; i++) { + CAnimBlendHierarchy* anim = CAnimManager::GetAnimation(i); + if (anim == nil) continue; // cannot happen anim->MoveMemory(); } // model info - for(int i = 0; i < MODELINFOSIZE; i++){ - CBaseModelInfo *mi = CModelInfo::GetModelInfo(i); - if(mi == nil) + for (int i = 0; i < MODELINFOSIZE; i++) { + CBaseModelInfo* mi = CModelInfo::GetModelInfo(i); + if (mi == nil) continue; TidyUpModelInfo(mi, false); } printf("Largest free block after tidy %d\n", gMainHeap.GetLargestFreeBlock()); #endif -} + } void CGame::ProcessTidyUpMemory(void) { @@ -1413,52 +1275,76 @@ void CGame::ProcessTidyUpMemory(void) static int32 animIndex = 0; static int32 txdIndex = 0; bool txdReturn = false; - RwTexDictionary *txd = nil; + RwTexDictionary* txd = nil; gNumMemMoved = 0; // model infos - for(int numCleanedUp = 0; numCleanedUp < 10; numCleanedUp++){ - CBaseModelInfo *mi; - do{ + for (int numCleanedUp = 0; numCleanedUp < 10; numCleanedUp++) { + CBaseModelInfo* mi; + do { mi = CModelInfo::GetModelInfo(modelIndex); modelIndex++; - if(modelIndex >= MODELINFOSIZE) + if (modelIndex >= MODELINFOSIZE) modelIndex = 0; - }while(mi == nil); + } while (mi == nil); - if(TidyUpModelInfo(mi, true)) + if (TidyUpModelInfo(mi, true)) return; } // tex dicts - for(int numCleanedUp = 0; numCleanedUp < 3; numCleanedUp++){ - if(gNumMemMoved > 80) + for (int numCleanedUp = 0; numCleanedUp < 3; numCleanedUp++) { + if (gNumMemMoved > 80) break; - do{ + do { #ifdef FIX_BUGS txd = nil; #endif - if(CTxdStore::GetSlot(txdIndex)) + if (CTxdStore::GetSlot(txdIndex)) txd = CTxdStore::GetSlot(txdIndex)->texDict; txdIndex++; - if(txdIndex >= TXDSTORESIZE) + if (txdIndex >= TXDSTORESIZE) txdIndex = 0; - }while(txd == nil); + } while (txd == nil); RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, &txdReturn); - if(txdReturn) + if (txdReturn) return; - } + } // animations - CAnimBlendHierarchy *anim; - do{ + CAnimBlendHierarchy* anim; + do { anim = CAnimManager::GetAnimation(animIndex); animIndex++; - if(animIndex >= NUMANIMATIONS) + if (animIndex >= NUMANIMATIONS) animIndex = 0; - }while(anim == nil); // always != nil + } while (anim == nil); // always != nil anim->MoveMemory(true); #endif } + +void +CGame::InitAfterFocusLoss() +{ + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = FrontEndMenuManager.m_lastWorking3DAudioProvider; + DMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_lastWorking3DAudioProvider); + + if (!FrontEndMenuManager.m_bGameNotLoaded && !FrontEndMenuManager.m_bMenuActive) + FrontEndMenuManager.m_bStartUpFrontEndRequested = true; +} + +bool +CGame::CanSeeWaterFromCurrArea(void) +{ + return currArea == AREA_MAIN_MAP || currArea == AREA_MANSION + || currArea == AREA_HOTEL; +} + +bool +CGame::CanSeeOutSideFromCurrArea(void) +{ + return currArea == AREA_MAIN_MAP || currArea == AREA_MALL || + currArea == AREA_MANSION || currArea == AREA_HOTEL; +} diff --git a/src/core/Game.h b/src/core/Game.h index 002033a0..4052eb00 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -3,16 +3,39 @@ enum eLevelName { LEVEL_IGNORE = -1, // beware, this is only used in CPhysical's m_nZoneLevel LEVEL_GENERIC = 0, - LEVEL_INDUSTRIAL, - LEVEL_COMMERCIAL, - LEVEL_SUBURBAN, + LEVEL_BEACH, + LEVEL_MAINLAND, + NUM_LEVELS }; +enum eAreaName { + AREA_MAIN_MAP, + AREA_HOTEL, + AREA_MANSION, + AREA_BANK, + AREA_MALL, + AREA_STRIP_CLUB, + AREA_LAWYERS, + AREA_COFFEE_SHOP, + AREA_CONCERT_HALL, + AREA_STUDIO, + AREA_RIFLE_RANGE, + AREA_BIKER_BAR, + AREA_POLICE_STATION, + AREA_EVERYWHERE, + AREA_DIRT, + AREA_BLOOD, + AREA_OVALRING, + AREA_MALIBU_CLUB, + AREA_PRINT_WORKS +}; + class CGame { public: static eLevelName currLevel; + static int32 currArea; static bool bDemoMode; static bool nastyGame; static bool frenchGame; @@ -25,25 +48,34 @@ public: static bool playingIntro; static char aDatFile[32]; +#ifndef MASTER + static CVector PlayerCoords; + static bool8 VarUpdatePlayerCoords; +#endif + static bool InitialiseOnceBeforeRW(void); static bool InitialiseRenderWare(void); static void ShutdownRenderWare(void); static bool InitialiseOnceAfterRW(void); static void FinalShutdown(void); -#if GTA_VERSION <= GTA3_PS2_160 - static bool Initialise(void); -#else static bool Initialise(const char *datFile); -#endif static bool ShutDown(void); static void ReInitGameObjectVariables(void); static void ReloadIPLs(void); static void ShutDownForRestart(void); static void InitialiseWhenRestarting(void); static void Process(void); + + static void InitAfterFocusLoss(void); + + static bool IsInInterior(void) { return currArea != AREA_MAIN_MAP; } + static bool CanSeeWaterFromCurrArea(void); + static bool CanSeeOutSideFromCurrArea(void); // NB: these do something on PS2 static void TidyUpMemory(bool, bool); static void DrasticTidyUpMemory(bool); static void ProcessTidyUpMemory(void); }; + +inline bool IsAreaVisible(int area) { return area == CGame::currArea || area == AREA_EVERYWHERE; } diff --git a/src/core/General.h b/src/core/General.h index d4b941dd..c17d916d 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -143,6 +143,18 @@ public: return *str2 != '\0'; } + static bool SolveQuadratic(float a, float b, float c, float &root1, float &root2) + { + float discriminant = b * b - 4.f * a * c; + if (discriminant < 0.f) + return false; + + float discriminantSqrt = Sqrt(discriminant); + root2 = (-b + discriminantSqrt) / (2.f * a); + root1 = (-b - discriminantSqrt) / (2.f * a); + return true; + } + // not too sure about all these... static uint16 GetRandomNumber(void) { return myrand() & MYRAND_MAX; } @@ -154,4 +166,6 @@ public: static int32 GetRandomNumberInRange(int32 low, int32 high) { return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); } + static void SetRandomSeed(int32 seed) + { mysrand(seed); } }; diff --git a/src/core/IniFile.cpp b/src/core/IniFile.cpp index 524632fe..5d343ec9 100644 --- a/src/core/IniFile.cpp +++ b/src/core/IniFile.cpp @@ -7,8 +7,8 @@ #include "main.h" #include "Population.h" -float CIniFile::PedNumberMultiplier = 1.0f; -float CIniFile::CarNumberMultiplier = 1.0f; +float CIniFile::PedNumberMultiplier = 0.6f; +float CIniFile::CarNumberMultiplier = 0.6f; void CIniFile::LoadIniFile() { @@ -24,5 +24,6 @@ void CIniFile::LoadIniFile() CFileMgr::CloseFile(f); } CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * PedNumberMultiplier; + CPopulation::MaxNumberOfPedsInUseInterior = DEFAULT_MAX_NUMBER_OF_PEDS_INTERIOR * PedNumberMultiplier; CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS * CarNumberMultiplier; }
\ No newline at end of file diff --git a/src/core/IniFile.h b/src/core/IniFile.h index 30dc8c21..dcaed980 100644 --- a/src/core/IniFile.h +++ b/src/core/IniFile.h @@ -1,6 +1,7 @@ #pragma once #define DEFAULT_MAX_NUMBER_OF_PEDS 25.0f +#define DEFAULT_MAX_NUMBER_OF_PEDS_INTERIOR 40.0f #define DEFAULT_MAX_NUMBER_OF_CARS 12.0f class CIniFile diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp index 3bd9adf4..3ffc4e83 100644 --- a/src/core/MenuScreens.cpp +++ b/src/core/MenuScreens.cpp @@ -6,443 +6,341 @@ // Check MenuScreensCustom.cpp #ifndef CUSTOM_FRONTEND_OPTIONS -CMenuScreen aScreens[MENUPAGES] = { - // MENUPAGE_NONE = 0 - { "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, }, - - // MENUPAGE_STATS = 1 - { "FET_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_NEW_GAME = 2 - { "FET_SGA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 0, 1, - MENUACTION_CHANGEMENU, "FES_SNG", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, - MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, - MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_BRIEFS = 3 - { "FET_BRE", 1, MENUPAGE_NONE, MENUPAGE_NONE, 6, 3, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_CONTROLLER_SETTINGS = 4 - { "FET_CON", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, - MENUACTION_CTRLCONFIG, "FEC_CCF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, - MENUACTION_CTRLDISPLAY, "FEC_CDP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, - MENUACTION_CTRLVIBRATION, "FEC_VIB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_SOUND_SETTINGS = 5 - { "FET_AUD", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 1, 1, - MENUACTION_MUSICVOLUME, "FEA_MUS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_SFXVOLUME, "FEA_SFX", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_AUDIOHW, "FEA_3DH", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_SPEAKERCONF, "FEA_SPK", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_DYNAMICACOUSTIC, "FET_DAM", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_RADIO, "FEA_RSS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_DISPLAY_SETTINGS = 6 - { "FET_DIS", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2, - MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_LANGUAGE_SETTINGS = 7 - { "FET_LAN", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 3, 3, - MENUACTION_LANG_ENG, "FEL_ENG", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, - MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, - MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, - MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, - MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, +CMenuScreen aScreens[] = { + // MENUPAGE_STATS = 0 + { "FEH_STA", MENUPAGE_NONE, 3, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT, }, - // MENUPAGE_CHOOSE_LOAD_SLOT = 8 - { "FET_LG", 1, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 1, 1, - MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_CHECKSAVE, "FEM_SL0", SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM, - MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM, + // MENUPAGE_NEW_GAME = 1 + { "FEP_STG", MENUPAGE_NONE, 1, + MENUACTION_CHANGEMENU, "FES_NGA", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, 320, 155, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FES_LOA", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FES_DEL", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_CHOOSE_DELETE_SLOT = 9 - { "FET_DG", 1, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 2, 2, - MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_CHANGEMENU, "FEM_SL0", SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM, + // MENUPAGE_BRIEFS = 2 + { "FEH_BRI", MENUPAGE_NONE, 4, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT, }, - // MENUPAGE_NEW_GAME_RELOAD = 10 - { "FET_NG", 1, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, 0, 0, - MENUACTION_LABEL, "FESZ_QR", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_NEWGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, + // MENUPAGE_SOUND_SETTINGS = 3 + { "FEH_AUD", MENUPAGE_OPTIONS, 1, + MENUACTION_MUSICVOLUME, "FEA_MUS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 40, 76, MENUALIGN_LEFT, + MENUACTION_SFXVOLUME, "FEA_SFX", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT, + MENUACTION_MP3VOLUMEBOOST, "FEA_MPB", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT, + MENUACTION_AUDIOHW, "FEA_3DH", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT, + MENUACTION_SPEAKERCONF, "FEA_SPK", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT, + MENUACTION_DYNAMICACOUSTIC, "FET_DAM", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT, + MENUACTION_RADIO, "FEA_RSS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 320, 367, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_LOAD_SLOT_CONFIRM = 11 - { "FET_LG", 1, MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, 0, 0, - MENUACTION_LABEL, "FESZ_QL", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, - MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS, - }, + // MENUPAGE_DISPLAY_SETTINGS = 4 +#ifdef LEGACY_MENU_OPTIONS + #define Y_OFFSET 50 +#else + #define Y_OFFSET 0 +#endif - // MENUPAGE_DELETE_SLOT_CONFIRM = 12 - { "FET_DG", 1, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, - MENUACTION_LABEL, "FESZ_QD", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, - MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_DELETING, + { "FEH_DIS", MENUPAGE_OPTIONS, 2, + MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 78, MENUALIGN_LEFT, + MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 103, MENUALIGN_LEFT, +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 128, MENUALIGN_LEFT, +#endif + MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 128 + Y_OFFSET/2, MENUALIGN_LEFT, +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 178, MENUALIGN_LEFT, +#endif + MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 153 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 178 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_LEGENDS, "MAP_LEG", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 202 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_RADARMODE, "FED_RDR", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 228 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_HUD, "FED_HUD", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 253 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 278 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 320, 303 + Y_OFFSET, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 320, 328 + Y_OFFSET, MENUALIGN_CENTER, }, - // MENUPAGE_NO_MEMORY_CARD = 13 - { "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - // hud adjustment page in mobile +#undef Y_OFFSET + + // MENUPAGE_LANGUAGE_SETTINGS = 5 + { "FEH_LAN", MENUPAGE_OPTIONS, 3, + MENUACTION_LANG_ENG, "FEL_ENG", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 320, 132, MENUALIGN_CENTER, + MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_LOADING_IN_PROGRESS = 14 - { "FET_LG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FED_LDW", SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM, + // MENUPAGE_MAP = 6 + { "FEH_MAP", MENUPAGE_NONE, 2, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 70, 380, MENUALIGN_CENTER, }, - // MENUPAGE_DELETING_IN_PROGRESS = 15 - { "FET_DG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FEDL_WR", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_NEW_GAME_RELOAD = 7 + { "FES_NGA", MENUPAGE_NEW_GAME, 0, + MENUACTION_LABEL, "FESZ_QR", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_NO, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NEW_GAME, 320, 200, MENUALIGN_CENTER, + MENUACTION_NEWGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_PS2_LOAD_FAILED = 16 - { "FET_LG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FES_LOE", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_CHOOSE_LOAD_SLOT = 8 + { "FET_LG", MENUPAGE_NEW_GAME, 1, + MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, 0, 40, 90, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 320, 345, MENUALIGN_CENTER, }, - // MENUPAGE_DELETE_FAILED = 17 - { "FET_DG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FES_DEE", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, + // MENUPAGE_CHOOSE_DELETE_SLOT = 9 + { "FES_DEL", MENUPAGE_NEW_GAME, 2, + MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, 0, 40, 90, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8, 0, 0, 0, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 320, 345, MENUALIGN_CENTER, }, - // MENUPAGE_DEBUG_MENU = 18 - { "FED_DBG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 4, 0, - MENUACTION_RELOADIDE, "FED_RID", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_RELOADIPL, "FED_RIP", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_SETDBGFLAG, "FED_DFL", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_PEDROADGROUPS, "FED_SPR", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CARROADGROUPS, "FED_SCR", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_COLLISIONPOLYS, "FED_SCP", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_PARSEHEAP, "FED_PAH", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_SHOWCULL, "FED_SCZ", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_DEBUGSTREAM, "FED_DSR", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_LOAD_SLOT_CONFIRM = 10 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, 0, + MENUACTION_LABEL, "FESZ_QL", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_NO, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, 320, 200, MENUALIGN_CENTER, + MENUACTION_YES, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_MEMORY_CARD_DEBUG = 19 - { "FEM_MCM", 1, MENUPAGE_NONE, MENUPAGE_NONE, 7, 0, - MENUACTION_REGMEMCARD1, "FEM_RMC", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_TESTFORMATMEMCARD1, "FEM_TFM", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_TESTUNFORMATMEMCARD1, "FEM_TUM", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CREATEROOTDIR, "FEM_CRD", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CREATELOADICONS, "FEM_CLI", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_FILLWITHGUFF, "FEM_FFF", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_SAVEONLYTHEGAME, "FEM_SOG", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_SAVEGAME, "FEM_STG", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_SAVEGAMEUNDERGTA, "FEM_STS", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CREATECOPYPROTECTED, "FEM_CPD", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_DELETE_SLOT_CONFIRM = 11 + { "FES_DEL", MENUPAGE_CHOOSE_DELETE_SLOT, 0, + MENUACTION_LABEL, "FESZ_QD", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_NO, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, 320, 200, MENUALIGN_CENTER, + MENUACTION_YES, "FEM_YES", SAVESLOT_NONE, MENUPAGE_DELETING_IN_PROGRESS, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_MEMORY_CARD_TEST = 20 - { "FEM_MC2", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_LOADING_IN_PROGRESS = 12 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, 0, + }, + // MENUPAGE_DELETING_IN_PROGRESS = 13 + { "FES_DEL", MENUPAGE_CHOOSE_DELETE_SLOT, 0, }, - // MENUPAGE_MULTIPLAYER_MAIN = 21 - { "FET_MP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_DELETE_SUCCESSFUL = 14 + { "FES_DEL", MENUPAGE_NEW_GAME, 0, + MENUACTION_LABEL, "FES_DSC", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_OK", SAVESLOT_NONE, MENUPAGE_NEW_GAME, 320, 225, MENUALIGN_CENTER, + }, + // MENUPAGE_CHOOSE_SAVE_SLOT = 15 + { "FET_SG", MENUPAGE_DISABLED, 0, + MENUACTION_SAVEGAME, "FEM_SL1", SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 40, 90, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL2", SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL3", SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL4", SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL5", SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL6", SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL7", SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL8", SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT, + MENUACTION_RESUME_FROM_SAVEZONE,"FESZ_CA", SAVESLOT_NONE, 0, 320, 345, MENUALIGN_CENTER, }, - // MENUPAGE_PS2_SAVE_FAILED = 22 - { "MCDNSP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 16 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, 0, + MENUACTION_LABEL, "FESZ_QZ", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_NO, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 320, 200, MENUALIGN_CENTER, + MENUACTION_YES, "FEM_YES", SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_PS2_SAVE_FAILED_2 = 23 - { "MCGNSP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_SAVING_IN_PROGRESS = 17 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, 0, }, - // Unused in PC but anyway - // MENUPAGE_SAVE = 24 -#ifdef PS2_SAVE_DIALOG - { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_CHANGEMENU, "FESZ_SA", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_SAVE_SUCCESSFUL = 18 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, 0, + MENUACTION_LABEL, "FES_SSC", SAVESLOT_LABEL, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_RESUME_FROM_SAVEZONE, "FEM_OK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 320, 225, MENUALIGN_CENTER, }, -#else - { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FES_SCG", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, + + // MENUPAGE_SAVE_CUSTOM_WARNING = 19 + { "FET_SG", MENUPAGE_NONE, 0, + MENUACTION_LABEL, "", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_OK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 320, 225, MENUALIGN_CENTER, }, -#endif - // MENUPAGE_NO_MEMORY_CARD_2 = 25 - { "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_SAVE_CHEAT_WARNING = 20 + { "FET_SG", MENUPAGE_NEW_GAME, 0, + MENUACTION_LABEL, "FES_CHE", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_OK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_CHOOSE_SAVE_SLOT = 26 - { "FET_SG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_SL1", SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL2", SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL3", SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL4", SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL5", SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL6", SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL7", SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM, - MENUACTION_CHANGEMENU, "FEM_SL8", SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM, + // MENUPAGE_SKIN_SELECT = 21 + { "FET_PS", MENUPAGE_OPTIONS, 4, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_OPTIONS, 0, 0, 0, }, - // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27 - { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, - MENUACTION_LABEL, "FESZ_QO", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS, - MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, + // MENUPAGE_SAVE_UNUSED = 22 + { "FET_SG", MENUPAGE_NEW_GAME, 0, + MENUACTION_LABEL, "FED_LWR", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_MAP = 28 - { "FET_MAP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_SAVE_FAILED = 23 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, 0, + MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, 0, + }, + // MENUPAGE_SAVE_FAILED_2 = 24 + { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, 0, + MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, 0, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_CONNECTION = 29 - { "FET_CON", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_LOAD_FAILED = 25 + { "FET_LG", MENUPAGE_NEW_GAME, 0, + MENUACTION_LABEL, "FEC_LUN", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NEW_GAME, 0, 0, 0, + }, + // MENUPAGE_CONTROLLER_PC = 26 + { "FET_CTL", MENUPAGE_OPTIONS, 0, +#ifdef PC_PLAYER_CONTROLS + MENUACTION_CTRLMETHOD, "FET_STI", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 320, 150, MENUALIGN_CENTER, + MENUACTION_KEYBOARDCTRLS,"FEC_RED", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 0, 0, MENUALIGN_CENTER, +#else + MENUACTION_KEYBOARDCTRLS,"FEC_RED", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 320, 150, MENUALIGN_CENTER, +#endif + MENUACTION_CHANGEMENU, "FEC_MOU", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_CENTER, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER, + }, + + // MENUPAGE_OPTIONS = 27 + { "FET_OPT", MENUPAGE_NONE, 5, + MENUACTION_CHANGEMENU, "FEO_CON", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 320, 132, MENUALIGN_CENTER, + MENUACTION_LOADRADIO, "FEO_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEO_DIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEO_LAN", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER, + MENUACTION_PLAYERSETUP, "FET_PS", SAVESLOT_NONE, MENUPAGE_SKIN_SELECT, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_MULTIPLAYER_FIND_GAME = 30 - { "FET_FG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_EXIT = 28 + { "FET_QG", MENUPAGE_NONE, 6, + MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, 0, 0, 0, 0, + MENUACTION_DONTCANCEL, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, 320, 200, MENUALIGN_CENTER, + MENUACTION_CANCELGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE, 320, 225, MENUALIGN_CENTER, + }, + // MENUPAGE_START_MENU = 29 + { "FEM_MM", MENUPAGE_DISABLED, 0, + MENUACTION_CHANGEMENU, "FEP_STG", SAVESLOT_NONE, MENUPAGE_NEW_GAME, 320, 170, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_QUI", SAVESLOT_NONE, MENUPAGE_EXIT, 0, 0, MENUALIGN_CENTER, + }, + + // MENUPAGE_KEYBOARD_CONTROLS = 30 + { "FET_STI", MENUPAGE_CONTROLLER_PC, 1, }, - // MENUPAGE_MULTIPLAYER_MODE = 31 - { "FET_GT", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_MOUSE_CONTROLS = 31 + { "FEC_MOU", MENUPAGE_CONTROLLER_PC, 2, + MENUACTION_MOUSESENS, "FEC_MSH", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 40, 170, MENUALIGN_LEFT, + MENUACTION_INVVERT, "FEC_IVV", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_LEFT, + MENUACTION_MOUSESTEER, "FET_MST", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, 0, 320, 260, MENUALIGN_CENTER, + }, + // MENUPAGE_PAUSE_MENU = 32 + { "FET_PAU", MENUPAGE_DISABLED, 0, + MENUACTION_RESUME, "FEP_RES", SAVESLOT_NONE, 0, 320, 120, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEH_SGA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEH_MAP", SAVESLOT_NONE, MENUPAGE_MAP, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEH_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_QUI", SAVESLOT_NONE, MENUPAGE_EXIT, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_MULTIPLAYER_CREATE = 32 - { "FET_HG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_NONE = 33 + { "", 0, 0, }, +#ifdef LEGACY_MENU_OPTIONS + // MENUPAGE_DEBUG_MENU + { "FED_DBG", MENUPAGE_NONE, 0, + MENUACTION_RELOADIDE, "FED_RID", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_SETDBGFLAG, "FED_DFL", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_COLLISIONPOLYS, "FED_SCP", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, }, + + // MENUPAGE_CONTROLLER_PC_OLD1 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, 0, + MENUACTION_GETKEY, "FEC_PLB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_CWL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_CWR", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_LKT", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_PJP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_PSP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TLF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TRG", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GETKEY, "FEC_CCM", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + }, + + // MENUPAGE_CONTROLLER_PC_OLD2 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, 1, - // MENUPAGE_MULTIPLAYER_START = 33 - { "FEN_STA", 2, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + }, + // MENUPAGE_CONTROLLER_PC_OLD3 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, 2, + MENUACTION_GETKEY, "FEC_LUP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0, + MENUACTION_GETKEY, "FEC_LDN", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0, + MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0, + MENUACTION_SHOWHEADBOB, "FEC_GSL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, }, - // MENUPAGE_SKIN_SELECT_OLD = 34 - { "FET_PS", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_CONTROLLER_PC_OLD4 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, 3, }, - // MENUPAGE_CONTROLLER_PC = 35 - { "FET_CTL", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, -#ifdef PC_PLAYER_CONTROLS - MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, + // MENUPAGE_CONTROLLER_DEBUG + { "FEC_DBG", MENUPAGE_CONTROLLER_PC, 3, + MENUACTION_GETKEY, "FEC_TGD", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TDO", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TSS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0, + MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + }, #endif - MENUACTION_KEYBOARDCTRLS,"FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, - MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, - MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_CONTROLLER_PC_OLD1 = 36 - { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 0, 0, - MENUACTION_GETKEY, "FEC_PLB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_CWL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_CWR", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_LKT", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_PJP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_PSP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_TLF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_TRG", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_GETKEY, "FEC_CCM", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_CONTROLLER_PC_OLD2 = 37 - { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1, - - }, - - // MENUPAGE_CONTROLLER_PC_OLD3 = 38 - { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 2, 2, - MENUACTION_GETKEY, "FEC_LUP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, - MENUACTION_GETKEY, "FEC_LDN", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, - MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, - MENUACTION_SHOWHEADBOB, "FEC_GSL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_CONTROLLER_PC_OLD4 = 39 - { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 3, 3, - - }, - - // MENUPAGE_CONTROLLER_DEBUG = 40 - { "FEC_DBG", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 3, 3, - MENUACTION_GETKEY, "FEC_TGD", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, - MENUACTION_GETKEY, "FEC_TDO", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, - MENUACTION_GETKEY, "FEC_TSS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, - MENUACTION_GETKEY, "FEC_SMS", SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_OPTIONS = 41 - { "FET_OPT", 1, MENUPAGE_NONE, MENUPAGE_NONE, 1, 4, - MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, - MENUACTION_LOADRADIO, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, - MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, - MENUACTION_CHANGEMENU, "FET_LAN", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, - MENUACTION_PLAYERSETUP, "FET_PSU", SAVESLOT_NONE, MENUPAGE_SKIN_SELECT, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_EXIT = 42 - { "FET_QG", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 5, - MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_DONTCANCEL, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CANCELGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_SAVING_IN_PROGRESS = 43 - { "", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, - MENUACTION_LABEL, "FES_WAR", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_SAVE_SUCCESSFUL = 44 - { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, - MENUACTION_LABEL, "FES_SSC", SAVESLOT_LABEL, MENUPAGE_NONE, - MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, - }, - - // MENUPAGE_DELETING = 45 - { "FET_DG", 1, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, - MENUACTION_LABEL, "FED_DLW", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_DELETE_SUCCESS = 46 - { "FET_DG", 1, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, - MENUACTION_LABEL, "DEL_FNM", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, - }, - - // MENUPAGE_SAVE_FAILED = 47 - { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, - MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, - }, - - // MENUPAGE_LOAD_FAILED = 48 - { "FET_SG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, - MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_LOAD_FAILED_2 = 49 - { "FET_LG", 1, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, - MENUACTION_LABEL, "FEC_LUN", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, - }, - - // MENUPAGE_FILTER_GAME = 50 - { "FIL_FLT", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - - }, - - // MENUPAGE_START_MENU = 51 - { "FEM_MM", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, - MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT, - }, - - // MENUPAGE_PAUSE_MENU = 52 - { "FET_PAU", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS, - MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS, - MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS, - MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT, - }, - - // MENUPAGE_CHOOSE_MODE = 53 - { "FEN_STA", 1, MENUPAGE_NONE, MENUPAGE_NONE, 0, 1, - MENUACTION_CHANGEMENU, "FET_SP", SAVESLOT_NONE, MENUPAGE_NEW_GAME, - MENUACTION_INITMP, "FET_MP", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - - // MENUPAGE_SKIN_SELECT = 54 - { "FET_PSU", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 4, 4, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN, - }, - - // MENUPAGE_KEYBOARD_CONTROLS = 55 - { "FET_STI", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, - }, - - // MENUPAGE_MOUSE_CONTROLS = 56 - { "FET_MTI", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 2, 2, - MENUACTION_MOUSESENS, "FEC_MSH", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, - MENUACTION_INVVERT, "FEC_IVV", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, - MENUACTION_MOUSESTEER, "FET_MST", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, - // MENUPAGE_MISSION_RETRY = 57 + #ifdef MISSION_REPLAY + // MENUPAGE_MISSION_RETRY = 57 on mobile - { "M_FAIL", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FESZ_RM", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS, - MENUACTION_REJECT_RETRY, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE - }, -#else - { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, - // mission failed, wanna restart page in mobile - }, + { "M_FAIL", MENUPAGE_DISABLED, 0, + MENUACTION_LABEL, "FESZ_RM", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS, 320, 200, MENUALIGN_CENTER, + MENUACTION_REJECT_RETRY, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE, 320, 225, MENUALIGN_CENTER, + }, #endif - // MENUPAGE_UNK - { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, - - }, - + // MENUPAGE_OUTRO - Originally 34 + { "", 0, 0, }, }; #endif diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp index 033ed9b9..431fd794 100644 --- a/src/core/MenuScreensCustom.cpp +++ b/src/core/MenuScreensCustom.cpp @@ -26,6 +26,7 @@ #include "ModelInfo.h" #include "Pad.h" #include "ControllerConfig.h" +#include "DMAudio.h" #include "IniFile.h" #include "CarCtrl.h" #include "Population.h" @@ -37,31 +38,31 @@ #ifdef CUSTOM_FRONTEND_OPTIONS #ifdef IMPROVED_VIDEOMODE - #define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, "VideoMode", "Windowed", screenModes, 2, true, ScreenModeAfterChange, true) }, + #define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, "VideoMode", "Windowed", screenModes, 2, true, ScreenModeAfterChange, true) }, 0, 0, MENUALIGN_LEFT, #else #define VIDEOMODE_SELECTOR #endif #ifdef MULTISAMPLING - #define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "Graphics", "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) }, + #define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "Graphics", "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) }, 0, 0, MENUALIGN_LEFT, #else #define MULTISAMPLING_SELECTOR #endif #ifdef CUTSCENE_BORDERS_SWITCH - #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&CMenuManager::m_PrefsCutsceneBorders, "Display", "CutsceneBorders", off_on, 2, false) }, + #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&FrontEndMenuManager.m_PrefsCutsceneBorders, "Display", "CutsceneBorders", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT, #else #define CUTSCENE_BORDERS_TOGGLE #endif #ifdef FREE_CAM - #define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "Display", "FreeCam", off_on, 2, false) }, + #define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "Display", "FreeCam", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT, #else #define FREE_CAM_TOGGLE #endif #ifdef PS2_ALPHA_TEST - #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "Graphics", "PS2AlphaTest", off_on, 2, false) }, + #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "Graphics", "PS2AlphaTest", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT, #else #define DUALPASS_SELECTOR #endif @@ -69,34 +70,34 @@ #ifdef PED_CAR_DENSITY_SLIDERS // 0.2f - 3.4f makes it possible to have 1.0f somewhere inbetween #define DENSITY_SLIDERS \ - MENUACTION_CFO_SLIDER, "FEM_PED", { new CCFOSlider(&CIniFile::PedNumberMultiplier, "Display", "PedDensity", 0.2f, 3.4f, PedDensityChange) }, \ - MENUACTION_CFO_SLIDER, "FEM_CAR", { new CCFOSlider(&CIniFile::CarNumberMultiplier, "Display", "CarDensity", 0.2f, 3.4f, CarDensityChange) }, + MENUACTION_CFO_SLIDER, "FEM_PED", { new CCFOSlider(&CIniFile::PedNumberMultiplier, "Display", "PedDensity", 0.2f, 3.4f, PedDensityChange) }, 0, 0, MENUALIGN_LEFT, \ + MENUACTION_CFO_SLIDER, "FEM_CAR", { new CCFOSlider(&CIniFile::CarNumberMultiplier, "Display", "CarDensity", 0.2f, 3.4f, CarDensityChange) }, 0, 0, MENUALIGN_LEFT, #else #define DENSITY_SLIDERS #endif #ifdef NO_ISLAND_LOADING - #define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&CMenuManager::m_PrefsIslandLoading, "Graphics", "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) }, + #define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&FrontEndMenuManager.m_PrefsIslandLoading, "Graphics", "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) }, 0, 0, MENUALIGN_LEFT, #else #define ISLAND_LOADING_SELECTOR #endif #ifdef EXTENDED_COLOURFILTER #define POSTFX_SELECTORS \ - MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "Graphics", "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false) }, \ - MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "Graphics", "MotionBlur", off_on, 2, false) }, + MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "Graphics", "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false) }, 0, 0, MENUALIGN_LEFT, \ + MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "Graphics", "MotionBlur", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT, #else #define POSTFX_SELECTORS #endif #ifdef INVERT_LOOK_FOR_PAD - #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_IVP", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, "Controller", "InvertPad", off_on, 2, false) }, + #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_ILU", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, "Controller", "InvertPad", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT, #else #define INVERT_PAD_SELECTOR #endif #ifdef GAMEPAD_MENU - #define SELECT_CONTROLLER_TYPE MENUACTION_CFO_SELECT, "FEC_TYP", { new CCFOSelect((int8*)&CMenuManager::m_PrefsControllerType, "Controller", "Type", controllerTypes, ARRAY_SIZE(controllerTypes), false, ControllerTypeAfterChange) }, + #define SELECT_CONTROLLER_TYPE MENUACTION_CFO_SELECT, "FEC_TYP", { new CCFOSelect((int8*)&FrontEndMenuManager.m_PrefsControllerType, "Controller", "Type", controllerTypes, ARRAY_SIZE(controllerTypes), false, ControllerTypeAfterChange) }, 0, 0, MENUALIGN_LEFT, #else #define SELECT_CONTROLLER_TYPE #endif @@ -117,32 +118,22 @@ void RestoreDefGraphics(int8 action) { #ifdef NO_ISLAND_LOADING if (!FrontEndMenuManager.m_bGameNotLoaded) { FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW; - CCollision::bAlreadyLoaded = false; - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - CStreaming::RequestIslands(CGame::currLevel); - CStreaming::LoadAllRequestedModels(true); + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + CStreaming::RequestIslands(CGame::currLevel); + CStreaming::LoadAllRequestedModels(true); } else FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW; #endif #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those - CMenuManager::m_PrefsFrameLimiter = true; - CMenuManager::m_PrefsVsyncDisp = true; - CMenuManager::m_PrefsVsync = true; - CMenuManager::m_PrefsUseWideScreen = false; - FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode; - #if GTA_VERSION >= GTA3_PC_11 - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } - #else - CMBlur::BlurOn = true; + FrontEndMenuManager.m_PrefsFrameLimiter = true; + FrontEndMenuManager.m_PrefsVsyncDisp = true; + #ifdef LEGACY_MENU_OPTIONS + FrontEndMenuManager.m_PrefsVsync = true; #endif + FrontEndMenuManager.m_PrefsUseWideScreen = false; + FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode; + CMBlur::BlurOn = false; FrontEndMenuManager.SaveSettings(); #endif } @@ -152,7 +143,7 @@ void RestoreDefDisplay(int8 action) { return; #ifdef CUTSCENE_BORDERS_SWITCH - CMenuManager::m_PrefsCutsceneBorders = true; + FrontEndMenuManager.m_PrefsCutsceneBorders = true; #endif #ifdef FREE_CAM TheCamera.bFreeCam = false; @@ -161,10 +152,13 @@ void RestoreDefDisplay(int8 action) { CIniFile::LoadIniFile(); #endif #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those - CMenuManager::m_PrefsBrightness = 256; - CMenuManager::m_PrefsLOD = 1.2f; + FrontEndMenuManager.m_PrefsBrightness = 256; + FrontEndMenuManager.m_PrefsLOD = 1.2f; CRenderer::ms_lodDistScale = 1.2f; - CMenuManager::m_PrefsShowSubtitles = true; + FrontEndMenuManager.m_PrefsShowSubtitles = false; + FrontEndMenuManager.m_PrefsShowLegends = true; + FrontEndMenuManager.m_PrefsRadarMode = 0; + FrontEndMenuManager.m_PrefsShowHud = true; FrontEndMenuManager.SaveSettings(); #endif } @@ -176,16 +170,11 @@ void IslandLoadingAfterChange(int8 before, int8 after) { if (after > FrontEndMenuManager.ISLAND_LOADING_LOW) { FrontEndMenuManager.m_PrefsIslandLoading = before; // calls below needs previous mode :shrug: - if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH) - CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC); + if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH) { + CStreaming::RemoveIslandsNotUsed(LEVEL_BEACH); + CStreaming::RemoveIslandsNotUsed(LEVEL_MAINLAND); + } if (before == FrontEndMenuManager.ISLAND_LOADING_LOW) { - if (CGame::currLevel != LEVEL_INDUSTRIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); - if (CGame::currLevel != LEVEL_COMMERCIAL) - CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); - if (CGame::currLevel != LEVEL_SUBURBAN) - CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); - CCollision::bAlreadyLoaded = true; FrontEndMenuManager.m_PrefsIslandLoading = after; CStreaming::RequestBigBuildings(CGame::currLevel); @@ -196,8 +185,6 @@ void IslandLoadingAfterChange(int8 before, int8 after) { FrontEndMenuManager.m_PrefsIslandLoading = after; } else { // low - CCollision::bAlreadyLoaded = false; - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); CStreaming::RequestIslands(CGame::currLevel); @@ -213,6 +200,7 @@ void IslandLoadingAfterChange(int8 before, int8 after) { #ifdef PED_CAR_DENSITY_SLIDERS void PedDensityChange(float before, float after) { CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * after; + CPopulation::MaxNumberOfPedsInUseInterior = DEFAULT_MAX_NUMBER_OF_PEDS_INTERIOR * after; } void CarDensityChange(float before, float after) { @@ -233,6 +221,8 @@ void MultiSamplingButtonPress(int8 action) { if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) { FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel; _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.Service(); FrontEndMenuManager.SetHelperText(0); FrontEndMenuManager.SaveSettings(); } @@ -294,6 +284,8 @@ const char* screenModes[] = { "FED_FLS", "FED_WND" }; void ScreenModeAfterChange(int8 before, int8 after) { _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.Service(); FrontEndMenuManager.SetHelperText(0); } @@ -395,531 +387,416 @@ void ControllerTypeAfterChange(int8 before, int8 after) } #endif -CMenuScreenCustom aScreens[MENUPAGES] = { - // MENUPAGE_NONE = 0 - { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, }, - - // MENUPAGE_STATS = 1 - { "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, +CMenuScreenCustom aScreens[] = { + // MENUPAGE_STATS = 0 + { "FEH_STA", MENUPAGE_NONE, nil, nil, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 190, 320, MENUALIGN_RIGHT, }, - // MENUPAGE_NEW_GAME = 2 - { "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_CHANGEMENU, "FES_SNG", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD }, - MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT }, - MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_NEW_GAME = 1 + { "FEP_STG", MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FES_NGA", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD}, 320, 155, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FES_LOA", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FES_DEL", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT}, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_BRIEFS = 3 - { "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_BRIEFS = 2 + { "FEH_BRI", MENUPAGE_NONE, nil, nil, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 190, 320, MENUALIGN_RIGHT, }, - // MENUPAGE_CONTROLLER_SETTINGS = 4 -#ifdef GAMEPAD_MENU - { "FET_AGS", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, -#else - { "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, -#endif - MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, - MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, - INVERT_PAD_SELECTOR - MENUACTION_CTRLVIBRATION, "FEC_VIB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, - SELECT_CONTROLLER_TYPE - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - - // MENUPAGE_SOUND_SETTINGS = 5 - { "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, - MENUACTION_MUSICVOLUME, "FEA_MUS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_SFXVOLUME, "FEA_SFX", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_AUDIOHW, "FEA_3DH", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_SPEAKERCONF, "FEA_SPK", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_DYNAMICACOUSTIC, "FET_DAM", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_RADIO, "FEA_RSS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_SOUND_SETTINGS = 3 + { "FEH_AUD", MENUPAGE_OPTIONS, nil, nil, + MENUACTION_MUSICVOLUME, "FEA_MUS", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 40, 76, MENUALIGN_LEFT, + MENUACTION_SFXVOLUME, "FEA_SFX", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_MP3VOLUMEBOOST, "FEA_MPB", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_AUDIOHW, "FEA_3DH", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SPEAKERCONF, "FEA_SPK", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_DYNAMICACOUSTIC, "FET_DAM", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_RADIO, "FEA_RSS", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_RESTOREDEF, "FET_DEF", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 320, 367, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, MENUALIGN_CENTER, }, + // MENUPAGE_DISPLAY_SETTINGS = 4 #ifndef GRAPHICS_MENU_OPTIONS - // MENUPAGE_DISPLAY_SETTINGS = 6 - { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, - MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - DENSITY_SLIDERS - MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, -#ifndef EXTENDED_COLOURFILTER - MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, -#endif - MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + { "FEH_DIS", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true}), nil, + MENUACTION_BRIGHTNESS, "FED_BRI", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_DRAWDIST, "FEM_LOD", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_FRAMESYNC, "FEM_VSC", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, +#endif + MENUACTION_FRAMELIMIT, "FEM_FRM", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, +#if defined LEGACY_MENU_OPTIONS && !defined EXTENDED_COLOURFILTER + MENUACTION_TRAILS, "FED_TRA", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, +#endif + MENUACTION_SUBTITLES, "FED_SUB", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_WIDESCREEN, "FED_WIS", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_LEGENDS, "MAP_LEG", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_RADARMODE, "FED_RDR", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_HUD, "FED_HUD", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SCREENRES, "FED_RES", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT, VIDEOMODE_SELECTOR MULTISAMPLING_SELECTOR ISLAND_LOADING_SELECTOR DUALPASS_SELECTOR CUTSCENE_BORDERS_TOGGLE FREE_CAM_TOGGLE + DENSITY_SLIDERS POSTFX_SELECTORS // re3.cpp inserts here pipeline selectors if neo/neo.txd exists and EXTENDED_PIPELINES defined - MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_RESTOREDEF, "FET_DEF", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 320, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 0, MENUALIGN_CENTER, }, #else - // MENUPAGE_DISPLAY_SETTINGS = 6 - { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, - MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - DENSITY_SLIDERS + { "FEH_DIS", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true}), nil, + MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT, + MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT, CUTSCENE_BORDERS_TOGGLE FREE_CAM_TOGGLE - MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, nil, RestoreDefDisplay) }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + DENSITY_SLIDERS + MENUACTION_LEGENDS, "MAP_LEG", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT, + MENUACTION_RADARMODE, "FED_RDR", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT, + MENUACTION_HUD, "FED_HUD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT, + MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT, + MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, nil, RestoreDefDisplay) }, 320, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 0, MENUALIGN_CENTER, }, #endif - // MENUPAGE_LANGUAGE_SETTINGS = 7 - { "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, - MENUACTION_LANG_ENG, "FEL_ENG", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, - MENUACTION_LANG_FRE, "FEL_FRE", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, - MENUACTION_LANG_GER, "FEL_GER", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, - MENUACTION_LANG_ITA, "FEL_ITA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, - MENUACTION_LANG_SPA, "FEL_SPA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, - // CustomFrontendOptionsPopulate will add languages here, if files are found - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - - // MENUPAGE_CHOOSE_LOAD_SLOT = 8 - { "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil, - MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, - MENUACTION_CHECKSAVE, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM }, - MENUACTION_CHECKSAVE, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM }, - }, - - // MENUPAGE_CHOOSE_DELETE_SLOT = 9 - { "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil, - MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, - MENUACTION_CHANGEMENU, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM }, - }, - - // MENUPAGE_NEW_GAME_RELOAD = 10 - { "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil, - MENUACTION_LABEL, "FESZ_QR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, - MENUACTION_NEWGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD }, - }, - - // MENUPAGE_LOAD_SLOT_CONFIRM = 11 - { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil, - MENUACTION_LABEL, "FESZ_QL", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT }, - MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS }, + // MENUPAGE_LANGUAGE_SETTINGS = 5 + { "FEH_LAN", MENUPAGE_OPTIONS, nil, nil, + MENUACTION_LANG_ENG, "FEL_ENG", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 320, 132, MENUALIGN_CENTER, + MENUACTION_LANG_FRE, "FEL_FRE", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_LANG_GER, "FEL_GER", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_LANG_ITA, "FEL_ITA", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_LANG_SPA, "FEL_SPA", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_DELETE_SLOT_CONFIRM = 12 - { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, - MENUACTION_LABEL, "FESZ_QD", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, - MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_DELETING }, + // MENUPAGE_MAP = 6 + { "FEH_MAP", MENUPAGE_NONE, nil, nil, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 70, 380, MENUALIGN_CENTER, }, - // MENUPAGE_NO_MEMORY_CARD = 13 - { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - // hud adjustment page in mobile + // MENUPAGE_NEW_GAME_RELOAD = 7 + { "FES_NGA", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_LABEL, "FESZ_QR", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_NO, "FEM_NO", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME}, 320, 200, MENUALIGN_CENTER, + MENUACTION_NEWGAME, "FEM_YES", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_LOADING_IN_PROGRESS = 14 - { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_LABEL, "FED_LDW", { nil, SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM }, + // MENUPAGE_CHOOSE_LOAD_SLOT = 8 + { "FET_LG", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_CHECKSAVE, "FEM_SL1", {nil, SAVESLOT_1, 0}, 40, 90, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL2", {nil, SAVESLOT_2, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL3", {nil, SAVESLOT_3, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL4", {nil, SAVESLOT_4, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL5", {nil, SAVESLOT_5, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL6", {nil, SAVESLOT_6, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL7", {nil, SAVESLOT_7, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL8", {nil, SAVESLOT_8, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 320, 345, MENUALIGN_CENTER, }, - // MENUPAGE_DELETING_IN_PROGRESS = 15 - { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_LABEL, "FEDL_WR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_CHOOSE_DELETE_SLOT = 9 + { "FES_DEL", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_CHECKSAVE, "FEM_SL1", {nil, SAVESLOT_1, 0}, 40, 90, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL2", {nil, SAVESLOT_2, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL3", {nil, SAVESLOT_3, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL4", {nil, SAVESLOT_4, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL5", {nil, SAVESLOT_5, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL6", {nil, SAVESLOT_6, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL7", {nil, SAVESLOT_7, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_CHECKSAVE, "FEM_SL8", {nil, SAVESLOT_8, 0}, 0, 0, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 320, 345, MENUALIGN_CENTER, }, - // MENUPAGE_PS2_LOAD_FAILED = 16 - { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_LABEL, "FES_LOE", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_LOAD_SLOT_CONFIRM = 10 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil, + MENUACTION_LABEL, "FESZ_QL", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_NO, "FEM_NO", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT}, 320, 200, MENUALIGN_CENTER, + MENUACTION_YES, "FEM_YES", {nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_DELETE_FAILED = 17 - { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_LABEL, "FES_DEE", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, + // MENUPAGE_DELETE_SLOT_CONFIRM = 11 + { "FES_DEL", MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, + MENUACTION_LABEL, "FESZ_QD", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_NO, "FEM_NO", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT}, 320, 200, MENUALIGN_CENTER, + MENUACTION_YES, "FEM_YES", {nil, SAVESLOT_NONE, MENUPAGE_DELETING_IN_PROGRESS}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_DEBUG_MENU = 18 - { "FED_DBG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_RELOADIDE, "FED_RID", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_RELOADIPL, "FED_RIP", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_SETDBGFLAG, "FED_DFL", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_PEDROADGROUPS, "FED_SPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CARROADGROUPS, "FED_SCR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_COLLISIONPOLYS, "FED_SCP", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_PARSEHEAP, "FED_PAH", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_SHOWCULL, "FED_SCZ", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_DEBUGSTREAM, "FED_DSR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_LOADING_IN_PROGRESS = 12 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil, }, - // MENUPAGE_MEMORY_CARD_DEBUG = 19 - { "FEM_MCM", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_REGMEMCARD1, "FEM_RMC", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_TESTFORMATMEMCARD1, "FEM_TFM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_TESTUNFORMATMEMCARD1, "FEM_TUM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CREATEROOTDIR, "FEM_CRD", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CREATELOADICONS, "FEM_CLI", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_FILLWITHGUFF, "FEM_FFF", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_SAVEONLYTHEGAME, "FEM_SOG", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_SAVEGAME, "FEM_STG", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_SAVEGAMEUNDERGTA, "FEM_STS", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CREATECOPYPROTECTED, "FEM_CPD", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_DELETING_IN_PROGRESS = 13 + { "FES_DEL", MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, }, - // MENUPAGE_MEMORY_CARD_TEST = 20 - { "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - + // MENUPAGE_DELETE_SUCCESSFUL = 14 + { "FES_DEL", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_LABEL, "FES_DSC", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_OK", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_MULTIPLAYER_MAIN = 21 - { "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - + // MENUPAGE_CHOOSE_SAVE_SLOT = 15 + { "FET_SG", MENUPAGE_DISABLED, nil, nil, + MENUACTION_SAVEGAME, "FEM_SL1", {nil, SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 40, 90, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL2", {nil, SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL3", {nil, SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL4", {nil, SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL5", {nil, SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL6", {nil, SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL7", {nil, SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_SAVEGAME, "FEM_SL8", {nil, SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT, + MENUACTION_RESUME_FROM_SAVEZONE,"FESZ_CA", {nil, SAVESLOT_NONE, 0}, 320, 345, MENUALIGN_CENTER, }, - // MENUPAGE_PS2_SAVE_FAILED = 22 - { "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 16 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FESZ_QZ", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_NO, "FEM_NO", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 320, 200, MENUALIGN_CENTER, + MENUACTION_YES, "FEM_YES", {nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_PS2_SAVE_FAILED_2 = 23 - { "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_SAVING_IN_PROGRESS = 17 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, }, - // Unused in PC but anyway - // MENUPAGE_SAVE = 24 -#ifdef PS2_SAVE_DIALOG - { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_CHANGEMENU, "FESZ_SA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, -#else - { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_LABEL, "FES_SCG", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_SAVE_SUCCESSFUL = 18 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FES_SSC", {nil, SAVESLOT_LABEL, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_RESUME_FROM_SAVEZONE, "FEM_OK", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 320, 225, MENUALIGN_CENTER, }, -#endif - // MENUPAGE_NO_MEMORY_CARD_2 = 25 - { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_SAVE_CUSTOM_WARNING = 19 + { "FET_SG", MENUPAGE_NONE, nil, nil, + MENUACTION_LABEL, "", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_OK", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_CHOOSE_SAVE_SLOT = 26 - { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, - MENUACTION_CHANGEMENU, "FEM_SL8", { nil, SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM }, + // MENUPAGE_SAVE_CHEAT_WARNING = 20 + { "FET_SG", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_LABEL, "FES_CHE", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_OK", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27 - { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, - MENUACTION_LABEL, "FESZ_QO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS }, - MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + // MENUPAGE_SKIN_SELECT = 21 + { "FET_PS", MENUPAGE_OPTIONS, nil, nil, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_OPTIONS}, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_MAP = 28 - { "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - + // MENUPAGE_SAVE_UNUSED = 22 + { "FET_SG", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_LABEL, "FED_LWR", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEC_OKK", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_CONNECTION = 29 - { "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - + // MENUPAGE_SAVE_FAILED = 23 + { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FEC_SVU", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEC_OKK", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_FIND_GAME = 30 - { "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - + // MENUPAGE_SAVE_FAILED_2 = 24 + { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, + MENUACTION_LABEL, "FEC_SVU", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_MODE = 31 - { "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - + // MENUPAGE_LOAD_FAILED = 25 + { "FET_LG", MENUPAGE_NEW_GAME, nil, nil, + MENUACTION_LABEL, "FEC_LUN", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME}, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_CREATE = 32 - { "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - - }, - - // MENUPAGE_MULTIPLAYER_START = 33 - { "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - - }, - - // MENUPAGE_SKIN_SELECT_OLD = 34 - { "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - - }, - - // MENUPAGE_CONTROLLER_PC = 35 - { "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, + // MENUPAGE_CONTROLLER_PC = 26 + { "FET_CTL", MENUPAGE_OPTIONS, new CCustomScreenLayout({0, 0, MENU_DEFAULT_LINE_HEIGHT, false, false, 150}), nil, #ifdef PC_PLAYER_CONTROLS - MENUACTION_CTRLMETHOD, "FET_CME", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, + MENUACTION_CTRLMETHOD, "FET_STI", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 150, MENUALIGN_CENTER, + MENUACTION_KEYBOARDCTRLS,"FEC_RED", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 0, 0, MENUALIGN_CENTER, +#else + MENUACTION_KEYBOARDCTRLS,"FEC_RED", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 320, 150, MENUALIGN_CENTER, #endif - MENUACTION_KEYBOARDCTRLS,"FET_RDK", { nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS }, #ifdef GAMEPAD_MENU - MENUACTION_CHANGEMENU, "FET_AGS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, + MENUACTION_CHANGEMENU, "FET_AGS", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS}, 0, 0, MENUALIGN_CENTER, #endif #ifdef DETECT_JOYSTICK_MENU - MENUACTION_CHANGEMENU, "FEC_JOD", { nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK }, + MENUACTION_CHANGEMENU, "FEC_JOD", {nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK}, 0, 0, MENUALIGN_CENTER, #endif - MENUACTION_CHANGEMENU, "FET_AMS", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, - MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - - // MENUPAGE_CONTROLLER_PC_OLD1 = 36 - { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - MENUACTION_GETKEY, "FEC_PLB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_CWL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_CWR", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_LKT", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_PJP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_PSP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_TLF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_TRG", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_GETKEY, "FEC_CCM", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - - // MENUPAGE_CONTROLLER_PC_OLD2 = 37 - { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - - }, - - // MENUPAGE_CONTROLLER_PC_OLD3 = 38 - { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - MENUACTION_GETKEY, "FEC_LUP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, - MENUACTION_GETKEY, "FEC_LDN", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, - MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, - MENUACTION_SHOWHEADBOB, "FEC_GSL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEC_MOU", {nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_RESTOREDEF, "FET_DEF", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 320, 0, MENUALIGN_CENTER, }, - // MENUPAGE_CONTROLLER_PC_OLD4 = 39 - { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - - }, - - // MENUPAGE_CONTROLLER_DEBUG = 40 - { "FEC_DBG", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - MENUACTION_GETKEY, "FEC_TGD", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, - MENUACTION_GETKEY, "FEC_TDO", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, - MENUACTION_GETKEY, "FEC_TSS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, - MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - - // MENUPAGE_OPTIONS = 41 - { "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_CHANGEMENU, "FET_CTL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, - MENUACTION_LOADRADIO, "FET_AUD", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS }, - MENUACTION_CHANGEMENU, "FET_DIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, + // MENUPAGE_OPTIONS = 27 + { "FET_OPT", MENUPAGE_NONE, nil, nil, + MENUACTION_CHANGEMENU, "FEO_CON", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 132, MENUALIGN_CENTER, + MENUACTION_LOADRADIO, "FEO_AUD", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEO_DIS", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_CENTER, #ifdef GRAPHICS_MENU_OPTIONS - MENUACTION_CHANGEMENU, "FET_GFX", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, + MENUACTION_CHANGEMENU, "FET_GFX", {nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS}, 0, 0, MENUALIGN_CENTER, #endif - MENUACTION_CHANGEMENU, "FET_LAN", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS }, - MENUACTION_PLAYERSETUP, "FET_PSU", { nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CHANGEMENU, "FEO_LAN", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_PLAYERSETUP, "FET_PS", {nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT}, 0, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_EXIT = 42 - { "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_LABEL, "FEQ_SRE", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_DONTCANCEL, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CANCELGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_EXIT = 28 + { "FET_QG", MENUPAGE_NONE, nil, nil, + MENUACTION_LABEL, "FEQ_SRE", {nil, SAVESLOT_NONE, 0}, 0, 0, 0, + MENUACTION_DONTCANCEL, "FEM_NO", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 200, MENUALIGN_CENTER, + MENUACTION_CANCELGAME, "FEM_YES", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 225, MENUALIGN_CENTER, }, - // MENUPAGE_SAVING_IN_PROGRESS = 43 - { "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, - MENUACTION_LABEL, "FES_WAR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_START_MENU = 29 + { "FEM_MM", MENUPAGE_DISABLED, nil, nil, + MENUACTION_CHANGEMENU, "FEP_STG", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME}, 320, 170, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_OPT", {nil, SAVESLOT_NONE, MENUPAGE_OPTIONS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_QUI", {nil, SAVESLOT_NONE, MENUPAGE_EXIT}, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_SAVE_SUCCESSFUL = 44 - { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, - MENUACTION_LABEL, "FES_SSC", { nil, SAVESLOT_LABEL, MENUPAGE_NONE }, - MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, + // MENUPAGE_KEYBOARD_CONTROLS = 30 + { "FET_STI", MENUPAGE_CONTROLLER_PC, nil, nil, }, - // MENUPAGE_DELETING = 45 - { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, - MENUACTION_LABEL, "FED_DLW", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - - // MENUPAGE_DELETE_SUCCESS = 46 - { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil, - MENUACTION_LABEL, "DEL_FNM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT }, - }, - - // MENUPAGE_SAVE_FAILED = 47 - { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, - MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT }, - }, - - // MENUPAGE_LOAD_FAILED = 48 - { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, - MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_MOUSE_CONTROLS = 31 + { "FEC_MOU", MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_MOUSESENS, "FEC_MSH", {nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 40, 170, MENUALIGN_LEFT, + MENUACTION_INVVERT, "FEC_IVV", {nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 0, 0, MENUALIGN_LEFT, +#ifndef GAMEPAD_MENU + INVERT_PAD_SELECTOR +#endif + MENUACTION_MOUSESTEER, "FET_MST", {nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 0, 0, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 320, 0, MENUALIGN_CENTER, + //MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, 0}, 320, 260, MENUALIGN_CENTER, // original y }, - // MENUPAGE_LOAD_FAILED_2 = 49 - { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil, - MENUACTION_LABEL, "FEC_LUN", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT }, + // MENUPAGE_PAUSE_MENU = 32 + { "FET_PAU", MENUPAGE_DISABLED, nil, nil, + MENUACTION_RESUME, "FEP_RES", {nil, SAVESLOT_NONE, 0}, 320, 120, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEH_SGA", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEH_MAP", {nil, SAVESLOT_NONE, MENUPAGE_MAP}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_STA", {nil, SAVESLOT_NONE, MENUPAGE_STATS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEH_BRI", {nil, SAVESLOT_NONE, MENUPAGE_BRIEFS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FET_OPT", {nil, SAVESLOT_NONE, MENUPAGE_OPTIONS}, 0, 0, MENUALIGN_CENTER, + MENUACTION_CHANGEMENU, "FEP_QUI", {nil, SAVESLOT_NONE, MENUPAGE_EXIT}, 0, 0, MENUALIGN_CENTER, }, - // MENUPAGE_FILTER_GAME = 50 - { "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - - }, + // MENUPAGE_NONE = 33 + { "", 0, nil, nil, }, - // MENUPAGE_START_MENU = 51 - { "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, - MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS }, - MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT }, +#ifdef GAMEPAD_MENU + { "FET_AGS", MENUPAGE_CONTROLLER_PC, new CCustomScreenLayout({40, 78, 25, true, true}), nil, + MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 40, 76, MENUALIGN_LEFT, + MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 0, 0, MENUALIGN_LEFT, + INVERT_PAD_SELECTOR + MENUACTION_CTRLVIBRATION, "FEC_VIB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 0, 0, MENUALIGN_LEFT, + SELECT_CONTROLLER_TYPE + MENUACTION_GOBACK, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, 0, 0, MENUALIGN_LEFT, + }, +#endif +#ifdef LEGACY_MENU_OPTIONS + // MENUPAGE_DEBUG_MENU = 18 + { "FED_DBG", MENUPAGE_NONE, nil, nil, + MENUACTION_RELOADIDE, "FED_RID", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_SETDBGFLAG, "FED_DFL", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_COLLISIONPOLYS, "FED_SCP", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, }, - // MENUPAGE_PAUSE_MENU = 52 - { "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_RESUME, "FEM_RES", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, - // CMenuManager::LoadAllTextures will add map here, if MENU_MAP enabled and map textures are found - MENUACTION_CHANGEMENU, "FEP_STA", { nil, SAVESLOT_NONE, MENUPAGE_STATS }, - MENUACTION_CHANGEMENU, "FEP_BRI", { nil, SAVESLOT_NONE, MENUPAGE_BRIEFS }, - MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS }, - MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT }, + // MENUPAGE_CONTROLLER_PC_OLD1 = 36 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_GETKEY, "FEC_PLB", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_CWL", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_CWR", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_LKT", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_PJP", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_PSP", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TLF", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TRG", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_CCM", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, }, - // MENUPAGE_CHOOSE_MODE = 53 - { "FEN_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_CHANGEMENU, "FET_SP", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME }, - MENUACTION_INITMP, "FET_MP", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, + // MENUPAGE_CONTROLLER_PC_OLD2 = 37 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, nil, nil, - // MENUPAGE_SKIN_SELECT = 54 - { "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN }, - }, + }, - // MENUPAGE_KEYBOARD_CONTROLS = 55 - { "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC }, + // MENUPAGE_CONTROLLER_PC_OLD3 = 38 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_GETKEY, "FEC_LUP", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_LDN", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_SMS", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0, + MENUACTION_SHOWHEADBOB, "FEC_GSL", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, }, - // MENUPAGE_MOUSE_CONTROLS = 56 - { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, - MENUACTION_MOUSESENS, "FEC_MSH", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, - MENUACTION_INVVERT, "FEC_IVV", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, -#ifndef GAMEPAD_MENU - INVERT_PAD_SELECTOR -#endif - MENUACTION_MOUSESTEER, "FET_MST", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, - // MENUPAGE_MISSION_RETRY = 57 -#ifdef MISSION_REPLAY + // MENUPAGE_CONTROLLER_PC_OLD4 = 39 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, nil, nil, - { "M_FAIL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, - MENUACTION_LABEL, "FESZ_RM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS }, - MENUACTION_REJECT_RETRY, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - }, -#else - { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - // mission failed, wanna restart page in mobile - }, -#endif + }, -#ifdef MENU_MAP - // MENUPAGE_MAP - { "FEG_MAP", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, - MENUACTION_UNK110, "", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, // to prevent cross/enter to go back - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + // MENUPAGE_CONTROLLER_DEBUG = 40 + { "FEC_DBG", MENUPAGE_CONTROLLER_PC, nil, nil, + MENUACTION_GETKEY, "FEC_TGD", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TDO", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_TSS", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0, + MENUACTION_GETKEY, "FEC_SMS", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0, }, #endif #ifdef GRAPHICS_MENU_OPTIONS // MENUPAGE_GRAPHICS_SETTINGS - { "FET_GFX", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, - new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), GraphicsGoBack, + { "FET_GFX", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true, true}), GraphicsGoBack, - MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, - MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, + MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT, + MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT, VIDEOMODE_SELECTOR - MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, - MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_FRAMESYNC, "FEM_VSC", {nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS}, 0, 0, MENUALIGN_LEFT, +#endif + MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT, MULTISAMPLING_SELECTOR ISLAND_LOADING_SELECTOR DUALPASS_SELECTOR #ifdef EXTENDED_COLOURFILTER POSTFX_SELECTORS -#else - MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, +#elif defined LEGACY_MENU_OPTIONS + MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT, #endif // re3.cpp inserts here pipeline selectors if neo/neo.txd exists and EXTENDED_PIPELINES defined - MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, nil, RestoreDefGraphics) }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, nil, RestoreDefGraphics) }, 320, 0, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 0, MENUALIGN_CENTER, }, #endif #ifdef DETECT_JOYSTICK_MENU // MENUPAGE_DETECT_JOYSTICK - { "FEC_JOD", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, - new CCustomScreenLayout({MENUSPRITE_MAINMENU, 40, 60, 20, FONT_BANK, FESCREEN_LEFT_ALIGN, false, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), DetectJoystickGoBack, - - MENUACTION_LABEL, "FEC_JPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, - MENUACTION_CFO_DYNAMIC, "FEC_JDE", { new CCFODynamic(nil, nil, nil, DetectJoystickDraw, nil) }, - MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, + { "FEC_JOD", MENUPAGE_CONTROLLER_PC, new CCustomScreenLayout({0, 0, 0, false, false, 30}), DetectJoystickGoBack, + MENUACTION_LABEL, "FEC_JPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, 0, 0, 0, + MENUACTION_CFO_DYNAMIC, "FEC_JDE", { new CCFODynamic(nil, nil, nil, DetectJoystickDraw, nil) }, 80, 200, MENUALIGN_LEFT, + MENUACTION_GOBACK, "FEDS_TB", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 225, MENUALIGN_CENTER, }, #endif - // MENUPAGE_UNK - { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil, + +#ifdef MISSION_REPLAY + // MENUPAGE_MISSION_RETRY = 57 on mobile - }, + { "M_FAIL", MENUPAGE_DISABLED, nil, nil, + MENUACTION_LABEL, "FESZ_RM", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, 0, 0, 0, + MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS }, 320, 200, MENUALIGN_CENTER, + MENUACTION_REJECT_RETRY, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, 320, 225, MENUALIGN_CENTER, + }, +#endif + // MENUPAGE_OUTRO = 34 + { "", 0, nil, nil, }, }; #endif diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 60bb7a76..e75510e5 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -33,7 +33,14 @@ #include "Streaming.h" #include "PathFind.h" #include "Wanted.h" +#include "WaterLevel.h" #include "General.h" +#include "Fluff.h" +#include "Gangs.h" +#include "platform.h" +#include "Stats.h" +#include "CarCtrl.h" +#include "TrafficLights.h" #ifdef GTA_PS2 #include "eetypes.h" @@ -52,9 +59,9 @@ bool CPad::bDisplayNoControllerMessage; bool CPad::bObsoleteControllerMessage; bool CPad::bOldDisplayNoControllerMessage; bool CPad::m_bMapPadOneToPadTwo; -#ifdef INVERT_LOOK_FOR_PAD +bool CPad::m_bDebugCamPCOn; +bool CPad::bHasPlayerCheated; bool CPad::bInvertLook4Pad; -#endif #ifdef GTA_PS2 unsigned char act_direct[6]; unsigned char act_align[6]; @@ -64,7 +71,7 @@ CKeyboardState CPad::OldKeyState; CKeyboardState CPad::NewKeyState; CKeyboardState CPad::TempKeyState; -char CPad::KeyBoardCheatString[20]; +char CPad::KeyBoardCheatString[30]; CMouseControllerState CPad::OldMouseControllerState; CMouseControllerState CPad::NewMouseControllerState; @@ -77,62 +84,260 @@ bool CPad::IsAffectedByController = false; _TODO("gbFastTime"); extern bool gbFastTime; -void WeaponCheat() +#ifdef WALLCLIMB_CHEAT +extern bool gGravityCheat; +#endif + +void SpecialCarCheats() +{ + if ( !CVehicle::bCheat9 ) + { + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_INFERNUS))->m_wheelScale *= 1.3f; + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHEETAH))->m_wheelScale *= 1.3f; + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_PHEONIX))->m_wheelScale *= 1.3f; + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_DELUXO))->m_wheelScale *= 1.3f; + mod_HandlingManager.GetHandlingData(HANDLING_LANDSTAL)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_PATRIOT)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_BOBCAT)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_BFINJECT)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_RANCHER)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_DESPERAD)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->Transmission.fEngineAcceleration *= 2.0f; + + mod_HandlingManager.GetHandlingData(HANDLING_BAGGAGE)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_BAGGAGE)->Transmission.fMaxVelocity *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_BAGGAGE)->Transmission.InitGearRatios(); + + mod_HandlingManager.GetHandlingData(HANDLING_GOLFCART)->Transmission.fEngineAcceleration *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_GOLFCART)->Transmission.fMaxVelocity *= 2.0f; + mod_HandlingManager.GetHandlingData(HANDLING_GOLFCART)->Transmission.InitGearRatios(); + + mod_HandlingManager.GetHandlingData(HANDLING_STINGER)->fCollisionDamageMultiplier *= 0.25f; + mod_HandlingManager.GetHandlingData(HANDLING_STINGER)->fMass *= 2.5f; + mod_HandlingManager.GetHandlingData(HANDLING_STINGER)->fTurnMass *= 4.0f; + + mod_HandlingManager.GetHandlingData(HANDLING_BANSHEE)->fCollisionDamageMultiplier *= 0.25f; + mod_HandlingManager.GetHandlingData(HANDLING_BANSHEE)->fMass *= 2.5f; + mod_HandlingManager.GetHandlingData(HANDLING_BANSHEE)->fTurnMass *= 4.0f; + + mod_HandlingManager.GetHandlingData(HANDLING_SABRETUR)->fCollisionDamageMultiplier *= 0.25f; + mod_HandlingManager.GetHandlingData(HANDLING_SABRETUR)->fMass *= 2.5f; + mod_HandlingManager.GetHandlingData(HANDLING_SABRETUR)->fTurnMass *= 4.0f; + + mod_HandlingManager.GetHandlingData(HANDLING_COMET)->fCollisionDamageMultiplier *= 0.25f; + mod_HandlingManager.GetHandlingData(HANDLING_COMET)->fMass *= 2.5f; + mod_HandlingManager.GetHandlingData(HANDLING_COMET)->fTurnMass *= 4.0f; + + mod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->fCollisionDamageMultiplier *= 0.25f; + mod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->fMass *= 2.5f; + mod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->fTurnMass *= 4.0f; + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CVehicle::bCheat9 = true; + CPad::bHasPlayerCheated = true; + } +} + +void PickUpChicksCheat() +{ + if ( FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike()) ) + { + CVehicle *vehicle = FindPlayerVehicle(); + if ( FindPlayerVehicle()->IsBike() ) + { + if ( vehicle->pPassengers[0] ) + vehicle->pPassengers[0]->SetObjective(OBJECTIVE_LEAVE_CAR, vehicle); + } + CPed* someoneElse = (CPed*)CWorld::TestSphereAgainstWorld(vehicle->GetPosition(), 6.0f, FindPlayerPed(), false, false, true, false, false, false); + if ( someoneElse && someoneElse->m_nPedState != PED_DRIVING ) + { + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + someoneElse->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, vehicle); + } + } +} + +void WeaponCheat1() { CHud::SetHelpMessage(TheText.Get("CHEAT2"), true); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0); + + CStreaming::RequestModel(MI_BRASS_KNUCKLES, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_BASEBALL_BAT, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_MOLOTOV, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_COLT45, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_TEC9, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_RUGER, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_SNIPERRIFLE, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_FLAMETHROWER, STREAMFLAGS_DONT_REMOVE); + CStreaming::LoadAllRequestedModels(false); + + FindPlayerPed()->GiveWeapon(WEAPONTYPE_BRASSKNUCKLE, 1); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 1); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 10); FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_UZI, 100); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_M16, 200); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 5); - FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 5); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 50); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_TEC9, 150); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_RUGER, 120); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 25); FindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200); + + CStreaming::SetModelIsDeletable(MI_BRASS_KNUCKLES); + CStreaming::SetModelIsDeletable(MI_BASEBALL_BAT); + CStreaming::SetModelIsDeletable(MI_MOLOTOV); + CStreaming::SetModelIsDeletable(MI_COLT45); + CStreaming::SetModelIsDeletable(MI_SHOTGUN); + CStreaming::SetModelIsDeletable(MI_TEC9); + CStreaming::SetModelIsDeletable(MI_RUGER); + CStreaming::SetModelIsDeletable(MI_SNIPERRIFLE); + CStreaming::SetModelIsDeletable(MI_FLAMETHROWER); +#ifdef MOBILE_IMPROVEMENTS + if (FindPlayerVehicle()) { + FindPlayerPed()->RemoveWeaponWhenEnteringVehicle(); + } +#endif +} + +void WeaponCheat2() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT2"), true); + + CStreaming::RequestModel(MI_KATANA, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_GRENADE, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_PYTHON, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_STUBBY_SHOTGUN, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_SILENCEDINGRAM, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_M4, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_LASERSCOPE, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_ROCKETLAUNCHER, STREAMFLAGS_DONT_REMOVE); + CStreaming::LoadAllRequestedModels(false); + +#ifdef FIX_BUGS + FindPlayerPed()->GiveWeapon(WEAPONTYPE_KATANA, 1); +#else + FindPlayerPed()->GiveWeapon(WEAPONTYPE_KATANA, 0); +#endif + FindPlayerPed()->GiveWeapon(WEAPONTYPE_DETONATOR_GRENADE, 10); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_PYTHON, 40); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_STUBBY_SHOTGUN, 25); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_SILENCED_INGRAM, 100); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_M4, 150); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_LASERSCOPE, 21); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5); + + CStreaming::SetModelIsDeletable(MI_KATANA); + CStreaming::SetModelIsDeletable(MI_GRENADE); + CStreaming::SetModelIsDeletable(MI_BOMB); + CStreaming::SetModelIsDeletable(MI_PYTHON); + CStreaming::SetModelIsDeletable(MI_STUBBY_SHOTGUN); + CStreaming::SetModelIsDeletable(MI_SILENCEDINGRAM); + CStreaming::SetModelIsDeletable(MI_M4); + CStreaming::SetModelIsDeletable(MI_LASERSCOPE); + CStreaming::SetModelIsDeletable(MI_ROCKETLAUNCHER); +#ifdef MOBILE_IMPROVEMENTS + if (FindPlayerVehicle()) { + FindPlayerPed()->RemoveWeaponWhenEnteringVehicle(); + } +#endif +} + +void WeaponCheat3() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT2"), true); + + CStreaming::RequestModel(MI_CHAINSAW, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_GRENADE, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_PYTHON, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_SPAS12_SHOTGUN, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_MP5, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_M4, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_LASERSCOPE, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_MINIGUN, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_MINIGUN2, STREAMFLAGS_DONT_REMOVE); + CStreaming::LoadAllRequestedModels(false); + +#ifdef FIX_BUGS + FindPlayerPed()->GiveWeapon(WEAPONTYPE_CHAINSAW, 1); +#else + FindPlayerPed()->GiveWeapon(WEAPONTYPE_CHAINSAW, 0); +#endif + FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 10); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_PYTHON, 40); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_SPAS12_SHOTGUN, 30); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_MP5, 100); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_M4, 150); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_LASERSCOPE, 21); + FindPlayerPed()->GiveWeapon(WEAPONTYPE_MINIGUN, 500); + + CStreaming::SetModelIsDeletable(MI_CHAINSAW); + CStreaming::SetModelIsDeletable(MI_GRENADE); + CStreaming::SetModelIsDeletable(MI_PYTHON); + CStreaming::SetModelIsDeletable(MI_SPAS12_SHOTGUN); + CStreaming::SetModelIsDeletable(MI_MP5); + CStreaming::SetModelIsDeletable(MI_M4); + CStreaming::SetModelIsDeletable(MI_LASERSCOPE); + CStreaming::SetModelIsDeletable(MI_MINIGUN); + CStreaming::SetModelIsDeletable(MI_MINIGUN2); + +#ifdef MOBILE_IMPROVEMENTS + if (FindPlayerVehicle()) { + FindPlayerPed()->RemoveWeaponWhenEnteringVehicle(); + } +#endif } void HealthCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT3"), true); - FindPlayerPed()->m_fHealth = 100.0f; + FindPlayerPed()->m_fHealth = CWorld::Players[0].m_nMaxHealth; if (FindPlayerVehicle()) { FindPlayerVehicle()->m_fHealth = 1000.0f; - if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR) + if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR) { ((CAutomobile*)FindPlayerVehicle())->Damage.SetEngineStatus(0); + for (int32 i = 0; i < 4; i++) + ((CAutomobile*)FindPlayerVehicle())->Damage.SetWheelStatus(i, WHEEL_STATUS_OK); + } } } -void TankCheat() +// TODO(Miami): this is HELLA different on mobile, although it mostly has debug oriented things like player exiting it's current car and enters spawned one etc. +void VehicleCheat(int model) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - CStreaming::RequestModel(MI_RHINO, 0); + CStreaming::RequestModel(model, STREAMFLAGS_DONT_REMOVE); CStreaming::LoadAllRequestedModels(false); - if (CStreaming::ms_aInfoForModel[MI_RHINO].m_loadState == STREAMSTATE_LOADED) { + if (CStreaming::ms_aInfoForModel[model].m_loadState == STREAMSTATE_LOADED) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f); + if (!(CStreaming::ms_aInfoForModel[model].m_loadState & STREAMFLAGS_DONT_REMOVE)) { + CStreaming::SetModelIsDeletable(model); + CStreaming::SetModelTxdIsDeletable(model); + } + + int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f); if (node < 0) return; #ifdef FIX_BUGS - CAutomobile* tank = new CAutomobile(MI_RHINO, RANDOM_VEHICLE); + CAutomobile* vehicle = new CAutomobile(model, RANDOM_VEHICLE); #else - CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE); + CAutomobile* vehicle = new CAutomobile(model, MISSION_VEHICLE); #endif - if (tank != nil) { + if (vehicle != nil) { CVector pos = ThePaths.m_pathNodes[node].GetPosition(); pos.z += 4.0f; - tank->SetPosition(pos); - tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f)); + vehicle->SetPosition(pos); + vehicle->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f)); - tank->SetStatus(STATUS_ABANDONED); - tank->m_nDoorLock = CARLOCK_UNLOCKED; - CWorld::Add(tank); + vehicle->SetStatus(STATUS_ABANDONED); + vehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CWorld::Add(vehicle); } } + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; } + void BlowUpCarsCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); @@ -146,7 +351,8 @@ void BlowUpCarsCheat() void ChangePlayerCheat() { - int modelId; + // I don't know wtf is going on in here... + int modelId, anotherModelId; if (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo("player", nil)) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); @@ -154,25 +360,34 @@ void ChangePlayerCheat() AssocGroupId AnimGrp = ped->m_animGroup; do { - do - modelId = CGeneral::GetRandomNumberInRange(0, MI_CAS_WOM+1); - while (!CModelInfo::GetModelInfo(modelId)); - } while (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL04 || modelId == MI_TAXI_D); + do { + modelId = CGeneral::GetRandomNumberInRange(0, MI_PGA); + anotherModelId = modelId+1; + } while (!CModelInfo::GetModelInfo(anotherModelId)); + } while (anotherModelId >= MI_SPECIAL01 && anotherModelId <= MI_SPECIAL04 || modelId == MI_TAXI_D); - uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags; + uint8 flags = CStreaming::ms_aInfoForModel[anotherModelId].m_flags; ped->DeleteRwObject(); - CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(anotherModelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE); CStreaming::LoadAllRequestedModels(false); ped->m_modelIndex = -1; - ped->SetModelIndex(modelId); + ped->SetModelIndex(anotherModelId); ped->m_animGroup = AnimGrp; - if (modelId != MI_PLAYER) { + if (modelId != -1) { if (!(flags & STREAMFLAGS_DONT_REMOVE)) - CStreaming::SetModelIsDeletable(modelId); + CStreaming::SetModelIsDeletable(anotherModelId); } } } +void ChangePlayerModel(const char* name) { + if (!FindPlayerVehicle()) { + FindPlayerPed()->Undress(name); + CStreaming::LoadAllRequestedModels(0); + FindPlayerPed()->Dress(); + } +} + void MayhemCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); @@ -182,6 +397,8 @@ void MayhemCheat() PED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 | PED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 | PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL ); + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; } void EverybodyAttacksPlayerCheat() @@ -189,12 +406,17 @@ void EverybodyAttacksPlayerCheat() CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++) CPedType::AddThreat(i, PED_FLAG_PLAYER1); + + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; } void WeaponsForAllCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); CPopulation::ms_bGivePedsWeapons = !CPopulation::ms_bGivePedsWeapons; + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; } void FastTimeCheat() @@ -220,19 +442,19 @@ void MoneyCheat() void ArmourCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT4"), true); - FindPlayerPed()->m_fArmour = 100.0f; + FindPlayerPed()->m_fArmour = CWorld::Players[0].m_nMaxArmour; } void WantedLevelUpCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT5"), true); - FindPlayerPed()->SetWantedLevel(Min(FindPlayerPed()->m_pWanted->GetWantedLevel() + 2, 6)); + FindPlayerPed()->m_pWanted->CheatWantedLevel(Min(FindPlayerPed()->m_pWanted->GetWantedLevel() + 2, 6)); } void WantedLevelDownCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT5"), true); - FindPlayerPed()->SetWantedLevel(0); + FindPlayerPed()->m_pWanted->CheatWantedLevel(0); } void SunnyWeatherCheat() @@ -241,6 +463,12 @@ void SunnyWeatherCheat() CWeather::ForceWeatherNow(WEATHER_SUNNY); } +void ExtraSunnyWeatherCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); + CWeather::ForceWeatherNow(WEATHER_EXTRA_SUNNY); +} + void CloudyWeatherCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); @@ -269,25 +497,101 @@ void OnlyRenderWheelsCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); CVehicle::bWheelsOnlyCheat = !CVehicle::bWheelsOnlyCheat; + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; } - void ChittyChittyBangBangCheat() { +#ifdef BETTER_ALLCARSAREDODO_CHEAT + CHud::SetHelpMessage(TheText.Get(!CVehicle::bAllDodosCheat ? "CHEAT1" : "CHEATOF"), true); +#else CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); +#endif CVehicle::bAllDodosCheat = !CVehicle::bAllDodosCheat; + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; } void StrongGripCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); CVehicle::bCheat3 = !CVehicle::bCheat3; + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; +} + +void FannyMagnetCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CPed::bFannyMagnetCheat = !CPed::bFannyMagnetCheat; + CPad::bHasPlayerCheated = true; +} + +void BlackCarsCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + gbBlackCars = true; + gbPinkCars = false; +} + +void PinkCarsCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + gbBlackCars = false; + gbPinkCars = true; +} + +void TrafficLightsCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CTrafficLights::bGreenLightsCheat = true; +} + +void MadCarsCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CCarCtrl::bMadDriversCheat = true; +} + +void NoSeaBedCheat(void) +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CWaterLevel::m_bRenderSeaBed = !CWaterLevel::m_bRenderSeaBed; } -void NastyLimbsCheat() +void RenderWaterLayersCheat(void) { - CPed::bNastyLimbsCheat = !CPed::bNastyLimbsCheat; + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + if ( ++CWaterLevel::m_nRenderWaterLayers > 5 ) + CWaterLevel::m_nRenderWaterLayers = 0; +} + +void BackToTheFuture(void) +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CVehicle::bHoverCheat = !CVehicle::bHoverCheat; + CPad::bHasPlayerCheated = true; +} + +void SuicideCheat(void) { + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + FindPlayerPed()->InflictDamage(nil, WEAPONTYPE_UNARMED, 1000.0f, PEDPIECE_TORSO, 0); } + +void DoChicksWithGunsCheat(void) { + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CStreaming::SetModelIsDeletable(CGangs::GetGangPedModel1(GANG_PLAYER)); + CStreaming::SetModelIsDeletable(CGangs::GetGangPedModel2(GANG_PLAYER)); + CStreaming::SetModelTxdIsDeletable(CGangs::GetGangPedModel1(GANG_PLAYER)); + CStreaming::SetModelTxdIsDeletable(CGangs::GetGangPedModel2(GANG_PLAYER)); + CStreaming::RemoveCurrentZonesModels(); + CGangs::SetGangPedModels(GANG_PLAYER, MI_HFYBE, MI_WFYBE); + CGangs::SetGangWeapons(GANG_PLAYER, WEAPONTYPE_M4, WEAPONTYPE_M4); + CStats::CheatedCount += 1000; + CPad::bHasPlayerCheated = true; +} + ////////////////////////////////////////////////////////////////////////// #ifdef KANGAROO_CHEAT @@ -312,7 +616,7 @@ void KangarooCheat() } #endif -#ifdef ALLCARSHELI_CHEAT +#ifdef RESTORE_ALLCARSHELI_CHEAT void AllCarsHeliCheat(void) { wchar* string; @@ -328,22 +632,34 @@ void AllCarsHeliCheat(void) } #endif -#ifdef ALT_DODO_CHEAT -void AltDodoCheat(void) +#ifdef WALLCLIMB_CHEAT +void WallClimbingCheat(void) { wchar* string; - if (CVehicle::bAltDodoCheat) { + if (gGravityCheat) { string = TheText.Get("CHEATOF"); - CVehicle::bAltDodoCheat = false; + gGravityCheat = false; } else { string = TheText.Get("CHEAT1"); - CVehicle::bAltDodoCheat = true; + gGravityCheat = true; } CHud::SetHelpMessage(string, true); } #endif +void FlyingFishCheat(void) +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CVehicle::bCheat8 = !CVehicle::bCheat8; + CPad::bHasPlayerCheated = true; +} + +void DoShowChaseStatCheat(void) { + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CStats::ShowChaseStatOnScreen = 1; +} + bool CControllerState::CheckForInput(void) { @@ -414,6 +730,8 @@ void CPad::Initialise(void) bObsoleteControllerMessage = false; bOldDisplayNoControllerMessage = false; bDisplayNoControllerMessage = false; + m_bMapPadOneToPadTwo = false; + m_bDebugCamPCOn = false; } #endif @@ -438,12 +756,17 @@ void CPad::Clear(bool bResetPlayerControls) ShakeFreq = 0; ShakeDur = 0; + for (int32 i = 0; i < DRUNK_STEERING_BUFFER_SIZE; i++) + SteeringLeftRightBuffer[i] = 0; + + DrunkDrivingBufferUsed = 0; + if ( bResetPlayerControls ) DisablePlayerControls = PLAYERCONTROL_ENABLED; + JustOutOfFrontend = 0; bApplyBrakes = false; - for ( int32 i = 0; i < HORNHISTORY_SIZE; i++ ) bHornHistory[i] = false; @@ -457,6 +780,11 @@ void CPad::Clear(bool bResetPlayerControls) AverageEntries = 0; } +uint32 CPad::InputHowLongAgo() +{ + return CTimer::GetTimeInMilliseconds() - LastTimeTouched; +} + void CPad::ClearMouseHistory() { PCTempMouseControllerState.Clear(); @@ -464,6 +792,14 @@ void CPad::ClearMouseHistory() OldMouseControllerState.Clear(); } +// unused +void CPad::ClearKeyBoardHistory() +{ + NewKeyState.Clear(); + OldKeyState.Clear(); + TempKeyState.Clear(); +} + CMouseControllerState::CMouseControllerState() { LMB = 0; @@ -495,7 +831,7 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() #if defined RW_D3D9 || defined RWLIBS if ( PSGLOBAL(mouse) == nil ) - _InputInitialiseMouse(); + _InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive()); if ( PSGLOBAL(mouse) != nil ) { @@ -549,7 +885,7 @@ void CPad::UpdateMouse() if ( IsForegroundApp() ) { if ( PSGLOBAL(mouse) == nil ) - _InputInitialiseMouse(); + _InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive()); DIMOUSESTATE2 state; @@ -693,7 +1029,7 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &Stat void CPad::StartShake(int16 nDur, uint8 nFreq) { - if ( !CMenuManager::m_PrefsUseVibration ) + if ( !FrontEndMenuManager.m_PrefsUseVibration ) return; if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) @@ -715,7 +1051,7 @@ void CPad::StartShake(int16 nDur, uint8 nFreq) void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fZ) { - if ( !CMenuManager::m_PrefsUseVibration ) + if ( !FrontEndMenuManager.m_PrefsUseVibration ) return; if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) @@ -742,7 +1078,7 @@ void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, floa void CPad::StartShake_Train(float fX, float fY) { - if ( !CMenuManager::m_PrefsUseVibration ) + if ( !FrontEndMenuManager.m_PrefsUseVibration ) return; if ( CCutsceneMgr::IsRunning() || CGame::playingIntro ) @@ -776,7 +1112,7 @@ void CPad::AddToCheatString(char c) #define _CHEATCMP(str) strncmp(str, CheatString, sizeof(str)-1) // "4414LDRULDRU" - R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP if ( !_CHEATCMP("URDLURDL4144") ) - WeaponCheat(); + WeaponCheat1(); // "4411LDRULDRU" - R2 R2 L1 L1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP else if ( !_CHEATCMP("URDLURDL1144") ) @@ -816,7 +1152,7 @@ void CPad::AddToCheatString(char c) // "CCCCCC321TCT" - CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE else if ( !_CHEATCMP("TCT123CCCCCC") ) - TankCheat(); + VehicleCheat(MI_RHINO); // "CCCSSSSS1TCT" - CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE else if ( !_CHEATCMP("TCT1SSSSSCCC") ) @@ -862,143 +1198,354 @@ void CPad::AddToCheatString(char c) else if ( !_CHEATCMP("T33L1413") ) StrongGripCheat(); - // "S1CD13TR1X" - SQUARE L1 CIRCLE DOWN L1 R1 TRIANGLE RIGHT L1 CROSS - else if ( !_CHEATCMP("X1RT31DC1S") ) - NastyLimbsCheat(); - -#ifdef KANGAROO_CHEAT - // "X1DUC3RLS3" - R1 SQUARE LEFT RIGHT R1 CIRCLE UP DOWN L1 CROSS - else if (!_CHEATCMP("X1DUC3RLS3")) - KangarooCheat(); -#endif - -#ifndef MASTER - // "31UD13XUD" - DOWN UP CROSS R1 L1 DOWN UP L1 R1 - else if (!_CHEATCMP("31UD13XUD")) - CPed::SwitchDebugDisplay(); -#endif - -#ifdef ALLCARSHELI_CHEAT - // "UCCL3R1TT" - TRIANGLE TRIANGLE L1 RIGHT R1 LEFT CIRCLE CIRCLE UP - else if (!_CHEATCMP("UCCL3R1TT")) - AllCarsHeliCheat(); -#endif - -#ifdef ALT_DODO_CHEAT - // "DUU31XX13" - R1 L1 CROSS CROSS L1 R1 UP UP DOWN - else if (!_CHEATCMP("DUU31XX13")) - AltDodoCheat(); -#endif #undef _CHEATCMP } #endif +int Cheat_strncmp(char* sourceStr, char* origCheatStr) +{ +#define ccmp(n) if((uint8)sourceStr[i] != (uint8)origCheatStr[i] - n) return 1; + int i = 0; + while(origCheatStr[i]) + { + switch(i) + { + case 0: ccmp(3); break; + case 1: ccmp(5); break; + case 2: ccmp(7); break; + case 3: ccmp(1); break; + case 4: ccmp(13); break; + case 5: ccmp(27); break; + case 6: ccmp(3); break; + case 7: ccmp(7); break; + case 8: ccmp(1); break; + case 9: ccmp(11); break; + case 10: ccmp(13); break; + case 11: ccmp(8); break; + case 12: ccmp(7); break; + case 13: ccmp(32); break; + case 14: ccmp(13); break; + case 15: ccmp(6); break; + case 16: ccmp(28); break; + case 17: ccmp(19); break; + case 18: ccmp(10); break; + case 19: ccmp(3); break; + case 20: ccmp(3); break; + case 21: ccmp(5); break; + case 22: ccmp(7); break; + case 23: ccmp(1); break; + case 24: ccmp(13); break; + case 25: ccmp(27); break; + case 26: ccmp(3); break; + case 27: ccmp(7); break; + default: return 1; + } + i++; + } + return 0; +#undef ccmp +} + +// TODO(Miami): Mobile has changed some of the cheats to include debugging things void CPad::AddToPCCheatString(char c) { - for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- ) + for (int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i--) KeyBoardCheatString[i + 1] = KeyBoardCheatString[i]; KeyBoardCheatString[0] = c; - #define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) - - // "GUNSGUNSGUNS" - if ( !_CHEATCMP("SNUGSNUGSNUG") ) - WeaponCheat(); - - // "IFIWEREARICHMAN" - if ( !_CHEATCMP("NAMHCIRAEREWIFI") ) - MoneyCheat(); +#define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) - // "GESUNDHEIT" - if ( !_CHEATCMP("TIEHDNUSEG") ) + // "THUGSTOOLS" + if (!Cheat_strncmp(KeyBoardCheatString, "VQVPanJ\\I_")) { + KeyBoardCheatString[0] = ' '; + WeaponCheat1(); + } + // "PROFESSIONALTOOLS" + else if (!Cheat_strncmp(KeyBoardCheatString, "VQVPagDUPT`[Lf\\Xl")) { + KeyBoardCheatString[0] = ' '; + WeaponCheat2(); + } + // "NUTTERTOOLS" + else if (!Cheat_strncmp(KeyBoardCheatString, "VQVPamH[U`[")) { + KeyBoardCheatString[0] = ' '; + WeaponCheat3(); + } + // "PRECIOUSPROTECTION" + else if (!Cheat_strncmp(KeyBoardCheatString, "QTPUP`WVS[`]ViPKnc")) { + KeyBoardCheatString[0] = ' '; + ArmourCheat(); + } + // "ASPIRINE" + else if (!Cheat_strncmp(KeyBoardCheatString, "HSPSVkVH")) { + KeyBoardCheatString[0] = ' '; HealthCheat(); - - // "MOREPOLICEPLEASE" - if ( !_CHEATCMP("ESAELPECILOPEROM") ) + } + // "YOUWONTTAKEMEALIVE" + else if (!Cheat_strncmp(KeyBoardCheatString, "H[PMN`PLLLa\\Uod[kl")) { + KeyBoardCheatString[0] = ' '; WantedLevelUpCheat(); - - // "NOPOLICEPLEASE" - if ( !_CHEATCMP("ESAELPECILOPON") ) + } + // "LEAVEMEALONE" + else if (!Cheat_strncmp(KeyBoardCheatString, "HSVMN`PLWLRT")) { + KeyBoardCheatString[0] = ' '; WantedLevelDownCheat(); - - // "GIVEUSATANK" - if ( !_CHEATCMP("KNATASUEVIG") ) - TankCheat(); - - // "BANGBANGBANG" - if ( !_CHEATCMP("GNABGNABGNAB") ) + } + // "APLEASANTDAY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\FKU[\\VHFW]I")) { + KeyBoardCheatString[0] = ' '; + SunnyWeatherCheat(); + } + // "ALOVELYDAY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\FKZY`YVML")) { + KeyBoardCheatString[0] = ' '; + ExtraSunnyWeatherCheat(); + } + // "ABITDRIEG" + else if (!Cheat_strncmp(KeyBoardCheatString, "JJPSQoLIB")) { + KeyBoardCheatString[0] = ' '; + CloudyWeatherCheat(); + } + // "CATSANDDOGS" + else if (!Cheat_strncmp(KeyBoardCheatString, "VLVEQiDZULP")) { + KeyBoardCheatString[0] = ' '; + RainyWeatherCheat(); + } + // "CANTSEEATHING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPIa\\HLT_[IJ")) { + KeyBoardCheatString[0] = ' '; + FoggyWeatherCheat(); + } + // "PANZER" + else if (!Cheat_strncmp(KeyBoardCheatString, "UJaONk")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_RHINO); + } + // "LIFEISPASSINGMEBY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\GLNTiLZTL][PeSOh")) { + KeyBoardCheatString[0] = ' '; + FastWeatherCheat(); + } + // "BIGBANG" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSHCTdE")) { + KeyBoardCheatString[0] = ' '; BlowUpCarsCheat(); - - // "ILIKEDRESSINGUP" - if ( !_CHEATCMP("PUGNISSERDEKILI") ) + } + // "STILLLIKEDRESSINGUP" + else if (!Cheat_strncmp(KeyBoardCheatString, "SZNOVnVLSORSPlYReg]")) { + KeyBoardCheatString[0] = ' '; ChangePlayerCheat(); - - // "ITSALLGOINGMAAAD" - if ( !_CHEATCMP("DAAAMGNIOGLLASTI") ) + } + // "FIGHTFIGHTFIGHT" + else if (!Cheat_strncmp(KeyBoardCheatString, "WMNJSoKNJQaPNiS")) { + KeyBoardCheatString[0] = ' '; MayhemCheat(); - + } // "NOBODYLIKESME" - if ( !_CHEATCMP("EMSEKILYDOBON") ) + else if (!Cheat_strncmp(KeyBoardCheatString, "HRZFXdO`EZOWU")) { + KeyBoardCheatString[0] = ' '; EverybodyAttacksPlayerCheat(); - - // "WEAPONSFORALL" - if ( !_CHEATCMP("LLAROFSNOPAEW") ) + } + // "OURGODGIVENRIGHTTOBEARARMS" + else if (!Cheat_strncmp(KeyBoardCheatString, "VRYB_\\HIP_aPNi_TaiSJGTNSbj")) { + KeyBoardCheatString[0] = ' '; WeaponsForAllCheat(); - - // "TIMEFLIESWHENYOU" - if ( !_CHEATCMP("UOYNEHWSEILFEMIT") ) + } + // "ONSPEED" + else if (!Cheat_strncmp(KeyBoardCheatString, "GJLQ`iR")) { + KeyBoardCheatString[0] = ' '; FastTimeCheat(); - - // "BOOOOORING" - if ( !_CHEATCMP("GNIROOOOOB") ) + } + // "BOOOOOORING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPS\\jRVPZO")) { + KeyBoardCheatString[0] = ' '; SlowTimeCheat(); - -#if GTA_VERSION < GTA3_PC_11 - // "TURTOISE" - if ( !_CHEATCMP("ESIOTRUT") ) - ArmourCheat(); -#else - // "TORTOISE" - if ( !_CHEATCMP("ESIOTROT") ) - ArmourCheat(); -#endif - - // "SKINCANCERFORME" - if ( !_CHEATCMP("EMROFRECNACNIKS") ) - SunnyWeatherCheat(); - - // "ILIKESCOTLAND" - if ( !_CHEATCMP("DNALTOCSEKILI") ) - CloudyWeatherCheat(); - - // "ILOVESCOTLAND" - if ( !_CHEATCMP("DNALTOCSEVOLI") ) - RainyWeatherCheat(); - - // "PEASOUP" - if ( !_CHEATCMP("PUOSAEP") ) - FoggyWeatherCheat(); - - // "MADWEATHER" - if ( !_CHEATCMP("REHTAEWDAM") ) - FastWeatherCheat(); - - // "ANICESETOFWHEELS" - if ( !_CHEATCMP("SLEEHWFOTESECINA") ) + } + // "WHEELSAREALLINEED" + else if (!Cheat_strncmp(KeyBoardCheatString, "GJLOVgOHF]N[SeRNs")) { + KeyBoardCheatString[0] = ' '; OnlyRenderWheelsCheat(); - - // "CHITTYCHITTYBB" - if ( !_CHEATCMP("BBYTTIHCYTTIHC") ) + } + //COMEFLYWITHME + else if (!Cheat_strncmp(KeyBoardCheatString, "HROUVr\\SGPZWJ")) { + KeyBoardCheatString[0] = ' '; ChittyChittyBangBangCheat(); - - // "CORNERSLIKEMAD" - if ( !_CHEATCMP("DAMEKILSRENROC") ) + } + // "GRIPISEVERYTHING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPIatULWP`QWi_M")) { + KeyBoardCheatString[0] = ' '; StrongGripCheat(); - - // "NASTYLIMBSCHEAT" - if ( !_CHEATCMP("TAEHCSBMILYTSAN") ) - NastyLimbsCheat(); + } + // "CHASESTAT" + else if (!Cheat_strncmp(KeyBoardCheatString, "WF[TRnDOD")) { + KeyBoardCheatString[0] = ' '; + DoShowChaseStatCheat(); + } + // "CHICKSWITHGUNS" + else if (!Cheat_strncmp(KeyBoardCheatString, "VS\\HUoL^TVPQOc")) { + KeyBoardCheatString[0] = ' '; + DoChicksWithGunsCheat(); + } + // "ICANTTAKEITANYMORE" + else if (!Cheat_strncmp(KeyBoardCheatString, "HWVNfiD[JPXI[t[G_\\")) { + KeyBoardCheatString[0] = ' '; + SuicideCheat(); + } + // "GREENLIGHT" + else if (!Cheat_strncmp(KeyBoardCheatString, "WMNJYiHLSR")) { + KeyBoardCheatString[0] = ' '; + TrafficLightsCheat(); + } + // "MIAMITRAFFIC" + else if (!Cheat_strncmp(KeyBoardCheatString, "FNMGNmWPNLVU")) { + KeyBoardCheatString[0] = ' '; + MadCarsCheat(); + } + // "AHAIRDRESSERSCAR" + else if (!Cheat_strncmp(KeyBoardCheatString, "UFJT_`VZF]QZPaUG")) { + KeyBoardCheatString[0] = ' '; + PinkCarsCheat(); + } + // "IWANTITPAINTEDBLACK" + else if (!Cheat_strncmp(KeyBoardCheatString, "NHHMO_H[OTNX[iaT]jS")) { + KeyBoardCheatString[0] = ' '; + BlackCarsCheat(); + } + // "TRAVELINSTYLE" + else if (!Cheat_strncmp(KeyBoardCheatString, "HQ`U`iLSFaNZ[")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_BLOODRA); + } + // "THELASTRIDE" + else if (!Cheat_strncmp(KeyBoardCheatString, "HIPSanDSFSa")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_ROMERO); + } + // "ROCKANDROLLCAR" + else if (!Cheat_strncmp(KeyBoardCheatString, "UFJMYjUKOLXKVr")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_LOVEFIST); + } + // "RUBBISHCAR" + else if (!Cheat_strncmp(KeyBoardCheatString, "UFJI`dEIV]")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_TRASH); + } + // "GETTHEREQUICKLY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\QRDVpTLSPU\\[eT")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_BLOODRB); + } + // "GETTHEREFAST" + else if (!Cheat_strncmp(KeyBoardCheatString, "WXHGRmHOU_RO")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_SABRETUR); + } + // "BETTERTHANWALKING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPLY\\ZUBSaZLtaK^")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_CADDY); + } + // "GETTHEREFASTINDEED" + else if (!Cheat_strncmp(KeyBoardCheatString, "GJLE[dWZBQfZLvRXa[^WHL")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_HOTRINA); + } + // "GETTHEREAMAZINGLYFAST" + else if (!Cheat_strncmp(KeyBoardCheatString, "WXHGfgJUJeNUHe_Kdg^HJ")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(MI_HOTRINB); + } + // LOOKLIKELANCE + else if (!Cheat_strncmp(KeyBoardCheatString, "HHUBY`NPMV\\WS")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igbuddy"); + } + // IWANTBIGTITS + else if (!Cheat_strncmp(KeyBoardCheatString, "VYPUTdE[OLdQ")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igcandy"); + } + // MYSONISALAWYER + else if (!Cheat_strncmp(KeyBoardCheatString, "UJ`XNgDZJY\\[`m")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igken"); + } + // ILOOKLIKEHILARY + else if (!Cheat_strncmp(KeyBoardCheatString, "\\WHMVcHRJWXWVlV")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("ighlary"); + } + // ROCKANDROLLMAN + else if (!Cheat_strncmp(KeyBoardCheatString, "QFTMYjUKOLXKVr")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igjezz"); + } + // ONEARMEDBANDIT + else if (!Cheat_strncmp(KeyBoardCheatString, "WNKON]GLN]NMUo")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igphil"); + } + // IDONTHAVETHEMONEYSONNY + else if (!Cheat_strncmp(KeyBoardCheatString, "\\SUP`tHUPXRP[ecGdgXRGN")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igsonny"); + } + // FOXYLITTLETHING + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPIa`O[UTYa_oS")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igmerc"); + } + // WELOVEOURDICK + else if (!Cheat_strncmp(KeyBoardCheatString, "NHPE_pRLWZYM^")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igdick"); + } + // CHEATSHAVEBEENCRACKED + else if (!Cheat_strncmp(KeyBoardCheatString, "GJRDNmFUFPOM]aUYpTOKF")) { + KeyBoardCheatString[0] = ' '; + ChangePlayerModel("igdiaz"); + } + // DEEPFRIEDMARSBARS + else if (!Cheat_strncmp(KeyBoardCheatString, "VWHC`mDTEPVZMpRK")) { + KeyBoardCheatString[0] = ' '; + gfTommyFatness = 0.26f; + } + // PROGRAMMER + else if (!Cheat_strncmp(KeyBoardCheatString, "UJTNNmJVS[")) { + KeyBoardCheatString[0] = ' '; + gfTommyFatness = -0.3f; + } + // SEAWAYS + else if (!Cheat_strncmp(KeyBoardCheatString, "V^HXN`V")) { + KeyBoardCheatString[0] = ' '; + BackToTheFuture(); + } + // LOADSOFLITTLETHINGS + else if (!Cheat_strncmp(KeyBoardCheatString, "VLUJUoHSU_VTMo`J]bV")) { + KeyBoardCheatString[0] = ' '; + SpecialCarCheats(); + } + // HOPINGIRL + else if (!Cheat_strncmp(KeyBoardCheatString, "OWPH[dSVI")) { + KeyBoardCheatString[0] = ' '; + PickUpChicksCheat(); + } + //CERTAINDEATH + else if (!Cheat_strncmp(KeyBoardCheatString, "KYHFQiLHU]RK")) { + KeyBoardCheatString[0] = ' '; + CSmokeTrails::CigOn = !CSmokeTrails::CigOn; + } + //AIRSHIP + else if (!Cheat_strncmp(KeyBoardCheatString, "SNOT_dD")) { + KeyBoardCheatString[0] = ' '; + FlyingFishCheat(); + } + //FANNYMAGNET + else if (!Cheat_strncmp(KeyBoardCheatString, "WJUHNh\\UOLS")) { + KeyBoardCheatString[0] = ' '; + FannyMagnetCheat(); + } #ifdef KANGAROO_CHEAT // "KANGAROO" @@ -1012,19 +1559,29 @@ void CPad::AddToPCCheatString(char c) CPed::SwitchDebugDisplay(); #endif -#ifdef ALLCARSHELI_CHEAT +#ifdef RESTORE_ALLCARSHELI_CHEAT // "CARSAREHELI" if (!_CHEATCMP("ILEHERASRAC")) AllCarsHeliCheat(); #endif -#ifdef ALT_DODO_CHEAT - // "IWANTTOMASTERDODO" - if (!_CHEATCMP("ODODRETSAMOTTNAWI")) - AltDodoCheat(); +#ifdef WALLCLIMB_CHEAT + // "SPIDERCAR" + if (!_CHEATCMP("RACREDIPS")) + WallClimbingCheat(); +#endif + +#if !defined(PC_WATER) && defined(WATER_CHEATS) + // SEABEDCHEAT + if (!_CHEATCMP("TAEHCDEBAESON")) + NoSeaBedCheat(); + + // WATERLAYERSCHEAT + if (!_CHEATCMP("TAEHCSREYALRETAW")) + RenderWaterLayersCheat(); #endif - #undef _CHEATCMP +#undef _CHEATCMP } #ifdef XINPUT @@ -1128,7 +1685,7 @@ void CPad::UpdatePads(void) IsAffectedByController = false; #endif - if ( CReplay::IsPlayingBackFromFile() ) + if ( CReplay::IsPlayingBackFromFile() && !FrontEndMenuManager.m_bMenuActive ) bUpdate = false; if ( bUpdate ) @@ -1428,14 +1985,23 @@ void CPad::Update(int16 pad) ProcessPCSpecificStuff(); + if (NewState.CheckForInput()) + LastTimeTouched = CTimer::GetTimeInMilliseconds(); + if ( ++iCurrHornHistory >= HORNHISTORY_SIZE ) iCurrHornHistory = 0; bHornHistory[iCurrHornHistory] = GetHorn(); + for (int32 i = DRUNK_STEERING_BUFFER_SIZE - 2; i >= 0; i--) { + SteeringLeftRightBuffer[i + 1] = SteeringLeftRightBuffer[i]; + } if ( !bDisplayNoControllerMessage ) CGame::bDemoMode = false; + + if ( JustOutOfFrontend != 0 ) + --JustOutOfFrontend; } void CPad::DoCheats(void) @@ -1520,12 +2086,12 @@ CPad *CPad::GetPad(int32 pad) #define CURMODE (Mode) #endif - int16 CPad::GetSteeringLeftRight(void) { if ( ArePlayerControlsDisabled() ) return 0; + int16 value; switch (CURMODE) { case 0: @@ -1535,9 +2101,12 @@ int16 CPad::GetSteeringLeftRight(void) int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; if ( Abs(axis) > Abs(dpad) ) - return axis; + value = axis; else - return dpad; + value = dpad; + + SteeringLeftRightBuffer[0] = value; + value = SteeringLeftRightBuffer[DrunkDrivingBufferUsed]; break; } @@ -1545,13 +2114,18 @@ int16 CPad::GetSteeringLeftRight(void) case 1: case 3: { - return NewState.LeftStickX; - + SteeringLeftRightBuffer[0] = NewState.LeftStickX; + value = SteeringLeftRightBuffer[DrunkDrivingBufferUsed]; + break; + } + default: + { + value = 0; break; } } - return 0; + return value; } int16 CPad::GetSteeringUpDown(void) @@ -1565,7 +2139,7 @@ int16 CPad::GetSteeringUpDown(void) case 2: { int16 axis = NewState.LeftStickY; - int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2; + int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2; if ( Abs(axis) > Abs(dpad) ) return axis; @@ -1674,7 +2248,6 @@ int16 CPad::GetPedWalkLeftRight(void) return 0; } - int16 CPad::GetPedWalkUpDown(void) { if ( ArePlayerControlsDisabled() ) @@ -1738,6 +2311,36 @@ int16 CPad::GetAnalogueUpDown(void) return 0; } +int16 CPad::GetAnalogueLeftRight(void) +{ + switch (CURMODE) + { + case 0: + case 2: + { + int16 axis = NewState.LeftStickX; + int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; + + if ( Abs(axis) > Abs(dpad) ) + return axis; + else + return dpad; + + break; + } + + case 1: + case 3: + { + return NewState.LeftStickX; + + break; + } + } + + return 0; +} + bool CPad::GetLookLeft(void) { if ( ArePlayerControlsDisabled() ) @@ -1849,7 +2452,6 @@ bool CPad::HornJustDown(void) return false; } - bool CPad::GetCarGunFired(void) { if ( ArePlayerControlsDisabled() ) @@ -1980,6 +2582,10 @@ bool CPad::GetExitVehicle(void) if ( ArePlayerControlsDisabled() ) return false; + + if ( JustOutOfFrontend != 0 ) + return false; + switch (CURMODE) { case 0: @@ -2007,6 +2613,9 @@ bool CPad::ExitVehicleJustDown(void) if ( ArePlayerControlsDisabled() ) return false; + if ( JustOutOfFrontend != 0 ) + return false; + switch (CURMODE) { case 0: @@ -2133,6 +2742,53 @@ int16 CPad::GetAccelerate(void) return 0; } +bool CPad::CycleCameraModeJustDown(void) +{ + bool result; + switch (CURMODE) + { + case 0: + case 2: + case 3: + { + result = !!(NewState.Select && !OldState.Select); + + break; + } + + case 1: + { + result = !!(NewState.DPadUp && !OldState.DPadUp); + + break; + } + default: + { + result = false; + break; + } + } + + if (!result) + { + switch (CURMODE) + { + case 1: + { + result = !!(NewState.DPadDown && !OldState.DPadDown); + break; + } + default: + { + result = false; + break; + } + } + } + + return result; +} + bool CPad::CycleCameraModeUpJustDown(void) { switch (CURMODE) @@ -2220,7 +2876,6 @@ bool CPad::ChangeStationJustDown(void) return false; } - bool CPad::CycleWeaponLeftJustDown(void) { if ( ArePlayerControlsDisabled() ) @@ -2291,6 +2946,46 @@ bool CPad::TargetJustDown(void) return false; } +bool CPad::CollectPickupJustDown(void) +{ + if ( ArePlayerControlsDisabled() ) + return false; + + switch (CURMODE) + { + case 0: + case 1: + { + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); + + break; + } + case 2: + { + return !!(NewState.Triangle && !OldState.Triangle); + + break; + } + + case 3: + { + return !!(NewState.Circle && !OldState.Circle); + + break; + } + } + + return false; +} + +bool CPad::DuckJustDown(void) +{ + if (ArePlayerControlsDisabled()) + return false; + + return !!(NewState.LeftShock && !OldState.LeftShock); +} + bool CPad::JumpJustDown(void) { if ( ArePlayerControlsDisabled() ) @@ -2339,11 +3034,9 @@ bool CPad::ShiftTargetRightJustDown(void) if ( ArePlayerControlsDisabled() ) return false; - return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); + return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1) || !!(NewState.RightShoulder2 && !OldState.RightShoulder2); } -#ifdef FIX_BUGS -// FIX: fixes from VC for the bug of double switching the controller setup bool CPad::GetAnaloguePadUp(void) { static int16 oldfStickY = 0; @@ -2456,120 +3149,6 @@ bool CPad::GetAnaloguePadRightJustUp(void) } } -#else -bool CPad::GetAnaloguePadUp(void) -{ - static int16 oldfStickY = 0; - - int16 Y = CPad::GetPad(0)->GetAnalogueUpDown(); - - if ( Y < 0 && oldfStickY >= 0 ) - { - oldfStickY = Y; - return true; - } - else - { - oldfStickY = Y; - return false; - } -} - -bool CPad::GetAnaloguePadDown(void) -{ - static int16 oldfStickY = 0; - - int16 Y = CPad::GetPad(0)->GetAnalogueUpDown(); - - if ( Y > 0 && oldfStickY <= 0 ) - { - oldfStickY = Y; - return true; - } - else - { - oldfStickY = Y; - return false; - } -} - -bool CPad::GetAnaloguePadLeft(void) -{ - static int16 oldfStickX = 0; - - int16 X = CPad::GetPad(0)->GetPedWalkLeftRight(); - - if ( X < 0 && oldfStickX >= 0 ) - { - oldfStickX = X; - return true; - } - else - { - oldfStickX = X; - return false; - } -} - -bool CPad::GetAnaloguePadRight(void) -{ - static int16 oldfStickX = 0; - - int16 X = CPad::GetPad(0)->GetPedWalkLeftRight(); - - if ( X > 0 && oldfStickX <= 0 ) - { - oldfStickX = X; - return true; - } - else - { - oldfStickX = X; - return false; - } -} - -bool CPad::GetAnaloguePadLeftJustUp(void) -{ - static int16 oldfStickX = 0; - - int16 X = GetPad(0)->GetPedWalkLeftRight(); - - if ( X == 0 && oldfStickX < 0 ) - { - oldfStickX = 0; - - return true; - } - else - { - oldfStickX = X; - - return false; - } -} - -bool CPad::GetAnaloguePadRightJustUp(void) -{ - static int16 oldfStickX = 0; - - int16 X = GetPad(0)->GetPedWalkLeftRight(); - - if ( X == 0 && oldfStickX > 0 ) - { - oldfStickX = 0; - - return true; - } - else - { - oldfStickX = X; - - return false; - } -} -#endif - bool CPad::ForceCameraBehindPlayer(void) { if ( ArePlayerControlsDisabled() ) @@ -2664,9 +3243,13 @@ int16 CPad::SniperModeLookLeftRight(void) int16 axis = NewState.LeftStickX; int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2; - if ( Abs(axis) > Abs(dpad) ) - return axis; - else + if ( Abs(axis) > Abs(dpad) ) { + if ( Abs(axis) > 35.0f ) { + return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35)); + } else { + return 0; + } + } else return dpad; } @@ -2674,23 +3257,24 @@ int16 CPad::SniperModeLookUpDown(void) { int16 axis = NewState.LeftStickY; int16 dpad; + #ifdef FIX_BUGS axis = -axis; #endif -#ifndef INVERT_LOOK_FOR_PAD - dpad = (NewState.DPadUp - NewState.DPadDown) / 2; -#else if (CPad::bInvertLook4Pad) { axis = -axis; dpad = (NewState.DPadDown - NewState.DPadUp) / 2; } else { dpad = (NewState.DPadUp - NewState.DPadDown) / 2; } -#endif - if ( Abs(axis) > Abs(dpad) ) - return axis; - else + if ( Abs(axis) > Abs(dpad) ) { + if ( Abs(axis) > 35.0f ) { + return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35)); + } else { + return 0; + } + } else return dpad; } @@ -2712,14 +3296,11 @@ int16 CPad::LookAroundLeftRight(void) int16 CPad::LookAroundUpDown(void) { int16 axis = GetPad(0)->NewState.RightStickY; - #ifdef FIX_BUGS axis = -axis; #endif -#ifdef INVERT_LOOK_FOR_PAD if (CPad::bInvertLook4Pad) axis = -axis; -#endif if ( Abs(axis) > 85 && !GetLookBehindForPed() ) return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) ) @@ -2732,7 +3313,6 @@ int16 CPad::LookAroundUpDown(void) return 0; } - void CPad::ResetAverageWeapon(void) { AverageWeapon = GetWeapon(); @@ -2741,8 +3321,12 @@ void CPad::ResetAverageWeapon(void) void CPad::PrintErrorMessage(void) { + if (TheCamera.m_WideScreenOn) + return; + if ( bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive ) { + CSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(20.0f), SCREEN_SCALE_FROM_BOTTOM(130.0f), SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_SCALE_Y(140.0f)), CRGBA(50, 50, 50, 210)); #ifdef FIX_BUGS CFont::SetScale(SCREEN_SCALE_X(0.85f), SCREEN_SCALE_Y(1.0f)); #else @@ -2758,16 +3342,17 @@ void CPad::PrintErrorMessage(void) CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::PrintString ( SCREEN_WIDTH / 2, - SCREEN_HEIGHT / 2, + SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(40.0f), TheText.Get("NOCONT") // Please reconnect an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). to controller port 1 to continue ); } else if ( bObsoleteControllerMessage ) { + CSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(20.0f), SCREEN_SCALE_FROM_BOTTOM(130.0f), SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_SCALE_Y(140.0f)), CRGBA(50, 50, 50, 210)); #ifdef FIX_BUGS CFont::SetScale(SCREEN_SCALE_X(0.85f), SCREEN_SCALE_Y(1.0f)); #else @@ -2783,11 +3368,11 @@ void CPad::PrintErrorMessage(void) CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetColor(CRGBA(255, 255, 200, 200)); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::PrintString ( SCREEN_WIDTH / 2, - SCREEN_HEIGHT / 2, + SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(40.0f), TheText.Get("WRCONT") // The controller connected to controller port 1 is an unsupported controller. Grand Theft Auto III requires an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). ); } @@ -2805,20 +3390,33 @@ void CPad::ResetCheats(void) { CWeather::ReleaseWeather(); + gbFastTime = false; CPopulation::ms_bGivePedsWeapons = false; - - CPed::bNastyLimbsCheat = false; - CPed::bPedCheat2 = false; - CPed::bPedCheat3 = false; + CTimer::SetTimeScale(1.0f); CVehicle::bWheelsOnlyCheat = false; CVehicle::bAllDodosCheat = false; CVehicle::bCheat3 = false; CVehicle::bCheat4 = false; CVehicle::bCheat5 = false; + CVehicle::bAllTaxisHaveNitro = false; + CVehicle::bHoverCheat = false; + CVehicle::bCheat8 = false; + CVehicle::bCheat9 = false; + CVehicle::bCheat10 = false; +#ifdef RESTORE_ALLCARSHELI_CHEAT + bAllCarCheat = false; +#endif + gbBlackCars = false; + gbPinkCars = false; + + CCarCtrl::bMadDriversCheat = false; + CTrafficLights::bGreenLightsCheat = false; + CStats::ShowChaseStatOnScreen = 0; + CPed::bNastyLimbsCheat = false; + CPed::bFannyMagnetCheat = false; + CPed::bPedCheat3 = false; - gbFastTime = false; - CTimer::SetTimeScale(1.0f); } char *CPad::EditString(char *pStr, int32 nSize) @@ -3023,3 +3621,13 @@ int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize) return pRsKeys; } + +void CPad::FixPadsAfterSave(void) +{ + UpdatePads(); + if ( bObsoleteControllerMessage ) + { + bObsoleteControllerMessage = false; + GetPad(0)->Phase = 0; + } +} diff --git a/src/core/Pad.h b/src/core/Pad.h index b37659cd..f141ed6c 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -10,6 +10,7 @@ enum { PLAYERCONTROL_PLAYERINFO = 32, PLAYERCONTROL_PHONE = 64, PLAYERCONTROL_CUTSCENE = 128, + PLAYERCONTROL_SHORTCUT_TAXI = 256, }; class CControllerState @@ -140,9 +141,12 @@ public: enum { HORNHISTORY_SIZE = 5, + DRUNK_STEERING_BUFFER_SIZE = 10, }; CControllerState NewState; CControllerState OldState; + int16 SteeringLeftRightBuffer[DRUNK_STEERING_BUFFER_SIZE]; + int32 DrunkDrivingBufferUsed; CControllerState PCTempKeyState; CControllerState PCTempJoyState; CControllerState PCTempMouseState; @@ -150,10 +154,11 @@ public: int16 Phase; int16 Mode; int16 ShakeDur; + uint16 DisablePlayerControls; uint8 ShakeFreq; bool bHornHistory[HORNHISTORY_SIZE]; uint8 iCurrHornHistory; - uint8 DisablePlayerControls; + int8 JustOutOfFrontend; int8 bApplyBrakes; char CheatString[12]; int32 LastTimeTouched; @@ -170,14 +175,14 @@ public: static bool bObsoleteControllerMessage; static bool bOldDisplayNoControllerMessage; static bool m_bMapPadOneToPadTwo; -#ifdef INVERT_LOOK_FOR_PAD + static bool m_bDebugCamPCOn; + static bool bHasPlayerCheated; static bool bInvertLook4Pad; -#endif static CKeyboardState OldKeyState; static CKeyboardState NewKeyState; static CKeyboardState TempKeyState; - static char KeyBoardCheatString[20]; + static char KeyBoardCheatString[30]; static CMouseControllerState OldMouseControllerState; static CMouseControllerState NewMouseControllerState; static CMouseControllerState PCTempMouseControllerState; @@ -188,6 +193,7 @@ public: #endif void Clear(bool bResetPlayerControls); void ClearMouseHistory(); + void ClearKeyBoardHistory(); void UpdateMouse(); CControllerState ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2); void StartShake(int16 nDur, uint8 nFreq); @@ -217,6 +223,7 @@ public: int16 GetPedWalkLeftRight(void); int16 GetPedWalkUpDown(void); int16 GetAnalogueUpDown(void); + int16 GetAnalogueLeftRight(void); bool GetLookLeft(void); bool GetLookRight(void); bool GetLookBehindForCar(void); @@ -232,6 +239,7 @@ public: int32 GetWeapon(void); bool WeaponJustDown(void); int16 GetAccelerate(void); + bool CycleCameraModeJustDown(void); bool CycleCameraModeUpJustDown(void); bool CycleCameraModeDownJustDown(void); bool ChangeStationJustDown(void); @@ -239,6 +247,8 @@ public: bool CycleWeaponRightJustDown(void); bool GetTarget(void); bool TargetJustDown(void); + bool DuckJustDown(void); + bool CollectPickupJustDown(void); bool JumpJustDown(void); bool GetSprint(void); bool ShiftTargetLeftJustDown(void); @@ -257,10 +267,13 @@ public: int16 LookAroundLeftRight(void); int16 LookAroundUpDown(void); void ResetAverageWeapon(void); + static void FixPadsAfterSave(void); static void PrintErrorMessage(void); static void ResetCheats(void); static char *EditString(char *pStr, int32 nSize); static int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize); + uint32 InputHowLongAgo(void); + void SetDrunkInputDelay(int32 delay) { DrunkDrivingBufferUsed = delay; } #ifdef XINPUT static int XInputJoy1; @@ -425,6 +438,7 @@ public: bool GetLeftShockJustDown() { return !!(NewState.LeftShock && !OldState.LeftShock); } bool GetRightShockJustDown() { return !!(NewState.RightShock && !OldState.RightShock); } bool GetStartJustDown() { return !!(NewState.Start && !OldState.Start); } + bool GetSelectJustDown() { return !!(NewState.Select && !OldState.Select); } bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); } bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); } @@ -450,15 +464,16 @@ public: bool GetRightShoulder1(void) { return !!NewState.RightShoulder1; } bool GetRightShoulder2(void) { return !!NewState.RightShoulder2; } bool GetStart() { return !!NewState.Start; } + bool GetSelect() { return !!NewState.Select; } int16 GetLeftStickX(void) { return NewState.LeftStickX; } int16 GetLeftStickY(void) { return NewState.LeftStickY; } int16 GetRightStickX(void) { return NewState.RightStickX; } int16 GetRightStickY(void) { return NewState.RightStickY; } bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; } - void SetDisablePlayerControls(uint8 who) { DisablePlayerControls |= who; } - void SetEnablePlayerControls(uint8 who) { DisablePlayerControls &= ~who; } - bool IsPlayerControlsDisabledBy(uint8 who) { return DisablePlayerControls & who; } + void SetDisablePlayerControls(uint16 who) { DisablePlayerControls |= who; } + void SetEnablePlayerControls(uint16 who) { DisablePlayerControls &= ~who; } + bool IsPlayerControlsDisabledBy(uint16 who) { return DisablePlayerControls & who; } int16 GetMode() { return Mode; } void SetMode(int16 mode) { Mode = mode; } @@ -468,7 +483,3 @@ public: VALIDATE_SIZE(CPad, 0xFC); extern CPad Pads[MAX_PADS]; - -#ifdef ALLCARSHELI_CHEAT -extern bool bAllCarCheat; -#endif diff --git a/src/core/Placeable.cpp b/src/core/Placeable.cpp index 162148f7..6efc1540 100644 --- a/src/core/Placeable.cpp +++ b/src/core/Placeable.cpp @@ -7,10 +7,6 @@ CPlaceable::CPlaceable(void) m_matrix.SetScale(1.0f); } -CPlaceable::~CPlaceable(void) -{ -} - void CPlaceable::SetHeading(float angle) { diff --git a/src/core/Placeable.h b/src/core/Placeable.h index 2f246bc5..94be3211 100644 --- a/src/core/Placeable.h +++ b/src/core/Placeable.h @@ -7,10 +7,9 @@ protected: public: // disable allocation - static void *operator new(size_t) throw(); + static void *operator new(size_t); CPlaceable(void); - virtual ~CPlaceable(void); const CVector &GetPosition(void) { return m_matrix.GetPosition(); } void SetPosition(float x, float y, float z) { m_matrix.GetPosition().x = x; @@ -34,4 +33,4 @@ public: bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2); }; -VALIDATE_SIZE(CPlaceable, 0x4C); +VALIDATE_SIZE(CPlaceable, 0x48); diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 91bd0691..36d05b82 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -31,7 +31,11 @@ #include "World.h" #include "ZoneCull.h" #include "main.h" +#include "Bike.h" +#include "Automobile.h" +#include "GameLogic.h" +CVector lastPlayerPos; void CPlayerInfo::Clear(void) @@ -49,6 +53,8 @@ CPlayerInfo::Clear(void) m_nTrafficMultiplier = 0; m_fRoadDensity = 1.0f; m_bInRemoteMode = false; + field_D5 = false; + field_D6 = false; m_bUnusedTaxiThing = false; m_nUnusedTaxiTimer = 0; m_nCollectedPackages = 0; @@ -60,14 +66,35 @@ CPlayerInfo::Clear(void) m_nSexFrequency = 0; m_pHooker = nil; m_nTimeTankShotGun = 0; - field_248 = 0; + field_EC = 0; m_nUpsideDownCounter = 0; + m_nTimeCarSpentOnTwoWheels = 0; + m_nDistanceCarTravelledOnTwoWheels = 0; + m_nTimeNotFullyOnGround = 0; + m_nTimeSpentOnWheelie = 0; + m_nDistanceTravelledOnWheelie = 0.0f; + m_nTimeSpentOnStoppie = 0; + m_nDistanceTravelledOnStoppie = 0.0f; + m_nCancelWheelStuntTimer = 0; + m_nLastTimeCarSpentOnTwoWheels = 0; + m_nLastDistanceCarTravelledOnTwoWheels = 0; + m_nLastTimeSpentOnWheelie = 0; + m_nLastDistanceTravelledOnWheelie = 0; + m_nLastTimeSpentOnStoppie = 0; + m_nLastDistanceTravelledOnStoppie = 0; m_bInfiniteSprint = false; m_bFastReload = false; + m_bFireproof = false; + m_nMaxHealth = m_nMaxArmour = 100; m_bGetOutOfJailFree = false; m_bGetOutOfHospitalFree = false; + m_bDriveByAllowed = true; m_nPreviousTimeRewardedForExplosion = 0; m_nExplosionsSinceLastReward = 0; + m_nHavocLevel = 0; + m_fMediaAttention = 0.0f; + m_nCurrentBustedAudio = 1; + m_nBustedAudioStatus = BUSTEDAUDIO_NONE; } void @@ -81,7 +108,7 @@ CPlayerInfo::Process(void) bool startTaxiTimer = true; if (m_bUnusedTaxiThing && m_pPed->bInVehicle) { CVehicle *veh = m_pPed->m_pMyVehicle; - if ((veh->GetModelIndex() == MI_TAXI || veh->GetModelIndex() == MI_CABBIE || veh->GetModelIndex() == MI_BORGNINE) + if (veh->IsTaxi() && veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) { for (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) { timePassed -= 1000; @@ -93,6 +120,157 @@ CPlayerInfo::Process(void) if (startTaxiTimer) m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds(); + if (!m_pPed->InVehicle()) { + m_nTimeCarSpentOnTwoWheels = 0; + m_nTimeNotFullyOnGround = 0; + m_nTimeSpentOnWheelie = 0; + m_nTimeSpentOnStoppie = 0; + m_nCancelWheelStuntTimer = 0; + } else if (m_pPed->m_pMyVehicle->IsCar()) { + CAutomobile *car = (CAutomobile*)m_pPed->m_pMyVehicle; + + if (car->m_nWheelsOnGround < 3) + m_nTimeNotFullyOnGround += CTimer::GetTimeStepInMilliseconds(); + else + m_nTimeNotFullyOnGround = 0; + + if (car->m_aSuspensionSpringRatioPrev[2] == 1.f && car->m_aSuspensionSpringRatioPrev[3] == 1.f) { + if (car->m_aSuspensionSpringRatioPrev[0] < 1.0f && car->m_aSuspensionSpringRatioPrev[1] < 1.0f && car->m_fDamageImpulse == 0.0f) { + m_nTimeCarSpentOnTwoWheels += CTimer::GetTimeStepInMilliseconds(); + m_nDistanceCarTravelledOnTwoWheels += car->m_fDistanceTravelled; + m_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.5f); + + } else { + if (m_nTimeCarSpentOnTwoWheels != 0 && m_nCancelWheelStuntTimer < 500) { + m_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds(); + } else { + if (m_nTimeCarSpentOnTwoWheels >= 2000) { + m_nLastTimeCarSpentOnTwoWheels = m_nTimeCarSpentOnTwoWheels; + m_nLastDistanceCarTravelledOnTwoWheels = m_nDistanceCarTravelledOnTwoWheels; + if (CStats::Longest2Wheel < m_nTimeCarSpentOnTwoWheels / 1000) + CStats::Longest2Wheel = m_nTimeCarSpentOnTwoWheels / 1000; + if (CStats::Longest2WheelDist < m_nDistanceCarTravelledOnTwoWheels) + CStats::Longest2WheelDist = m_nDistanceCarTravelledOnTwoWheels; + } + m_nTimeCarSpentOnTwoWheels = 0; + m_nDistanceCarTravelledOnTwoWheels = 0; + m_nCancelWheelStuntTimer = 0; + } + } + } else if (car->m_aSuspensionSpringRatioPrev[0] == 1.0f && car->m_aSuspensionSpringRatioPrev[1] == 1.0f) { +#ifdef FIX_BUGS + if (car->m_aSuspensionSpringRatioPrev[2] < 1.f +#else + if (car->m_aSuspensionSpringRatioPrev[1] < 1.f +#endif + && car->m_aSuspensionSpringRatioPrev[3] < 1.f && 0.0f == car->m_fDamageImpulse) { + m_nTimeCarSpentOnTwoWheels += CTimer::GetTimeStepInMilliseconds(); + m_nDistanceCarTravelledOnTwoWheels += car->m_fDistanceTravelled; + m_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.2f); + + } else if (m_nTimeCarSpentOnTwoWheels != 0 && m_nCancelWheelStuntTimer < 500) { + m_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds(); + + } else { + if (m_nTimeCarSpentOnTwoWheels >= 2000) { + m_nLastTimeCarSpentOnTwoWheels = m_nTimeCarSpentOnTwoWheels; + m_nLastDistanceCarTravelledOnTwoWheels = m_nDistanceCarTravelledOnTwoWheels; + if (CStats::Longest2Wheel < m_nTimeCarSpentOnTwoWheels / 1000) + CStats::Longest2Wheel = m_nTimeCarSpentOnTwoWheels / 1000; + if (CStats::Longest2WheelDist < m_nDistanceCarTravelledOnTwoWheels) + CStats::Longest2WheelDist = m_nDistanceCarTravelledOnTwoWheels; + } + m_nTimeCarSpentOnTwoWheels = 0; + m_nDistanceCarTravelledOnTwoWheels = 0; + m_nCancelWheelStuntTimer = 0; + } + } else if (m_nTimeCarSpentOnTwoWheels != 0) { + if (m_nTimeCarSpentOnTwoWheels >= 2000) { + m_nLastTimeCarSpentOnTwoWheels = m_nTimeCarSpentOnTwoWheels; + m_nLastDistanceCarTravelledOnTwoWheels = m_nDistanceCarTravelledOnTwoWheels; + if (CStats::Longest2Wheel < m_nTimeCarSpentOnTwoWheels / 1000) + CStats::Longest2Wheel = m_nTimeCarSpentOnTwoWheels / 1000; + if (CStats::Longest2WheelDist < m_nDistanceCarTravelledOnTwoWheels) + CStats::Longest2WheelDist = m_nDistanceCarTravelledOnTwoWheels; + } + m_nTimeCarSpentOnTwoWheels = 0; + m_nDistanceCarTravelledOnTwoWheels = 0; + m_nCancelWheelStuntTimer = 0; + } + m_nTimeSpentOnWheelie = 0; + m_nTimeSpentOnStoppie = 0; + } else if (m_pPed->m_pMyVehicle->IsBike()) { + CBike *bike = (CBike*)m_pPed->m_pMyVehicle; + if (bike->m_aSuspensionSpringRatioPrev[0] == 1.0f && bike->m_aSuspensionSpringRatioPrev[1] == 1.0f) { + if (bike->m_aSuspensionSpringRatioPrev[2] < 1.0f + || (bike->m_aSuspensionSpringRatioPrev[3] < 1.0f && 0.0f == bike->m_fDamageImpulse)) { + m_nTimeSpentOnWheelie += CTimer::GetTimeStepInMilliseconds(); + m_nDistanceTravelledOnWheelie += bike->m_fDistanceTravelled; + m_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.2f); + + } else { + if (m_nTimeSpentOnWheelie != 0 && m_nCancelWheelStuntTimer < 500) { + m_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds(); + } else { + if (m_nTimeSpentOnWheelie >= 5000) { + m_nLastTimeSpentOnWheelie = m_nTimeSpentOnWheelie; + m_nLastDistanceTravelledOnWheelie = m_nDistanceTravelledOnWheelie; + if (CStats::LongestWheelie < m_nTimeSpentOnWheelie / 1000) + CStats::LongestWheelie = m_nTimeSpentOnWheelie / 1000; + if (CStats::LongestWheelieDist < m_nDistanceTravelledOnWheelie) + CStats::LongestWheelieDist = m_nDistanceTravelledOnWheelie; + } + m_nTimeSpentOnWheelie = 0; + m_nDistanceTravelledOnWheelie = 0; + m_nCancelWheelStuntTimer = 0; + } + } + } else if (m_nTimeSpentOnWheelie != 0) { + if (m_nTimeSpentOnWheelie >= 5000) { + m_nLastTimeSpentOnWheelie = m_nTimeSpentOnWheelie; + m_nLastDistanceTravelledOnWheelie = m_nDistanceTravelledOnWheelie; + if (CStats::LongestWheelie < m_nTimeSpentOnWheelie / 1000) + CStats::LongestWheelie = m_nTimeSpentOnWheelie / 1000; + if (CStats::LongestWheelieDist < m_nDistanceTravelledOnWheelie) + CStats::LongestWheelieDist = m_nDistanceTravelledOnWheelie; + } + m_nTimeSpentOnWheelie = 0; + m_nDistanceTravelledOnWheelie = 0; + m_nCancelWheelStuntTimer = 0; + + } else if (bike->m_aSuspensionSpringRatioPrev[2] == 1.0f && bike->m_aSuspensionSpringRatioPrev[3] == 1.0f + && 0.0f == bike->m_fDamageImpulse) { + m_nTimeSpentOnStoppie += CTimer::GetTimeStepInMilliseconds(); + m_nDistanceTravelledOnStoppie += bike->m_fDistanceTravelled; + m_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.2f); + + } else { + if (m_nTimeSpentOnStoppie != 0 && m_nCancelWheelStuntTimer < 500) { + m_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds(); + } else { + if (m_nTimeSpentOnStoppie >= 2000) { + m_nLastTimeSpentOnStoppie = m_nTimeSpentOnStoppie; + m_nLastDistanceTravelledOnStoppie = m_nDistanceTravelledOnStoppie; + if (CStats::LongestStoppie < m_nTimeSpentOnStoppie / 1000) + CStats::LongestStoppie = m_nTimeSpentOnStoppie / 1000; + if (CStats::LongestStoppieDist < m_nDistanceTravelledOnStoppie) + CStats::LongestStoppieDist = m_nDistanceTravelledOnStoppie; + } + m_nTimeSpentOnStoppie = 0; + m_nDistanceTravelledOnStoppie = 0; + m_nCancelWheelStuntTimer = 0; + } + } + m_nTimeCarSpentOnTwoWheels = 0; + m_nTimeNotFullyOnGround = 0; + } else { + m_nTimeCarSpentOnTwoWheels = 0; + m_nTimeNotFullyOnGround = 0; + m_nTimeSpentOnWheelie = 0; + m_nTimeSpentOnStoppie = 0; + m_nCancelWheelStuntTimer = 0; + } + // The effect that makes money counter does while earning/losing money if (m_nVisibleMoney != m_nMoney) { int diff = m_nMoney - m_nVisibleMoney; @@ -121,7 +299,7 @@ CPlayerInfo::Process(void) m_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y); } - m_fRoadDensity = Clamp(m_fRoadDensity, 0.4f, 1.45f); + m_fRoadDensity = Clamp(m_fRoadDensity, 0.5f, 1.45f); // Because vehicle enter/exit use same key binding. bool enterOrExitVeh; @@ -130,39 +308,31 @@ CPlayerInfo::Process(void) else enterOrExitVeh = CPad::GetPad(0)->GetExitVehicle(); - if (enterOrExitVeh && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_MODE) { + if (enterOrExitVeh && m_pPed->m_nPedState != PED_ANSWER_MOBILE && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_MODE) { if (m_pPed->bInVehicle) { if (!m_pRemoteVehicle) { CEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity; if (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->GetModelIndex())) { CVehicle *veh = m_pPed->m_pMyVehicle; if (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { + if (veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) { + bool canJumpOff = false; + if (veh->m_vehType == VEHICLE_TYPE_BIKE) { + canJumpOff = veh->CanPedJumpOffBike(); + } else if (veh->pDriver == m_pPed) { + canJumpOff = veh->CanPedJumpOutCar(); + } - // This condition will always return true, else block was probably WIP Miami code. - if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { - if (veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) { - if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) { + if (canJumpOff || veh->m_vecMoveSpeed.Magnitude() < 0.1f) { + if (!veh->bIsInWater) m_pPed->SetObjective(OBJECTIVE_LEAVE_CAR, veh); - } + + } else if (veh->GetStatus() != STATUS_PLAYER && veh != CGameLogic::pShortCutTaxi) { + veh->AutoPilot.m_nTempAction = TEMPACT_WAIT; + veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; } - } else { - CVector sth = 0.7f * veh->GetRight() + veh->GetPosition(); - bool found = false; - float groundZ = CWorld::FindGroundZFor3DCoord(sth.x, sth.y, 2.0f + sth.z, &found); - - if (found) - sth.z = 1.0f + groundZ; - m_pPed->SetPedState(PED_IDLE); - m_pPed->SetMoveState(PEDMOVE_STILL); - CPed::PedSetOutCarCB(0, m_pPed); - CAnimManager::BlendAnimation(m_pPed->GetClump(), m_pPed->m_animGroup, ANIM_STD_IDLE, 100.0f); - CAnimManager::BlendAnimation(m_pPed->GetClump(), ASSOCGRP_STD, ANIM_STD_FALL_LAND, 100.0f); - m_pPed->SetPosition(sth); - m_pPed->SetMoveState(PEDMOVE_STILL); - m_pPed->m_vecMoveSpeed = veh->m_vecMoveSpeed; } } else { - // The code in here was under CPed::SetExitBoat in VC, did the same for here. m_pPed->SetExitBoat(veh); m_pPed->bTryingToReachDryLand = true; } @@ -177,14 +347,10 @@ CPlayerInfo::Process(void) CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface; if (surfaceBelow && surfaceBelow->IsVehicle()) { carBelow = (CVehicle*)surfaceBelow; - if (carBelow->IsBoat()) { + if (carBelow->IsBoat() && carBelow->m_modelIndex != MI_SKIMMER) { weAreOnBoat = true; m_pPed->bOnBoat = true; -#ifdef VC_PED_PORTS if (carBelow->GetStatus() != STATUS_WRECKED && carBelow->GetUp().z > 0.3f) -#else - if (carBelow->GetStatus() != STATUS_WRECKED) -#endif m_pPed->SetSeekBoatPosition(carBelow); } } @@ -232,14 +398,15 @@ CPlayerInfo::Process(void) } } } + if (m_bInRemoteMode) { uint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar; - if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING) { + if (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING && field_D6) { TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(1.0f, FADE_OUT); } if (timeWithoutRemoteCar > 2000) { - if (m_WBState == WBSTATE_PLAYING) { + if (m_WBState == WBSTATE_PLAYING && field_D6) { TheCamera.RestoreWithJumpCut(); TheCamera.SetFadeColour(0, 0, 0); TheCamera.Fade(1.0f, FADE_IN); @@ -251,6 +418,7 @@ CPlayerInfo::Process(void) CTimer::Update(); } m_bInRemoteMode = false; + CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bRemoveFromWorld = true; CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil; if (FindPlayerVehicle()) { FindPlayerVehicle()->SetStatus(STATUS_PLAYER); @@ -260,11 +428,10 @@ CPlayerInfo::Process(void) if (!(CTimer::GetFrameCounter() & 31)) { CVehicle *veh = FindPlayerVehicle(); if (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f - && veh->m_vecMoveSpeed.Magnitude() < 0.05f && veh->IsCar() && !veh->bIsInWater) { + && veh->m_vecMoveSpeed.Magnitude() < 0.05f && (veh->IsCar() || veh->IsBoat()) && !veh->bIsInWater) { if (veh->GetUp().z < -0.5f) { m_nUpsideDownCounter += 2; - } else { m_nUpsideDownCounter++; } @@ -288,10 +455,76 @@ CPlayerInfo::Process(void) if (veh->pPassengers[i]) veh->pPassengers[i]->m_nZoneLevel = LEVEL_GENERIC; } - CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled; + if(veh->m_modelIndex == MI_CADDY) + CStats::DistanceTravelledByGolfCart += veh->m_fDistanceTravelled; + else { + if(veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI) + CStats::DistanceTravelledByHelicoptor += veh->m_fDistanceTravelled; + if (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) + CStats::DistanceTravelledByPlane += veh->m_fDistanceTravelled; + if (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR) + CStats::DistanceTravelledByCar += veh->m_fDistanceTravelled; + if (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) + CStats::DistanceTravelledByBike += veh->m_fDistanceTravelled; + if (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) + CStats::DistanceTravelledByBoat += veh->m_fDistanceTravelled; + + if (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) { + if (veh->m_vecMoveSpeed.Magnitude() > 0.2f) { + CStats::FlightTime += CTimer::GetTimeStep() * 16.f; // what a weird choice + } + } + } } else { CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled; } + + if (m_pPed->m_pWanted->GetWantedLevel() && !CTheScripts::IsPlayerOnAMission()) { + float maxDelta = 0.0f; + static bool movedSignificantly = true; + static bool thereIsACarPathNear = true; + // there was one more guard without variable's itself??? + + if (CTimer::GetTimeInMilliseconds() / 20000 != CTimer::GetPreviousTimeInMilliseconds() / 20000) { + float posChange = (lastPlayerPos - FindPlayerCoors()).Magnitude(); + movedSignificantly = posChange >= 10.0f; + lastPlayerPos = FindPlayerCoors(); + thereIsACarPathNear = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 60.0f, true, false, false, false) != 0; + } + switch (m_pPed->m_pWanted->GetWantedLevel()) { + case 1: + maxDelta = 31.f; + break; + case 2: + maxDelta = 62.f; + break; + case 3: + maxDelta = 125.f; + break; + case 4: + maxDelta = 250.f; + break; + case 5: + maxDelta = 500.f; + break; + case 6: + maxDelta = 1000.f; + break; + default: + break; + } + float increaseDelta = maxDelta - m_fMediaAttention; + float increaseAttentionBy = CTimer::GetTimeStep() * 0.0001f * increaseDelta; + if (increaseAttentionBy < 0.0f + || movedSignificantly && thereIsACarPathNear && !CCullZones::NoPolice() && !CCullZones::PoliceAbandonCars() && CGame::currArea == AREA_MAIN_MAP) { + m_fMediaAttention += increaseAttentionBy; + } + } else { + m_fMediaAttention = 0.0f; + } + CStats::HighestChaseValue = Max(m_fMediaAttention, CStats::HighestChaseValue); + m_nMoney = Min(999999999, m_nMoney); + m_nVisibleMoney = Min(999999999, m_nVisibleMoney); } bool @@ -317,9 +550,15 @@ CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size) CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFireproof); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxHealth); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxArmour); CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bDriveByAllowed); CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nBustedAudioStatus); + CopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCurrentBustedAudio); #undef CopyToBuf } @@ -337,9 +576,15 @@ CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size) CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint); CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFireproof); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxHealth); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxArmour); CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree); CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree); - CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName) + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bDriveByAllowed); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nBustedAudioStatus); + CopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCurrentBustedAudio) #undef CopyFromBuf } @@ -357,7 +602,7 @@ CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, && (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) { CVector carCentre = car->GetBoundCentre(); - if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) { + if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f || car->IsCar() && carCentre.z < ped->GetPosition().z && ped->GetPosition().z - 4.f < carCentre.z) { float dist = (ped->GetPosition() - carCentre).Magnitude2D(); if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput); @@ -531,6 +776,7 @@ CPlayerInfo::ArrestPlayer() m_WBState = WBSTATE_BUSTED; m_nWBTime = CTimer::GetTimeInMilliseconds(); + m_nBustedAudioStatus = BUSTEDAUDIO_NONE; CDarkel::ResetOnPlayerDeath(); CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2); CStats::TimesArrested++; @@ -561,7 +807,6 @@ void CPlayerInfo::MakePlayerSafe(bool toggle) { if (toggle) { - CTheScripts::ResetCountdownToMakePlayerUnsafe(); m_pPed->m_pWanted->m_bIgnoredByEveryone = true; CWorld::StopAllLawEnforcersInTheirTracks(); CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PLAYERINFO); @@ -582,7 +827,7 @@ CPlayerInfo::MakePlayerSafe(bool toggle) CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); CReplay::DisableReplays(); - } else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { + } else { m_pPed->m_pWanted->m_bIgnoredByEveryone = false; CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PLAYERINFO); m_pPed->bBulletProof = false; @@ -598,39 +843,14 @@ CPlayerInfo::MakePlayerSafe(bool toggle) } void -CPlayerInfo::BlowUpRCBuggy(void) +CPlayerInfo::BlowUpRCBuggy(bool actually) { if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld) return; - CRemote::TakeRemoteControlledCarFromPlayer(); - m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); -} - -// There is something unfinished in here... Sadly all IDBs we have have it unfinished. -void -CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar) -{ - if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000) - ++m_nExplosionsSinceLastReward; - else - m_nExplosionsSinceLastReward = 1; - - m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds(); - int award = wreckedCar->pHandling->nMonetaryValue * 0.002f; - sprintf(gString, "$%d", award); -#ifdef MONEY_MESSAGES - // This line is a leftover from PS2, I don't know what it was meant to be. - // CVector sth(TheCamera.GetPosition() * 4.0f); - - CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f); -#endif - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; - - for (int i = m_nExplosionsSinceLastReward; i > 1; --i) { - CGeneral::GetRandomNumber(); - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award; - } + CRemote::TakeRemoteControlledCarFromPlayer(actually); + if (actually) + m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); } #ifdef GTA_PC @@ -647,8 +867,6 @@ CPlayerInfo::LoadPlayerSkin() DeletePlayerSkin(); m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName); - if (!m_pSkinTexture) - m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME); } void @@ -659,4 +877,4 @@ CPlayerInfo::DeletePlayerSkin() m_pSkinTexture = nil; } } -#endif
\ No newline at end of file +#endif diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 956756e4..fc12267d 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -10,6 +10,13 @@ enum eWastedBustedState WBSTATE_FAILED_CRITICAL_MISSION, }; +enum eBustedAudioState +{ + BUSTEDAUDIO_NONE, + BUSTEDAUDIO_LOADING, + BUSTEDAUDIO_DONE +}; + class CEntity; class CPed; class CVehicle; @@ -38,29 +45,51 @@ public: int8 m_WBState; // eWastedBustedState uint32 m_nWBTime; bool m_bInRemoteMode; + bool field_D5; + bool field_D6; uint32 m_nTimeLostRemoteCar; uint32 m_nTimeLastHealthLoss; uint32 m_nTimeLastArmourLoss; uint32 m_nTimeTankShotGun; int32 m_nUpsideDownCounter; - int32 field_248; + int32 field_EC; + int32 m_nTimeCarSpentOnTwoWheels; + float m_nDistanceCarTravelledOnTwoWheels; + int32 m_nTimeNotFullyOnGround; + int32 m_nTimeSpentOnWheelie; + float m_nDistanceTravelledOnWheelie; + int32 m_nTimeSpentOnStoppie; + float m_nDistanceTravelledOnStoppie; + int32 m_nCancelWheelStuntTimer; + int32 m_nLastTimeCarSpentOnTwoWheels; + float m_nLastDistanceCarTravelledOnTwoWheels; + int32 m_nLastTimeSpentOnWheelie; + float m_nLastDistanceTravelledOnWheelie; + int32 m_nLastTimeSpentOnStoppie; + float m_nLastDistanceTravelledOnStoppie; int16 m_nTrafficMultiplier; + int16 field_12A; float m_fRoadDensity; uint32 m_nPreviousTimeRewardedForExplosion; - int32 m_nExplosionsSinceLastReward; - int32 field_268; - int32 field_272; + uint32 m_nExplosionsSinceLastReward; + uint32 m_nHavocLevel; + float m_fMediaAttention; bool m_bInfiniteSprint; bool m_bFastReload; + bool m_bFireproof; + uint8 m_nMaxHealth; + uint8 m_nMaxArmour; bool m_bGetOutOfJailFree; bool m_bGetOutOfHospitalFree; + bool m_bDriveByAllowed; + uint8 m_nBustedAudioStatus; + int16 m_nCurrentBustedAudio; #ifdef GTA_PC char m_aSkinName[32]; RwTexture *m_pSkinTexture; #endif void MakePlayerSafe(bool); - void AwardMoneyForExplosion(CVehicle *vehicle); const CVector &GetPos(); void Process(void); void KillPlayer(void); @@ -68,7 +97,7 @@ public: bool IsPlayerInRemoteMode(void); void PlayerFailedCriticalMission(void); void Clear(void); - void BlowUpRCBuggy(void); + void BlowUpRCBuggy(bool); void CancelPlayerEnteringCars(CVehicle*); bool IsRestartingAfterDeath(void); bool IsRestartingAfterArrest(void); @@ -92,6 +121,4 @@ CVector FindPlayerCoors(void); const CVector &FindPlayerSpeed(void); const CVector &FindPlayerCentreOfWorld(int32 player); const CVector &FindPlayerCentreOfWorld_NoSniperShift(void); -float FindPlayerHeading(void); - -VALIDATE_SIZE(CPlayerInfo, 0x13C); +float FindPlayerHeading(void);
\ No newline at end of file diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index b0248664..e601b3c8 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -2,6 +2,7 @@ #include "Pools.h" +#include "Bike.h" #include "Boat.h" #include "CarCtrl.h" #ifdef MISSION_REPLAY @@ -14,6 +15,7 @@ #include "Wanted.h" #include "World.h" #include "MemoryHeap.h" +#include "SaveBuf.h" CCPtrNodePool *CPools::ms_pPtrNodePool; CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool; @@ -24,8 +26,10 @@ CTreadablePool *CPools::ms_pTreadablePool; CObjectPool *CPools::ms_pObjectPool; CDummyPool *CPools::ms_pDummyPool; CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool; +CColModelPool *CPools::ms_pColModelPool; -#ifdef GTA_PS2 // or USE_CUSTOM_ALLOCATOR +#if defined GTA_PS2 && !defined MASTER // or USE_CUSTOM_ALLOCATOR +// not in VC. perhaps ifdef'ed away #define CHECKMEM(msg) CMemCheck::AllocateMemCheckBlock(msg) #else #define CHECKMEM(msg) @@ -36,23 +40,25 @@ CPools::Initialise(void) { PUSH_MEMID(MEMID_POOLS); CHECKMEM("before pools"); - ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES); + ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES, "PtrNode"); CHECKMEM("after CPtrNodePool"); - ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS); + ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS, "EntryInfoNode"); CHECKMEM("after CEntryInfoNodePool"); - ms_pPedPool = new CPedPool(NUMPEDS); + ms_pPedPool = new CPedPool(NUMPEDS, "Peds"); CHECKMEM("after CPedPool"); - ms_pVehiclePool = new CVehiclePool(NUMVEHICLES); + ms_pVehiclePool = new CVehiclePool(NUMVEHICLES, "Vehicles"); CHECKMEM("after CVehiclePool"); - ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS); + ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS, "Buildings"); CHECKMEM("after CBuildingPool"); - ms_pTreadablePool = new CTreadablePool(NUMTREADABLES); + ms_pTreadablePool = new CTreadablePool(NUMTREADABLES, "Treadables"); CHECKMEM("after CTreadablePool"); - ms_pObjectPool = new CObjectPool(NUMOBJECTS); + ms_pObjectPool = new CObjectPool(NUMOBJECTS, "Objects"); CHECKMEM("after CObjectPool"); - ms_pDummyPool = new CDummyPool(NUMDUMMIES); + ms_pDummyPool = new CDummyPool(NUMDUMMIES, "Dummys"); CHECKMEM("after CDummyPool"); - ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS); + ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS, "AudioScriptObj"); + CHECKMEM("after cAudioScriptObjectPool"); + ms_pColModelPool = new CColModelPool(NUMCOLMODELS, "ColModel"); CHECKMEM("after pools"); POP_MEMID(); } @@ -69,6 +75,7 @@ CPools::ShutDown(void) debug("Objects left %d\n", ms_pObjectPool->GetNoOfUsedSpaces()); debug("Dummys left %d\n", ms_pDummyPool->GetNoOfUsedSpaces()); debug("AudioScriptObjects left %d\n", ms_pAudioScriptObjectPool->GetNoOfUsedSpaces()); + debug("ColModels left %d\n", ms_pColModelPool->GetNoOfUsedSpaces()); printf("Shutdown pool started\n"); delete ms_pPtrNodePool; @@ -80,6 +87,7 @@ CPools::ShutDown(void) delete ms_pObjectPool; delete ms_pDummyPool; delete ms_pAudioScriptObjectPool; + delete ms_pColModelPool; printf("Shutdown pool done\n"); } @@ -99,7 +107,7 @@ CPools::CheckPoolsEmpty() printf("pools have been cleared\n"); } - +// Thankfully unused, it would break the game! void CPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot) { @@ -131,10 +139,11 @@ CPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot) void CPools::LoadVehiclePool(uint8* buf, uint32 size) { INITSAVEBUF - int nNumCars, nNumBoats; + int nNumCars, nNumBoats, nNumBikes; ReadSaveBuf(&nNumCars, buf); ReadSaveBuf(&nNumBoats, buf); - for (int i = 0; i < nNumCars + nNumBoats; i++) { + ReadSaveBuf(&nNumBikes, buf); + for (int i = 0; i < nNumCars + nNumBoats + nNumBikes; i++) { uint32 type; int16 model; int32 slot; @@ -150,13 +159,15 @@ INITSAVEBUF pVehicle = new(slot) CBoat(model, RANDOM_VEHICLE); else if (type == VEHICLE_TYPE_CAR) pVehicle = new(slot) CAutomobile(model, RANDOM_VEHICLE); + else if (type == VEHICLE_TYPE_BIKE) + pVehicle = new(slot) CBike(model, RANDOM_VEHICLE); else assert(0); --CCarCtrl::NumRandomCars; pVehicle->Load(buf); CWorld::Add(pVehicle); #else - char* vbuf = new char[Max(CAutomobile::nSaveStructSize, CBoat::nSaveStructSize)]; + char* vbuf = new char[Max(CBike::nSaveStructSize, Max(CAutomobile::nSaveStructSize, CBoat::nSaveStructSize))]; if (type == VEHICLE_TYPE_BOAT) { memcpy(vbuf, buf, sizeof(CBoat)); SkipSaveBuf(buf, sizeof(CBoat)); @@ -175,6 +186,17 @@ INITSAVEBUF pAutomobile->Damage = ((CAutomobile*)vbuf)->Damage; pAutomobile->SetupDamageAfterLoad(); } + else if (type == VEHICLE_TYPE_BIKE) { +#ifdef FIX_BUGS + memcpy(vbuf, buf, sizeof(CBike)); +#else + memcpy(vbuf, buf, sizeof(CAutomobile)); +#endif + SkipSaveBuf(buf, sizeof(CBike)); + CBike* pBike = new(slot) CBike(model, RANDOM_VEHICLE); + pVehicle = pBike; + --CCarCtrl::NumRandomCars; + } else assert(0); CVehicle* pBufferVehicle = (CVehicle*)vbuf; @@ -212,6 +234,7 @@ INITSAVEBUF (pVehicle->GetAddressOfEntityProperties())[0] = (pBufferVehicle->GetAddressOfEntityProperties())[0]; (pVehicle->GetAddressOfEntityProperties())[1] = (pBufferVehicle->GetAddressOfEntityProperties())[1]; pVehicle->AutoPilot = pBufferVehicle->AutoPilot; + CCarCtrl::UpdateCarCount(pVehicle, false); CWorld::Add(pVehicle); delete[] vbuf; #endif @@ -224,6 +247,7 @@ void CPools::SaveVehiclePool(uint8* buf, uint32* size) INITSAVEBUF int nNumCars = 0; int nNumBoats = 0; + int nNumBikes = 0; int nPoolSize = GetVehiclePool()->GetSize(); for (int i = 0; i < nPoolSize; i++) { CVehicle* pVehicle = GetVehiclePool()->GetSlot(i); @@ -245,19 +269,25 @@ INITSAVEBUF ++nNumCars; if (pVehicle->IsBoat() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) ++nNumBoats; + if (pVehicle->IsBike() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) + ++nNumBikes; #else if (!pVehicle->pDriver && !bHasPassenger) { if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) ++nNumCars; if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) ++nNumBoats; + if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) + ++nNumBikes; #endif } } *size = nNumCars * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CAutomobile::nSaveStructSize) + sizeof(int) + - nNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBoat::nSaveStructSize) + sizeof(int); + nNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBoat::nSaveStructSize) + sizeof(int) + + nNumBikes * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBike::nSaveStructSize) + sizeof(int); WriteSaveBuf(buf, nNumCars); WriteSaveBuf(buf, nNumBoats); + WriteSaveBuf(buf, nNumBikes); for (int i = 0; i < nPoolSize; i++) { CVehicle* pVehicle = GetVehiclePool()->GetSlot(i); if (!pVehicle) @@ -277,9 +307,9 @@ INITSAVEBUF #endif #ifdef COMPATIBLE_SAVES #ifdef MISSION_REPLAY - if ((pVehicle->IsCar() || pVehicle->IsBoat()) && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) { + if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) { #else - if ((pVehicle->IsCar() || pVehicle->IsBoat()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { + if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif WriteSaveBuf(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->GetModelIndex()); @@ -309,6 +339,17 @@ INITSAVEBUF memcpy(buf, pVehicle, sizeof(CBoat)); SkipSaveBuf(buf, sizeof(CBoat)); } +#ifdef MISSION_REPLAY + if (pVehicle->IsBike() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) { +#else + if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { +#endif + WriteSaveBuf(buf, pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->GetModelIndex()); + WriteSaveBuf(buf, GetVehicleRef(pVehicle)); + memcpy(buf, pVehicle, sizeof(CBike)); + SkipSaveBuf(buf, sizeof(CBike)); + } #endif } } @@ -330,8 +371,9 @@ INITSAVEBUF ++nObjects; } *size = nObjects * (sizeof(int16) + sizeof(int) + sizeof(CCompressedMatrix) + - sizeof(float) + sizeof(CCompressedMatrix) + sizeof(int8) + 7 * sizeof(bool) + sizeof(float) + - sizeof(int8) + sizeof(int8) + sizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int); + sizeof(float) + sizeof(CCompressedMatrix) + sizeof(int8) + 7 * sizeof(bool) + sizeof(int16) + + + sizeof(int8) * 2 + sizeof(float) + sizeof(int8) + sizeof(int8) + + sizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int); CopyToBuf(buf, nObjects); for (int i = 0; i < nPoolSize; i++) { CObject* pObject = GetObjectPool()->GetSlot(i); @@ -362,6 +404,9 @@ INITSAVEBUF CopyToBuf(buf, bGlassBroken); CopyToBuf(buf, bHasBeenDamaged); CopyToBuf(buf, bUseVehicleColours); + CopyToBuf(buf, pObject->m_nCostValue); + CopyToBuf(buf, pObject->m_nBonusValue); + SkipSaveBuf(buf, 1); CopyToBuf(buf, pObject->m_fCollisionDamageMultiplier); CopyToBuf(buf, pObject->m_nCollisionDamageEffect); CopyToBuf(buf, pObject->m_nSpecialCollisionResponseCases); @@ -411,6 +456,9 @@ INITSAVEBUF pBufferObject->bHasBeenDamaged = bitFlag; CopyFromBuf(buf, bitFlag); pBufferObject->bUseVehicleColours = bitFlag; + CopyFromBuf(buf, pBufferObject->m_nCostValue); + CopyFromBuf(buf, pBufferObject->m_nBonusValue); + SkipSaveBuf(buf, 1); CopyFromBuf(buf, pBufferObject->m_fCollisionDamageMultiplier); CopyFromBuf(buf, pBufferObject->m_nCollisionDamageEffect); CopyFromBuf(buf, pBufferObject->m_nSpecialCollisionResponseCases); @@ -445,6 +493,8 @@ INITSAVEBUF (pObject->GetAddressOfEntityProperties())[1] = (pBufferObject->GetAddressOfEntityProperties())[1]; #endif pObject->bHasCollided = false; + pObject->m_nCostValue = pBufferObject->m_nCostValue; + pObject->m_nBonusValue = pBufferObject->m_nBonusValue; CWorld::Add(pObject); delete[] obuf; } @@ -567,8 +617,20 @@ INITSAVEBUF pPed->CharCreatedBy = pBufferPlayer->CharCreatedBy; pPed->m_currentWeapon = 0; pPed->m_maxWeaponTypeAllowed = pBufferPlayer->m_maxWeaponTypeAllowed; - for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) - pPed->m_weapons[i] = pBufferPlayer->m_weapons[i]; + for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) { + if (pBufferPlayer->HasWeaponSlot(i)) { + int modelId = CWeaponInfo::GetWeaponInfo(pBufferPlayer->GetWeapon(i).m_eWeaponType)->m_nModelId; + if (modelId != -1) { + CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY); + int modelId2 = CWeaponInfo::GetWeaponInfo(pBufferPlayer->GetWeapon(i).m_eWeaponType)->m_nModel2Id; + if (modelId2 != -1) + CStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY); + + CStreaming::LoadAllRequestedModels(false); + } + pPed->GiveWeapon(pBufferPlayer->GetWeapon(i).m_eWeaponType, pBufferPlayer->GetWeapon(i).m_nAmmoTotal, false); + } + } if (pedtype == PEDTYPE_PLAYER1) { pPed->m_wepAccuracy = 100; diff --git a/src/core/Pools.h b/src/core/Pools.h index b0ba6598..afef1b85 100644 --- a/src/core/Pools.h +++ b/src/core/Pools.h @@ -4,7 +4,7 @@ #include "Lists.h" #include "Treadable.h" #include "Object.h" -#include "CutsceneHead.h" +#include "CutsceneObject.h" #include "PlayerPed.h" #include "Automobile.h" #include "DummyPed.h" @@ -16,9 +16,10 @@ typedef CPool<CPed,CPlayerPed> CPedPool; typedef CPool<CVehicle,CAutomobile> CVehiclePool; typedef CPool<CBuilding> CBuildingPool; typedef CPool<CTreadable> CTreadablePool; -typedef CPool<CObject, CCutsceneHead> CObjectPool; +typedef CPool<CObject, CCutsceneObject> CObjectPool; typedef CPool<CDummy, CDummyPed> CDummyPool; typedef CPool<cAudioScriptObject> CAudioScriptObjectPool; +typedef CPool<CColModel> CColModelPool; class CPools { @@ -31,6 +32,7 @@ class CPools static CObjectPool *ms_pObjectPool; static CDummyPool *ms_pDummyPool; static CAudioScriptObjectPool *ms_pAudioScriptObjectPool; + static CColModelPool *ms_pColModelPool; public: static CCPtrNodePool *GetPtrNodePool(void) { return ms_pPtrNodePool; } static CEntryInfoNodePool *GetEntryInfoNodePool(void) { return ms_pEntryInfoNodePool; } @@ -41,6 +43,7 @@ public: static CObjectPool *GetObjectPool(void) { return ms_pObjectPool; } static CDummyPool *GetDummyPool(void) { return ms_pDummyPool; } static CAudioScriptObjectPool *GetAudioScriptObjectPool(void) { return ms_pAudioScriptObjectPool; } + static CColModelPool *GetColModelPool(void) { return ms_pColModelPool; } static void Initialise(void); static void ShutDown(void); diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index cccf1d2e..0792008a 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -19,55 +19,95 @@ #include "SaveBuf.h" #include "Streaming.h" #include "SpecialFX.h" +#include "Font.h" +#include "SaveBuf.h" float CRadar::m_radarRange; sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS]; CVector2D vec2DRadarOrigin; int32 gRadarTxdIds[64]; -CSprite2d CRadar::AsukaSprite; -CSprite2d CRadar::BombSprite; -CSprite2d CRadar::CatSprite; CSprite2d CRadar::CentreSprite; -CSprite2d CRadar::CopcarSprite; -CSprite2d CRadar::DonSprite; -CSprite2d CRadar::EightSprite; -CSprite2d CRadar::ElSprite; -CSprite2d CRadar::IceSprite; -CSprite2d CRadar::JoeySprite; -CSprite2d CRadar::KenjiSprite; -CSprite2d CRadar::LizSprite; -CSprite2d CRadar::LuigiSprite; +CSprite2d CRadar::MapHereSprite; CSprite2d CRadar::NorthSprite; -CSprite2d CRadar::RaySprite; -CSprite2d CRadar::SalSprite; -CSprite2d CRadar::SaveSprite; +CSprite2d CRadar::AverySprite; +CSprite2d CRadar::BikerSprite; +CSprite2d CRadar::CortezSprite; +CSprite2d CRadar::DiazSprite; +CSprite2d CRadar::KentSprite; +CSprite2d CRadar::LawyerSprite; +CSprite2d CRadar::PhilSprite; +CSprite2d CRadar::BikersSprite; +CSprite2d CRadar::BoatyardSprite; +CSprite2d CRadar::MalibuClubSprite; +CSprite2d CRadar::CubansSprite; +CSprite2d CRadar::FilmSprite; +CSprite2d CRadar::GunSprite; +CSprite2d CRadar::HaitiansSprite; +CSprite2d CRadar::HardwareSprite; +CSprite2d CRadar::SaveHouseSprite; +CSprite2d CRadar::StripSprite; +CSprite2d CRadar::IceSprite; +CSprite2d CRadar::KCabsSprite; +CSprite2d CRadar::LovefistSprite; +CSprite2d CRadar::PrintworksSprite; +CSprite2d CRadar::PropertySprite; +CSprite2d CRadar::SunYardSprite; CSprite2d CRadar::SpraySprite; -CSprite2d CRadar::TonySprite; -CSprite2d CRadar::WeaponSprite; +CSprite2d CRadar::TShirtSprite; +CSprite2d CRadar::TommySprite; +CSprite2d CRadar::PhoneSprite; +CSprite2d CRadar::RadioWildstyleSprite; +CSprite2d CRadar::RadioFlashSprite; +CSprite2d CRadar::RadioKChatSprite; +CSprite2d CRadar::RadioFeverSprite; +CSprite2d CRadar::RadioVRockSprite; +CSprite2d CRadar::RadioVCPRSprite; +CSprite2d CRadar::RadioEspantosoSprite; +CSprite2d CRadar::RadioEmotionSprite; +CSprite2d CRadar::RadioWaveSprite; CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { nil, - &AsukaSprite, - &BombSprite, - &CatSprite, &CentreSprite, - &CopcarSprite, - &DonSprite, - &EightSprite, - &ElSprite, - &IceSprite, - &JoeySprite, - &KenjiSprite, - &LizSprite, - &LuigiSprite, + &MapHereSprite, &NorthSprite, - &RaySprite, - &SalSprite, - &SaveSprite, + &AverySprite, + &BikerSprite, + &CortezSprite, + &DiazSprite, + &KentSprite, + &LawyerSprite, + &PhilSprite, + &BikersSprite, + &BoatyardSprite, + &MalibuClubSprite, + &CubansSprite, + &FilmSprite, + &GunSprite, + &HaitiansSprite, + &HardwareSprite, + &SaveHouseSprite, + &StripSprite, + &IceSprite, + &KCabsSprite, + &LovefistSprite, + &PrintworksSprite, + &PropertySprite, + &SunYardSprite, &SpraySprite, - &TonySprite, - &WeaponSprite + &TShirtSprite, + &TommySprite, + &PhoneSprite, + &RadioWildstyleSprite, + &RadioFlashSprite, + &RadioKChatSprite, + &RadioFeverSprite, + &RadioVRockSprite, + &RadioVCPRSprite, + &RadioEspantosoSprite, + &RadioEmotionSprite, + &RadioWaveSprite }; // Why this doesn't coincide with world coordinates i don't know @@ -87,12 +127,15 @@ static_assert(RADAR_TILE_SIZE == (RADAR_SIZE_Y / RADAR_NUM_TILES), "CRadar: not #define RADAR_MIN_SPEED (0.3f) #define RADAR_MAX_SPEED (0.9f) -#ifdef MENU_MAP +CRGBA CRadar::ArrowBlipColour1; +CRGBA CRadar::ArrowBlipColour2; +int16 CRadar::MapLegendCounter; +int16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; +#ifdef MAP_ENHANCEMENTS int CRadar::TargetMarkerId = -1; CVector CRadar::TargetMarkerPos; #endif -// taken from VC float CRadar::cachedCos; float CRadar::cachedSin; @@ -145,15 +188,14 @@ void GetTextureCorners(int32 x, int32 y, CVector2D *out) uint8 CRadar::CalculateBlipAlpha(float dist) { -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) + if (FrontEndMenuManager.m_bMenuMapActive) return 255; -#endif + if (dist <= 1.0f) return 255; - if (dist <= 5.0f) - return (128.0f * ((dist - 1.0f) / 4.0f)) + ((1.0f - (dist - 1.0f) / 4.0f) * 255.0f); + if (dist <= 10.0f) + return (128.0f * ((dist - 1.0f) / 9.0f)) + ((1.0f - (dist - 1.0f) / 9.0f) * 255.0f); return 128; } @@ -192,12 +234,9 @@ void CRadar::ClearBlip(int32 i) if (index != -1) { SetRadarMarkerState(index, false); ms_RadarTrace[index].m_bInUse = false; -#ifndef MENU_MAP - // Ssshhh ms_RadarTrace[index].m_eBlipType = BLIP_NONE; ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER; ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE; -#endif } } @@ -422,9 +461,8 @@ int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect) bool CRadar::DisplayThisBlip(int32 counter) { switch (ms_RadarTrace[counter].m_eRadarSprite) { - case RADAR_SPRITE_BOMB: case RADAR_SPRITE_SPRAY: - case RADAR_SPRITE_WEAPON: + case RADAR_SPRITE_GUN: return true; default: return false; @@ -442,7 +480,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_ARROW, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_ARROW, pos, 2.5f, CARBLIP_MARKER_COLOR_R, CARBLIP_MARKER_COLOR_G, CARBLIP_MARKER_COLOR_B, CARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -456,7 +494,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += 3.0f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_ARROW, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_ARROW, pos, 1.5f, CHARBLIP_MARKER_COLOR_R, CHARBLIP_MARKER_COLOR_G, CHARBLIP_MARKER_COLOR_B, CHARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -466,7 +504,7 @@ void CRadar::Draw3dMarkers() if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { CVector pos = entity->GetPosition(); pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f; - C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_ARROW, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_ARROW, pos, 1.0f, OBJECTBLIP_MARKER_COLOR_R, OBJECTBLIP_MARKER_COLOR_G, OBJECTBLIP_MARKER_COLOR_B, OBJECTBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -475,7 +513,7 @@ void CRadar::Draw3dMarkers() case BLIP_CONTACT_POINT: if (!CTheScripts::IsPlayerOnAMission()) { if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) - C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_CYLINDER, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0); + C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), MARKERTYPE_CYLINDER, ms_RadarTrace[i].m_vecPos, 2.0f, COORDBLIP_MARKER_COLOR_R, COORDBLIP_MARKER_COLOR_G, COORDBLIP_MARKER_COLOR_B, COORDBLIP_MARKER_COLOR_A, 2048, 0.2f, 0); } break; } @@ -485,11 +523,11 @@ void CRadar::Draw3dMarkers() void CRadar::DrawBlips() { - if ((!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) -#ifdef MENU_MAP - || CMenuManager::bMenuMapActive + if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { +#ifdef SECUROM + extern uint8 roadBlocksPirateCheck; + if (roadBlocksPirateCheck == 2) return; #endif - ) { RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); @@ -501,9 +539,7 @@ void CRadar::DrawBlips() CVector2D in = CVector2D(0.0f, 0.0f); TransformRadarPointToScreenSpace(out, in); -#ifdef MENU_MAP - if (!CMenuManager::bMenuMapActive) { -#endif + if (!FrontEndMenuManager.m_bMenuMapActive) { float angle; if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN) angle = PI + FindPlayerHeading(); @@ -523,17 +559,9 @@ void CRadar::DrawBlips() LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255); -#ifdef MENU_MAP } -#endif - CEntity *blipEntity = nil; for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) { -#ifdef MENU_MAP - // A little hack to reuse cleared blips in menu map. hehe - if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR || - ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT) -#endif if (!ms_RadarTrace[blipId].m_bInUse) continue; @@ -541,165 +569,65 @@ void CRadar::DrawBlips() case BLIP_CAR: case BLIP_CHAR: case BLIP_OBJECT: - if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE - || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) { + if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_PROPERTY + && (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive)) + DrawEntityBlip(blipId); - switch (ms_RadarTrace[blipId].m_eBlipType) { - case BLIP_CAR: - blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - break; - case BLIP_CHAR: - blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - if (blipEntity != nil) { - if (((CPed*)blipEntity)->InVehicle()) - blipEntity = ((CPed*)blipEntity)->m_pMyVehicle; - } - break; - case BLIP_OBJECT: - blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - break; - default: - break; - } - if (blipEntity) { - uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { - if (CTheScripts::IsDebugOn()) { - ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius); - ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f; - if (ms_RadarTrace[blipId].m_Radius < 1.0f) - ms_RadarTrace[blipId].m_Radius = 5.0f; - } - } - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { - TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition()); - float dist = LimitRadarPoint(in); - TransformRadarPointToScreenSpace(out, in); - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) { - DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); - } else { -#ifdef TRIANGULAR_BLIPS - const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift(); - const CVector &blipPos = blipEntity->GetPosition(); - uint8 mode = BLIP_MODE_TRIANGULAR_UP; - if (blipPos.z - pos.z <= 2.0f) { - if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN; - else mode = BLIP_MODE_SQUARE; - } - ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); -#else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); -#endif - } - } - } - } break; case BLIP_COORD: case BLIP_CONTACT_POINT: - if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE - || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) - && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) { - - uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { - if (CTheScripts::IsDebugOn()) { - ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius); - ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f; - if (ms_RadarTrace[blipId].m_Radius < 1.0f) - ms_RadarTrace[blipId].m_Radius = 5.0f; - } - } - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { - TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos); - float dist = LimitRadarPoint(in); - TransformRadarPointToScreenSpace(out, in); - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) { - DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); - } else { -#ifdef TRIANGULAR_BLIPS - const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift(); - const CVector &blipPos = ms_RadarTrace[blipId].m_vecPos; - uint8 mode = BLIP_MODE_TRIANGULAR_UP; - if (blipPos.z - pos.z <= 2.0f) { - if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN; - else mode = BLIP_MODE_SQUARE; - } - ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); -#else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); -#endif - } - } - } + if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_PHONE + && (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive)) + DrawCoordBlip(blipId); + break; default: break; } } + + // New in VC: Always draw Hardware/gun/pay'n spray/save blips for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) { if (!ms_RadarTrace[blipId].m_bInUse) continue; + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_HARDWARE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN) + continue; + switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_CAR: case BLIP_CHAR: case BLIP_OBJECT: - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE - && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) { + if (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive) + DrawEntityBlip(blipId); - switch (ms_RadarTrace[blipId].m_eBlipType) { - case BLIP_CAR: - blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - break; - case BLIP_CHAR: - blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - if (blipEntity != nil) { - if (((CPed*)blipEntity)->InVehicle()) - blipEntity = ((CPed*)blipEntity)->m_pMyVehicle; - } - break; - case BLIP_OBJECT: - blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - break; - default: - break; - } + break; + case BLIP_COORD: + case BLIP_CONTACT_POINT: + if (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive) + DrawCoordBlip(blipId); + + break; + default: + break; + } + } - if (blipEntity) { - uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { - if (CTheScripts::IsDebugOn()) { - ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius); - ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f; - if (ms_RadarTrace[blipId].m_Radius < 1.0f) - ms_RadarTrace[blipId].m_Radius = 5.0f; - } - } - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { - TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition()); - float dist = LimitRadarPoint(in); - TransformRadarPointToScreenSpace(out, in); - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) - DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); - else -#ifdef TRIANGULAR_BLIPS - { - const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift(); - const CVector &blipPos = blipEntity->GetPosition(); - uint8 mode = BLIP_MODE_TRIANGULAR_UP; - if (blipPos.z - pos.z <= 2.0f) { - if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN; - else mode = BLIP_MODE_SQUARE; - } - ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); - } -#else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); -#endif - } - } - } + for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) { + if (!ms_RadarTrace[blipId].m_bInUse) + continue; + + switch (ms_RadarTrace[blipId].m_eBlipType) { + case BLIP_CAR: + case BLIP_CHAR: + case BLIP_OBJECT: + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_HARDWARE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_PROPERTY + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN + && (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive)) + + DrawEntityBlip(blipId); break; default: break; @@ -712,65 +640,35 @@ void CRadar::DrawBlips() switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_COORD: case BLIP_CONTACT_POINT: - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE - && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON - && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) { - - uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { - if (CTheScripts::IsDebugOn()) { - ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius); - ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f; - if (ms_RadarTrace[blipId].m_Radius < 1.0f) - ms_RadarTrace[blipId].m_Radius = 5.0f; - } - } - if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { - TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos); - float dist = LimitRadarPoint(in); - TransformRadarPointToScreenSpace(out, in); - if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) - DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); - else -#ifdef TRIANGULAR_BLIPS - { - const CVector &pos = FindPlayerCentreOfWorld_NoSniperShift(); - const CVector &blipPos = ms_RadarTrace[blipId].m_vecPos; - uint8 mode = BLIP_MODE_TRIANGULAR_UP; - if (blipPos.z - pos.z <= 2.0f) { - if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN; - else mode = BLIP_MODE_SQUARE; - } - ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); - } -#else - ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); -#endif - } - } + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_HARDWARE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_PROPERTY + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_PHONE + && (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive)) + + DrawCoordBlip(blipId); break; default: break; } } -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { + if (FrontEndMenuManager.m_bMenuMapActive) { CVector2D in, out; - TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift()); + if (!CTheScripts::bPlayerIsInTheStatium) + TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift()); + else + TransformRealWorldPointToRadarSpace(in, CVector2D(-1302.5f, 1332.8f)); + LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); DrawYouAreHereSprite(out.x, out.y); } -#endif } } void CRadar::DrawMap() { if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) { -#if 1 // from VC CalculateCachedSinCos(); -#endif if (FindPlayerVehicle()) { float speed = FindPlayerSpeed().Magnitude(); if (speed < RADAR_MIN_SPEED) @@ -784,14 +682,13 @@ void CRadar::DrawMap() m_radarRange = RADAR_MIN_RANGE; vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); - DrawRadarMap(); + if (FrontEndMenuManager.m_PrefsRadarMode != 1) + DrawRadarMap(); } } void CRadar::DrawRadarMap() { - // Game calculates an unused CRect here - DrawRadarMask(); // top left ist (0, 0) @@ -869,6 +766,7 @@ void CRadar::DrawRadarMask() #if !defined(GTA_PS2_STUFF) && defined(RWLIBS) RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); #endif + } void CRadar::DrawRadarSection(int32 x, int32 y) @@ -886,11 +784,8 @@ void CRadar::DrawRadarSection(int32 x, int32 y) GetTextureCorners(x, y, worldPoly); ClipRadarTileCoords(x, y); - assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])); - txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict; - if (txd) - texture = GetFirstTexture(txd); - if (texture == nil) + if (!CTheScripts::bPlayerIsInTheStatium && + (!(txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict) || !(texture = GetFirstTexture(txd)))) return; for (i = 0; i < 4; i++) @@ -908,8 +803,15 @@ void CRadar::DrawRadarSection(int32 x, int32 y) TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y); TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]); } - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); - CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); + + if (CTheScripts::bPlayerIsInTheStatium) { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(204, 204, 204, 255)); + } else { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture)); + CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255)); + } + // check done above now // if(numVertices > 2) RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices); @@ -918,6 +820,18 @@ void CRadar::DrawRadarSection(int32 x, int32 y) void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha) { RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); + + if (FrontEndMenuManager.m_bMenuMapActive) { + bool alreadyThere = false; + for (int i = 0; i < NUM_MAP_LEGENDS; i++) { + if (MapLegendList[i] == sprite) + alreadyThere = true; + } + if (!alreadyThere) { + MapLegendList[MapLegendCounter] = sprite; + MapLegendCounter++; + } + } } void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) @@ -1022,14 +936,11 @@ const char* gRadarTexNames[] = { void CRadar::Initialise() { -#ifdef MENU_MAP - TargetMarkerId = -1; -#endif - for (int i = 0; i < NUMRADARBLIPS; i++) { ms_RadarTrace[i].m_BlipIndex = 1; SetRadarMarkerState(i, false); ms_RadarTrace[i].m_bInUse = false; + ms_RadarTrace[i].m_bShortRange = false; ms_RadarTrace[i].m_eBlipType = BLIP_NONE; ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER; ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE; @@ -1045,10 +956,10 @@ float CRadar::LimitRadarPoint(CVector2D &point) float dist, invdist; dist = point.Magnitude(); -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) + + if (FrontEndMenuManager.m_bMenuMapActive) return dist; -#endif + if (dist > 1.0f) { invdist = 1.0f / dist; point.x *= invdist; @@ -1063,37 +974,109 @@ void CRadar::LoadAllRadarBlips(uint8 *buf, uint32 size) INITSAVEBUF CheckSaveHeader(buf, 'R', 'D', 'R', '\0', size - SAVE_HEADER_SIZE); - for (int i = 0; i < NUMRADARBLIPS; i++) - ReadSaveBuf(&ms_RadarTrace[i], buf); + for (int i = 0; i < NUMRADARBLIPS; i++) { + ReadSaveBuf(&ms_RadarTrace[i].m_nColor, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_Radius, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_eBlipType, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_nEntityHandle, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_vec2DPos.x, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_vec2DPos.y, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_vecPos, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_BlipIndex, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_bDim, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_bInUse, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_bShortRange, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_unused, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_wScale, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_eBlipDisplay, buf); + ReadSaveBuf(&ms_RadarTrace[i].m_eRadarSprite, buf); + } VALIDATESAVEBUF(size); } +void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size) +{ + *size = SAVE_HEADER_SIZE + NUMRADARBLIPS * sizeof(sRadarTraceSave); + +INITSAVEBUF + WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE); + +#ifdef MAP_ENHANCEMENTS + if (TargetMarkerId != -1) { + ClearBlip(TargetMarkerId); + TargetMarkerId = -1; + } +#endif + + for (int i = 0; i < NUMRADARBLIPS; i++) { + sRadarTraceSave *saveStruct = (sRadarTraceSave*) buf; + + saveStruct->m_nColor = ms_RadarTrace[i].m_nColor; + saveStruct->m_Radius = ms_RadarTrace[i].m_Radius; + saveStruct->m_eBlipType = ms_RadarTrace[i].m_eBlipType; + saveStruct->m_nEntityHandle = ms_RadarTrace[i].m_nEntityHandle; + saveStruct->m_vec2DPos = ms_RadarTrace[i].m_vec2DPos; + saveStruct->m_vecPos = ms_RadarTrace[i].m_vecPos; + saveStruct->m_BlipIndex = ms_RadarTrace[i].m_BlipIndex; + saveStruct->m_bDim = ms_RadarTrace[i].m_bDim; + saveStruct->m_bInUse = ms_RadarTrace[i].m_bInUse; + saveStruct->m_bShortRange = ms_RadarTrace[i].m_bShortRange; + saveStruct->m_unused = ms_RadarTrace[i].m_unused; + saveStruct->m_wScale = ms_RadarTrace[i].m_wScale; + saveStruct->m_eBlipDisplay = ms_RadarTrace[i].m_eBlipDisplay; + saveStruct->m_eRadarSprite = ms_RadarTrace[i].m_eRadarSprite; + + SkipSaveBuf(buf, sizeof(sRadarTraceSave)); + } + +VALIDATESAVEBUF(*size); +} + void CRadar::LoadTextures() { CTxdStore::PushCurrentTxd(); CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud")); - AsukaSprite.SetTexture("radar_asuka"); - BombSprite.SetTexture("radar_bomb"); - CatSprite.SetTexture("radar_cat"); CentreSprite.SetTexture("radar_centre"); - CopcarSprite.SetTexture("radar_copcar"); - DonSprite.SetTexture("radar_don"); - EightSprite.SetTexture("radar_eight"); - ElSprite.SetTexture("radar_el"); - IceSprite.SetTexture("radar_ice"); - JoeySprite.SetTexture("radar_joey"); - KenjiSprite.SetTexture("radar_kenji"); - LizSprite.SetTexture("radar_liz"); - LuigiSprite.SetTexture("radar_luigi"); + MapHereSprite.SetTexture("arrow"); NorthSprite.SetTexture("radar_north"); - RaySprite.SetTexture("radar_ray"); - SalSprite.SetTexture("radar_sal"); - SaveSprite.SetTexture("radar_save"); - SpraySprite.SetTexture("radar_spray"); - TonySprite.SetTexture("radar_tony"); - WeaponSprite.SetTexture("radar_weapon"); + AverySprite.SetTexture("radar_avery"); + BikerSprite.SetTexture("radar_biker"); + CortezSprite.SetTexture("radar_cortez"); + DiazSprite.SetTexture("radar_diaz"); + KentSprite.SetTexture("radar_kent"); + LawyerSprite.SetTexture("radar_lawyer"); + PhilSprite.SetTexture("radar_phil"); + BikersSprite.SetTexture("bikers"); + BoatyardSprite.SetTexture("boatyard"); + MalibuClubSprite.SetTexture("club"); + CubansSprite.SetTexture("cubans"); + FilmSprite.SetTexture("filmstudio"); + GunSprite.SetTexture("gun"); + HaitiansSprite.SetTexture("haitians"); + HardwareSprite.SetTexture("hardware"); + SaveHouseSprite.SetTexture("radar_save"); + StripSprite.SetTexture("radar_strip"); + IceSprite.SetTexture("icecream"); + KCabsSprite.SetTexture("kcabs"); + LovefistSprite.SetTexture("lovefist"); + PrintworksSprite.SetTexture("printworks"); + PropertySprite.SetTexture("property"); + SunYardSprite.SetTexture("SunYard"); + SpraySprite.SetTexture("spray"); + TShirtSprite.SetTexture("tshirt"); + TommySprite.SetTexture("tommy"); + PhoneSprite.SetTexture("phone"); + RadioWildstyleSprite.SetTexture("RWildstyle"); + RadioFlashSprite.SetTexture("RFlash"); + RadioKChatSprite.SetTexture("RKchat"); + RadioFeverSprite.SetTexture("RFever"); + RadioVRockSprite.SetTexture("RVRock"); + RadioVCPRSprite.SetTexture("RVCPR"); + RadioEspantosoSprite.SetTexture("REspantoso"); + RadioEmotionSprite.SetTexture("REmotion"); + RadioWaveSprite.SetTexture("RWave"); CTxdStore::PopCurrentTxd(); } @@ -1104,33 +1087,6 @@ void CRadar::RemoveRadarSections() RemoveMapSection(i, j); } -void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size) -{ - *size = SAVE_HEADER_SIZE + sizeof(ms_RadarTrace); -INITSAVEBUF - WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE); - -#ifdef MENU_MAP - bool bWaypointDeleted = false; - if (TargetMarkerId != -1) { - ClearBlip(TargetMarkerId); - TargetMarkerId = -1; - bWaypointDeleted = true; - } -#endif - - for (int i = 0; i < NUMRADARBLIPS; i++) - WriteSaveBuf(buf, ms_RadarTrace[i]); - - -#ifdef MENU_MAP - if(bWaypointDeleted) - ToggleTargetMarker(TargetMarkerPos.x, TargetMarkerPos.y); -#endif - -VALIDATESAVEBUF(*size); -} - void CRadar::SetBlipSprite(int32 i, int32 icon) { int index = CRadar::GetActualBlipArrayIndex(i); @@ -1139,7 +1095,7 @@ void CRadar::SetBlipSprite(int32 i, int32 icon) } } -int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay display) +int CRadar::SetCoordBlip(eBlipType type, CVector pos, uint32 color, eBlipDisplay display) { int nextBlip; for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) { @@ -1151,9 +1107,10 @@ int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay return -1; #endif ms_RadarTrace[nextBlip].m_eBlipType = type; - ms_RadarTrace[nextBlip].m_nColor = color; - ms_RadarTrace[nextBlip].m_bDim = 1; - ms_RadarTrace[nextBlip].m_bInUse = 1; + ms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_MAGENTA; + ms_RadarTrace[nextBlip].m_bDim = true; + ms_RadarTrace[nextBlip].m_bInUse = true; + ms_RadarTrace[nextBlip].m_bShortRange = false; ms_RadarTrace[nextBlip].m_Radius = 1.0f; ms_RadarTrace[nextBlip].m_vec2DPos = pos; ms_RadarTrace[nextBlip].m_vecPos = pos; @@ -1164,7 +1121,16 @@ int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay return CRadar::GetNewUniqueBlipIndex(nextBlip); } -int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDisplay display) +int CRadar::SetShortRangeCoordBlip(eBlipType type, CVector pos, uint32 color, eBlipDisplay display) +{ + int index = SetCoordBlip(type, pos, color, display); + if (index == -1) + return -1; + ms_RadarTrace[GetActualBlipArrayIndex(index)].m_bShortRange = true; + return index; +} + +int CRadar::SetEntityBlip(eBlipType type, int32 handle, uint32 color, eBlipDisplay display) { int nextBlip; for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) { @@ -1176,9 +1142,10 @@ int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDispla return -1; #endif ms_RadarTrace[nextBlip].m_eBlipType = type; - ms_RadarTrace[nextBlip].m_nColor = color; - ms_RadarTrace[nextBlip].m_bDim = 1; - ms_RadarTrace[nextBlip].m_bInUse = 1; + ms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_YELLOW; + ms_RadarTrace[nextBlip].m_bDim = true; + ms_RadarTrace[nextBlip].m_bInUse = true; + ms_RadarTrace[nextBlip].m_bShortRange = false; ms_RadarTrace[nextBlip].m_Radius = 1.0f; ms_RadarTrace[nextBlip].m_nEntityHandle = handle; ms_RadarTrace[nextBlip].m_wScale = 1; @@ -1232,11 +1199,7 @@ void CRadar::ShowRadarMarker(CVector pos, uint32 color, float radius) { void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha) { - if ((TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud) -#ifdef MENU_MAP - && !CMenuManager::bMenuMapActive -#endif - ) + if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn) return; CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha)); @@ -1245,22 +1208,18 @@ void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 gree void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode) { - if ((TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud) -#ifdef MENU_MAP - && !CMenuManager::bMenuMapActive -#endif - ) + if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn) return; switch (mode) { case BLIP_MODE_TRIANGULAR_UP: - // size++; // VC does size + 1 for triangles + size++; CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 3.0f), y + SCREEN_SCALE_Y(size + 2.0f), x - (SCREEN_SCALE_X(size + 3.0f)), y + SCREEN_SCALE_Y(size + 2.0f), x, y - (SCREEN_SCALE_Y(size + 3.0f)), x, y - (SCREEN_SCALE_Y(size + 3.0f)), CRGBA(0, 0, 0, alpha)); CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 1.0f), y + SCREEN_SCALE_Y(size + 1.0f), x - (SCREEN_SCALE_X(size + 1.0f)), y + SCREEN_SCALE_Y(size + 1.0f), x, y - (SCREEN_SCALE_Y(size + 1.0f)), x, y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha)); break; case BLIP_MODE_TRIANGULAR_DOWN: - // size++; // VC does size + 1 for triangles + size++; CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 2.0f), x, y + SCREEN_SCALE_Y(size + 3.0f), x + SCREEN_SCALE_X(size + 3.0f), y - (SCREEN_SCALE_Y(size + 2.0f)), x - (SCREEN_SCALE_X(size + 3.0f)), y - (SCREEN_SCALE_Y(size + 2.0f)), CRGBA(0, 0, 0, alpha)); CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 1.0f), x, y + SCREEN_SCALE_Y(size + 1.0f), x + SCREEN_SCALE_X(size + 1.0f), y - (SCREEN_SCALE_Y(size + 1.0f)), x - (SCREEN_SCALE_X(size + 1.0f)), y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha)); break; @@ -1273,32 +1232,52 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, void CRadar::Shutdown() { - AsukaSprite.Delete(); - BombSprite.Delete(); - CatSprite.Delete(); CentreSprite.Delete(); - CopcarSprite.Delete(); - DonSprite.Delete(); - EightSprite.Delete(); - ElSprite.Delete(); - IceSprite.Delete(); - JoeySprite.Delete(); - KenjiSprite.Delete(); - LizSprite.Delete(); - LuigiSprite.Delete(); + MapHereSprite.Delete(); NorthSprite.Delete(); - RaySprite.Delete(); - SalSprite.Delete(); - SaveSprite.Delete(); + AverySprite.Delete(); + BikerSprite.Delete(); + CortezSprite.Delete(); + DiazSprite.Delete(); + KentSprite.Delete(); + LawyerSprite.Delete(); + PhilSprite.Delete(); + BikersSprite.Delete(); + BoatyardSprite.Delete(); + MalibuClubSprite.Delete(); + CubansSprite.Delete(); + FilmSprite.Delete(); + GunSprite.Delete(); + HaitiansSprite.Delete(); + HardwareSprite.Delete(); + SaveHouseSprite.Delete(); + StripSprite.Delete(); + IceSprite.Delete(); + KCabsSprite.Delete(); + LovefistSprite.Delete(); + PrintworksSprite.Delete(); + PropertySprite.Delete(); + SunYardSprite.Delete(); SpraySprite.Delete(); - TonySprite.Delete(); - WeaponSprite.Delete(); + TShirtSprite.Delete(); + TommySprite.Delete(); + PhoneSprite.Delete(); + RadioWildstyleSprite.Delete(); + RadioFlashSprite.Delete(); + RadioKChatSprite.Delete(); + RadioFeverSprite.Delete(); + RadioVRockSprite.Delete(); + RadioVCPRSprite.Delete(); + RadioEspantosoSprite.Delete(); + RadioEmotionSprite.Delete(); + RadioWaveSprite.Delete(); RemoveRadarSections(); } void CRadar::StreamRadarSections(const CVector &posn) { - StreamRadarSections(Floor((2000.0f + posn.x) / 500.0f), Ceil(7.0f - (2000.0f + posn.y) / 500.0f)); + if (!CStreaming::ms_disableStreaming) + StreamRadarSections(Floor((RADAR_MAX_X + posn.x) / RADAR_TILE_SIZE), Ceil((RADAR_NUM_TILES - 1) - (RADAR_MAX_Y + posn.y) / RADAR_TILE_SIZE)); } void CRadar::StreamRadarSections(int32 x, int32 y) @@ -1324,33 +1303,8 @@ void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D & void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in) { float s, c; -#if 1 s = -cachedSin; c = cachedCos; -#else - // Original code - - s = -Sin(TheCamera.GetForward().Heading()); - c = Cos(TheCamera.GetForward().Heading()); - - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) { - s = 0.0f; - c = 1.0f; - } - else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) { - CVector forward; - - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) { - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); - forward.Normalise(); // a bit useless... - } - else - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; - - s = -Sin(forward.Heading()); - c = Cos(forward.Heading()); - } -#endif out.x = s * in.y + c * in.x; out.y = c * in.y - s * in.x; @@ -1361,14 +1315,10 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D // Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) { -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { - // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0. - out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f; - out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f; - } else -#endif - { + if (FrontEndMenuManager.m_bMenuMapActive) { + out.x = (FrontEndMenuManager.m_fMapCenterX - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * FrontEndMenuManager.m_fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH; + out.y = (FrontEndMenuManager.m_fMapCenterY - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * FrontEndMenuManager.m_fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH; + } else { #ifdef FIX_BUGS out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); #else @@ -1381,35 +1331,8 @@ void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &i void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in) { float s, c; -#if 1 s = cachedSin; c = cachedCos; -#else - // Original code - - float s, c; - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) { - s = 0.0f; - c = 1.0f; - } - else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { - s = Sin(TheCamera.GetForward().Heading()); - c = Cos(TheCamera.GetForward().Heading()); - } - else { - CVector forward; - - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) { - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward(); - forward.Normalise(); // a bit useless... - } - else - forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind; - - s = Sin(forward.Heading()); - c = Cos(forward.Heading()); - } -#endif float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange); float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange); @@ -1421,11 +1344,8 @@ void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D void CRadar::CalculateCachedSinCos() { - if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED -#ifdef MENU_MAP - || CMenuManager::bMenuMapActive -#endif - ) { + if (/*TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || */ + FrontEndMenuManager.m_bMenuMapActive ) { cachedSin = 0.0f; cachedCos = 1.0f; } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { @@ -1446,14 +1366,19 @@ CRadar::CalculateCachedSinCos() } } -#ifdef MENU_MAP void CRadar::InitFrontEndMap() { CalculateCachedSinCos(); vec2DRadarOrigin.x = 0.0f; vec2DRadarOrigin.y = 0.0f; - m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace + m_radarRange = MENU_MAP_LENGTH_UNIT; // just affects the multiplier in TransformRadarPointToScreenSpace + for (int i = 0; i < NUM_MAP_LEGENDS; i++) { + MapLegendList[i] = RADAR_SPRITE_NONE; + } + MapLegendCounter = 0; + ArrowBlipColour1 = CRGBA(0, 0, 0, 0); + ArrowBlipColour2 = CRGBA(0, 0, 0, 0); } void @@ -1475,14 +1400,33 @@ CRadar::DrawYouAreHereSprite(float x, float y) } if (show) { - float left = x - SCREEN_SCALE_X(12.0f); - float top = y; - float right = SCREEN_SCALE_X(12.0) + x; - float bottom = y - SCREEN_SCALE_Y(24.0f); - CentreSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 255, 255, 255)); + const float left = x - SCREEN_SCALE_X(8.0f); + const float top = y - SCREEN_SCALE_Y(40.0f); + const float right = x + SCREEN_SCALE_X(40.0); + const float bottom = y + SCREEN_SCALE_Y(8.0f); + MapHereSprite.Draw(CRect(left + SCREEN_SCALE_X(2.f), top + SCREEN_SCALE_Y(2.f), right + SCREEN_SCALE_X(2.f), bottom + SCREEN_SCALE_Y(2.f)), + CRGBA(0, 0, 0, 255)); + + MapHereSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 255, 255, 255)); + + CFont::SetWrapx(right + SCREEN_SCALE_X(28.0f)); + CFont::SetRightJustifyWrap(right); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetColor(CRGBA(255, 150, 225, 255)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOff(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(SCREEN_SCALE_X(0.65f), SCREEN_SCALE_Y(0.95f)); + CFont::PrintString(right, top, TheText.Get("MAP_YAH")); + CFont::SetDropShadowPosition(0); + CFont::DrawFonts(); } + MapLegendList[MapLegendCounter++] = RADAR_SPRITE_MAP_HERE; } +#ifdef MAP_ENHANCEMENTS void CRadar::ToggleTargetMarker(float x, float y) { @@ -1492,10 +1436,10 @@ CRadar::ToggleTargetMarker(float x, float y) if (!ms_RadarTrace[nextBlip].m_bInUse) break; } -#ifdef FIX_BUGS + if (nextBlip == NUMRADARBLIPS) return; -#endif + ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD; ms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_GRAY; ms_RadarTrace[nextBlip].m_bDim = 0; @@ -1517,3 +1461,287 @@ CRadar::ToggleTargetMarker(float x, float y) } #endif +void +CRadar::DrawEntityBlip(int32 blipId) +{ + CVector2D out; + CVector2D in; + CEntity *blipEntity; + switch (ms_RadarTrace[blipId].m_eBlipType) { + case BLIP_CAR: + blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); + break; + case BLIP_CHAR: + blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); + if (blipEntity != nil) { + if (((CPed*)blipEntity)->InVehicle()) + blipEntity = ((CPed*)blipEntity)->m_pMyVehicle; + } + break; + case BLIP_OBJECT: + blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); + break; + default: + break; + } + if (blipEntity) { + uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); + if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { + if (CTheScripts::IsDebugOn()) { + ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius); + ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f; + if (ms_RadarTrace[blipId].m_Radius < 1.0f) + ms_RadarTrace[blipId].m_Radius = 5.0f; + } + } + if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { + TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition()); + float dist = LimitRadarPoint(in); + TransformRadarPointToScreenSpace(out, in); + if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) { + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) { + DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); + } else { + const CVector& pos = FindPlayerCentreOfWorld_NoSniperShift(); + const CVector& blipPos = blipEntity->GetPosition(); + uint8 mode = BLIP_MODE_TRIANGULAR_UP; + if (blipPos.z - pos.z <= 2.0f) { + if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN; + else mode = BLIP_MODE_SQUARE; + } + ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); + + if (FrontEndMenuManager.m_bMenuMapActive) { + bool alreadyThere = false; + for (int i = 0; i < NUM_MAP_LEGENDS; i++) { + if (MapLegendList[i] == -2) + alreadyThere = true; + } + if (!alreadyThere) { + MapLegendList[MapLegendCounter] = -2; + MapLegendCounter++; + ArrowBlipColour2 = CRGBA((uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); + } + } + } + } + } + } +} + +void +CRadar::DrawCoordBlip(int32 blipId) +{ + CVector2D out; + CVector2D in; + if (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission()) { + + uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); + if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) { + if (CTheScripts::IsDebugOn()) { + ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius); + ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f; + if (ms_RadarTrace[blipId].m_Radius < 1.0f) + ms_RadarTrace[blipId].m_Radius = 5.0f; + } + } + if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) { + TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos); + float dist = LimitRadarPoint(in); + TransformRadarPointToScreenSpace(out, in); + if (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) { + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) { + DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist)); + } else { + const CVector& pos = FindPlayerCentreOfWorld_NoSniperShift(); + const CVector& blipPos = ms_RadarTrace[blipId].m_vecPos; + uint8 mode = BLIP_MODE_TRIANGULAR_UP; + if (blipPos.z - pos.z <= 2.0f) { + if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN; + else mode = BLIP_MODE_SQUARE; + } + ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); + + if (FrontEndMenuManager.m_bMenuMapActive) { + bool alreadyThere = false; + for (int i = 0; i < NUM_MAP_LEGENDS; i++) { + if (MapLegendList[i] == -1) + alreadyThere = true; + } + if (!alreadyThere) { + MapLegendList[MapLegendCounter] = -1; + MapLegendCounter++; + ArrowBlipColour1 = CRGBA((uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); + } + } + } + } + } + } +} + +void +CRadar::DrawLegend(int32 x, int32 y, int32 sprite) +{ + if (sprite < 0) { + static uint32 lastChange = 0; + static int8 blipMode = 0; + + CRGBA color; + if (sprite == -1) { + color = ArrowBlipColour1; + } else { + color = ArrowBlipColour2; + } + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 600) { + lastChange = CTimer::GetTimeInMillisecondsPauseMode(); + if ( blipMode == 2 ) + blipMode = 0; + else + ++blipMode; + } + + switch (blipMode) { + case BLIP_MODE_TRIANGULAR_UP: + CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(14.0f), y + SCREEN_SCALE_Y(13.0f), x + SCREEN_SCALE_X(2.0f), y + SCREEN_SCALE_Y(13.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(2.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(2.0f), CRGBA(0, 0, 0, 255)); + CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(12.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(4.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(4.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(4.0f), color); + break; + case BLIP_MODE_TRIANGULAR_DOWN: + CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(14.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(14.0f), x + SCREEN_SCALE_X(2.f), y + SCREEN_SCALE_Y(3.0f), x + SCREEN_SCALE_X(2.f), y + SCREEN_SCALE_Y(3.0f), CRGBA(0, 0, 0, 255)); + CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(12.f), y + SCREEN_SCALE_Y(4.0f), x + SCREEN_SCALE_X(4.f), y + SCREEN_SCALE_Y(4.0f), color); + break; + case BLIP_MODE_SQUARE: + CSprite2d::DrawRect(CRect(x + SCREEN_SCALE_X(4.0f), y + SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_X(12.0f) + x, SCREEN_SCALE_Y(12.0f) + y), CRGBA(0, 0, 0, 255)); + CSprite2d::DrawRect(CRect(x + SCREEN_SCALE_X(5.0f), y + SCREEN_SCALE_Y(4.0f), SCREEN_SCALE_X(11.0f) + x, SCREEN_SCALE_Y(11.0f) + y), color); + break; + } + + } else { + RadarSprites[sprite]->Draw(CRect(x, y, x + SCREEN_SCALE_X(16.f), y + SCREEN_SCALE_X(16.f)), CRGBA(255, 255, 255, 255)); + } + + wchar *text; + switch ( sprite ) { + case RADAR_SPRITE_ENTITY_BLIP: + text = TheText.Get("LG_38"); + break; + case RADAR_SPRITE_COORD_BLIP: + text = TheText.Get("LG_35"); + break; + case RADAR_SPRITE_MAP_HERE: + text = TheText.Get("LG_01"); + break; + case RADAR_SPRITE_AVERY: + text = TheText.Get("LG_02"); + break; + case RADAR_SPRITE_BIKER: + text = TheText.Get("LG_03"); + break; + case RADAR_SPRITE_CORTEZ: + text = TheText.Get("LG_04"); + break; + case RADAR_SPRITE_DIAZ: + text = TheText.Get("LG_05"); + break; + case RADAR_SPRITE_KENT: + text = TheText.Get("LG_06"); + break; + case RADAR_SPRITE_LAWYER: + text = TheText.Get("LG_07"); + break; + case RADAR_SPRITE_PHIL: + text = TheText.Get("LG_08"); + break; + case RADAR_SPRITE_BIKERS: + text = TheText.Get("LG_03"); + break; + case RADAR_SPRITE_BOATYARD: + text = TheText.Get("LG_09"); + break; + case RADAR_SPRITE_MALIBU_CLUB: + text = TheText.Get("LG_10"); + break; + case RADAR_SPRITE_CUBANS: + text = TheText.Get("LG_11"); + break; + case RADAR_SPRITE_FILM: + text = TheText.Get("LG_12"); + break; + case RADAR_SPRITE_GUN: + text = TheText.Get("LG_13"); + break; + case RADAR_SPRITE_HAITIANS: + text = TheText.Get("LG_14"); + break; + case RADAR_SPRITE_HARDWARE: + text = TheText.Get("LG_15"); + break; + case RADAR_SPRITE_SAVE: + text = TheText.Get("LG_16"); + break; + case RADAR_SPRITE_STRIP: + text = TheText.Get("LG_37"); + break; + case RADAR_SPRITE_ICE: + text = TheText.Get("LG_17"); + break; + case RADAR_SPRITE_KCABS: + text = TheText.Get("LG_18"); + break; + case RADAR_SPRITE_LOVEFIST: + text = TheText.Get("LG_19"); + break; + case RADAR_SPRITE_PRINTWORKS: + text = TheText.Get("LG_20"); + break; + case RADAR_SPRITE_PROPERTY: + text = TheText.Get("LG_21"); + break; + case RADAR_SPRITE_SUNYARD: + text = TheText.Get("LG_36"); + break; + case RADAR_SPRITE_SPRAY: + text = TheText.Get("LG_22"); + break; + case RADAR_SPRITE_TSHIRT: + text = TheText.Get("LG_23"); + break; + case RADAR_SPRITE_TOMMY: + text = TheText.Get("LG_24"); + break; + case RADAR_SPRITE_PHONE: + text = TheText.Get("LG_25"); + break; + case RADAR_SPRITE_RADIO_WILDSTYLE: + text = TheText.Get("LG_26"); + break; + case RADAR_SPRITE_RADIO_FLASH: + text = TheText.Get("LG_27"); + break; + case RADAR_SPRITE_RADIO_KCHAT: + text = TheText.Get("LG_28"); + break; + case RADAR_SPRITE_RADIO_FEVER: + text = TheText.Get("LG_29"); + break; + case RADAR_SPRITE_RADIO_VROCK: + text = TheText.Get("LG_30"); + break; + case RADAR_SPRITE_RADIO_VCPR: + text = TheText.Get("LG_31"); + break; + case RADAR_SPRITE_RADIO_ESPANTOSO: + text = TheText.Get("LG_32"); + break; + case RADAR_SPRITE_RADIO_EMOTION: + text = TheText.Get("LG_33"); + break; + case RADAR_SPRITE_RADIO_WAVE: + text = TheText.Get("LG_34"); + break; + default: + break; + } + CFont::PrintString(SCREEN_SCALE_X(20.f) + x, SCREEN_SCALE_Y(3.0f) + y, text); +} diff --git a/src/core/Radar.h b/src/core/Radar.h index 5b38d350..b01a5d04 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -2,6 +2,35 @@ #include "Sprite2d.h" #include "Draw.h" +#define CARBLIP_MARKER_COLOR_R 252 +#define CARBLIP_MARKER_COLOR_G 138 +#define CARBLIP_MARKER_COLOR_B 242 +#define CARBLIP_MARKER_COLOR_A 255 + +#define CHARBLIP_MARKER_COLOR_R 252 +#define CHARBLIP_MARKER_COLOR_G 138 +#define CHARBLIP_MARKER_COLOR_B 242 +#define CHARBLIP_MARKER_COLOR_A 255 + +#define OBJECTBLIP_MARKER_COLOR_R 252 +#define OBJECTBLIP_MARKER_COLOR_G 138 +#define OBJECTBLIP_MARKER_COLOR_B 242 +#define OBJECTBLIP_MARKER_COLOR_A 255 + +#define COORDBLIP_MARKER_COLOR_R 252 +#define COORDBLIP_MARKER_COLOR_G 138 +#define COORDBLIP_MARKER_COLOR_B 242 +#define COORDBLIP_MARKER_COLOR_A 228 + +#define NUM_MAP_LEGENDS 75 + +#define MENU_MAP_LENGTH_UNIT 1190.0f // in game unit +#define MENU_MAP_WIDTH_SCALE 1.112f // in game unit (originally 1.112494151260504f) +#define MENU_MAP_HEIGHT_SCALE 1.119f // in game unit (originally 1.118714268907563f) +#define MENU_MAP_TOP_OFFSET 0.28f // in length unit defined above - ~333 game unit +#define MENU_MAP_LEFT_OFFSET 0.185f // in length unit defined above - ~220 game unit +#define MENU_MAP_LENGTH (4000.f / MENU_MAP_LENGTH_UNIT) + enum eBlipType { BLIP_NONE, @@ -22,31 +51,49 @@ enum eBlipDisplay enum eRadarSprite { -#ifdef MENU_MAP RADAR_SPRITE_ENTITY_BLIP = -2, RADAR_SPRITE_COORD_BLIP = -1, -#endif RADAR_SPRITE_NONE = 0, - RADAR_SPRITE_ASUKA, - RADAR_SPRITE_BOMB, - RADAR_SPRITE_CAT, RADAR_SPRITE_CENTRE, - RADAR_SPRITE_COPCAR, - RADAR_SPRITE_DON, - RADAR_SPRITE_EIGHT, - RADAR_SPRITE_EL, - RADAR_SPRITE_ICE, - RADAR_SPRITE_JOEY, - RADAR_SPRITE_KENJI, - RADAR_SPRITE_LIZ, - RADAR_SPRITE_LUIGI, + RADAR_SPRITE_MAP_HERE, RADAR_SPRITE_NORTH, - RADAR_SPRITE_RAY, - RADAR_SPRITE_SAL, + RADAR_SPRITE_AVERY, + RADAR_SPRITE_BIKER, + RADAR_SPRITE_CORTEZ, + RADAR_SPRITE_DIAZ, + RADAR_SPRITE_KENT, + RADAR_SPRITE_LAWYER, + RADAR_SPRITE_PHIL, + RADAR_SPRITE_BIKERS, + RADAR_SPRITE_BOATYARD, + RADAR_SPRITE_MALIBU_CLUB, + RADAR_SPRITE_CUBANS, + RADAR_SPRITE_FILM, + RADAR_SPRITE_GUN, + RADAR_SPRITE_HAITIANS, + RADAR_SPRITE_HARDWARE, RADAR_SPRITE_SAVE, + RADAR_SPRITE_STRIP, + RADAR_SPRITE_ICE, + RADAR_SPRITE_KCABS, + RADAR_SPRITE_LOVEFIST, + RADAR_SPRITE_PRINTWORKS, + RADAR_SPRITE_PROPERTY, + RADAR_SPRITE_SUNYARD, RADAR_SPRITE_SPRAY, - RADAR_SPRITE_TONY, - RADAR_SPRITE_WEAPON, + RADAR_SPRITE_TSHIRT, + RADAR_SPRITE_TOMMY, + RADAR_SPRITE_PHONE, + RADAR_SPRITE_RADIO_WILDSTYLE, + RADAR_SPRITE_RADIO_FLASH, + RADAR_SPRITE_RADIO_KCHAT, + RADAR_SPRITE_RADIO_FEVER, + RADAR_SPRITE_RADIO_VROCK, + RADAR_SPRITE_RADIO_VCPR, + RADAR_SPRITE_RADIO_ESPANTOSO, + RADAR_SPRITE_RADIO_EMOTION, + RADAR_SPRITE_RADIO_WAVE, + RADAR_SPRITE_COUNT }; @@ -73,25 +120,43 @@ struct sRadarTrace uint32 m_nColor; uint32 m_eBlipType; // eBlipType int32 m_nEntityHandle; - CVector2D m_vec2DPos; + CVector m_vec2DPos; CVector m_vecPos; uint16 m_BlipIndex; bool m_bDim; bool m_bInUse; + bool m_bShortRange; + bool m_unused; float m_Radius; int16 m_wScale; uint16 m_eBlipDisplay; // eBlipDisplay uint16 m_eRadarSprite; // eRadarSprite }; -VALIDATE_SIZE(sRadarTrace, 0x30); + +// Either that was a thing while saving/loading blips, or they added sizes of each field one by one. I want to do the former. +#pragma pack(push,1) +struct sRadarTraceSave +{ + uint32 m_nColor; + float m_Radius; + uint32 m_eBlipType; // eBlipType + int32 m_nEntityHandle; + CVector2D m_vec2DPos; + CVector m_vecPos; + uint16 m_BlipIndex; + bool m_bDim; + bool m_bInUse; + bool m_bShortRange; + bool m_unused; + int16 m_wScale; + uint16 m_eBlipDisplay; // eBlipDisplay + uint16 m_eRadarSprite; // eRadarSprite +}; +#pragma pack(pop) // Values for screen space #define RADAR_LEFT (40.0f) -#ifdef PS2_HUD -#define RADAR_BOTTOM (44.0f) -#else -#define RADAR_BOTTOM (47.0f) -#endif +#define RADAR_BOTTOM (40.0f) #ifdef FIX_RADAR /* @@ -120,35 +185,61 @@ class CRadar public: static float m_radarRange; static sRadarTrace ms_RadarTrace[NUMRADARBLIPS]; - static CSprite2d AsukaSprite; - static CSprite2d BombSprite; - static CSprite2d CatSprite; static CSprite2d CentreSprite; - static CSprite2d CopcarSprite; - static CSprite2d DonSprite; - static CSprite2d EightSprite; - static CSprite2d ElSprite; - static CSprite2d IceSprite; - static CSprite2d JoeySprite; - static CSprite2d KenjiSprite; - static CSprite2d LizSprite; - static CSprite2d LuigiSprite; + static CSprite2d MapHereSprite; static CSprite2d NorthSprite; - static CSprite2d RaySprite; - static CSprite2d SalSprite; - static CSprite2d SaveSprite; + static CSprite2d AverySprite; + static CSprite2d BikerSprite; + static CSprite2d CortezSprite; + static CSprite2d DiazSprite; + static CSprite2d KentSprite; + static CSprite2d LawyerSprite; + static CSprite2d PhilSprite; + static CSprite2d BikersSprite; + static CSprite2d BoatyardSprite; + static CSprite2d MalibuClubSprite; + static CSprite2d CubansSprite; + static CSprite2d FilmSprite; + static CSprite2d GunSprite; + static CSprite2d HaitiansSprite; + static CSprite2d HardwareSprite; + static CSprite2d SaveHouseSprite; + static CSprite2d StripSprite; + static CSprite2d IceSprite; + static CSprite2d KCabsSprite; + static CSprite2d LovefistSprite; + static CSprite2d PrintworksSprite; + static CSprite2d PropertySprite; + static CSprite2d SunYardSprite; static CSprite2d SpraySprite; - static CSprite2d TonySprite; - static CSprite2d WeaponSprite; + static CSprite2d TShirtSprite; + static CSprite2d TommySprite; + static CSprite2d PhoneSprite; + static CSprite2d RadioWildstyleSprite; + static CSprite2d RadioFlashSprite; + static CSprite2d RadioKChatSprite; + static CSprite2d RadioFeverSprite; + static CSprite2d RadioVRockSprite; + static CSprite2d RadioVCPRSprite; + static CSprite2d RadioEspantosoSprite; + static CSprite2d RadioEmotionSprite; + static CSprite2d RadioWaveSprite; static CSprite2d *RadarSprites[RADAR_SPRITE_COUNT]; static float cachedCos; static float cachedSin; -#ifdef MENU_MAP + static CRGBA ArrowBlipColour1; + static CRGBA ArrowBlipColour2; + static int16 MapLegendList[NUM_MAP_LEGENDS]; + static int16 MapLegendCounter; + +#ifdef MAP_ENHANCEMENTS static int TargetMarkerId; static CVector TargetMarkerPos; +#endif static void InitFrontEndMap(); static void DrawYouAreHereSprite(float, float); +#ifdef MAP_ENHANCEMENTS static void ToggleTargetMarker(float, float); #endif static uint8 CalculateBlipAlpha(float dist); @@ -178,8 +269,9 @@ public: static void RemoveRadarSections(); static void SaveAllRadarBlips(uint8*, uint32*); static void SetBlipSprite(int32 i, int32 icon); - static int32 SetCoordBlip(eBlipType type, CVector pos, int32, eBlipDisplay); - static int32 SetEntityBlip(eBlipType type, int32, int32, eBlipDisplay); + static int32 SetCoordBlip(eBlipType type, CVector pos, uint32, eBlipDisplay); + static int32 SetEntityBlip(eBlipType type, int32, uint32, eBlipDisplay); + static int32 SetShortRangeCoordBlip(eBlipType type, CVector pos, uint32, eBlipDisplay); static void SetRadarMarkerState(int32 i, bool flag); static void ShowRadarMarker(CVector pos, uint32 color, float radius); static void ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha); @@ -191,7 +283,8 @@ public: static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in); static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in); static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in); - - // no in CRadar in the game: static void CalculateCachedSinCos(); + static void DrawEntityBlip(int32 blipId); + static void DrawCoordBlip(int32 blipId); + static void DrawLegend(int32, int32, int32); }; diff --git a/src/core/References.cpp b/src/core/References.cpp index b7782099..09913817 100644 --- a/src/core/References.cpp +++ b/src/core/References.cpp @@ -42,6 +42,23 @@ CEntity::RegisterReference(CEntity **pent) } } +// Clean up the reference from *pent -> 'this' +void +CEntity::CleanUpOldReference(CEntity **pent) +{ + CReference* ref, ** lastnextp; + lastnextp = &m_pFirstReference; + for (ref = m_pFirstReference; ref; ref = ref->next) { + if (ref->pentity == pent) { + *lastnextp = ref->next; + ref->next = CReferences::pEmptyList; + CReferences::pEmptyList = ref; + break; + } + lastnextp = &ref->next; + } +} + // Clear all references to this entity void CEntity::ResolveReferences(void) diff --git a/src/core/Ropes.cpp b/src/core/Ropes.cpp new file mode 100644 index 00000000..71297eb1 --- /dev/null +++ b/src/core/Ropes.cpp @@ -0,0 +1,176 @@ +#include "common.h" + +#include "main.h" +#include "Timer.h" +#include "ModelIndices.h" +#include "Streaming.h" +#include "CopPed.h" +#include "Population.h" +#include "RenderBuffer.h" +#include "Camera.h" +#include "Ropes.h" + +CRope CRopes::aRopes[8]; + +RwImVertexIndex RopeIndices[64] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, + 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, + 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, + 31, 32 // unused +}; + +void +CRope::Update(void) +{ + int i; + float step = Pow(0.85f, CTimer::GetTimeStep()); + if(!m_bWasRegistered && CTimer::GetTimeInMilliseconds() > m_updateTimer){ + m_speed[0].z -= 0.0015f*CTimer::GetTimeStep(); + m_pos[0] += m_speed[0]*CTimer::GetTimeStep(); + } + for(i = 1; i < ARRAY_SIZE(m_pos); i++){ + CVector prevPos = m_pos[i]; + m_pos[i] += m_speed[i]*step*CTimer::GetTimeStep(); + m_pos[i].z -= 0.05f*CTimer::GetTimeStep(); + CVector dist = m_pos[i] - m_pos[i-1]; + m_pos[i] = m_pos[i-1] + (0.625f/dist.Magnitude())*dist; + m_speed[i] = (m_pos[i] - prevPos)/CTimer::GetTimeStep(); + } + if(!m_bWasRegistered && m_pos[0].z < 0.0f) + m_bActive = false; + m_bWasRegistered = false; +} + +void +CRope::Render(void) +{ + int i; + int numVerts = 0; + if(!TheCamera.IsSphereVisible(m_pos[16], 20.0f)) + return; + + for(i = 0; i < ARRAY_SIZE(m_pos); i++){ + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 128, 128, 128, 100); + RwIm3DVertexSetPos(&TempBufferRenderVertices[i], m_pos[i].x, m_pos[i].y, m_pos[i].z); + } + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + if(RwIm3DTransform(TempBufferRenderVertices, ARRAY_SIZE(m_pos), nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){ +#ifdef FIX_BUGS + RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); +#else + RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); +#endif + RwIm3DEnd(); + } +} + + +void +CRopes::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + aRopes[i].m_bActive = false; +} + +void +CRopes::Update(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive) + aRopes[i].Update(); +} + +void +CRopes::Render(void) +{ + int i; + PUSH_RENDERGROUP("CRopes::Render"); + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive) + aRopes[i].Render(); + POP_RENDERGROUP(); +} + +bool +CRopes::RegisterRope(uintptr id, CVector pos, bool setUpdateTimer) +{ + int i, j; + for(i = 0; i < ARRAY_SIZE(aRopes); i++){ + if(aRopes[i].m_bActive && aRopes[i].m_id == id){ + aRopes[i].m_pos[0] = pos; + aRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f); + aRopes[i].m_bWasRegistered = true; + return true; + } + } + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(!aRopes[i].m_bActive){ + aRopes[i].m_id = id; + aRopes[i].m_pos[0] = pos; + aRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f); + aRopes[i].m_unk = false; + aRopes[i].m_bWasRegistered = true; + aRopes[i].m_updateTimer = setUpdateTimer ? CTimer::GetTimeInMilliseconds() + 20000 : 0; + for(j = 1; j < ARRAY_SIZE(aRopes[0].m_pos); j++){ + if(j & 1) + aRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] + CVector(0.0f, 0.0f, 0.625f); + else + aRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] - CVector(0.0f, 0.0f, 0.625f); + aRopes[i].m_speed[j] = CVector(0.0f, 0.0f, 0.0f); + } + aRopes[i].m_bActive = true; + return true; + } + return false; +} + +void +CRopes::SetSpeedOfTopNode(uintptr id, CVector speed) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive && aRopes[i].m_id == id){ + aRopes[i].m_speed[0] = speed; + return; + } +} + +bool +CRopes::FindCoorsAlongRope(uintptr id, float t, CVector *coors) +{ + int i, j; + float f; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive && aRopes[i].m_id == id){ + t = (ARRAY_SIZE(aRopes[0].m_pos)-1)*Clamp(t, 0.0f, 0.999f); + j = t; + f = t - j; + *coors = (1.0f-f)*aRopes[i].m_pos[j] + f*aRopes[i].m_pos[j+1]; + return true; + } + return false; +} + +bool +CRopes::CreateRopeWithSwatComingDown(CVector pos) +{ + static uint32 ropeId = 0; + + if(!CStreaming::HasModelLoaded(MI_SWAT) || !RegisterRope(ropeId+100, pos, true)) + return false; + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos); + swat->bUsesCollision = false; + swat->m_pRopeEntity = (CEntity*)1; + swat->m_nRopeID = 100 + ropeId; + CAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_STD_ABSEIL, 4.0f); + ropeId++; + return true; +} diff --git a/src/core/Ropes.h b/src/core/Ropes.h new file mode 100644 index 00000000..7930fa98 --- /dev/null +++ b/src/core/Ropes.h @@ -0,0 +1,31 @@ +#pragma once + +class CRope +{ +public: + bool m_bActive; + bool m_bWasRegistered; + bool m_unk; + uintptr m_id; + uint32 m_updateTimer; + CVector m_pos[32]; + CVector m_speed[32]; + + void Update(void); + void Render(void); +}; + +class CRopes +{ + static CRope aRopes[8]; + +public: + + static void Init(void); + static void Update(void); + static void Render(void); + static bool RegisterRope(uintptr id, CVector pos, bool setUpdateTimer); + static void SetSpeedOfTopNode(uintptr id, CVector speed); + static bool FindCoorsAlongRope(uintptr id, float t, CVector *coors); + static bool CreateRopeWithSwatComingDown(CVector pos); +}; diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 9afd8ac3..8c6137f2 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -3,7 +3,27 @@ #include "Stats.h" #include "Text.h" #include "World.h" +#include "Pad.h" +#include "DMAudio.h" +#include "main.h" +#include "Font.h" +#include "Frontend.h" +#include "audio_enums.h" +#include <climits> + +#ifdef USE_PRECISE_MEASUREMENT_CONVERTION +#define MILES_IN_METER 0.000621371192f +#define FEET_IN_METER 3.28084f +#else +#define MILES_IN_METER (1 / 1670.f) +#define FEET_IN_METER 3.33f +#endif + +int32 CStats::SeagullsKilled; +int32 CStats::BoatsExploded; +int32 CStats::WantedStarsAttained; +int32 CStats::WantedStarsEvaded; int32 CStats::DaysPassed; int32 CStats::HeadsPopped; int32 CStats::CommercialPassed; @@ -16,10 +36,27 @@ int32 CStats::PedsKilledOfThisType[NUM_PEDTYPES]; int32 CStats::TimesDied; int32 CStats::TimesArrested; int32 CStats::KillsSinceLastCheckpoint; -float CStats::DistanceTravelledInVehicle; +float CStats::DistanceTravelledByCar; +float CStats::DistanceTravelledByHelicoptor; +float CStats::DistanceTravelledByBike; +float CStats::DistanceTravelledByBoat; +float CStats::DistanceTravelledByPlane; +float CStats::DistanceTravelledByGolfCart; float CStats::DistanceTravelledOnFoot; -int32 CStats::ProgressMade; -int32 CStats::TotalProgressInGame; +int32 CStats::FlightTime; +int32 CStats::TimesDrowned; +int32 CStats::PhotosTaken; +float CStats::LoanSharks; +float CStats::StoresKnockedOff; +float CStats::MovieStunts; +float CStats::Assassinations; +float CStats::PizzasDelivered; +float CStats::GarbagePickups; +float CStats::IceCreamSold; +float CStats::TopShootingRangeScore; +float CStats::ShootingRank; +float CStats::ProgressMade; +float CStats::TotalProgressInGame; int32 CStats::CarsExploded; int32 CStats::PeopleKilledByPlayer; float CStats::MaximumJumpDistance; @@ -35,84 +72,156 @@ int32 CStats::MissionsGiven; int32 CStats::MissionsPassed; char CStats::LastMissionPassedName[8]; int32 CStats::TotalLegitimateKills; -int32 CStats::ElBurroTime; -int32 CStats::Record4x4One; -int32 CStats::Record4x4Two; -int32 CStats::Record4x4Three; -int32 CStats::Record4x4Mayhem; int32 CStats::LivesSavedWithAmbulance; int32 CStats::CriminalsCaught; int32 CStats::HighestLevelAmbulanceMission; +int32 CStats::HighestLevelVigilanteMission; +int32 CStats::HighestLevelFireMission; int32 CStats::FiresExtinguished; -int32 CStats::LongestFlightInDodo; -int32 CStats::TimeTakenDefuseMission; int32 CStats::TotalNumberKillFrenzies; int32 CStats::TotalNumberMissions; int32 CStats::RoundsFiredByPlayer; int32 CStats::KgsOfExplosivesUsed; -int32 CStats::InstantHitsFiredByPlayer; -int32 CStats::InstantHitsHitByPlayer; +int32 CStats::BulletsThatHit; int32 CStats::BestTimeBombDefusal; -int32 CStats::mmRain; -int32 CStats::CarsCrushed; int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES]; int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; +int32 CStats::BestPositions[CStats::TOTAL_BEST_POSITIONS]; +bool CStats::PropertyOwned[CStats::TOTAL_PROPERTIES]; +int32 CStats::NumPropertyOwned; +int32 CStats::PropertyDestroyed; +float CStats::HighestChaseValue; +int32 CStats::CheatedCount; +int32 CStats::ShowChaseStatOnScreen; +int32 CStats::PamphletMissionPassed; +bool CStats::abSonyCDs[1]; +int32 CStats::BloodRingKills; +int32 CStats::BloodRingTime; +float CStats::FavoriteRadioStationList[NUM_RADIOS]; + +int32 CStats::Sprayings; +float CStats::AutoPaintingBudget; +int32 CStats::NoMoreHurricanes; +float CStats::FashionBudget; +float CStats::PropertyBudget; +float CStats::WeaponBudget; +int32 CStats::SafeHouseVisits; +int32 CStats::TyresPopped; + +int32 CStats::LongestWheelie; +int32 CStats::LongestStoppie; +int32 CStats::Longest2Wheel; +float CStats::LongestWheelieDist; +float CStats::LongestStoppieDist; +float CStats::Longest2WheelDist; void CStats::Init() { PeopleKilledByOthers = 0; PeopleKilledByPlayer = 0; - RoundsFiredByPlayer = 0; CarsExploded = 0; + BoatsExploded = 0; + RoundsFiredByPlayer = 0; + for (int i = 0; i < NUM_PEDTYPES; i++) + PedsKilledOfThisType[i] = 0; HelisDestroyed = 0; - ProgressMade = 0; + ProgressMade = 0.0f; KgsOfExplosivesUsed = 0; - InstantHitsFiredByPlayer = 0; - InstantHitsHitByPlayer = 0; - CarsCrushed = 0; + BulletsThatHit = 0; + TyresPopped = 0; HeadsPopped = 0; + WantedStarsAttained = 0; + WantedStarsEvaded = 0; TimesArrested = 0; TimesDied = 0; DaysPassed = 0; - NumberOfUniqueJumpsFound = 0; - mmRain = 0; - MaximumJumpFlips = 0; - MaximumJumpSpins = 0; + SafeHouseVisits = 0; + Sprayings = 0; MaximumJumpDistance = 0; MaximumJumpHeight = 0; + MaximumJumpFlips = 0; + MaximumJumpSpins = 0; BestStuntJump = 0; + NumberOfUniqueJumpsFound = 0; TotalNumberOfUniqueJumps = 0; - Record4x4One = 0; - LongestFlightInDodo = 0; - Record4x4Two = 0; + MissionsGiven = 0; + MissionsPassed = 0; PassengersDroppedOffWithTaxi = 0; - Record4x4Three = 0; MoneyMadeWithTaxi = 0; - Record4x4Mayhem = 0; + DistanceTravelledOnFoot = 0; + DistanceTravelledByCar = 0; + DistanceTravelledByBike = 0; + DistanceTravelledByBoat = 0; + DistanceTravelledByGolfCart = 0; + DistanceTravelledByHelicoptor = 0; +#ifdef FIX_BUGS + DistanceTravelledByPlane = 0; +#endif LivesSavedWithAmbulance = 0; - ElBurroTime = 0; CriminalsCaught = 0; - MissionsGiven = 0; + HighestLevelVigilanteMission = 0; HighestLevelAmbulanceMission = 0; - MissionsPassed = 0; + HighestLevelFireMission = 0; FiresExtinguished = 0; - DistanceTravelledOnFoot = 0; - TimeTakenDefuseMission = 0; + PhotosTaken = 0; NumberKillFrenziesPassed = 0; - DistanceTravelledInVehicle = 0; TotalNumberKillFrenzies = 0; TotalNumberMissions = 0; - KillsSinceLastCheckpoint = 0; - TotalLegitimateKills = 0; + FlightTime = 0; + TimesDrowned = 0; + SeagullsKilled = 0; + WeaponBudget = 0.0f; + FashionBudget = 0.0f; + LoanSharks = 0.0f; + StoresKnockedOff = 0.0f; + MovieStunts = 0.0f; + Assassinations = 0.0f; + PizzasDelivered = 0.0f; + GarbagePickups = 0.0f; + IceCreamSold = 0.0f; + TopShootingRangeScore = 0.0f; + ShootingRank = 0.0f; + LongestWheelie = 0; + LongestStoppie = 0; + Longest2Wheel = 0; + LongestWheelieDist = 0.0f; + LongestStoppieDist = 0.0f; + Longest2WheelDist = 0.0f; + PropertyBudget = 0.0f; + AutoPaintingBudget = 0.0f; + PropertyDestroyed = 0; + HighestChaseValue = 0.0f; + CheatedCount = 0; + for (int i = 0; i < TOTAL_FASTEST_TIMES; i++) FastestTimes[i] = 0; for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++) HighestScores[i] = 0; - for (int i = 0; i < NUM_PEDTYPES; i++) - PedsKilledOfThisType[i] = 0; + for (int i = 0; i < TOTAL_BEST_POSITIONS; i++) + BestPositions[i] = INT_MAX; + + KillsSinceLastCheckpoint = 0; + TotalLegitimateKills = 0; + + for (int i = 0; i < ARRAY_SIZE(LastMissionPassedName); i++) + LastMissionPassedName[i] = 0; + IndustrialPassed = 0; CommercialPassed = 0; SuburbanPassed = 0; + PamphletMissionPassed = 0; + NoMoreHurricanes = 0; + ShowChaseStatOnScreen = 0; + for (int i = 0; i < ARRAY_SIZE(abSonyCDs); i++) + abSonyCDs[i] = 0; + PopulateFavoriteRadioStationList(); + + NumPropertyOwned = 0; + for (int i = 0; i < TOTAL_PROPERTIES; i++) + PropertyOwned[i] = false; + + BloodRingKills = 0; + BloodRingTime = 0; } void CStats::RegisterFastestTime(int32 index, int32 time) @@ -130,29 +239,10 @@ void CStats::RegisterHighestScore(int32 index, int32 score) HighestScores[index] = Max(HighestScores[index], score); } -void CStats::RegisterElBurroTime(int32 time) -{ - ElBurroTime = (ElBurroTime && ElBurroTime < time) ? ElBurroTime : time; -} - -void CStats::Register4x4OneTime(int32 time) -{ - Record4x4One = (Record4x4One && Record4x4One < time) ? Record4x4One : time; -} - -void CStats::Register4x4TwoTime(int32 time) -{ - Record4x4Two = (Record4x4Two && Record4x4Two < time) ? Record4x4Two : time; -} - -void CStats::Register4x4ThreeTime(int32 time) -{ - Record4x4Three = (Record4x4Three && Record4x4Three < time) ? Record4x4Three : time; -} - -void CStats::Register4x4MayhemTime(int32 time) +void CStats::RegisterBestPosition(int32 index, int32 position) { - Record4x4Mayhem = (Record4x4Mayhem && Record4x4Mayhem < time) ? Record4x4Mayhem : time; + assert(index >= 0 && index < TOTAL_BEST_POSITIONS); + BestPositions[index] = Min(BestPositions[index], position); } void CStats::AnotherLifeSavedWithAmbulance() @@ -170,19 +260,19 @@ void CStats::RegisterLevelAmbulanceMission(int32 level) HighestLevelAmbulanceMission = Max(HighestLevelAmbulanceMission, level); } -void CStats::AnotherFireExtinguished() +void CStats::RegisterLevelVigilanteMission(int32 level) { - ++FiresExtinguished; + HighestLevelVigilanteMission = Max(HighestLevelVigilanteMission, level); } -void CStats::RegisterLongestFlightInDodo(int32 time) +void CStats::RegisterLevelFireMission(int32 level) { - LongestFlightInDodo = Max(LongestFlightInDodo, time); + HighestLevelFireMission = Max(HighestLevelFireMission, level); } -void CStats::RegisterTimeTakenDefuseMission(int32 time) +void CStats::AnotherFireExtinguished() { - TimeTakenDefuseMission = (TimeTakenDefuseMission && TimeTakenDefuseMission < time) ? TimeTakenDefuseMission : time; + ++FiresExtinguished; } void CStats::AnotherKillFrenzyPassed() @@ -204,43 +294,202 @@ wchar *CStats::FindCriminalRatingString() { int rating = FindCriminalRatingNumber(); - if (rating < 10) return TheText.Get("RATNG1"); - if (rating < 25) return TheText.Get("RATNG2"); - if (rating < 70) return TheText.Get("RATNG3"); - if (rating < 150) return TheText.Get("RATNG4"); - if (rating < 250) return TheText.Get("RATNG5"); - if (rating < 450) return TheText.Get("RATNG6"); - if (rating < 700) return TheText.Get("RATNG7"); - if (rating < 1000) return TheText.Get("RATNG8"); - if (rating < 1400) return TheText.Get("RATNG9"); - if (rating < 1900) return TheText.Get("RATNG10"); - if (rating < 2500) return TheText.Get("RATNG11"); - if (rating < 3200) return TheText.Get("RATNG12"); - if (rating < 4000) return TheText.Get("RATNG13"); - if (rating < 5000) return TheText.Get("RATNG14"); - return TheText.Get("RATNG15"); + if (rating < 0) { + if (rating > -500) return TheText.Get("RATNG53"); + if (rating > -2000) return TheText.Get("RATNG54"); + if (rating > -4000) return TheText.Get("RATNG55"); + if (rating > -6000) return TheText.Get("RATNG56"); + return TheText.Get("RATNG57"); + } + if (rating < 20) return TheText.Get("RATNG1"); + if (rating < 50) return TheText.Get("RATNG2"); + if (rating < 75) return TheText.Get("RATNG3"); + if (rating < 100) return TheText.Get("RATNG4"); + if (rating < 120) return TheText.Get("RATNG5"); + if (rating < 150) return TheText.Get("RATNG6"); + if (rating < 200) return TheText.Get("RATNG7"); + if (rating < 240) return TheText.Get("RATNG8"); + if (rating < 270) return TheText.Get("RATNG9"); + if (rating < 300) return TheText.Get("RATNG10"); + if (rating < 335) return TheText.Get("RATNG11"); + if (rating < 370) return TheText.Get("RATNG12"); + if (rating < 400) return TheText.Get("RATNG13"); + if (rating < 450) return TheText.Get("RATNG14"); + if (rating < 500) return TheText.Get("RATNG15"); + if (rating < 550) return TheText.Get("RATNG16"); + if (rating < 600) return TheText.Get("RATNG17"); + if (rating < 610) return TheText.Get("RATNG18"); + if (rating < 650) return TheText.Get("RATNG19"); + if (rating < 700) return TheText.Get("RATNG20"); + if (rating < 850) return TheText.Get("RATNG21"); + if (rating < 1000) return TheText.Get("RATNG22"); + if (rating < 1005) return TheText.Get("RATNG23"); + if (rating < 1150) return TheText.Get("RATNG24"); + if (rating < 1300) return TheText.Get(TimesArrested > 0 ? "RATNG25" : "RATNG24"); + if (rating < 1500) return TheText.Get("RATNG26"); + if (rating < 1700) return TheText.Get("RATNG27"); + if (rating < 2000) return TheText.Get("RATNG28"); + if (rating < 2100) return TheText.Get("RATNG29"); + if (rating < 2300) return TheText.Get("RATNG30"); + if (rating < 2500) return TheText.Get("RATNG31"); + if (rating < 2750) return TheText.Get("RATNG32"); + if (rating < 3000) return TheText.Get("RATNG33"); + if (rating < 3500) return TheText.Get("RATNG34"); + if (rating < 4000) return TheText.Get("RATNG35"); + if (rating < 5000) return TheText.Get("RATNG36"); + if (rating < 7500) return TheText.Get("RATNG37"); + if (rating < 10000) return TheText.Get("RATNG38"); + if (rating < 20000) return TheText.Get("RATNG39"); + if (rating < 30000) return TheText.Get("RATNG40"); + if (rating < 40000) return TheText.Get("RATNG41"); + if (rating < 50000) return TheText.Get("RATNG42"); + if (rating < 65000) return TheText.Get("RATNG43"); + if (rating < 80000) return TheText.Get("RATNG44"); + if (rating < 100000) return TheText.Get("RATNG45"); + if (rating < 150000) return TheText.Get("RATNG46"); + if (rating < 200000) return TheText.Get("RATNG47"); + if (rating < 300000) return TheText.Get("RATNG48"); + if (rating < 375000) return TheText.Get("RATNG49"); + if (rating < 500000) return TheText.Get(FlightTime / 60000 / 60 > 10 ? "RATNG50" : "RATNG49"); + if (rating < 1000000) return TheText.Get("RATNG51"); + return TheText.Get(CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney > 10000000 ? "RATNG52" : "RATNG51"); +} + +wchar *CStats::FindChaseString(float fMediaLevel) { + if (fMediaLevel < 20.0f) return TheText.Get("CHASE1"); + if (fMediaLevel < 50.0f) return TheText.Get("CHASE2"); + if (fMediaLevel < 75.0f) return TheText.Get("CHASE3"); + if (fMediaLevel < 100.0f) return TheText.Get("CHASE4"); + if (fMediaLevel < 150.0f) return TheText.Get("CHASE5"); + if (fMediaLevel < 200.0f) return TheText.Get("CHASE6"); + if (fMediaLevel < 250.0f) return TheText.Get("CHASE7"); + if (fMediaLevel < 300.0f) return TheText.Get("CHASE8"); + if (fMediaLevel < 350.0f) return TheText.Get("CHASE9"); + if (fMediaLevel < 400.0f) return TheText.Get("CHASE10"); + if (fMediaLevel < 500.0f) return TheText.Get("CHASE11"); + if (fMediaLevel < 600.0f) return TheText.Get("CHASE12"); + if (fMediaLevel < 700.0f) return TheText.Get("CHASE13"); + if (fMediaLevel < 800.0f) return TheText.Get("CHASE14"); + if (fMediaLevel < 900.0f) return TheText.Get("CHASE15"); + if (fMediaLevel < 1000.0f) return TheText.Get("CHASE16"); + if (fMediaLevel < 1200.0f) return TheText.Get("CHASE17"); + if (fMediaLevel < 1400.0f) return TheText.Get("CHASE18"); + if (fMediaLevel < 1600.0f) return TheText.Get("CHASE19"); + if (fMediaLevel < 1800.0f) return TheText.Get("CHASE20"); + return TheText.Get("CHASE21"); } int32 CStats::FindCriminalRatingNumber() { int32 rating; - rating = FiresExtinguished + 10 * HighestLevelAmbulanceMission + CriminalsCaught + LivesSavedWithAmbulance + rating = FiresExtinguished + 10 * HighestLevelFireMission + 10 * HighestLevelAmbulanceMission + + CriminalsCaught + LivesSavedWithAmbulance + 30 * HelisDestroyed + TotalLegitimateKills - 3 * TimesArrested - 3 * TimesDied + CWorld::Players[CWorld::PlayerInFocus].m_nMoney / 5000; - if (rating <= 0) rating = 0; + if (CPad::bHasPlayerCheated || CheatedCount > 0) { + rating -= CheatedCount; + if (rating <= -10000) + rating = -10000; + + } else if (rating <= 0) { + rating = 0; + } - if (InstantHitsFiredByPlayer > 100) - rating += (float)CStats::InstantHitsHitByPlayer / (float)CStats::InstantHitsFiredByPlayer * 500.0f; + if (RoundsFiredByPlayer > 100) + rating += (float)BulletsThatHit / (float)RoundsFiredByPlayer * 500.0f; if (TotalProgressInGame) - rating += (float)CStats::ProgressMade / (float)CStats::TotalProgressInGame * 1000.0f; - if (!IndustrialPassed && rating >= 3521) - rating = 3521; - if (!CommercialPassed && rating >= 4552) - rating = 4552; + rating += ProgressMade / TotalProgressInGame * 1000.0f; return rating; } +float CStats::GetPercentageProgress() +{ + float percentCompleted = (TotalProgressInGame == 0.f ? 0.f : + 100.0f * ProgressMade / (CGame::nastyGame ? TotalProgressInGame : TotalProgressInGame - 1.0f)); + + return Min(percentCompleted, 100.0f); +} + +void CStats::MoneySpentOnWeapons(int32 money) +{ + WeaponBudget += money; +} + +void CStats::MoneySpentOnProperty(int32 money) +{ + PropertyBudget += money; +} + +void CStats::MoneySpentOnAutoPainting(int32 money) +{ + AutoPaintingBudget += money; +} + +void CStats::MoneySpentOnFashion(int32 money) +{ + FashionBudget += money; +} + +void CStats::NumOfVisitsFromLoanSharks(int32 num) +{ + LoanSharks += num; +} + +void CStats::NumOfStoresKnockedOff(int32 num) +{ + StoresKnockedOff += num; +} + +void CStats::NumOfMovieStunts(int32 num) +{ + MovieStunts += num; +} + +void CStats::NumOfAssassinations(int32 num) +{ + Assassinations += num; +} + +void CStats::NumOfPizzasDelivered(int32 num) +{ + PizzasDelivered += num; +} + +void CStats::NumOfGarbagePickups(int32 num) +{ + GarbagePickups += num; +} + +void CStats::NumOfIceCreamSold(int32 num) +{ + IceCreamSold += num; +} + +void CStats::AddNumBloodRingKills(int32 num) +{ + BloodRingKills += num; +} + +void CStats::LongestTimeInBloodRing(int32 time) +{ + if (BloodRingTime < time) + BloodRingTime = time; +} + +void CStats::AddPropertyAsOwned(int32 id) +{ + if (!PropertyOwned[id]) { + PropertyOwned[id] = true; + ++NumPropertyOwned; + } +} + +float CStats::GetFavoriteRadioStationList(int32 station) +{ + return FavoriteRadioStationList[station]; +} + void CStats::SaveStats(uint8 *buf, uint32 *size) { CheckPointReachedSuccessfully(); @@ -248,20 +497,23 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) *size = sizeof(PeopleKilledByPlayer) + sizeof(PeopleKilledByOthers) + sizeof(CarsExploded) + + sizeof(BoatsExploded) + + sizeof(TyresPopped) + sizeof(RoundsFiredByPlayer) + sizeof(PedsKilledOfThisType) + sizeof(HelisDestroyed) + sizeof(ProgressMade) + sizeof(TotalProgressInGame) + sizeof(KgsOfExplosivesUsed) + - sizeof(InstantHitsFiredByPlayer) + - sizeof(InstantHitsHitByPlayer) + - sizeof(CarsCrushed) + + sizeof(BulletsThatHit) + sizeof(HeadsPopped) + + sizeof(WantedStarsAttained) + + sizeof(WantedStarsEvaded) + sizeof(TimesArrested) + sizeof(TimesDied) + sizeof(DaysPassed) + - sizeof(mmRain) + + sizeof(SafeHouseVisits) + + sizeof(Sprayings) + sizeof(MaximumJumpDistance) + sizeof(MaximumJumpHeight) + sizeof(MaximumJumpFlips) + @@ -270,52 +522,88 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) sizeof(NumberOfUniqueJumpsFound) + sizeof(TotalNumberOfUniqueJumps) + sizeof(MissionsGiven) + - sizeof(MissionsPassed) + sizeof(PassengersDroppedOffWithTaxi) + sizeof(MoneyMadeWithTaxi) + sizeof(IndustrialPassed) + sizeof(CommercialPassed) + sizeof(SuburbanPassed) + - sizeof(ElBurroTime) + + sizeof(PamphletMissionPassed) + + sizeof(NoMoreHurricanes) + sizeof(DistanceTravelledOnFoot) + - sizeof(DistanceTravelledInVehicle) + - sizeof(Record4x4One) + - sizeof(Record4x4Two) + - sizeof(Record4x4Three) + - sizeof(Record4x4Mayhem) + + sizeof(DistanceTravelledByCar) + + sizeof(DistanceTravelledByBike) + + sizeof(DistanceTravelledByBoat) + + sizeof(DistanceTravelledByGolfCart) + + sizeof(DistanceTravelledByHelicoptor) + + sizeof(DistanceTravelledByPlane) + sizeof(LivesSavedWithAmbulance) + sizeof(CriminalsCaught) + - sizeof(HighestLevelAmbulanceMission) + sizeof(FiresExtinguished) + - sizeof(LongestFlightInDodo) + - sizeof(TimeTakenDefuseMission) + + sizeof(HighestLevelVigilanteMission) + + sizeof(HighestLevelAmbulanceMission) + + sizeof(HighestLevelFireMission) + + sizeof(PhotosTaken) + sizeof(NumberKillFrenziesPassed) + sizeof(TotalNumberKillFrenzies) + sizeof(TotalNumberMissions) + + sizeof(FlightTime) + + sizeof(TimesDrowned) + + sizeof(SeagullsKilled) + + sizeof(WeaponBudget) + + sizeof(FashionBudget) + + sizeof(LoanSharks) + + sizeof(StoresKnockedOff) + + sizeof(MovieStunts) + + sizeof(Assassinations) + + sizeof(PizzasDelivered) + + sizeof(GarbagePickups) + + sizeof(IceCreamSold) + + sizeof(TopShootingRangeScore) + + sizeof(ShootingRank) + + sizeof(LongestWheelie) + + sizeof(LongestStoppie) + + sizeof(Longest2Wheel) + + sizeof(LongestWheelieDist) + + sizeof(LongestStoppieDist) + + sizeof(Longest2WheelDist) + + sizeof(PropertyBudget) + + sizeof(AutoPaintingBudget) + + sizeof(PropertyDestroyed) + + sizeof(NumPropertyOwned) + + sizeof(BloodRingKills) + + sizeof(BloodRingTime) + + sizeof(PropertyOwned) + + sizeof(HighestChaseValue) + sizeof(FastestTimes) + sizeof(HighestScores) + + sizeof(BestPositions) + sizeof(KillsSinceLastCheckpoint) + sizeof(TotalLegitimateKills) + - sizeof(LastMissionPassedName); + sizeof(LastMissionPassedName) + + sizeof(CheatedCount) + + sizeof(FavoriteRadioStationList); #define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data); CopyToBuf(buf, PeopleKilledByPlayer); CopyToBuf(buf, PeopleKilledByOthers); CopyToBuf(buf, CarsExploded); + CopyToBuf(buf, BoatsExploded); + CopyToBuf(buf, TyresPopped); CopyToBuf(buf, RoundsFiredByPlayer); CopyToBuf(buf, PedsKilledOfThisType); CopyToBuf(buf, HelisDestroyed); CopyToBuf(buf, ProgressMade); CopyToBuf(buf, TotalProgressInGame); CopyToBuf(buf, KgsOfExplosivesUsed); - CopyToBuf(buf, InstantHitsFiredByPlayer); - CopyToBuf(buf, InstantHitsHitByPlayer); - CopyToBuf(buf, CarsCrushed); + CopyToBuf(buf, BulletsThatHit); CopyToBuf(buf, HeadsPopped); + CopyToBuf(buf, WantedStarsAttained); + CopyToBuf(buf, WantedStarsEvaded); CopyToBuf(buf, TimesArrested); CopyToBuf(buf, TimesDied); CopyToBuf(buf, DaysPassed); - CopyToBuf(buf, mmRain); + CopyToBuf(buf, SafeHouseVisits); + CopyToBuf(buf, Sprayings); CopyToBuf(buf, MaximumJumpDistance); CopyToBuf(buf, MaximumJumpHeight); CopyToBuf(buf, MaximumJumpFlips); @@ -324,33 +612,67 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) CopyToBuf(buf, NumberOfUniqueJumpsFound); CopyToBuf(buf, TotalNumberOfUniqueJumps); CopyToBuf(buf, MissionsGiven); - CopyToBuf(buf, MissionsPassed); CopyToBuf(buf, PassengersDroppedOffWithTaxi); CopyToBuf(buf, MoneyMadeWithTaxi); CopyToBuf(buf, IndustrialPassed); CopyToBuf(buf, CommercialPassed); CopyToBuf(buf, SuburbanPassed); - CopyToBuf(buf, ElBurroTime); + CopyToBuf(buf, PamphletMissionPassed); + CopyToBuf(buf, NoMoreHurricanes); CopyToBuf(buf, DistanceTravelledOnFoot); - CopyToBuf(buf, DistanceTravelledInVehicle); - CopyToBuf(buf, Record4x4One); - CopyToBuf(buf, Record4x4Two); - CopyToBuf(buf, Record4x4Three); - CopyToBuf(buf, Record4x4Mayhem); + CopyToBuf(buf, DistanceTravelledByCar); + CopyToBuf(buf, DistanceTravelledByBike); + CopyToBuf(buf, DistanceTravelledByBoat); + CopyToBuf(buf, DistanceTravelledByGolfCart); + CopyToBuf(buf, DistanceTravelledByHelicoptor); + CopyToBuf(buf, DistanceTravelledByPlane); CopyToBuf(buf, LivesSavedWithAmbulance); CopyToBuf(buf, CriminalsCaught); - CopyToBuf(buf, HighestLevelAmbulanceMission); CopyToBuf(buf, FiresExtinguished); - CopyToBuf(buf, LongestFlightInDodo); - CopyToBuf(buf, TimeTakenDefuseMission); + CopyToBuf(buf, HighestLevelVigilanteMission); + CopyToBuf(buf, HighestLevelAmbulanceMission); + CopyToBuf(buf, HighestLevelFireMission); + CopyToBuf(buf, PhotosTaken); CopyToBuf(buf, NumberKillFrenziesPassed); CopyToBuf(buf, TotalNumberKillFrenzies); CopyToBuf(buf, TotalNumberMissions); + CopyToBuf(buf, FlightTime); + CopyToBuf(buf, TimesDrowned); + CopyToBuf(buf, SeagullsKilled); + CopyToBuf(buf, WeaponBudget); + CopyToBuf(buf, FashionBudget); + CopyToBuf(buf, LoanSharks); + CopyToBuf(buf, StoresKnockedOff); + CopyToBuf(buf, MovieStunts); + CopyToBuf(buf, Assassinations); + CopyToBuf(buf, PizzasDelivered); + CopyToBuf(buf, GarbagePickups); + CopyToBuf(buf, IceCreamSold); + CopyToBuf(buf, TopShootingRangeScore); + CopyToBuf(buf, ShootingRank); + CopyToBuf(buf, LongestWheelie); + CopyToBuf(buf, LongestStoppie); + CopyToBuf(buf, Longest2Wheel); + CopyToBuf(buf, LongestWheelieDist); + CopyToBuf(buf, LongestStoppieDist); + CopyToBuf(buf, Longest2WheelDist); + CopyToBuf(buf, PropertyBudget); + CopyToBuf(buf, AutoPaintingBudget); + CopyToBuf(buf, PropertyDestroyed); + CopyToBuf(buf, NumPropertyOwned); + CopyToBuf(buf, BloodRingKills); + CopyToBuf(buf, BloodRingTime); + CopyToBuf(buf, PropertyOwned); + CopyToBuf(buf, HighestChaseValue); CopyToBuf(buf, FastestTimes); CopyToBuf(buf, HighestScores); + CopyToBuf(buf, BestPositions); CopyToBuf(buf, KillsSinceLastCheckpoint); CopyToBuf(buf, TotalLegitimateKills); CopyToBuf(buf, LastMissionPassedName); + CopyToBuf(buf, CheatedCount); + PopulateFavoriteRadioStationList(); + CopyToBuf(buf, FavoriteRadioStationList); assert(buf - buf_start == *size); #undef CopyToBuf @@ -365,20 +687,23 @@ void CStats::LoadStats(uint8 *buf, uint32 size) CopyFromBuf(buf, PeopleKilledByPlayer); CopyFromBuf(buf, PeopleKilledByOthers); CopyFromBuf(buf, CarsExploded); + CopyFromBuf(buf, BoatsExploded); + CopyFromBuf(buf, TyresPopped); CopyFromBuf(buf, RoundsFiredByPlayer); CopyFromBuf(buf, PedsKilledOfThisType); CopyFromBuf(buf, HelisDestroyed); CopyFromBuf(buf, ProgressMade); CopyFromBuf(buf, TotalProgressInGame); CopyFromBuf(buf, KgsOfExplosivesUsed); - CopyFromBuf(buf, InstantHitsFiredByPlayer); - CopyFromBuf(buf, InstantHitsHitByPlayer); - CopyFromBuf(buf, CarsCrushed); + CopyFromBuf(buf, BulletsThatHit); CopyFromBuf(buf, HeadsPopped); + CopyFromBuf(buf, WantedStarsAttained); + CopyFromBuf(buf, WantedStarsEvaded); CopyFromBuf(buf, TimesArrested); CopyFromBuf(buf, TimesDied); CopyFromBuf(buf, DaysPassed); - CopyFromBuf(buf, mmRain); + CopyFromBuf(buf, SafeHouseVisits); + CopyFromBuf(buf, Sprayings); CopyFromBuf(buf, MaximumJumpDistance); CopyFromBuf(buf, MaximumJumpHeight); CopyFromBuf(buf, MaximumJumpFlips); @@ -387,34 +712,732 @@ void CStats::LoadStats(uint8 *buf, uint32 size) CopyFromBuf(buf, NumberOfUniqueJumpsFound); CopyFromBuf(buf, TotalNumberOfUniqueJumps); CopyFromBuf(buf, MissionsGiven); - CopyFromBuf(buf, MissionsPassed); CopyFromBuf(buf, PassengersDroppedOffWithTaxi); CopyFromBuf(buf, MoneyMadeWithTaxi); CopyFromBuf(buf, IndustrialPassed); CopyFromBuf(buf, CommercialPassed); CopyFromBuf(buf, SuburbanPassed); - CopyFromBuf(buf, ElBurroTime); + CopyFromBuf(buf, PamphletMissionPassed); + CopyFromBuf(buf, NoMoreHurricanes); CopyFromBuf(buf, DistanceTravelledOnFoot); - CopyFromBuf(buf, DistanceTravelledInVehicle); - CopyFromBuf(buf, Record4x4One); - CopyFromBuf(buf, Record4x4Two); - CopyFromBuf(buf, Record4x4Three); - CopyFromBuf(buf, Record4x4Mayhem); + CopyFromBuf(buf, DistanceTravelledByCar); + CopyFromBuf(buf, DistanceTravelledByBike); + CopyFromBuf(buf, DistanceTravelledByBoat); + CopyFromBuf(buf, DistanceTravelledByGolfCart); + CopyFromBuf(buf, DistanceTravelledByHelicoptor); + CopyFromBuf(buf, DistanceTravelledByPlane); CopyFromBuf(buf, LivesSavedWithAmbulance); CopyFromBuf(buf, CriminalsCaught); - CopyFromBuf(buf, HighestLevelAmbulanceMission); CopyFromBuf(buf, FiresExtinguished); - CopyFromBuf(buf, LongestFlightInDodo); - CopyFromBuf(buf, TimeTakenDefuseMission); + CopyFromBuf(buf, HighestLevelVigilanteMission); + CopyFromBuf(buf, HighestLevelAmbulanceMission); + CopyFromBuf(buf, HighestLevelFireMission); + CopyFromBuf(buf, PhotosTaken); CopyFromBuf(buf, NumberKillFrenziesPassed); CopyFromBuf(buf, TotalNumberKillFrenzies); CopyFromBuf(buf, TotalNumberMissions); + CopyFromBuf(buf, FlightTime); + CopyFromBuf(buf, TimesDrowned); + CopyFromBuf(buf, SeagullsKilled); + CopyFromBuf(buf, WeaponBudget); + CopyFromBuf(buf, FashionBudget); + CopyFromBuf(buf, LoanSharks); + CopyFromBuf(buf, StoresKnockedOff); + CopyFromBuf(buf, MovieStunts); + CopyFromBuf(buf, Assassinations); + CopyFromBuf(buf, PizzasDelivered); + CopyFromBuf(buf, GarbagePickups); + CopyFromBuf(buf, IceCreamSold); + CopyFromBuf(buf, TopShootingRangeScore); + CopyFromBuf(buf, ShootingRank); + CopyFromBuf(buf, LongestWheelie); + CopyFromBuf(buf, LongestStoppie); + CopyFromBuf(buf, Longest2Wheel); + CopyFromBuf(buf, LongestWheelieDist); + CopyFromBuf(buf, LongestStoppieDist); + CopyFromBuf(buf, Longest2WheelDist); + CopyFromBuf(buf, PropertyBudget); + CopyFromBuf(buf, AutoPaintingBudget); + CopyFromBuf(buf, PropertyDestroyed); + CopyFromBuf(buf, NumPropertyOwned); + CopyFromBuf(buf, BloodRingKills); + CopyFromBuf(buf, BloodRingTime); + CopyFromBuf(buf, PropertyOwned); + CopyFromBuf(buf, HighestChaseValue); CopyFromBuf(buf, FastestTimes); CopyFromBuf(buf, HighestScores); + CopyFromBuf(buf, BestPositions); CopyFromBuf(buf, KillsSinceLastCheckpoint); CopyFromBuf(buf, TotalLegitimateKills); CopyFromBuf(buf, LastMissionPassedName); + CopyFromBuf(buf, CheatedCount); + CopyFromBuf(buf, FavoriteRadioStationList); assert(buf - buf_start == size); #undef CopyFromBuf } + +void +CStats::PopulateFavoriteRadioStationList() +{ + float* pListenTimeArray = DMAudio.GetListenTimeArray(); + for (int i = 0; i < NUM_RADIOS; i++) + FavoriteRadioStationList[i] = pListenTimeArray[i]; +} + +void +CStats::BuildStatLine(Const char *text, void *stat, int displayType, void *stat2, int isTime) +{ +#define STAT_D *(int*)stat +#define STAT_F *(float*)stat +#define STAT2_D *(int*)stat2 +#define STAT2_F *(float*)stat2 + if (!text) + return; + + gString2[0] = '\0'; + if (isTime == 1) { + if (*((int*)stat2) >= 10) + sprintf(gString2, " %d:%d", STAT_D, STAT2_D); + else + sprintf(gString2, " %d:0%d", STAT_D, STAT2_D); + + } else if (stat2) { +#ifdef MORE_LANGUAGES + if (CFont::IsJapanese()) { + switch (displayType) { + case 0: + case 4: + sprintf(gString2, " %d/%d", STAT_D, STAT2_D); + break; + case 1: + sprintf(gString2, " %.2f/%.2f", STAT_F, STAT2_F); + break; + case 2: + sprintf(gString2, " %d%%/%d%%", STAT_D, STAT2_D); + break; + case 3: + sprintf(gString2, " $%.2f/$%.2f", STAT_F, STAT2_F); + break; + default: + break; + } + } else +#endif + { + switch (displayType) { + case 0: + sprintf(gString2, " %d %s %d", STAT_D, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_D); + break; + case 1: + sprintf(gString2, " %.2f %s %.2f", STAT_F, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_F); + break; + case 2: + sprintf(gString2, " %d%% %s %d%%", STAT_D, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_D); + break; + case 3: + sprintf(gString2, " $%.2f %s $%.2f", STAT_F, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_F); + break; + case 4: + sprintf(gString2, " %d_ %s %d_", STAT_D, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_D); + break; + default: + break; + } + } + } else if (stat) { + switch (displayType) { + case 0: + sprintf(gString2, "%d", STAT_D); + break; + case 1: + sprintf(gString2, "%.2f", STAT_F); + break; + case 2: + sprintf(gString2, "%d%%", STAT_D); + break; + case 3: + sprintf(gString2, "$%.2f", STAT_F); + break; + case 4: +#ifdef MORE_LANGUAGES + if (CFont::IsJapanese()) + sprintf(gString2, "%d", STAT_D); + else +#endif + sprintf(gString2, "%d_", STAT_D); + break; + default: + break; + } + } + UnicodeStrcpy(gUString, TheText.Get(text)); + CFont::FilterOutTokensFromString(gUString); + AsciiToUnicode(gString2, gUString2); +#undef STAT_D +#undef STAT_F +#undef STAT2_D +#undef STAT2_F +} + +// rowIdx 99999 returns total numbers of rows. otherwise it returns 0. +int +CStats::ConstructStatLine(int rowIdx) +{ + +#define STAT_LINE_1(varType, left, right1, type) \ + do { \ + if(counter == rowIdx){ \ + varType a = right1; \ + BuildStatLine(left, &a, type, nil, 0); \ + return 0; \ + } counter++; \ + } while(0) + +#define STAT_LINE_2(varType, left, right1, type, right2, time) \ + do { \ + if(counter == rowIdx){ \ + varType a = right1; \ + varType b = right2; \ + BuildStatLine(left, &a, type, &b, time); \ + return 0; \ + } counter++; \ + } while(0) + +#define TEXT_ON_LEFT_GXT(name) \ + do { \ + if(counter == rowIdx){ \ + BuildStatLine(name, nil, 0, nil, 0); \ + return 0; \ + } counter++; \ + } while(0) + +#define TEXT_ON_RIGHT(text) \ + do { \ + if(counter == rowIdx){ \ + gUString[0] = '\0'; \ + UnicodeStrcpy(gUString2, text); \ + return 0; \ + } counter++; \ + } while(0) + +#define FASTEST_TIME(id, str) \ + do { \ + if(FastestTimes[id]) { \ + if(counter == rowIdx){ \ + int hour = 0, minute; \ + for (int i = FastestTimes[id]; i > 59; i -= 60) hour++; \ + for (minute = FastestTimes[id]; minute > 59; minute -= 60); \ + if (minute < 0) minute = -minute; \ + BuildStatLine(str, &hour, 0, &minute, 1); \ + return 0; \ + } \ + counter++; \ + } \ + } while(0) + + switch (rowIdx) { + case 0: { + int percentCompleted = GetPercentageProgress(); + BuildStatLine("PER_COM", &percentCompleted, 2, nil, 0); + return 0; + } + case 1: { + BuildStatLine("NMISON", &MissionsGiven, 0, nil, 0); + return 0; + } + case 2: { + int hour = (CTimer::GetTimeInMilliseconds() / 60000) / 60; + int minute = (CTimer::GetTimeInMilliseconds() / 60000) % 60; + BuildStatLine("ST_TIME", &hour, 0, &minute, 1); + return 0; + } + case 3: { + BuildStatLine("DAYSPS", &DaysPassed, 0, nil, 0); + return 0; + } + case 4: { + BuildStatLine("NUMSHV", &SafeHouseVisits, 0, nil, 0); + return 0; + } + } + int counter = 5; + + if (CGame::nastyGame) { + STAT_LINE_2(int, "FEST_RP", NumberKillFrenziesPassed, 0, TotalNumberKillFrenzies, 0); + } + + CPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus]; + + // Hidden packages shouldn't be shown with percent +#ifdef FIX_BUGS + STAT_LINE_2(int, "PERPIC", player.m_nCollectedPackages, 0, player.m_nTotalPackages, 0); +#else + float fPackagesPercent = 0.0f; + if (player.m_nTotalPackages != 0) + fPackagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; + + STAT_LINE_2(int, "PERPIC", fPackagesPercent, 0, 100, 0); +#endif + + if (CGame::nastyGame) { + STAT_LINE_1(int, "PE_WAST", PeopleKilledByPlayer, 0); + STAT_LINE_1(int, "PE_WSOT", PeopleKilledByOthers, 0); + } + STAT_LINE_1(int, "CAR_EXP", CarsExploded, 0); + STAT_LINE_1(int, "BOA_EXP", BoatsExploded, 0); + STAT_LINE_1(int, "HEL_DST", HelisDestroyed, 0); + STAT_LINE_1(int, "TYREPOP", TyresPopped, 0); + STAT_LINE_1(int, "ST_STAR", WantedStarsAttained, 0); + STAT_LINE_1(int, "ST_STGN", WantedStarsEvaded, 0); + STAT_LINE_1(int, "TM_BUST", TimesArrested, 0); + STAT_LINE_1(int, "TM_DED", TimesDied, 0); + +#ifdef MORE_LANGUAGES + // JP version removed it altogether actually + if (!CFont::IsJapanese()) +#endif + STAT_LINE_1(int, "ST_HEAD", HeadsPopped, 0); + + static uint32 lastProcessedDay = UINT32_MAX; + static uint32 lastPoliceSpending = 0; + + // What a random stat... + if (lastProcessedDay != DaysPassed) { + lastProcessedDay = DaysPassed; + lastPoliceSpending = (CTimer::GetTimeInMilliseconds() & 255 + 80) * 255.44f; + } + STAT_LINE_1(float, "DAYPLC", lastPoliceSpending, 3); + + int mostPatheticGang = 0; + int mostKill = 0; + for (int i = PEDTYPE_GANG1; i < PEDTYPE_GANG9; ++i) { + if (CStats::PedsKilledOfThisType[i] > mostKill) { + mostKill = CStats::PedsKilledOfThisType[i]; + mostPatheticGang = i; + } + } + if (mostPatheticGang > 0) { + TEXT_ON_LEFT_GXT("ST_GANG"); + + switch (mostPatheticGang) { + case PEDTYPE_GANG1: + TEXT_ON_RIGHT(TheText.Get("ST_GNG1")); + break; + case PEDTYPE_GANG2: + TEXT_ON_RIGHT(TheText.Get("ST_GNG2")); + break; + case PEDTYPE_GANG3: + TEXT_ON_RIGHT(TheText.Get("ST_GNG3")); + break; + case PEDTYPE_GANG4: + TEXT_ON_RIGHT(TheText.Get("ST_GNG4")); + break; + case PEDTYPE_GANG5: + TEXT_ON_RIGHT(TheText.Get("ST_GNG5")); + break; + case PEDTYPE_GANG6: + TEXT_ON_RIGHT(TheText.Get("ST_GNG6")); + break; + case PEDTYPE_GANG7: + TEXT_ON_RIGHT(TheText.Get("ST_GNG7")); + break; + case PEDTYPE_GANG8: + TEXT_ON_RIGHT(TheText.Get("ST_GNG8")); + break; + default: + break; + } + } + + STAT_LINE_1(int, "GNG_WST", PedsKilledOfThisType[PEDTYPE_GANG9] + PedsKilledOfThisType[PEDTYPE_GANG8] + + PedsKilledOfThisType[PEDTYPE_GANG7] + PedsKilledOfThisType[PEDTYPE_GANG6] + + PedsKilledOfThisType[PEDTYPE_GANG5] + PedsKilledOfThisType[PEDTYPE_GANG4] + + PedsKilledOfThisType[PEDTYPE_GANG3] + PedsKilledOfThisType[PEDTYPE_GANG2] + + PedsKilledOfThisType[PEDTYPE_GANG1], 0); + + STAT_LINE_1(int, "DED_CRI", PedsKilledOfThisType[PEDTYPE_CRIMINAL], 0); + STAT_LINE_1(int, "KGS_EXP", KgsOfExplosivesUsed, 0); + STAT_LINE_1(int, "BUL_FIR", RoundsFiredByPlayer, 0); + STAT_LINE_1(int, "BUL_HIT", BulletsThatHit, 0); +; + STAT_LINE_1(int, "ACCURA", RoundsFiredByPlayer == 0 ? 0 : (BulletsThatHit * 100.0f / (float)RoundsFiredByPlayer), 2); + + switch (FrontEndMenuManager.m_PrefsLanguage) { + case CMenuManager::LANGUAGE_AMERICAN: +#ifndef USE_MEASUREMENTS_IN_METERS + STAT_LINE_1(float, "FEST_DF", DistanceTravelledOnFoot * MILES_IN_METER, 1); + STAT_LINE_1(float, "FEST_DC", DistanceTravelledByCar * MILES_IN_METER, 1); + STAT_LINE_1(float, "DISTBIK", DistanceTravelledByBike * MILES_IN_METER, 1); + STAT_LINE_1(float, "DISTBOA", DistanceTravelledByBoat * MILES_IN_METER, 1); + STAT_LINE_1(float, "DISTGOL", DistanceTravelledByGolfCart * MILES_IN_METER, 1); + STAT_LINE_1(float, "DISTHEL", DistanceTravelledByHelicoptor * MILES_IN_METER, 1); +#ifdef FIX_BUGS + STAT_LINE_1(float, "TOT_DIS", (DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat + DistanceTravelledByBike + + DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor + DistanceTravelledByPlane) * MILES_IN_METER, 1); + STAT_LINE_1(float, "MXCARD", MaximumJumpDistance * FEET_IN_METER, 1); + STAT_LINE_1(float, "MXCARJ", MaximumJumpHeight * FEET_IN_METER, 1); +#else + STAT_LINE_1(float, "TOT_DIS", (DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat + DistanceTravelledByBike + + DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor) * MILES_IN_METER, 1); +#endif + break; +#endif + case CMenuManager::LANGUAGE_FRENCH: + case CMenuManager::LANGUAGE_GERMAN: + case CMenuManager::LANGUAGE_ITALIAN: + case CMenuManager::LANGUAGE_SPANISH: +#ifdef MORE_LANGUAGES + case CMenuManager::LANGUAGE_POLISH: + case CMenuManager::LANGUAGE_RUSSIAN: + case CMenuManager::LANGUAGE_JAPANESE: +#endif + STAT_LINE_1(float, "FESTDFM", DistanceTravelledOnFoot, 1); + STAT_LINE_1(float, "FESTDCM", DistanceTravelledByCar, 1); + STAT_LINE_1(float, "DISTBIM", DistanceTravelledByBike, 1); + STAT_LINE_1(float, "DISTBOM", DistanceTravelledByBoat, 1); + STAT_LINE_1(float, "DISTGOM", DistanceTravelledByGolfCart, 1); + STAT_LINE_1(float, "DISTHEM", DistanceTravelledByHelicoptor, 1); +#ifdef FIX_BUGS + STAT_LINE_1(float, "TOTDISM", DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat + + DistanceTravelledByBike + DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor + DistanceTravelledByPlane, 1); + STAT_LINE_1(float, "MXCARDM", MaximumJumpDistance, 1); + STAT_LINE_1(float, "MXCARJM", MaximumJumpHeight, 1); +#else + STAT_LINE_1(float, "TOTDISM", DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat + + DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor, 1); +#endif + break; + default: + break; + } + + // They were selecting the unit according to language in III, but they deleted the feet code in VC. Weird +#ifndef FIX_BUGS + STAT_LINE_1(float, "MXCARDM", MaximumJumpDistance, 1); + STAT_LINE_1(float, "MXCARJM", MaximumJumpHeight, 1); +#endif + STAT_LINE_1(int, "MXFLIP", MaximumJumpFlips, 0); + STAT_LINE_2(int, "NOUNIF", NumberOfUniqueJumpsFound, 0, TotalNumberOfUniqueJumps, 0); + STAT_LINE_1(int, "MXJUMP", MaximumJumpSpins, 4); + + TEXT_ON_LEFT_GXT("BSTSTU"); + switch (BestStuntJump) { + case 1: + TEXT_ON_RIGHT(TheText.Get("INSTUN")); + break; + case 2: + TEXT_ON_RIGHT(TheText.Get("PRINST")); + break; + case 3: + TEXT_ON_RIGHT(TheText.Get("DBINST")); + break; + case 4: + TEXT_ON_RIGHT(TheText.Get("DBPINS")); + break; + case 5: + TEXT_ON_RIGHT(TheText.Get("TRINST")); + break; + case 6: + TEXT_ON_RIGHT(TheText.Get("PRTRST")); + break; + case 7: + TEXT_ON_RIGHT(TheText.Get("QUINST")); + break; + case 8: + TEXT_ON_RIGHT(TheText.Get("PQUINS")); + break; + default: + TEXT_ON_RIGHT(TheText.Get("NOSTUC")); + break; + } + STAT_LINE_1(int, "ST_WHEE", LongestWheelie, 0); + STAT_LINE_1(float, "ST_WHED", LongestWheelieDist, 1); + STAT_LINE_1(int, "ST_STOP", LongestStoppie, 0); + STAT_LINE_1(float, "ST_STOD", LongestStoppieDist, 1); + STAT_LINE_1(int, "ST_2WHE", Longest2Wheel, 0); + STAT_LINE_1(float, "ST_2WHD", Longest2WheelDist, 1); + + if (LoanSharks > 0.0f) + STAT_LINE_1(int, "ST_LOAN", LoanSharks, 0); + + STAT_LINE_1(int, "FEST_CC", CriminalsCaught, 0); + STAT_LINE_1(int, "FEST_HV", HighestLevelVigilanteMission, 0); + STAT_LINE_1(int, "PASDRO", PassengersDroppedOffWithTaxi, 0); + STAT_LINE_1(float, "MONTAX", MoneyMadeWithTaxi, 3); + STAT_LINE_1(int, "FEST_LS", LivesSavedWithAmbulance, 0); + STAT_LINE_1(int, "FEST_HA", HighestLevelAmbulanceMission, 0); + STAT_LINE_1(int, "FEST_FE", FiresExtinguished, 0); + STAT_LINE_1(int, "FIRELVL", HighestLevelFireMission, 0); + + STAT_LINE_2(int, "ST_STOR", StoresKnockedOff, 0, 15, 0); + + if (MovieStunts > 0.0f) + STAT_LINE_1(int, "ST_MOVI", MovieStunts, 0); + + STAT_LINE_2(int, "ST_ASSI", Assassinations, 0, 5, 0); + + if (PhotosTaken > 0) + STAT_LINE_1(int, "ST_PHOT", PhotosTaken, 0); + + if (PizzasDelivered > 0.0f) + STAT_LINE_1(int, "ST_PIZZ", PizzasDelivered, 0); + + if (GarbagePickups > 0.0f) + STAT_LINE_1(int, "ST_GARB", GarbagePickups, 0); + + if (IceCreamSold > 0.0f) + STAT_LINE_1(int, "ST_ICEC", IceCreamSold, 0); + + if (HighestScores[1]) + STAT_LINE_1(int, "STHC_02", HighestScores[1], 0); + + FASTEST_TIME(0, "STFT_01"); + FASTEST_TIME(1, "STFT_02"); + FASTEST_TIME(2, "STFT_03"); + FASTEST_TIME(3, "STFT_04"); + FASTEST_TIME(4, "STFT_05"); + FASTEST_TIME(5, "STFT_06"); + FASTEST_TIME(6, "STFT_07"); + FASTEST_TIME(7, "STFT_08"); + FASTEST_TIME(8, "STFT_09"); + FASTEST_TIME(9, "STFT_10"); + FASTEST_TIME(10, "STFT_11"); + FASTEST_TIME(11, "STFT_12"); + FASTEST_TIME(12, "STFT_13"); + FASTEST_TIME(13, "STFT_14"); + FASTEST_TIME(14, "STFT_15"); + FASTEST_TIME(15, "STFT_16"); + FASTEST_TIME(16, "STFT_17"); + FASTEST_TIME(17, "STFT_18"); + FASTEST_TIME(18, "STFT_19"); + FASTEST_TIME(19, "STFT_20"); + FASTEST_TIME(22, "STFT_23"); + + if (HighestScores[0]) + STAT_LINE_1(int, "STHC_01", HighestScores[0], 0); + + if (HighestScores[3]) + STAT_LINE_1(int, "STHC_04", HighestScores[3], 0); + + if (HighestScores[2]) + STAT_LINE_1(int, "STHC_03", HighestScores[2], 0); + + if (BestPositions[0] != INT_MAX) + STAT_LINE_1(int, "STHC_05", BestPositions[0], 0); + + FASTEST_TIME(20, "STFT_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); +#endif + + if (TopShootingRangeScore > 0.0f) + STAT_LINE_1(int, "TOP_SHO", TopShootingRangeScore, 0); + + if (ShootingRank > 0.0f) + STAT_LINE_1(int, "SHO_RAN", ShootingRank, 0); + + int flightMinute = (FlightTime / 60000) % 60; + int flightHour = (FlightTime / 60000) / 60; + STAT_LINE_2(int, "ST_FTIM", flightHour, 0, flightMinute, 1); + + // We always have pilot rank if we flew more then 5 minutes +#ifndef FIX_BUGS + if (flightHour != 0) + TEXT_ON_LEFT_GXT("ST_PRAN"); +#endif + +#ifdef FIX_BUGS +#define FL_TIME_MORE_THAN(hour, minute) (flightHour > hour || (flightHour == hour && flightMinute >= minute)) +#else +#define FL_TIME_MORE_THAN(hour, minute) (flightHour > hour || flightMinute >= minute) +#endif + + if (FL_TIME_MORE_THAN(0,5)) { + +#ifdef FIX_BUGS + TEXT_ON_LEFT_GXT("ST_PRAN"); +#endif + if (!FL_TIME_MORE_THAN(0,10)) TEXT_ON_RIGHT(TheText.Get("ST_PR01")); + else if (!FL_TIME_MORE_THAN(0,20)) TEXT_ON_RIGHT(TheText.Get("ST_PR02")); + else if (!FL_TIME_MORE_THAN(0,30)) TEXT_ON_RIGHT(TheText.Get("ST_PR03")); + else if (!FL_TIME_MORE_THAN(1,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR04")); + else if (!FL_TIME_MORE_THAN(1,30)) TEXT_ON_RIGHT(TheText.Get("ST_PR05")); + else if (!FL_TIME_MORE_THAN(2,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR06")); + else if (!FL_TIME_MORE_THAN(2,30)) TEXT_ON_RIGHT(TheText.Get("ST_PR07")); + else if (!FL_TIME_MORE_THAN(3,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR08")); + else if (!FL_TIME_MORE_THAN(3,30)) TEXT_ON_RIGHT(TheText.Get("ST_PR09")); + else if (!FL_TIME_MORE_THAN(4,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR10")); + else if (!FL_TIME_MORE_THAN(5,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR11")); + else if (!FL_TIME_MORE_THAN(10,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR12")); + else if (!FL_TIME_MORE_THAN(20,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR13")); + else if (!FL_TIME_MORE_THAN(25,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR14")); + else if (!FL_TIME_MORE_THAN(30,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR15")); + else if (!FL_TIME_MORE_THAN(49,2)) TEXT_ON_RIGHT(TheText.Get("ST_PR16")); + else if (!FL_TIME_MORE_THAN(50,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR17")); + else if (!FL_TIME_MORE_THAN(100,0)) TEXT_ON_RIGHT(TheText.Get("ST_PR18")); + else TEXT_ON_RIGHT(TheText.Get("ST_PR19")); + } +#undef FL_TIME_MORE_THAN + + if (BloodRingKills > 0) + STAT_LINE_1(int, "ST_BRK", BloodRingKills, 0); + + if (BloodRingTime > 0) + STAT_LINE_1(int, "ST_LTBR", BloodRingTime, 0); + + STAT_LINE_1(int, "ST_DRWN", TimesDrowned, 0); + + if (SeagullsKilled > 0) + STAT_LINE_1(int, "SEAGULL", SeagullsKilled, 0); + + bool playerHatesRadio = true; + float* pListenTimeArray = DMAudio.GetListenTimeArray(); + for (int i = 0; i < NUM_RADIOS; i++) { + FavoriteRadioStationList[i] = pListenTimeArray[i]; + if (FavoriteRadioStationList[i] != 0.0) // double + playerHatesRadio = false; + } + + if (!playerHatesRadio) { + // Most listened + TEXT_ON_LEFT_GXT("FST_MFR"); + float mostListenTime = FavoriteRadioStationList[0]; + int mostListenedRadio = 0; + for (int i = 0; i < NUM_RADIOS; i++) { + if (FavoriteRadioStationList[i] > mostListenTime) { + mostListenTime = FavoriteRadioStationList[i]; + mostListenedRadio = i; + } + } + switch (mostListenedRadio) { + case WILDSTYLE: + TEXT_ON_RIGHT(TheText.Get("FEA_FM0")); + break; + case FLASH_FM: + TEXT_ON_RIGHT(TheText.Get("FEA_FM1")); + break; + case KCHAT: + TEXT_ON_RIGHT(TheText.Get("FEA_FM2")); + break; + case FEVER: + TEXT_ON_RIGHT(TheText.Get("FEA_FM3")); + break; + case V_ROCK: + TEXT_ON_RIGHT(TheText.Get("FEA_FM4")); + break; + case VCPR: + TEXT_ON_RIGHT(TheText.Get("FEA_FM5")); + break; + case RADIO_ESPANTOSO: + TEXT_ON_RIGHT(TheText.Get("FEA_FM6")); + break; + case EMOTION: + TEXT_ON_RIGHT(TheText.Get("FEA_FM7")); + break; + case WAVE: + TEXT_ON_RIGHT(TheText.Get("FEA_FM8")); + break; + case USERTRACK: + TEXT_ON_RIGHT(TheText.Get("FEA_MP3")); + break; + default: + TEXT_ON_RIGHT(TheText.Get("FEA_FM8")); // heh + break; + } + + // Least listened + TEXT_ON_LEFT_GXT("FST_LFR"); + float leastListenTime = FavoriteRadioStationList[0]; + int leastListenedRadio = 0; + for (int i = 0; i < NUM_RADIOS; i++) { +#ifdef FIX_BUGS + if (!DMAudio.IsMP3RadioChannelAvailable() && i == USERTRACK) + continue; +#endif + if (FavoriteRadioStationList[i] < leastListenTime) { + leastListenTime = FavoriteRadioStationList[i]; + leastListenedRadio = i; + } + } +#ifndef FIX_BUGS + if (!DMAudio.IsMP3RadioChannelAvailable() && leastListenedRadio == USERTRACK) + leastListenedRadio = WAVE; +#endif + + switch (leastListenedRadio) { + case WILDSTYLE: + TEXT_ON_RIGHT(TheText.Get("FEA_FM0")); + break; + case FLASH_FM: + TEXT_ON_RIGHT(TheText.Get("FEA_FM1")); + break; + case KCHAT: + TEXT_ON_RIGHT(TheText.Get("FEA_FM2")); + break; + case FEVER: + TEXT_ON_RIGHT(TheText.Get("FEA_FM3")); + break; + case V_ROCK: + TEXT_ON_RIGHT(TheText.Get("FEA_FM4")); + break; + case VCPR: + TEXT_ON_RIGHT(TheText.Get("FEA_FM5")); + break; + case RADIO_ESPANTOSO: + TEXT_ON_RIGHT(TheText.Get("FEA_FM6")); + break; + case EMOTION: + TEXT_ON_RIGHT(TheText.Get("FEA_FM7")); + break; + case WAVE: + TEXT_ON_RIGHT(TheText.Get("FEA_FM8")); + break; + case USERTRACK: + TEXT_ON_RIGHT(TheText.Get("FEA_MP3")); + break; + default: + TEXT_ON_RIGHT(TheText.Get("FEA_FM8")); // heh + break; + } + } + STAT_LINE_1(int, "SPRAYIN", Sprayings, 0); + STAT_LINE_1(float, "ST_WEAP", WeaponBudget, 3); + STAT_LINE_1(float, "ST_FASH", FashionBudget, 3); + STAT_LINE_1(float, "ST_PROP", PropertyBudget, 3); + STAT_LINE_1(float, "ST_AUTO", AutoPaintingBudget, 3); + STAT_LINE_1(float, "ST_DAMA", PropertyBudget, 3); + + if (NumPropertyOwned > 0) { + STAT_LINE_1(int, "PROPOWN", NumPropertyOwned, 0); + if (PropertyOwned[0]) TEXT_ON_RIGHT(TheText.Get("STPR_1")); + if (PropertyOwned[1]) TEXT_ON_RIGHT(TheText.Get("STPR_2")); + if (PropertyOwned[2]) TEXT_ON_RIGHT(TheText.Get("STPR_3")); + if (PropertyOwned[3]) TEXT_ON_RIGHT(TheText.Get("STPR_4")); + if (PropertyOwned[4]) TEXT_ON_RIGHT(TheText.Get("STPR_5")); + if (PropertyOwned[5]) TEXT_ON_RIGHT(TheText.Get("STPR_6")); + if (PropertyOwned[6]) TEXT_ON_RIGHT(TheText.Get("STPR_7")); + if (PropertyOwned[7]) TEXT_ON_RIGHT(TheText.Get("STPR_8")); + if (PropertyOwned[8]) TEXT_ON_RIGHT(TheText.Get("STPR_9")); + if (PropertyOwned[9]) TEXT_ON_RIGHT(TheText.Get("STPR_10")); + if (PropertyOwned[10]) TEXT_ON_RIGHT(TheText.Get("STPR_11")); + if (PropertyOwned[11]) TEXT_ON_RIGHT(TheText.Get("STPR_12")); + if (PropertyOwned[12]) TEXT_ON_RIGHT(TheText.Get("STPR_13")); + if (PropertyOwned[13]) TEXT_ON_RIGHT(TheText.Get("STPR_14")); + if (PropertyOwned[14]) TEXT_ON_RIGHT(TheText.Get("STPR_15")); + } + STAT_LINE_1(int, "CHASE", HighestChaseValue, 0); + TEXT_ON_RIGHT(FindChaseString(HighestChaseValue)); + + return counter; + +#undef STAT_LINE_1 +#undef STAT_LINE_2 +#undef TEXT_ON_LEFT_GXT +#undef TEXT_ON_RIGHT +#undef FASTEST_TIME +} diff --git a/src/core/Stats.h b/src/core/Stats.h index 6abcfb61..243ff0ec 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -1,14 +1,18 @@ #pragma once #include "PedType.h" +#include "audio_enums.h" class CStats { public: enum { - TOTAL_FASTEST_TIMES = 16, - TOTAL_HIGHEST_SCORES = 16 + TOTAL_FASTEST_TIMES = 23, + TOTAL_HIGHEST_SCORES = 5, + TOTAL_BEST_POSITIONS = 1, + TOTAL_PROPERTIES = 15 }; + static int32 SeagullsKilled; static int32 DaysPassed; static int32 HeadsPopped; static int32 CommercialPassed; @@ -21,12 +25,32 @@ public: static int32 TimesDied; static int32 TimesArrested; static int32 KillsSinceLastCheckpoint; - static float DistanceTravelledInVehicle; + static float DistanceTravelledByCar; + static float DistanceTravelledByHelicoptor; + static float DistanceTravelledByBike; + static float DistanceTravelledByBoat; + static float DistanceTravelledByPlane; + static float DistanceTravelledByGolfCart; static float DistanceTravelledOnFoot; + static int32 FlightTime; + static int32 TimesDrowned; + static int32 PhotosTaken; + static float LoanSharks; + static float StoresKnockedOff; + static float MovieStunts; + static float Assassinations; + static float PizzasDelivered; + static float GarbagePickups; + static float IceCreamSold; + static float TopShootingRangeScore; + static float ShootingRank; static int32 CarsExploded; + static int32 BoatsExploded; + static int32 WantedStarsAttained; + static int32 WantedStarsEvaded; static int32 PeopleKilledByPlayer; - static int32 ProgressMade; - static int32 TotalProgressInGame; + static float ProgressMade; + static float TotalProgressInGame; static float MaximumJumpDistance; static float MaximumJumpHeight; static int32 MaximumJumpFlips; @@ -40,45 +64,61 @@ public: static int32 MissionsPassed; static char LastMissionPassedName[8]; static int32 TotalLegitimateKills; - static int32 ElBurroTime; - static int32 Record4x4One; - static int32 Record4x4Two; - static int32 Record4x4Three; - static int32 Record4x4Mayhem; static int32 LivesSavedWithAmbulance; static int32 CriminalsCaught; static int32 HighestLevelAmbulanceMission; + static int32 HighestLevelVigilanteMission; + static int32 HighestLevelFireMission; static int32 FiresExtinguished; - static int32 LongestFlightInDodo; - static int32 TimeTakenDefuseMission; static int32 TotalNumberKillFrenzies; static int32 TotalNumberMissions; static int32 RoundsFiredByPlayer; static int32 KgsOfExplosivesUsed; - static int32 InstantHitsFiredByPlayer; - static int32 InstantHitsHitByPlayer; + static int32 BulletsThatHit; static int32 BestTimeBombDefusal; - static int32 mmRain; - static int32 CarsCrushed; static int32 FastestTimes[TOTAL_FASTEST_TIMES]; static int32 HighestScores[TOTAL_HIGHEST_SCORES]; + static int32 BestPositions[TOTAL_BEST_POSITIONS]; + static bool PropertyOwned[TOTAL_PROPERTIES]; + static int32 NumPropertyOwned; + static int32 PropertyDestroyed; + static float HighestChaseValue; + static int32 CheatedCount; + static int32 ShowChaseStatOnScreen; + static int32 PamphletMissionPassed; + static bool abSonyCDs[1]; + static int32 BloodRingKills; + static int32 BloodRingTime; + static float FavoriteRadioStationList[NUM_RADIOS]; + static int32 Sprayings; + static float AutoPaintingBudget; + static int32 NoMoreHurricanes; + static float FashionBudget; + static float PropertyBudget; + static float WeaponBudget; + static int32 SafeHouseVisits; + static int32 TyresPopped; + + static int32 LongestWheelie; + static int32 LongestStoppie; + static int32 Longest2Wheel; + static float LongestWheelieDist; + static float LongestStoppieDist; + static float Longest2WheelDist; public: static void Init(void); static void RegisterFastestTime(int32, int32); static void RegisterHighestScore(int32, int32); - static void RegisterElBurroTime(int32); - static void Register4x4OneTime(int32); - static void Register4x4TwoTime(int32); - static void Register4x4ThreeTime(int32); - static void Register4x4MayhemTime(int32); + static void RegisterBestPosition(int32, int32); static void AnotherLifeSavedWithAmbulance(); static void AnotherCriminalCaught(); static void RegisterLevelAmbulanceMission(int32); + static void RegisterLevelVigilanteMission(int32); + static void RegisterLevelFireMission(int32); static void AnotherFireExtinguished(); static wchar *FindCriminalRatingString(); - static void RegisterLongestFlightInDodo(int32); - static void RegisterTimeTakenDefuseMission(int32); + static wchar *FindChaseString(float fMediaLevel); static void AnotherKillFrenzyPassed(); static void SetTotalNumberKillFrenzies(int32); static void SetTotalNumberMissions(int32); @@ -87,4 +127,26 @@ public: static int32 FindCriminalRatingNumber(); static void SaveStats(uint8 *buf, uint32 *size); static void LoadStats(uint8 *buf, uint32 size); + static float GetPercentageProgress(); + + static void MoneySpentOnWeapons(int32); + static void MoneySpentOnProperty(int32); + static void MoneySpentOnAutoPainting(int32); + static void MoneySpentOnFashion(int32); + + static void NumOfVisitsFromLoanSharks(int32); + static void NumOfStoresKnockedOff(int32); + static void NumOfMovieStunts(int32); + static void NumOfAssassinations(int32); + static void NumOfPizzasDelivered(int32); + static void NumOfGarbagePickups(int32); + static void NumOfIceCreamSold(int32); + static void AddNumBloodRingKills(int32); + + static void LongestTimeInBloodRing(int32); + static void AddPropertyAsOwned(int32); + static void PopulateFavoriteRadioStationList(); + static float GetFavoriteRadioStationList(int32); + static void BuildStatLine(Const char *, void *, int, void *, int); + static int ConstructStatLine(int); }; diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 9ac22096..6d980e18 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -18,7 +18,6 @@ #include "FileMgr.h" #include "FileLoader.h" #include "Zones.h" -#include "ZoneCull.h" #include "Radar.h" #include "Camera.h" #include "Record.h" @@ -28,14 +27,16 @@ #include "CutsceneMgr.h" #include "CdStream.h" #include "Streaming.h" -#ifdef FIX_BUGS #include "Replay.h" -#endif #include "main.h" -#include "Frontend.h" -#include "Font.h" +#include "ColStore.h" +#include "DMAudio.h" +#include "Script.h" #include "MemoryMgr.h" #include "MemoryHeap.h" +#include "Font.h" +#include "Frontend.h" +#include "VarConsole.h" bool CStreaming::ms_disableStreaming; bool CStreaming::ms_bLoadingBigModel; @@ -57,11 +58,12 @@ size_t CStreaming::ms_memoryUsed; CStreamingChannel CStreaming::ms_channel[2]; int32 CStreaming::ms_channelError; int32 CStreaming::ms_numVehiclesLoaded; +int32 CStreaming::ms_numPedsLoaded; int32 CStreaming::ms_vehiclesLoaded[MAXVEHICLESLOADED]; int32 CStreaming::ms_lastVehicleDeleted; +bool CStreaming::ms_bIsPedFromPedGroupLoaded[NUMMODELSPERPEDGROUP]; CDirectory *CStreaming::ms_pExtraObjectsDir; int32 CStreaming::ms_numPriorityRequests; -bool CStreaming::ms_hasLoadedLODs; int32 CStreaming::ms_currentPedGrp; int32 CStreaming::ms_currentPedLoading; int32 CStreaming::ms_lastCullZone; @@ -74,16 +76,16 @@ size_t CStreaming::ms_memoryAvailable; int32 desiredNumVehiclesLoaded = 12; -CEntity *pIslandLODindustEntity; -CEntity *pIslandLODcomIndEntity; -CEntity *pIslandLODcomSubEntity; -CEntity *pIslandLODsubIndEntity; -CEntity *pIslandLODsubComEntity; -int32 islandLODindust; -int32 islandLODcomInd; -int32 islandLODcomSub; -int32 islandLODsubInd; -int32 islandLODsubCom; +CEntity *pIslandLODmainlandEntity; +CEntity *pIslandLODbeachEntity; +int32 islandLODmainland; +int32 islandLODbeach; + +#ifndef MASTER +bool gbPrintStats; +bool gbPrintVehiclesInMemory; // TODO +bool gbPrintStreamingBuffer; // TODO +#endif bool CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) @@ -189,14 +191,17 @@ CStreaming::Init2(void) for(i = 0; i < MAXVEHICLESLOADED; i++) ms_vehiclesLoaded[i] = -1; ms_numVehiclesLoaded = 0; + ms_numPedsLoaded = 8; + + for(i = 0; i < ARRAY_SIZE(ms_bIsPedFromPedGroupLoaded); i++) + ms_bIsPedFromPedGroupLoaded[i] = false; ms_pExtraObjectsDir = new CDirectory(EXTRADIRSIZE); ms_numPriorityRequests = 0; - ms_hasLoadedLODs = true; ms_currentPedGrp = -1; ms_lastCullZone = -1; // unused because RemoveModelsNotVisibleFromCullzone is gone ms_loadedGangs = 0; - ms_currentPedLoading = 8; // unused, whatever it is + ms_currentPedLoading = NUMMODELSPERPEDGROUP; // unused, whatever it is LoadCdDirectory(); @@ -218,77 +223,84 @@ CStreaming::Init2(void) // PC only, figure out how much memory we got #ifdef GTA_PC #define MB (1024*1024) - +#ifdef FIX_BUGS + // do what gta3 does extern size_t _dwMemAvailPhys; ms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2; - if(ms_memoryAvailable < 50*MB) - ms_memoryAvailable = 50*MB; - desiredNumVehiclesLoaded = (int32)((ms_memoryAvailable / MB - 50) / 3 + 12); + if(ms_memoryAvailable < 65*MB) + ms_memoryAvailable = 65*MB; + desiredNumVehiclesLoaded = (int32)((ms_memoryAvailable / MB - 65) / 3 + 12); if(desiredNumVehiclesLoaded > MAXVEHICLESLOADED) desiredNumVehiclesLoaded = MAXVEHICLESLOADED; +#else + ms_memoryAvailable = 65 * MB; + desiredNumVehiclesLoaded = 25; debug("Memory allocated to Streaming is %zuMB", ms_memoryAvailable/MB); // original modifier was %d +#endif #undef MB #endif // find island LODs - pIslandLODindustEntity = nil; - pIslandLODcomIndEntity = nil; - pIslandLODcomSubEntity = nil; - pIslandLODsubIndEntity = nil; - pIslandLODsubComEntity = nil; - islandLODindust = -1; - islandLODcomInd = -1; - islandLODcomSub = -1; - islandLODsubInd = -1; - islandLODsubCom = -1; - CModelInfo::GetModelInfo("IslandLODInd", &islandLODindust); - CModelInfo::GetModelInfo("IslandLODcomIND", &islandLODcomInd); - CModelInfo::GetModelInfo("IslandLODcomSUB", &islandLODcomSub); - CModelInfo::GetModelInfo("IslandLODsubIND", &islandLODsubInd); - CModelInfo::GetModelInfo("IslandLODsubCOM", &islandLODsubCom); + pIslandLODmainlandEntity = nil; + pIslandLODbeachEntity = nil; + islandLODmainland = -1; + islandLODbeach = -1; + CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland); + CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach); - for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){ - CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); - if(building == nil) - continue; - if(building->GetModelIndex() == islandLODindust) pIslandLODindustEntity = building; - if(building->GetModelIndex() == islandLODcomInd) pIslandLODcomIndEntity = building; - if(building->GetModelIndex() == islandLODcomSub) pIslandLODcomSubEntity = building; - if(building->GetModelIndex() == islandLODsubInd) pIslandLODsubIndEntity = building; - if(building->GetModelIndex() == islandLODsubCom) pIslandLODsubComEntity = building; - } +#ifndef MASTER + VarConsole.Add("Streaming Debug", &gbPrintStats, true); + VarConsole.Add("Streaming Vehicle Debug", &gbPrintVehiclesInMemory, true); + VarConsole.Add("Printf Streaming Buffer contents", &gbPrintStreamingBuffer, true); +#endif } void CStreaming::Init(void) { #ifdef USE_TXD_CDIMAGE - int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r"); - if (txdHandle) - CFileMgr::CloseFile(txdHandle); - if (!CheckVideoCardCaps() && txdHandle) { - CdStreamAddImage("MODELS\\TXD.IMG"); - CStreaming::Init2(); - } else { - CStreaming::Init2(); - if (CreateTxdImageForVideoCard()) { - CStreaming::Shutdown(); + if(!CanVideoCardDoDXT()){ + int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r"); + if (txdHandle) + CFileMgr::CloseFile(txdHandle); + if (!CheckVideoCardCaps() && txdHandle) { CdStreamAddImage("MODELS\\TXD.IMG"); CStreaming::Init2(); + } else { + CStreaming::Init2(); + if (CreateTxdImageForVideoCard()) { + CStreaming::Shutdown(); + CdStreamAddImage("MODELS\\TXD.IMG"); + CStreaming::Init2(); + } } - } + } else + CStreaming::Init2(); #else CStreaming::Init2(); #endif } void +CStreaming::ReInit(void) +{ + int i; + CStreaming::FlushRequestList(); + CStreaming::DeleteAllRwObjects(); + CStreaming::RemoveAllUnusedModels(); + for(i = 0; i < MODELINFOSIZE; i++) + if(CModelInfo::GetModelInfo(i) && ms_aInfoForModel[i].m_flags & STREAMFLAGS_SCRIPTOWNED) + SetMissionDoesntRequireModel(i); + CStreaming::ms_disableStreaming = false; +} + +void CStreaming::Shutdown(void) { RwFreeAlign(ms_pStreamingBuffer[0]); ms_streamingBufferSize = 0; - if(ms_pExtraObjectsDir){ + if(ms_pExtraObjectsDir) { delete ms_pExtraObjectsDir; #ifdef FIX_BUGS ms_pExtraObjectsDir = nil; @@ -304,7 +316,6 @@ uint64 timeProcessingDFF; void CStreaming::Update(void) { - CEntity *train; CStreamingInfo *si, *prev; bool requestedSubway = false; @@ -323,39 +334,36 @@ CStreaming::Update(void) if(CTimer::GetIsPaused()) return; - train = FindPlayerTrain(); - if(train && train->GetPosition().z < 0.0f){ - RequestSubway(); - requestedSubway = true; - }else if(!ms_disableStreaming) - AddModelsToRequestList(TheCamera.GetPosition()); + LoadBigBuildingsWhenNeeded(); + if(!ms_disableStreaming && TheCamera.GetPosition().z < 55.0f) + AddModelsToRequestList(TheCamera.GetPosition(), 0); DeleteFarAwayRwObjects(TheCamera.GetPosition()); if(!ms_disableStreaming && - !CCutsceneMgr::IsRunning() && - !requestedSubway && - !CGame::playingIntro && + !CCutsceneMgr::IsCutsceneProcessing() && ms_numModelsRequested < 5 && - !CRenderer::m_loadingPriority -#ifdef FIX_BUGS - && !CReplay::IsPlayingBack() -#endif - ){ + !CRenderer::m_loadingPriority && + CGame::currArea == AREA_MAIN_MAP && + !CReplay::IsPlayingBack()){ StreamVehiclesAndPeds(); StreamZoneModels(FindPlayerCoors()); } LoadRequestedModels(); -#ifndef MASTER - if (CPad::GetPad(1)->GetLeftShoulder1JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2()) - PrintStreamingBufferState(); + if(CWorld::Players[0].m_pRemoteVehicle){ + CColStore::AddCollisionNeededAtPosn(FindPlayerCoors()); + CColStore::LoadCollision(CWorld::Players[0].m_pRemoteVehicle->GetPosition()); + CColStore::EnsureCollisionIsInMemory(CWorld::Players[0].m_pRemoteVehicle->GetPosition()); + }else{ + CColStore::LoadCollision(FindPlayerCoors()); + CColStore::EnsureCollisionIsInMemory(FindPlayerCoors()); + } // TODO: PrintRequestList //if (CPad::GetPad(1)->GetLeftShoulder2JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2()) // PrintRequestList(); -#endif for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){ prev = si->m_prev; @@ -377,12 +385,6 @@ CStreaming::LoadCdDirectory(void) ms_imageOffsets[3] = -1; ms_imageOffsets[4] = -1; ms_imageOffsets[5] = -1; - ms_imageOffsets[6] = -1; - ms_imageOffsets[7] = -1; - ms_imageOffsets[8] = -1; - ms_imageOffsets[9] = -1; - ms_imageOffsets[10] = -1; - ms_imageOffsets[11] = -1; ms_imageSize = GetGTA3ImgSize(); // PS2 uses CFileMgr::GetCdFile on all IMG files to fill the array #endif @@ -402,8 +404,7 @@ void CStreaming::LoadCdDirectory(const char *dirname, int n) { int fd, lastID, imgSelector; - int modelId, txdId; - uint32 posn, size; + int modelId; CDirectory::DirectoryInfo direntry; char *dot; @@ -414,24 +415,23 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) imgSelector = n<<24; assert(sizeof(direntry) == 32); while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){ - dot = strchr(direntry.name, '.'); - assert(dot); - if(dot) *dot = '\0'; + bool bAddToStreaming = false; + if(direntry.size > (uint32)ms_streamingBufferSize) ms_streamingBufferSize = direntry.size; + direntry.name[23] = '\0'; + dot = strchr(direntry.name, '.'); + if(dot == nil || dot-direntry.name > 20){ + debug("%s is too long\n", direntry.name); + lastID = -1; + continue; + } + + *dot = '\0'; - if(!CGeneral::faststrcmp(dot+1, "DFF") || !CGeneral::faststrcmp(dot+1, "dff")){ + if(strncasecmp(dot+1, "DFF", 3) == 0){ if(CModelInfo::GetModelInfo(direntry.name, &modelId)){ - if(ms_aInfoForModel[modelId].GetCdPosnAndSize(posn, size)){ - debug("%s appears more than once in %s\n", direntry.name, dirname); - lastID = -1; - }else{ - direntry.offset |= imgSelector; - ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size); - if(lastID != -1) - ms_aInfoForModel[lastID].m_nextID = modelId; - lastID = modelId; - } + bAddToStreaming = true; }else{ #ifdef FIX_BUGS // remember which cdimage this came from @@ -441,52 +441,66 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) #endif lastID = -1; } - }else if(!CGeneral::faststrcmp(dot+1, "TXD") || !CGeneral::faststrcmp(dot+1, "txd")){ - txdId = CTxdStore::FindTxdSlot(direntry.name); - if(txdId == -1) - txdId = CTxdStore::AddTxdSlot(direntry.name); - if(ms_aInfoForModel[txdId + STREAM_OFFSET_TXD].GetCdPosnAndSize(posn, size)){ - debug("%s appears more than once in %s\n", direntry.name, dirname); + }else if(strncasecmp(dot+1, "TXD", 3) == 0){ + modelId = CTxdStore::FindTxdSlot(direntry.name); + if(modelId == -1) + modelId = CTxdStore::AddTxdSlot(direntry.name); + modelId += STREAM_OFFSET_TXD; + bAddToStreaming = true; + }else if(strncasecmp(dot+1, "COL", 3) == 0){ + modelId = CColStore::FindColSlot(direntry.name); + if(modelId == -1) + modelId = CColStore::AddColSlot(direntry.name); + modelId += STREAM_OFFSET_COL; + bAddToStreaming = true; + }else if(strncasecmp(dot+1, "IFP", 3) == 0){ + modelId = CAnimManager::RegisterAnimBlock(direntry.name); + modelId += STREAM_OFFSET_ANIM; + bAddToStreaming = true; + }else{ + *dot = '.'; + lastID = -1; + } + + if(bAddToStreaming){ + if(ms_aInfoForModel[modelId].GetCdSize()){ + debug("%s.%s appears more than once in %s\n", direntry.name, dot+1, dirname); lastID = -1; }else{ direntry.offset |= imgSelector; - ms_aInfoForModel[txdId + STREAM_OFFSET_TXD].SetCdPosnAndSize(direntry.offset, direntry.size); + ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size); if(lastID != -1) - ms_aInfoForModel[lastID].m_nextID = txdId + STREAM_OFFSET_TXD; - lastID = txdId + STREAM_OFFSET_TXD; + ms_aInfoForModel[lastID].m_nextID = modelId; + lastID = modelId; } - }else - lastID = -1; + } } CFileMgr::CloseFile(fd); } +static char* +GetObjectName(int streamId) +{ + static char objname[32]; + if(streamId < STREAM_OFFSET_TXD) + sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetModelName()); + else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL) + sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD)); + else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM) + sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL)); + else{ + assert(streamId < NUMSTREAMINFO); + sprintf(objname, "%s.ifp", CAnimManager::GetAnimationBlock(streamId-STREAM_OFFSET_ANIM)->name); + } + return objname; +} + #ifdef USE_CUSTOM_ALLOCATOR RpAtomic* RegisterAtomicMemPtrsCB(RpAtomic *atomic, void *data) { -#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31 - // not quite sure what's going on here: - // gta3's RW 3.1 allocates separate memory for geometry data of RpGeometry. - // Is that a R* change? rpDefaultGeometryInstance also depends on it - RpGeometry *geo = RpAtomicGetGeometry(atomic); - if(geo->triangles) - REGISTER_MEMPTR(&geo->triangles); - if(geo->matList.materials) - REGISTER_MEMPTR(&geo->matList.materials); - if(geo->preLitLum) - REGISTER_MEMPTR(&geo->preLitLum); - if(geo->texCoords[0]) - REGISTER_MEMPTR(&geo->texCoords[0]); - if(geo->texCoords[1]) - REGISTER_MEMPTR(&geo->texCoords[1]); -#else - // normally RpGeometry is allocated in one block (excluding morph targets) - // so we don't really have allocated pointers in the struct. - // NB: in librw we actually do it in two allocations (geometry itself and data) - // so we could conceivably come up with something here -#endif + // empty because we expect models to be pre-instanced return atomic; } #endif @@ -512,34 +526,33 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) // Model mi = CModelInfo::GetModelInfo(streamId); - // Txd has to be loaded + // Txd and anim have to be loaded + int animId = mi->GetAnimFileIndex(); #ifdef FIX_BUGS - if(!HasTxdLoaded(mi->GetTxdSlot())){ + if(!HasTxdLoaded(mi->GetTxdSlot()) || #else // texDict will exist even if only first part has loaded - if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil){ + if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil || #endif - debug("failed to load %s because TXD %s is not in memory\n", mi->GetModelName(), CTxdStore::GetTxdName(mi->GetTxdSlot())); + animId != -1 && !CAnimManager::GetAnimationBlock(animId)->isLoaded){ RemoveModel(streamId); -#ifndef FIX_BUGS - // if we're just waiting for it to load, don't remove this - RemoveTxd(mi->GetTxdSlot()); -#endif ReRequestModel(streamId); RwStreamClose(stream, &mem); return false; } - // Set Txd to use + // Set Txd and anims to use CTxdStore::AddRef(mi->GetTxdSlot()); +#if GTA_VERSION > GTAVC_PS2 + if(animId != -1) + CAnimManager::AddAnimBlockRef(animId); +#endif PUSH_MEMID(MEMID_STREAM_MODELS); CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); if(mi->IsSimple()){ success = CFileLoader::LoadAtomicFile(stream, streamId); -#ifdef USE_CUSTOM_ALLOCATOR - RegisterAtomicMemPtrsCB(((CSimpleModelInfo*)mi)->m_atomics[0], nil); -#endif + // TODO(MIAMI)? complain if file is not pre-instanced. we hardly are interested in that } else if (mi->GetModelType() == MITYPE_VEHICLE) { // load vehicles in two parts CModelInfo::GetModelInfo(streamId)->AddRef(); @@ -556,9 +569,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) POP_MEMID(); UpdateMemoryUsed(); - // Txd no longer needed unless we only read part of the file - if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED) + // Txd and anims no longer needed unless we only read part of the file + if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){ CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot()); +#if GTA_VERSION > GTAVC_PS2 + if(animId != -1) + CAnimManager::RemoveAnimBlockRefWithoutDelete(animId); +#endif + } if(!success){ debug("Failed to load %s\n", CModelInfo::GetModelInfo(streamId)->GetModelName()); @@ -567,9 +585,8 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) RwStreamClose(stream, &mem); return false; } - }else{ + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ // Txd - assert(streamId < NUMSTREAMINFO); if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 && !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){ RemoveModel(streamId); @@ -594,20 +611,33 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) RwStreamClose(stream, &mem); return false; } + }else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM){ + PUSH_MEMID(MEMID_STREAM_COLLISION); + bool success = CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length); + POP_MEMID(); + if(!success){ + debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL)); + RemoveModel(streamId); + ReRequestModel(streamId); + RwStreamClose(stream, &mem); + return false; + } + }else if(streamId >= STREAM_OFFSET_ANIM){ + assert(streamId < NUMSTREAMINFO); + if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 && + !AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)){ + RemoveModel(streamId); + RwStreamClose(stream, &mem); + return false; + } + PUSH_MEMID(MEMID_STREAM_ANIMATION); + CAnimManager::LoadAnimFile(stream, true, nil); + CAnimManager::CreateAnimAssocGroups(); + POP_MEMID(); } RwStreamClose(stream, &mem); - // We shouldn't even end up here unless load was successful - if(!success){ - ReRequestModel(streamId); - if(streamId < STREAM_OFFSET_TXD) - debug("Failed to load %s.dff\n", mi->GetModelName()); - else - debug("Failed to load %s.txd\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD)); - return false; - } - if(streamId < STREAM_OFFSET_TXD){ // Model // Vehicles and Peds not in loaded list @@ -622,12 +652,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) smi->m_alpha = 0; } - if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0) + if(CanRemoveModel(streamId)) ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList); } - }else{ - // Txd - if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0) + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL || + streamId >= STREAM_OFFSET_ANIM){ + assert(streamId < NUMSTREAMINFO); + // Txd and anims + if(CanRemoveModel(streamId)) ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList); } @@ -641,17 +673,12 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); timeDiff = endTime - startTime; - if(timeDiff > 5){ - if(streamId < STREAM_OFFSET_TXD) - debug("model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetModelName(), timeDiff); - else - debug("txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff); - } + if(timeDiff > 5) + debug("%s took %d ms\n", GetObjectName(streamId), timeDiff); return true; } - bool CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) { @@ -688,18 +715,24 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) POP_MEMID(); mi->RemoveRef(); CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot()); - }else{ +#if GTA_VERSION > GTAVC_PS2 + if(mi->GetAnimFileIndex() != -1) + CAnimManager::RemoveAnimBlockRefWithoutDelete(mi->GetAnimFileIndex()); +#endif + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ // Txd CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD); PUSH_MEMID(MEMID_STREAM_TEXUTRES); success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream); POP_MEMID(); CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD); + }else{ + assert(0 && "invalid streamId"); } RwStreamClose(stream, &mem); - ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; // only done if success on PS2 + ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; #ifndef USE_CUSTOM_ALLOCATOR ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE; #endif @@ -707,20 +740,16 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) if(!success){ RemoveModel(streamId); ReRequestModel(streamId); - UpdateMemoryUsed(); // directly after pop on PS2 + UpdateMemoryUsed(); return false; } - UpdateMemoryUsed(); // directly after pop on PS2 + UpdateMemoryUsed(); endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); timeDiff = endTime - startTime; - if(timeDiff > 5){ - if(streamId < STREAM_OFFSET_TXD) - debug("finish model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetModelName(), timeDiff); - else - debug("finish txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff); - } + if(timeDiff > 5) + debug("%s took %d ms\n", GetObjectName(streamId), timeDiff); return true; } @@ -753,15 +782,20 @@ CStreaming::RequestModel(int32 id, int32 flags) // reinsert into list if(ms_aInfoForModel[id].m_next){ ms_aInfoForModel[id].RemoveFromList(); - if((ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0) + if(CanRemoveModel(id)) ms_aInfoForModel[id].AddToList(&ms_startLoadedList); } }else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED || ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){ // how can this be true again? if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED){ - if(id < STREAM_OFFSET_TXD) - RequestTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot(), flags); + if(id < STREAM_OFFSET_TXD){ + mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); + RequestTxd(mi->GetTxdSlot(), flags); + int anim = mi->GetAnimFileIndex(); + if(anim != -1) + RequestAnim(anim, STREAMFLAGS_DEPENDENCY); + } ms_aInfoForModel[id].AddToList(&ms_startRequestedList); ms_numModelsRequested++; if(flags & STREAMFLAGS_PRIORITY) @@ -773,52 +807,34 @@ CStreaming::RequestModel(int32 id, int32 flags) } } +#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE + void -CStreaming::RequestSubway(void) -{ - RequestModel(MI_SUBWAY1, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY2, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY3, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY4, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY5, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY6, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY7, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY8, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY9, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY10, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY11, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY12, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY13, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY14, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY15, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY16, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY17, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBWAY18, STREAMFLAGS_NOFADE); - - switch(CGame::currLevel){ - case LEVEL_INDUSTRIAL: - RequestModel(MI_SUBPLATFORM_IND, STREAMFLAGS_NOFADE); - break; - case LEVEL_COMMERCIAL: - if(FindPlayerTrain()->GetPosition().y < -700.0f){ - RequestModel(MI_SUBPLATFORM_COMS, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBPLATFORM_COMS2, STREAMFLAGS_NOFADE); - }else{ - RequestModel(MI_SUBPLATFORM_COMN, STREAMFLAGS_NOFADE); - } - break; - case LEVEL_SUBURBAN: - RequestModel(MI_SUBPLATFORM_SUB, STREAMFLAGS_NOFADE); - RequestModel(MI_SUBPLATFORM_SUB2, STREAMFLAGS_NOFADE); - break; - default: break; +CStreaming::RequestBigBuildings(eLevelName level) +{ + int i, n; + CBuilding *b; + + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + b = CPools::GetBuildingPool()->GetSlot(i); + if(b && b->bIsBIGBuilding +#ifdef NO_ISLAND_LOADING + && (((FrontEndMenuManager.m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODmainlandEntity) && + (b != pIslandLODbeachEntity)) || + (b->m_level == level)) +#else + && b->m_level == level +#endif + ) + if(!b->bStreamBIGBuilding) + RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); } + RequestIslands(level); } -#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY - void -CStreaming::RequestBigBuildings(eLevelName level) +CStreaming::RequestBigBuildings(eLevelName level, const CVector &pos) { int i, n; CBuilding *b; @@ -828,17 +844,74 @@ CStreaming::RequestBigBuildings(eLevelName level) b = CPools::GetBuildingPool()->GetSlot(i); if(b && b->bIsBIGBuilding #ifdef NO_ISLAND_LOADING - && (((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODindustEntity) && (b != pIslandLODcomIndEntity) && - (b != pIslandLODcomSubEntity) && (b != pIslandLODsubIndEntity) && (b != pIslandLODsubComEntity) + && (((FrontEndMenuManager.m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODmainlandEntity) && (b != pIslandLODbeachEntity) ) || (b->m_level == level)) #else - && b->m_level == level + && b->m_level == level #endif ) - RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); + if(b->bStreamBIGBuilding){ + if(CRenderer::ShouldModelBeStreamed(b, pos)) + RequestModel(b->GetModelIndex(), 0); + }else + RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); } RequestIslands(level); - ms_hasLoadedLODs = false; +} + +void +CStreaming::InstanceBigBuildings(eLevelName level, const CVector &pos) +{ + int i, n; + CBuilding *b; + + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + b = CPools::GetBuildingPool()->GetSlot(i); + if(b && b->bIsBIGBuilding && b->m_level == level && + b->bStreamBIGBuilding && b->m_rwObject == nil) + if(CRenderer::ShouldModelBeStreamed(b, pos)) + b->CreateRwObject(); + } +} + +void +CStreaming::InstanceLoadedModelsInSectorList(CPtrList &list) +{ + CPtrNode *node; + CEntity *e; + for(node = list.first; node; node = node->next) { + e = (CEntity *)node->item; + if(IsAreaVisible(e->m_area) && e->m_rwObject == nil) + e->CreateRwObject(); + } +} + +void +CStreaming::InstanceLoadedModels(const CVector &pos) +{ + int minX = CWorld::GetSectorIndexX(pos.x - 80.0f); + if(minX <= 0) minX = 0; + + int minY = CWorld::GetSectorIndexY(pos.y - 80.0f); + if(minY <= 0) minY = 0; + + int maxX = CWorld::GetSectorIndexX(pos.x + 80.0f); + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; + + int maxY = CWorld::GetSectorIndexY(pos.y + 80.0f); + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; + + int x, y; + for(y = minY; y <= maxY; y++){ + for(x = minX; x <= maxX; x++){ + CSector *sector = CWorld::GetSector(x, y); + InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_BUILDINGS]); + InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]); + InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_OBJECTS]); + InstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_DUMMIES]); + } + } } void @@ -846,22 +919,68 @@ CStreaming::RequestIslands(eLevelName level) { ISLAND_LOADING_ISNT(HIGH) switch(level){ - case LEVEL_INDUSTRIAL: - RequestModel(islandLODcomInd, BIGBUILDINGFLAGS); - RequestModel(islandLODsubInd, BIGBUILDINGFLAGS); + case LEVEL_MAINLAND: + if(islandLODbeach != -1) + RequestModel(islandLODbeach, BIGBUILDINGFLAGS); break; - case LEVEL_COMMERCIAL: - RequestModel(islandLODindust, BIGBUILDINGFLAGS); - RequestModel(islandLODsubCom, BIGBUILDINGFLAGS); - break; - case LEVEL_SUBURBAN: - RequestModel(islandLODindust, BIGBUILDINGFLAGS); - RequestModel(islandLODcomSub, BIGBUILDINGFLAGS); + case LEVEL_BEACH: + if(islandLODmainland != -1) + RequestModel(islandLODmainland, BIGBUILDINGFLAGS); break; default: break; } } +static char *IGnames[] = { + "player", + "player2", + "player3", + "player4", + "player5", + "player6", + "player7", + "player8", + "player9", + "play10", + "play11", + "igken", + "igcandy", + "igsonny", + "igbuddy", + "igjezz", + "ighlary", + "igphil", + "igmerc", + "igdick", + "igdiaz", + "" +}; + +static char *CSnames[] = { + "csplay", + "csplay2", + "csplay3", + "csplay4", + "csplay5", + "csplay6", + "csplay7", + "csplay8", + "csplay9", + "csplay10", + "csplay11", + "csken", + "cscandy", + "cssonny", + "csbuddy", + "csjezz", + "cshlary", + "csphil", + "csmerc", + "csdick", + "csdiaz", + "" +}; + void CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flags) { @@ -869,14 +988,43 @@ CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flag int txdId; char oldName[48]; uint32 pos, size; + int i, n; mi = CModelInfo::GetModelInfo(modelId); + if(strncasecmp("CSPlay", modelName, 6) == 0){ + char *curname = CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName(); + for(int i = 0; CSnames[i][0]; i++){ + if(strcasecmp(curname, IGnames[i]) == 0){ + modelName = CSnames[i]; + break; + } + } + } if(!CGeneral::faststrcmp(mi->GetModelName(), modelName)){ // Already have the correct name, just request it RequestModel(modelId, flags); return; } + if(mi->GetNumRefs() > 0){ + n = CPools::GetPedPool()->GetSize()-1; + for(i = n; i >= 0 && mi->GetNumRefs() > 0; i--){ + CPed *ped = CPools::GetPedPool()->GetSlot(i); + if(ped && ped->GetModelIndex() == modelId && + !ped->IsPlayer() && ped->CanBeDeletedEvenInVehicle()) + CTheScripts::RemoveThisPed(ped); + } + n = CPools::GetObjectPool()->GetSize()-1; + for(i = n; i >= 0 && mi->GetNumRefs() > 0; i--){ + CObject *obj = CPools::GetObjectPool()->GetSlot(i); + if(obj && obj->GetModelIndex() == modelId && obj->CanBeDeleted()){ + CWorld::Remove(obj); + CWorld::RemoveReferencesToDeletedObject(obj); + delete obj; + } + } + } + strcpy(oldName, mi->GetModelName()); mi->SetModelName(modelName); @@ -942,13 +1090,15 @@ CStreaming::RemoveModel(int32 id) if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){ if(id < STREAM_OFFSET_TXD) CModelInfo::GetModelInfo(id)->DeleteRwObject(); - else + else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL) CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); -#ifdef USE_CUSTOM_ALLOCATOR - UpdateMemoryUsed(); -#else + else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM) + CColStore::RemoveCol(id - STREAM_OFFSET_COL); + else if(id >= STREAM_OFFSET_ANIM){ + assert(id < NUMSTREAMINFO); + CAnimManager::RemoveAnimBlock(id - STREAM_OFFSET_ANIM); + } ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE; -#endif } if(ms_aInfoForModel[id].m_next){ @@ -968,11 +1118,14 @@ CStreaming::RemoveModel(int32 id) if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){ if(id < STREAM_OFFSET_TXD) RpClumpGtaCancelStream(); - else + else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL) CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); -#ifdef USE_CUSTOM_ALLOCATOR - UpdateMemoryUsed(); -#endif + else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM) + CColStore::RemoveCol(id - STREAM_OFFSET_COL); + else if(id >= STREAM_OFFSET_ANIM){ + assert(id < NUMSTREAMINFO); + CAnimManager::RemoveAnimBlock(id - STREAM_OFFSET_ANIM); + } } ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED; @@ -981,12 +1134,10 @@ CStreaming::RemoveModel(int32 id) void CStreaming::RemoveUnusedBuildings(eLevelName level) { - if(level != LEVEL_INDUSTRIAL) - RemoveBuildings(LEVEL_INDUSTRIAL); - if(level != LEVEL_COMMERCIAL) - RemoveBuildings(LEVEL_COMMERCIAL); - if(level != LEVEL_SUBURBAN) - RemoveBuildings(LEVEL_SUBURBAN); + if(level != LEVEL_BEACH) + RemoveBuildings(LEVEL_BEACH); + if(level != LEVEL_MAINLAND) + RemoveBuildings(LEVEL_MAINLAND); } void @@ -1050,16 +1201,69 @@ CStreaming::RemoveBuildings(eLevelName level) } void +CStreaming::RemoveBuildingsNotInArea(int32 area) +{ + int i, n; + CEntity *e; + + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + e = CPools::GetBuildingPool()->GetSlot(i); + if(e && e->m_rwObject && !IsAreaVisible(area) && + (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){ + if(e->bIsBIGBuilding) + RequestModel(e->GetModelIndex(), 0); + if(!e->bImBeingRendered) + e->DeleteRwObject(); + } + } + + n = CPools::GetTreadablePool()->GetSize()-1; + for(i = n; i >= 0; i--){ + e = CPools::GetTreadablePool()->GetSlot(i); + if(e && e->m_rwObject && !IsAreaVisible(area) && + (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){ + if(e->bIsBIGBuilding) + RequestModel(e->GetModelIndex(), 0); + if(!e->bImBeingRendered) + e->DeleteRwObject(); + } + } + + n = CPools::GetObjectPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + e = CPools::GetObjectPool()->GetSlot(i); + if(e && e->m_rwObject && !IsAreaVisible(area) && + (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){ + if(e->bIsBIGBuilding) + RequestModel(e->GetModelIndex(), 0); + if(!e->bImBeingRendered) + e->DeleteRwObject(); + } + } + + n = CPools::GetDummyPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + e = CPools::GetDummyPool()->GetSlot(i); + if(e && e->m_rwObject && !IsAreaVisible(area) && + (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){ + if(e->bIsBIGBuilding) + RequestModel(e->GetModelIndex(), 0); + if(!e->bImBeingRendered) + e->DeleteRwObject(); + } + } +} + +void CStreaming::RemoveUnusedBigBuildings(eLevelName level) { ISLAND_LOADING_IS(LOW) { - if (level != LEVEL_INDUSTRIAL) - RemoveBigBuildings(LEVEL_INDUSTRIAL); - if (level != LEVEL_COMMERCIAL) - RemoveBigBuildings(LEVEL_COMMERCIAL); - if (level != LEVEL_SUBURBAN) - RemoveBigBuildings(LEVEL_SUBURBAN); + if(level != LEVEL_BEACH) + RemoveBigBuildings(LEVEL_BEACH); + if(level != LEVEL_MAINLAND) + RemoveBigBuildings(LEVEL_MAINLAND); } RemoveIslandsNotUsed(level); } @@ -1080,37 +1284,30 @@ DeleteIsland(CEntity *island) void CStreaming::RemoveIslandsNotUsed(eLevelName level) { + int i; + if(pIslandLODmainlandEntity == nil) + for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){ + CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); + if(building == nil) + continue; + if(building->GetModelIndex() == islandLODmainland) + pIslandLODmainlandEntity = building; + if(building->GetModelIndex() == islandLODbeach) + pIslandLODbeachEntity = building; + } #ifdef NO_ISLAND_LOADING - if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_HIGH) { - DeleteIsland(pIslandLODindustEntity); - DeleteIsland(pIslandLODcomIndEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubIndEntity); - DeleteIsland(pIslandLODsubComEntity); + if(FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_HIGH) { + DeleteIsland(pIslandLODmainlandEntity); + DeleteIsland(pIslandLODbeachEntity); } else #endif switch(level){ - case LEVEL_INDUSTRIAL: - DeleteIsland(pIslandLODindustEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubComEntity); - break; - case LEVEL_COMMERCIAL: - DeleteIsland(pIslandLODcomIndEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubIndEntity); - break; - case LEVEL_SUBURBAN: - DeleteIsland(pIslandLODsubIndEntity); - DeleteIsland(pIslandLODsubComEntity); - DeleteIsland(pIslandLODcomIndEntity); + case LEVEL_MAINLAND: + DeleteIsland(pIslandLODmainlandEntity); break; - default: - DeleteIsland(pIslandLODindustEntity); - DeleteIsland(pIslandLODcomIndEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubIndEntity); - DeleteIsland(pIslandLODsubComEntity); + case LEVEL_BEACH: + DeleteIsland(pIslandLODbeachEntity); + break; } } @@ -1146,8 +1343,7 @@ CStreaming::RemoveLoadedVehicle(void) if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) ms_lastVehicleDeleted = 0; id = ms_vehiclesLoaded[ms_lastVehicleDeleted]; - if(id != -1 && - (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0 && + if(id != -1 && CanRemoveModel(id) && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0 && ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED) goto found; } @@ -1156,31 +1352,43 @@ found: RemoveModel(ms_vehiclesLoaded[ms_lastVehicleDeleted]); ms_numVehiclesLoaded--; ms_vehiclesLoaded[ms_lastVehicleDeleted] = -1; + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); + if (pVehicleInfo->m_vehicleClass != -1) + CCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass); return true; } bool -CStreaming::RemoveLeastUsedModel(void) +CStreaming::RemoveLeastUsedModel(uint32 excludeMask) { CStreamingInfo *si; int streamId; for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){ + if(si->m_flags & excludeMask) + continue; streamId = si - ms_aInfoForModel; if(streamId < STREAM_OFFSET_TXD){ if (CModelInfo::GetModelInfo(streamId)->GetNumRefs() == 0) { RemoveModel(streamId); return true; } - }else{ + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ if(CTxdStore::GetNumRefs(streamId - STREAM_OFFSET_TXD) == 0 && !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){ RemoveModel(streamId); return true; } + }else if(streamId >= STREAM_OFFSET_ANIM){ + assert(streamId < NUMSTREAMINFO); + if(CAnimManager::GetNumRefsToAnimBlock(streamId - STREAM_OFFSET_ANIM) == 0 && + !AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)){ + RemoveModel(streamId); + return true; + } } } - return ms_numVehiclesLoaded > 7 && RemoveLoadedVehicle(); + return (ms_numVehiclesLoaded > 7 || CGame::currArea != AREA_MAIN_MAP && ms_numVehiclesLoaded > 4) && RemoveLoadedVehicle(); } void @@ -1193,7 +1401,6 @@ CStreaming::RemoveAllUnusedModels(void) for(i = NUM_DEFAULT_MODELS; i < MODELINFOSIZE; i++){ if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED && - ms_aInfoForModel[i].m_flags & STREAMFLAGS_DONT_REMOVE && CModelInfo::GetModelInfo(i)->GetNumRefs() == 0) { RemoveModel(i); ms_aInfoForModel[i].m_loadState = STREAMSTATE_NOTLOADED; @@ -1201,28 +1408,33 @@ CStreaming::RemoveAllUnusedModels(void) } } +void +CStreaming::RemoveUnusedModelsInLoadedList(void) +{ + // empty +} + bool -CStreaming::RemoveReferencedTxds(size_t mem) +CStreaming::RemoveLoadedZoneModel(void) { - CStreamingInfo *si; - int streamId; + int i; - for(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){ - streamId = si - ms_aInfoForModel; - if(streamId >= STREAM_OFFSET_TXD && - CTxdStore::GetNumRefs(streamId-STREAM_OFFSET_TXD) == 0){ - RemoveModel(streamId); - if(ms_memoryUsed < mem) - return true; + if(ms_currentPedGrp == -1) + return false; + + for(i = 0; i < NUMMODELSPERPEDGROUP; i++){ + int mi = CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]; + if(mi != -1 && ms_bIsPedFromPedGroupLoaded[i] && + HasModelLoaded(mi) && CanRemoveModel(mi) && + CModelInfo::GetModelInfo(mi)->GetNumRefs() == 0){ + RemoveModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]); + ms_numPedsLoaded--; + ms_bIsPedFromPedGroupLoaded[i] = false; + return true; } } - return false; -} -void -CStreaming::RemoveUnusedModelsInLoadedList(void) -{ - // empty + return false; } bool @@ -1253,6 +1465,34 @@ CStreaming::IsTxdUsedByRequestedModels(int32 txdId) return false; } +bool +CStreaming::AreAnimsUsedByRequestedModels(int32 animId) +{ + CStreamingInfo *si; + int streamId; + int i; + + for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = si->m_next){ + streamId = si - ms_aInfoForModel; + if(streamId < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId) + return true; + } + + for(i = 0; i < 4; i++){ + streamId = ms_channel[0].streamIds[i]; + if(streamId != -1 && streamId < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId) + return true; + streamId = ms_channel[1].streamIds[i]; + if(streamId != -1 && streamId < STREAM_OFFSET_TXD && + CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId) + return true; + } + + return false; +} + int32 CStreaming::GetAvailableVehicleSlot(void) { @@ -1284,8 +1524,8 @@ CStreaming::AddToLoadedVehiclesList(int32 modelId) // find vehicle we can remove for(i = 0; i < MAXVEHICLESLOADED; i++){ id = ms_vehiclesLoaded[ms_lastVehicleDeleted]; - if(id != -1 && - (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0) + if(id != -1 && CanRemoveModel(id) && + CModelInfo::GetModelInfo(id)->GetNumRefs() == 0) goto found; ms_lastVehicleDeleted++; if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) @@ -1301,13 +1541,21 @@ found: ms_lastVehicleDeleted = id; // this is more than we wanted actually ms_numVehiclesLoaded++; - }else + } + else{ RemoveModel(id); + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); + if (pVehicleInfo->m_vehicleClass != -1) + CCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass); + } } ms_vehiclesLoaded[ms_lastVehicleDeleted++] = modelId; if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) ms_lastVehicleDeleted = 0; + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(modelId); + if (pVehicleInfo->m_vehicleClass != -1) + CCarCtrl::AddToLoadedVehicleArray(modelId, pVehicleInfo->m_vehicleClass, pVehicleInfo->m_frequency); return true; } @@ -1319,45 +1567,10 @@ CStreaming::IsObjectInCdImage(int32 id) } void -CStreaming::HaveAllBigBuildingsLoaded(eLevelName level) -{ - int i, n; - CEntity *e; - - if(ms_hasLoadedLODs) - return; - - if(level == LEVEL_INDUSTRIAL){ - if(ms_aInfoForModel[islandLODcomInd].m_loadState != STREAMSTATE_LOADED || - ms_aInfoForModel[islandLODsubInd].m_loadState != STREAMSTATE_LOADED) - return; - }else if(level == LEVEL_COMMERCIAL){ - if(ms_aInfoForModel[islandLODindust].m_loadState != STREAMSTATE_LOADED || - ms_aInfoForModel[islandLODsubCom].m_loadState != STREAMSTATE_LOADED) - return; - }else if(level == LEVEL_SUBURBAN){ - if(ms_aInfoForModel[islandLODindust].m_loadState != STREAMSTATE_LOADED || - ms_aInfoForModel[islandLODcomSub].m_loadState != STREAMSTATE_LOADED) - return; - } - - n = CPools::GetBuildingPool()->GetSize()-1; - for(i = n; i >= 0; i--){ - e = CPools::GetBuildingPool()->GetSlot(i); - if(e && e->bIsBIGBuilding && e->m_level == level && - ms_aInfoForModel[e->GetModelIndex()].m_loadState != STREAMSTATE_LOADED) - return; - } - - RemoveUnusedBigBuildings(level); - ms_hasLoadedLODs = true; -} - -void CStreaming::SetModelIsDeletable(int32 id) { ms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_DONT_REMOVE; - if ((id >= STREAM_OFFSET_TXD || CModelInfo::GetModelInfo(id)->GetModelType() != MITYPE_VEHICLE) && + if ((id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL || CModelInfo::GetModelInfo(id)->GetModelType() != MITYPE_VEHICLE) && (ms_aInfoForModel[id].m_flags & STREAMFLAGS_SCRIPTOWNED) == 0){ if(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED) RemoveModel(id); @@ -1394,17 +1607,19 @@ CStreaming::LoadInitialPeds(void) } void -CStreaming::LoadInitialVehicles(void) +CStreaming::LoadInitialWeapons(void) { - int id; + CStreaming::RequestModel(MI_NIGHTSTICK, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_MISSILE, STREAMFLAGS_DONT_REMOVE); +} +void +CStreaming::LoadInitialVehicles(void) +{ ms_numVehiclesLoaded = 0; ms_lastVehicleDeleted = 0; - if(CModelInfo::GetModelInfo("taxi", &id)) - RequestModel(id, STREAMFLAGS_DONT_REMOVE); - if(CModelInfo::GetModelInfo("police", &id)) - RequestModel(id, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_POLICE, STREAMFLAGS_DONT_REMOVE); } void @@ -1432,11 +1647,11 @@ CStreaming::StreamVehiclesAndPeds(void) } if(FindPlayerPed()->m_pWanted->AreFbiRequired()){ - RequestModel(MI_FBICAR, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_FBIRANCH, STREAMFLAGS_DONT_REMOVE); RequestModel(MI_FBI, STREAMFLAGS_DONT_REMOVE); }else{ - SetModelIsDeletable(MI_FBICAR); - if(!HasModelLoaded(MI_FBICAR)) + SetModelIsDeletable(MI_FBIRANCH); + if(!HasModelLoaded(MI_FBIRANCH)) SetModelIsDeletable(MI_FBI); } @@ -1456,34 +1671,86 @@ CStreaming::StreamVehiclesAndPeds(void) else SetModelIsDeletable(MI_CHOPPER); + if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired()) { + SetModelIsDeletable(MI_VICE1); + SetModelIsDeletable(MI_VICE2); + SetModelIsDeletable(MI_VICE3); + SetModelIsDeletable(MI_VICE4); + SetModelIsDeletable(MI_VICE5); + SetModelIsDeletable(MI_VICE6); + SetModelIsDeletable(MI_VICE7); + SetModelIsDeletable(MI_VICE8); + RequestModel(MI_VICECHEE, STREAMFLAGS_DONT_REMOVE); + if(CPopulation::NumMiamiViceCops == 0) + switch (CCarCtrl::MiamiViceCycle) { + case 0: + RequestModel(MI_VICE1, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_VICE2, STREAMFLAGS_DONT_REMOVE); + break; + case 1: + RequestModel(MI_VICE3, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_VICE4, STREAMFLAGS_DONT_REMOVE); + break; + case 2: + RequestModel(MI_VICE5, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_VICE6, STREAMFLAGS_DONT_REMOVE); + break; + case 3: + RequestModel(MI_VICE7, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_VICE8, STREAMFLAGS_DONT_REMOVE); + break; + } + } + else { + SetModelIsDeletable(MI_VICECHEE); + SetModelIsDeletable(MI_VICE1); + SetModelIsDeletable(MI_VICE2); + SetModelIsDeletable(MI_VICE3); + SetModelIsDeletable(MI_VICE4); + SetModelIsDeletable(MI_VICE5); + SetModelIsDeletable(MI_VICE6); + SetModelIsDeletable(MI_VICE7); + SetModelIsDeletable(MI_VICE8); + } + if(timeBeforeNextLoad >= 0) timeBeforeNextLoad--; else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){ - for(i = 1; i <= 10; i++){ - model = CCarCtrl::ChooseCarModel(modelQualityClass); - modelQualityClass++; - if(modelQualityClass >= CCarCtrl::TOTAL_CUSTOM_CLASSES) - modelQualityClass = 0; - - // check if we want to load this model - if(ms_aInfoForModel[model].m_loadState == STREAMSTATE_NOTLOADED && - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(model))->m_level & (1 << (CGame::currLevel-1))) - break; + CZoneInfo zone; + CVector coors = FindPlayerCoors(); + CTheZones::GetZoneInfoForTimeOfDay(&coors, &zone); + int32 maxReq = -1; + int32 mostRequestedRating = 0; + for(i = 0; i < CCarCtrl::TOTAL_CUSTOM_CLASSES; i++){ + if(CCarCtrl::NumRequestsOfCarRating[i] > maxReq && + ((i == 0 && zone.carThreshold[0] != 0) || +#ifdef FIX_BUGS + (i < CCarCtrl::NUM_CAR_CLASSES && zone.carThreshold[i] != zone.carThreshold[i-1]) || + (i == CCarCtrl::NUM_CAR_CLASSES && zone.boatThreshold[i - CCarCtrl::NUM_CAR_CLASSES] != 0) || + (i > CCarCtrl::NUM_CAR_CLASSES && i < CCarCtrl::TOTAL_CUSTOM_CLASSES && zone.boatThreshold[i - CCarCtrl::NUM_CAR_CLASSES] != zone.boatThreshold[i - CCarCtrl::NUM_CAR_CLASSES - 1]))) { +#else + (i != 0 && zone.carThreshold[i] != zone.carThreshold[i-1]))) { +#endif + maxReq = CCarCtrl::NumRequestsOfCarRating[i]; + mostRequestedRating = i; + } } - - if(i <= 10){ + model = CCarCtrl::ChooseCarModelToLoad(mostRequestedRating); + if(!HasModelLoaded(model)){ RequestModel(model, STREAMFLAGS_DEPENDENCY); - timeBeforeNextLoad = 500; + timeBeforeNextLoad = 350; } + CCarCtrl::NumRequestsOfCarRating[mostRequestedRating] = 0; } } void CStreaming::StreamZoneModels(const CVector &pos) { - int i; + int i, j; uint16 gangsToLoad, gangCarsToLoad, bit; CZoneInfo info; + static int timeBeforeNextLoad = 0; CTheZones::GetZoneInfoForTimeOfDay(&pos, &info); @@ -1492,6 +1759,7 @@ CStreaming::StreamZoneModels(const CVector &pos) // unload pevious group if(ms_currentPedGrp != -1) for(i = 0; i < NUMMODELSPERPEDGROUP; i++){ + ms_bIsPedFromPedGroupLoaded[i] = false; if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != -1){ SetModelIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]); SetModelTxdIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]); @@ -1500,63 +1768,101 @@ CStreaming::StreamZoneModels(const CVector &pos) ms_currentPedGrp = info.pedGroup; - for(i = 0; i < NUMMODELSPERPEDGROUP; i++){ - if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != -1) - RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i], STREAMFLAGS_DONT_REMOVE); + for(i = 0; i < MAXZONEPEDSLOADED; i++){ + do + j = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP); + while(ms_bIsPedFromPedGroupLoaded[j]); + ms_bIsPedFromPedGroupLoaded[j] = true; + if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[j] != -1) + RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[j], STREAMFLAGS_DEPENDENCY); } + ms_numPedsLoaded = MAXZONEPEDSLOADED; + timeBeforeNextLoad = 300; } + + if(timeBeforeNextLoad >= 0) + timeBeforeNextLoad--; + else{ + // Switch a ped + int oldMI; + // Find a ped to unload + for(i = 0; i < NUMMODELSPERPEDGROUP; i++) + if(ms_bIsPedFromPedGroupLoaded[i]){ + oldMI = CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]; + if(oldMI != -1 && CModelInfo::GetModelInfo(oldMI)->GetNumRefs() == 0) + break; + } + // And load a new one + if(i != NUMMODELSPERPEDGROUP || ms_numPedsLoaded < MAXZONEPEDSLOADED){ + do + j = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP); + while(ms_bIsPedFromPedGroupLoaded[j]); + if(ms_numPedsLoaded == MAXZONEPEDSLOADED) + ms_bIsPedFromPedGroupLoaded[i] = false; + ms_bIsPedFromPedGroupLoaded[j] = true; + int newMI = CPopulation::ms_pPedGroups[ms_currentPedGrp].models[j]; + if(newMI != oldMI){ + RequestModel(newMI, STREAMFLAGS_DEPENDENCY); + debug("Request Ped %s\n", CModelInfo::GetModelInfo(newMI)->GetModelName()); + if(ms_numPedsLoaded == MAXZONEPEDSLOADED){ + SetModelIsDeletable(oldMI); + SetModelTxdIsDeletable(oldMI); + debug("Remove Ped %s\n", CModelInfo::GetModelInfo(oldMI)->GetModelName()); + }else + ms_numPedsLoaded++; + timeBeforeNextLoad = 300; + } + } + } + RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_TAXI_D, STREAMFLAGS_DONT_REMOVE); gangsToLoad = 0; gangCarsToLoad = 0; - if(info.gangDensity[0] != 0) gangsToLoad |= 1<<0; - if(info.gangDensity[1] != 0) gangsToLoad |= 1<<1; - if(info.gangDensity[2] != 0) gangsToLoad |= 1<<2; - if(info.gangDensity[3] != 0) gangsToLoad |= 1<<3; - if(info.gangDensity[4] != 0) gangsToLoad |= 1<<4; - if(info.gangDensity[5] != 0) gangsToLoad |= 1<<5; - if(info.gangDensity[6] != 0) gangsToLoad |= 1<<6; - if(info.gangDensity[7] != 0) gangsToLoad |= 1<<7; - if(info.gangDensity[8] != 0) gangsToLoad |= 1<<8; - if(info.gangThreshold[0] != info.copDensity) gangCarsToLoad |= 1<<0; - if(info.gangThreshold[1] != info.gangThreshold[0]) gangCarsToLoad |= 1<<1; - if(info.gangThreshold[2] != info.gangThreshold[1]) gangCarsToLoad |= 1<<2; - if(info.gangThreshold[3] != info.gangThreshold[2]) gangCarsToLoad |= 1<<3; - if(info.gangThreshold[4] != info.gangThreshold[3]) gangCarsToLoad |= 1<<4; - if(info.gangThreshold[5] != info.gangThreshold[4]) gangCarsToLoad |= 1<<5; - if(info.gangThreshold[6] != info.gangThreshold[5]) gangCarsToLoad |= 1<<6; - if(info.gangThreshold[7] != info.gangThreshold[6]) gangCarsToLoad |= 1<<7; - if(info.gangThreshold[8] != info.gangThreshold[7]) gangCarsToLoad |= 1<<8; + if(info.gangPedThreshold[0] != info.copPedThreshold) + gangsToLoad = 1; + for(i = 1; i < NUM_GANGS; i++) + if(info.gangPedThreshold[i] != info.gangPedThreshold[i-1]) + gangsToLoad |= 1<<i; + if(info.gangThreshold[0] != info.copThreshold) + gangCarsToLoad = 1; + for(i = 1; i < NUM_GANGS; i++) + if(info.gangThreshold[i] != info.gangThreshold[i-1]) + gangCarsToLoad |= 1<<i; if(gangsToLoad == ms_loadedGangs && gangCarsToLoad == ms_loadedGangCars) return; - // This makes things simpler than the game does it - gangsToLoad |= gangCarsToLoad; - - for(i = 0; i < NUM_GANGS; i++){ - bit = 1<<i; - - if(gangsToLoad & bit && (ms_loadedGangs & bit) == 0){ - RequestModel(MI_GANG01 + i*2, STREAMFLAGS_DONT_REMOVE); - RequestModel(MI_GANG01 + i*2 + 1, STREAMFLAGS_DONT_REMOVE); - ms_loadedGangs |= bit; - }else if((gangsToLoad & bit) == 0 && ms_loadedGangs & bit){ - SetModelIsDeletable(MI_GANG01 + i*2); - SetModelIsDeletable(MI_GANG01 + i*2 + 1); - SetModelTxdIsDeletable(MI_GANG01 + i*2); - SetModelTxdIsDeletable(MI_GANG01 + i*2 + 1); - ms_loadedGangs &= ~bit; - } + int gangModelsToload = gangsToLoad | gangCarsToLoad; + + if(gangsToLoad != ms_loadedGangs || gangCarsToLoad != ms_loadedGangCars){ + for(i = 0; i < NUM_GANGS; i++){ + bit = 1<<i; + + if(gangModelsToload & bit && (ms_loadedGangs & bit) == 0){ + RequestModel(CGangs::GetGangPedModel1(i), STREAMFLAGS_DEPENDENCY); + RequestModel(CGangs::GetGangPedModel2(i), STREAMFLAGS_DEPENDENCY); + ms_loadedGangs |= bit; + }else if((gangModelsToload & bit) == 0 && ms_loadedGangs & bit){ + SetModelIsDeletable(CGangs::GetGangPedModel1(i)); + SetModelIsDeletable(CGangs::GetGangPedModel2(i)); + SetModelTxdIsDeletable(CGangs::GetGangPedModel1(i)); + SetModelTxdIsDeletable(CGangs::GetGangPedModel2(i)); + ms_loadedGangs &= ~bit; + } - if(gangCarsToLoad & bit && (ms_loadedGangCars & bit) == 0){ - RequestModel(CGangs::GetGangInfo(i)->m_nVehicleMI, STREAMFLAGS_DONT_REMOVE); - }else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){ - SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); - SetModelTxdIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); + if(CGangs::GetGangVehicleModel(i) != -1){ + if((gangCarsToLoad & bit) && (ms_loadedGangCars & bit) == 0){ + RequestModel(CGangs::GetGangVehicleModel(i), STREAMFLAGS_DEPENDENCY); + }else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){ + SetModelIsDeletable(CGangs::GetGangVehicleModel(i)); + SetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i)); + } + } } + ms_loadedGangCars = gangCarsToLoad; } - ms_loadedGangCars = gangCarsToLoad; } void @@ -1564,19 +1870,31 @@ CStreaming::RemoveCurrentZonesModels(void) { int i; - if(ms_currentPedGrp != -1) - for(i = 0; i < 8; i++){ - if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1) - break; - if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != MI_MALE01) + if (ms_currentPedGrp != -1) + for (i = 0; i < NUMMODELSPERPEDGROUP; i++) { + ms_bIsPedFromPedGroupLoaded[i] = false; + if (CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != -1) { SetModelIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]); + SetModelTxdIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]); + } } - for(i = 0; i < NUM_GANGS; i++){ - SetModelIsDeletable(MI_GANG01 + i*2); - SetModelIsDeletable(MI_GANG01 + i*2 + 1); - if(CGangs::GetGangInfo(i)->m_nVehicleMI != -1) - SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); + CStreaming::RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_TAXI_D, STREAMFLAGS_DONT_REMOVE); + + for (i = 0; i < NUM_GANGS; i++) { + if (CGangs::GetGangPedModel1(i) != -1) { + SetModelIsDeletable(CGangs::GetGangPedModel1(i)); + SetModelTxdIsDeletable(CGangs::GetGangPedModel1(i)); + } + if (CGangs::GetGangPedModel2(i) != -1) { + SetModelIsDeletable(CGangs::GetGangPedModel2(i)); + SetModelTxdIsDeletable(CGangs::GetGangPedModel2(i)); + } + if (CGangs::GetGangVehicleModel(i) != -1) { + SetModelIsDeletable(CGangs::GetGangVehicleModel(i)); + SetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i)); + } } ms_currentPedGrp = -1; @@ -1584,6 +1902,53 @@ CStreaming::RemoveCurrentZonesModels(void) ms_loadedGangCars = 0; } +void +CStreaming::LoadBigBuildingsWhenNeeded(void) +{ + // Very much like CCollision::Update and CCollision::LoadCollisionWhenINeedIt + if(CCutsceneMgr::IsCutsceneProcessing()) + return; + + if(CTheZones::m_CurrLevel == LEVEL_GENERIC || + CTheZones::m_CurrLevel == CGame::currLevel) + return; + + CTimer::Suspend(); + CGame::currLevel = CTheZones::m_CurrLevel; + ISLAND_LOADING_IS(LOW) + { + DMAudio.SetEffectsFadeVol(0); + CPad::StopPadsShaking(); + CCollision::LoadCollisionScreen(CGame::currLevel); + DMAudio.Service(); + + RemoveUnusedBigBuildings(CGame::currLevel); + RemoveUnusedBuildings(CGame::currLevel); + RemoveUnusedModelsInLoadedList(); + CGame::TidyUpMemory(true, true); + } + CReplay::EmptyReplayBuffer(); + if(CGame::currLevel != LEVEL_GENERIC) + LoadSplash(GetLevelSplashScreen(CGame::currLevel)); + + ISLAND_LOADING_IS(LOW) + CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition()); +#ifdef NO_ISLAND_LOADING + else if(FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM) { + RemoveIslandsNotUsed(CGame::currLevel); + CStreaming::RequestIslands(CGame::currLevel); + } +#endif + + CStreaming::LoadAllRequestedModels(false); + + CGame::TidyUpMemory(true, true); + CTimer::Resume(); + + ISLAND_LOADING_IS(LOW) + DMAudio.SetEffectsFadeVol(127); +} + // Find starting offset of the cdimage we next want to read // Not useful at all on PC... @@ -1630,6 +1995,7 @@ ModelNotLoaded(int32 modelId) } inline bool TxdNotLoaded(int32 txdId) { return ModelNotLoaded(txdId + STREAM_OFFSET_TXD); } +inline bool AnimNotLoaded(int32 animId) { return animId != -1 && ModelNotLoaded(animId + STREAM_OFFSET_ANIM); } // Find stream id of next requested file in cdimage int32 @@ -1654,14 +2020,20 @@ CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority) if(priority && ms_numPriorityRequests != 0 && !si->IsPriority()) continue; - // request Txd if necessary + // request Txds or anims if necessary if(streamId < STREAM_OFFSET_TXD){ int txdId = CModelInfo::GetModelInfo(streamId)->GetTxdSlot(); if(TxdNotLoaded(txdId)){ ReRequestTxd(txdId); continue; } - } + int animId = CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex(); + if(AnimNotLoaded(animId)){ + ReRequestAnim(animId); + continue; + } + }else if(streamId >= STREAM_OFFSET_ANIM && CCutsceneMgr::IsCutsceneProcessing()) + continue; if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){ if(posn < posnFirst){ @@ -1716,13 +2088,18 @@ CStreaming::RequestModelStream(int32 ch) imgOffset = GetCdImageOffset(lastPosn); streamId = GetNextFileOnCd(lastPosn - imgOffset, true); - if(streamId == -1) - return; - - // remove Txds that aren't requested anymore - while(streamId >= STREAM_OFFSET_TXD){ - if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY || - IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)) + // remove Txds and Anims that aren't requested anymore + while(streamId != -1){ + if(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) + break; + if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ + if(IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)) + break; + }else if(streamId >= STREAM_OFFSET_ANIM){ + assert(streamId < NUMSTREAMINFO); + if(AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)) + break; + }else break; RemoveModel(streamId); // so try next file @@ -1759,7 +2136,8 @@ CStreaming::RequestModelStream(int32 ch) if(streamId < STREAM_OFFSET_TXD){ if (havePed && CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_PED || haveBigFile && CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_VEHICLE || - TxdNotLoaded(CModelInfo::GetModelInfo(streamId)->GetTxdSlot())) + TxdNotLoaded(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()) || + AnimNotLoaded(CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex())) break; }else{ if(haveBigFile && size > 200) @@ -1840,10 +2218,10 @@ CStreaming::ProcessLoadingChannel(int32 ch) if(id < STREAM_OFFSET_TXD && CModelInfo::GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE && ms_numVehiclesLoaded >= desiredNumVehiclesLoaded && !RemoveLoadedVehicle() && - ((ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 || GetAvailableVehicleSlot() == -1)){ + (CanRemoveModel(id) || GetAvailableVehicleSlot() == -1)){ // can't load vehicle RemoveModel(id); - if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) + if(!CanRemoveModel(id)) ReRequestModel(id); else if(CTxdStore::GetNumRefs(CModelInfo::GetModelInfo(id)->GetTxdSlot()) == 0) RemoveTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot()); @@ -1950,6 +2328,7 @@ CStreaming::LoadAllRequestedModels(bool priority) if(bInsideLoadAll) return; + bInsideLoadAll = true; FlushChannels(); imgOffset = GetCdImageOffset(CdStreamGetLastPosn()); @@ -2072,18 +2451,26 @@ CStreaming::LoadAllRequestedModels(bool priority) int i; uint32 posn, size; + int numRequests = 4*ms_numModelsRequested; + if(bInsideLoadAll) return; + bInsideLoadAll = true; + + if(priority) + numRequests = ms_numPriorityRequests; FlushChannels(); imgOffset = GetCdImageOffset(CdStreamGetLastPosn()); - while(ms_endRequestedList.m_prev != &ms_startRequestedList){ + while(ms_endRequestedList.m_prev != &ms_startRequestedList && numRequests > 0){ + numRequests--; streamId = GetNextFileOnCd(0, priority); if(streamId == -1) break; ms_aInfoForModel[streamId].RemoveFromList(); + ms_channel[0].streamIds[0] = streamId; DecrementRef(streamId); if(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){ @@ -2180,14 +2567,16 @@ CStreaming::UpdateMemoryUsed(void) ms_memoryUsed = gMainHeap.GetMemoryUsed(MEMID_STREAM) + gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS) + - gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES); + gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES) + + gMainHeap.GetMemoryUsed(MEMID_STREAM_COLLISION) + + gMainHeap.GetMemoryUsed(MEMID_STREAM_ANIMATION); #endif } #define STREAM_DIST 80.0f void -CStreaming::AddModelsToRequestList(const CVector &pos) +CStreaming::AddModelsToRequestList(const CVector &pos, int32 flags) { float xmin, xmax, ymin, ymax; int ixmin, ixmax, iymin, iymax; @@ -2221,23 +2610,23 @@ CStreaming::AddModelsToRequestList(const CVector &pos) dx = ix - CWorld::GetSectorIndexX(pos.x); d = dx*dx + dy*dy; sect = CWorld::GetSector(ix, iy); - if(d <= 1){ - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]); - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]); - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]); - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]); - }else if(d <= 4*4){ - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], pos.x, pos.y, xmin, ymin, xmax, ymax); - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], pos.x, pos.y, xmin, ymin, xmax, ymax); - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], pos.x, pos.y, xmin, ymin, xmax, ymax); - ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], pos.x, pos.y, xmin, ymin, xmax, ymax); + if(d <= 0){ + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], flags); + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], flags); + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], flags); + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], flags); + }else if(d <= 3*3){ + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], pos.x, pos.y, xmin, ymin, xmax, ymax, flags); + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], pos.x, pos.y, xmin, ymin, xmax, ymax, flags); + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], pos.x, pos.y, xmin, ymin, xmax, ymax, flags); + ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], pos.x, pos.y, xmin, ymin, xmax, ymax, flags); } } } } void -CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax) +CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax, int32 flags) { CPtrNode *node; CEntity *e; @@ -2251,8 +2640,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float continue; e->m_scanCode = CWorld::GetCurrentScanCode(); - if(!e->bStreamingDontDelete && !e->bIsSubway && - (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){ + if(!e->bStreamingDontDelete && IsAreaVisible(e->m_area) && !e->bDontStream && e->bIsVisible){ CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()); if (mi->GetModelType() != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())) { lodDistSq = sq(mi->GetLargestLodDistance()); @@ -2261,15 +2649,14 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float if(xmin < pos.x && pos.x < xmax && ymin < pos.y && pos.y < ymax && (CVector2D(x, y) - pos).MagnitudeSqr() < lodDistSq) - if(CRenderer::IsEntityCullZoneVisible(e)) - RequestModel(e->GetModelIndex(), 0); + RequestModel(e->GetModelIndex(), flags); } } } } void -CStreaming::ProcessEntitiesInSectorList(CPtrList &list) +CStreaming::ProcessEntitiesInSectorList(CPtrList &list, int32 flags) { CPtrNode *node; CEntity *e; @@ -2281,12 +2668,10 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list) continue; e->m_scanCode = CWorld::GetCurrentScanCode(); - if(!e->bStreamingDontDelete && !e->bIsSubway && - (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){ + if(!e->bStreamingDontDelete && IsAreaVisible(e->m_area) && !e->bDontStream && e->bIsVisible){ CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()); if (mi->GetModelType() != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())) - if(CRenderer::IsEntityCullZoneVisible(e)) - RequestModel(e->GetModelIndex(), 0); + RequestModel(e->GetModelIndex(), flags); } } } @@ -2502,6 +2887,11 @@ CStreaming::DeleteRwObjectsBehindCamera(size_t mem) } } + + while(RemoveLoadedZoneModel()) + if(ms_memoryUsed < mem) + return; + // Now a block that intersects with the camera's frustum if(TheCamera.GetForward().x > 0.0f){ // looking east @@ -2524,9 +2914,6 @@ CStreaming::DeleteRwObjectsBehindCamera(size_t mem) } } - if(RemoveReferencedTxds(mem)) - return; - // As last resort, delete objects from the last step more aggressively for(y = ymin; y <= ymax; y++){ for(x = xmax; x != xmin; x -= inc){ @@ -2566,6 +2953,10 @@ CStreaming::DeleteRwObjectsBehindCamera(size_t mem) } } + while(RemoveLoadedZoneModel()) + if(ms_memoryUsed < mem) + return; + // Now a block that intersects with the camera's frustum if(TheCamera.GetForward().y > 0.0f){ // looking north @@ -2588,8 +2979,9 @@ CStreaming::DeleteRwObjectsBehindCamera(size_t mem) } } - if(RemoveReferencedTxds(mem)) - return; +// this is gone in mobile together with RemoveReferencedTxds +// if(RemoveReferencedTxds(mem)) +// return; // As last resort, delete objects from the last step more aggressively for(x = xmin; x <= xmax; x++){ @@ -2602,6 +2994,8 @@ CStreaming::DeleteRwObjectsBehindCamera(size_t mem) } } } + + while(ms_memoryUsed >= mem && RemoveLeastUsedModel(0)); } void @@ -2627,13 +3021,13 @@ CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y) e = (CEntity*)node->item; if(e->m_rwObject && !e->bStreamingDontDelete && !e->bImBeingRendered){ // Now this is pretty weird... - if(Abs(CWorld::GetSectorIndexX(e->GetPosition().x) - x) >= 2.0f) + if(Abs(CWorld::GetSectorIndexX(e->GetPosition().x) - x) >= 1.6f) // { e->DeleteRwObject(); // return; // BUG? // } else // FIX? - if(Abs(CWorld::GetSectorIndexY(e->GetPosition().y) - y) >= 2.0f) + if(Abs(CWorld::GetSectorIndexY(e->GetPosition().y) - y) >= 1.6f) e->DeleteRwObject(); } } @@ -2648,7 +3042,8 @@ CStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, size_t mem) for(node = list.first; node; node = node->next){ e = (CEntity*)node->item; if(!e->bStreamingDontDelete && !e->bImBeingRendered && - e->m_rwObject && ms_aInfoForModel[e->GetModelIndex()].m_next){ + e->m_rwObject && ms_aInfoForModel[e->GetModelIndex()].m_next && + FindPlayerPed()->m_pCurSurface != e){ e->DeleteRwObject(); if (CModelInfo::GetModelInfo(e->GetModelIndex())->GetNumRefs() == 0) { RemoveModel(e->GetModelIndex()); @@ -2669,7 +3064,7 @@ CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem) for(node = list.first; node; node = node->next){ e = (CEntity*)node->item; if(!e->bStreamingDontDelete && !e->bImBeingRendered && - e->m_rwObject && !e->IsVisible() && ms_aInfoForModel[e->GetModelIndex()].m_next){ + e->m_rwObject && (!e->IsVisible() || e->bOffscreen) && ms_aInfoForModel[e->GetModelIndex()].m_next){ e->DeleteRwObject(); if (CModelInfo::GetModelInfo(e->GetModelIndex())->GetNumRefs() == 0) { RemoveModel(e->GetModelIndex()); @@ -2689,12 +3084,12 @@ CStreaming::MakeSpaceFor(int32 size) if(ms_memoryAvailable == 0) { extern size_t _dwMemAvailPhys; ms_memoryAvailable = (_dwMemAvailPhys - 10 * MB) / 2; - if(ms_memoryAvailable < 50 * MB) ms_memoryAvailable = 50 * MB; + if(ms_memoryAvailable < 65 * MB) ms_memoryAvailable = 65 * MB; } #undef MB #endif while(ms_memoryUsed >= ms_memoryAvailable - size) - if(!RemoveLeastUsedModel()) { + if(!RemoveLeastUsedModel(STREAMFLAGS_20)){ DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); return; } @@ -2714,17 +3109,44 @@ CStreaming::LoadScene(const CVector &pos) RemoveModel(si - ms_aInfoForModel); } CRenderer::m_loadingPriority = false; - CCullZones::ForceCullZoneCoors(pos); DeleteAllRwObjects(); - AddModelsToRequestList(pos); - CRadar::StreamRadarSections(pos); + if(level == LEVEL_GENERIC) + level = CGame::currLevel; + CGame::currLevel = level; RemoveUnusedBigBuildings(level); - RequestBigBuildings(level); + RequestBigBuildings(level, pos); + RequestBigBuildings(LEVEL_GENERIC, pos); + RemoveIslandsNotUsed(level); + LoadAllRequestedModels(false); + InstanceBigBuildings(level, pos); + InstanceBigBuildings(LEVEL_GENERIC, pos); + AddModelsToRequestList(pos, STREAMFLAGS_20); + CRadar::StreamRadarSections(pos); + + if (!CGame::IsInInterior()) { + for (int i = 0; i < 5; i++) { + CZoneInfo zone; + CTheZones::GetZoneInfoForTimeOfDay(&pos, &zone); + int32 model = CCarCtrl::ChooseCarModelToLoad(CCarCtrl::ChooseCarRating(&zone)); + CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY); + } + } LoadAllRequestedModels(false); + InstanceLoadedModels(pos); + + for(int i = 0; i < NUMSTREAMINFO; i++) + ms_aInfoForModel[i].m_flags &= ~STREAMFLAGS_20; debug("End load scene\n"); } void +CStreaming::LoadSceneCollision(const CVector &pos) +{ + CColStore::LoadCollision(pos); + CStreaming::LoadAllRequestedModels(false); +} + +void CStreaming::MemoryCardSave(uint8 *buf, uint32 *size) { int i; @@ -2753,9 +3175,10 @@ void CStreaming::UpdateForAnimViewer(void) { if (CStreaming::ms_channelError == -1) { - CStreaming::AddModelsToRequestList(CVector(0.0f, 0.0f, 0.0f)); + CStreaming::AddModelsToRequestList(CVector(0.0f, 0.0f, 0.0f), 0); CStreaming::LoadRequestedModels(); - sprintf(gString, "Requested %d, memory size %zuK\n", CStreaming::ms_numModelsRequested, 2 * CStreaming::ms_memoryUsed); // original modifier was %d + // original modifier was %d + sprintf(gString, "Requested %d, memory size %zuK\n", CStreaming::ms_numModelsRequested, 2 * CStreaming::ms_memoryUsed); } else { CStreaming::RetryLoadFile(CStreaming::ms_channelError); diff --git a/src/core/Streaming.h b/src/core/Streaming.h index 3294a88e..4ddf0b3b 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -4,7 +4,9 @@ enum { STREAM_OFFSET_TXD = MODELINFOSIZE, - NUMSTREAMINFO = STREAM_OFFSET_TXD+TXDSTORESIZE + STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE, + STREAM_OFFSET_ANIM = STREAM_OFFSET_COL+COLSTORESIZE, + NUMSTREAMINFO = STREAM_OFFSET_ANIM+NUMANIMBLOCKS }; enum StreamFlags @@ -14,6 +16,7 @@ enum StreamFlags STREAMFLAGS_DEPENDENCY = 0x04, // Is this right? STREAMFLAGS_PRIORITY = 0x08, STREAMFLAGS_NOFADE = 0x10, + STREAMFLAGS_20 = 0x20, // TODO(MIAMI): what's this STREAMFLAGS_CANT_REMOVE = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED, STREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY, @@ -94,11 +97,12 @@ public: static CStreamingChannel ms_channel[2]; static int32 ms_channelError; static int32 ms_numVehiclesLoaded; + static int32 ms_numPedsLoaded; static int32 ms_vehiclesLoaded[MAXVEHICLESLOADED]; static int32 ms_lastVehicleDeleted; + static bool ms_bIsPedFromPedGroupLoaded[NUMMODELSPERPEDGROUP]; static CDirectory *ms_pExtraObjectsDir; static int32 ms_numPriorityRequests; - static bool ms_hasLoadedLODs; static int32 ms_currentPedGrp; static int32 ms_lastCullZone; static uint16 ms_loadedGangs; @@ -111,6 +115,7 @@ public: static void Init(void); static void Init2(void); + static void ReInit(void); static void Shutdown(void); static void Update(void); static void LoadCdDirectory(void); @@ -119,14 +124,25 @@ public: static bool FinishLoadingLargeFile(int8 *buf, int32 streamId); static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; } static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); } + static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); } + static bool HasAnimLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_ANIM); } static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; } static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); } + static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); } + static bool CanRemoveAnim(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_ANIM); } static void RequestModel(int32 model, int32 flags); static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); } static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); } static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); } - static void RequestSubway(void); + static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); } + static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); } + static void RequestAnim(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_ANIM, flags); } + static void ReRequestAnim(int32 col) { ReRequestModel(col + STREAM_OFFSET_ANIM); } static void RequestBigBuildings(eLevelName level); + static void RequestBigBuildings(eLevelName level, const CVector &pos); + static void InstanceBigBuildings(eLevelName level, const CVector &pos); + static void InstanceLoadedModelsInSectorList(CPtrList &list); + static void InstanceLoadedModels(const CVector &pos); static void RequestIslands(eLevelName level); static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags); static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags); @@ -135,29 +151,34 @@ public: static void DecrementRef(int32 id); static void RemoveModel(int32 id); static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); } + static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); } + static void RemoveAnim(int32 id) { RemoveModel(id + STREAM_OFFSET_ANIM); } static void RemoveUnusedBuildings(eLevelName level); static void RemoveBuildings(eLevelName level); + static void RemoveBuildingsNotInArea(int32 area); static void RemoveUnusedBigBuildings(eLevelName level); static void RemoveIslandsNotUsed(eLevelName level); static void RemoveBigBuildings(eLevelName level); static bool RemoveLoadedVehicle(void); - static bool RemoveLeastUsedModel(void); + static bool RemoveLeastUsedModel(uint32 excludeMask); static void RemoveAllUnusedModels(void); static void RemoveUnusedModelsInLoadedList(void); - static bool RemoveReferencedTxds(size_t mem); // originally signed + static bool RemoveLoadedZoneModel(void); static int32 GetAvailableVehicleSlot(void); static bool IsTxdUsedByRequestedModels(int32 txdId); + static bool AreAnimsUsedByRequestedModels(int32 animId); static bool AddToLoadedVehiclesList(int32 modelId); static bool IsObjectInCdImage(int32 id); - static void HaveAllBigBuildingsLoaded(eLevelName level); static void SetModelIsDeletable(int32 id); static void SetModelTxdIsDeletable(int32 id); static void SetMissionDoesntRequireModel(int32 id); static void LoadInitialPeds(void); + static void LoadInitialWeapons(void); static void LoadInitialVehicles(void); static void StreamVehiclesAndPeds(void); static void StreamZoneModels(const CVector &pos); static void RemoveCurrentZonesModels(void); + static void LoadBigBuildingsWhenNeeded(void); static int32 GetCdImageOffset(int32 lastPosn); static int32 GetNextFileOnCd(int32 position, bool priority); @@ -174,9 +195,9 @@ public: static void IHaveUsedStreamingMemory(void); static void UpdateMemoryUsed(void); - static void AddModelsToRequestList(const CVector &pos); - static void ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax); - static void ProcessEntitiesInSectorList(CPtrList &list); + static void AddModelsToRequestList(const CVector &pos, int32 flags); + static void ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax, int32 flags); + static void ProcessEntitiesInSectorList(CPtrList &list, int32 flags); static void DeleteFarAwayRwObjects(const CVector &pos); static void DeleteAllRwObjects(void); static void DeleteRwObjectsAfterDeath(const CVector &pos); @@ -187,6 +208,7 @@ public: static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem); // originally signed static void LoadScene(const CVector &pos); + static void LoadSceneCollision(const CVector &pos); static void MemoryCardSave(uint8 *buffer, uint32 *length); static void MemoryCardLoad(uint8 *buffer, uint32 length); diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index b1bcceb6..c4b184bf 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -74,7 +74,7 @@ CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) case SURFACE_GIRDER: return ADHESIVE_HARD; case SURFACE_METAL_CHAIN_FENCE: return ADHESIVE_HARD; case SURFACE_PED: return ADHESIVE_RUBBER; - case SURFACE_SAND: return ADHESIVE_LOOSE; + case SURFACE_SAND: return ADHESIVE_SAND; case SURFACE_WATER: return ADHESIVE_WET; case SURFACE_WOOD_CRATES: return ADHESIVE_ROAD; case SURFACE_WOOD_BENCH: return ADHESIVE_ROAD; @@ -89,6 +89,8 @@ CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) case SURFACE_CARDBOARDBOX: return ADHESIVE_LOOSE; case SURFACE_TRANSPARENT_STONE: return ADHESIVE_HARD; case SURFACE_METAL_GATE: return ADHESIVE_HARD; + case SURFACE_SAND_BEACH: return ADHESIVE_SAND; + case SURFACE_CONCRETE_BEACH: return ADHESIVE_ROAD; default: return ADHESIVE_ROAD; } } @@ -108,6 +110,7 @@ CSurfaceTable::GetWetMultiplier(uint8 surfaceType) case SURFACE_HEDGE: case SURFACE_CARDBOARDBOX: case SURFACE_TRANSPARENT_STONE: + case SURFACE_CONCRETE_BEACH: return 1.0f - CWeather::WetRoads*0.25f; case SURFACE_GRASS: @@ -131,6 +134,10 @@ CSurfaceTable::GetWetMultiplier(uint8 surfaceType) case SURFACE_METAL_GATE: return 1.0f - CWeather::WetRoads*0.4f; + case SURFACE_SAND: + case SURFACE_SAND_BEACH: + return 1.0f + CWeather::WetRoads*0.5f; + default: return 1.0f; } @@ -141,3 +148,9 @@ CSurfaceTable::GetAdhesiveLimit(CColPoint &colpoint) { return ms_aAdhesiveLimitTable[GetAdhesionGroup(colpoint.surfaceB)][GetAdhesionGroup(colpoint.surfaceA)]; } + +bool +CSurfaceTable::IsSoftLanding(uint8 surf) +{ + return surf == SURFACE_GRASS || surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH; +} diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 8ee1724e..8ff43106 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -35,8 +35,6 @@ enum eSurfaceType SURFACE_CARDBOARDBOX, SURFACE_TRANSPARENT_STONE, SURFACE_METAL_GATE, - - // These are illegal SURFACE_SAND_BEACH, SURFACE_CONCRETE_BEACH, }; @@ -47,6 +45,7 @@ enum ADHESIVE_HARD, ADHESIVE_ROAD, ADHESIVE_LOOSE, + ADHESIVE_SAND, ADHESIVE_WET, NUMADHESIVEGROUPS @@ -60,11 +59,32 @@ IsSeeThrough(uint8 surfType) switch(surfType) case SURFACE_GLASS: case SURFACE_TRANSPARENT_CLOTH: -#if defined(FIX_BUGS) || defined(GTA_PS2) case SURFACE_METAL_CHAIN_FENCE: case SURFACE_TRANSPARENT_STONE: case SURFACE_SCAFFOLD_POLE: -#endif + return true; + return false; +} + +// I think the necessity of this function is really a bug +inline bool +IsSeeThroughVertical(uint8 surfType) +{ + switch(surfType) + case SURFACE_GLASS: + case SURFACE_TRANSPARENT_CLOTH: + return true; + return false; +} + +inline bool +IsShootThrough(uint8 surfType) +{ + switch(surfType) + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_TRANSPARENT_STONE: + case SURFACE_SCAFFOLD_POLE: return true; return false; } @@ -77,4 +97,5 @@ public: static int GetAdhesionGroup(uint8 surfaceType); static float GetWetMultiplier(uint8 surfaceType); static float GetAdhesiveLimit(CColPoint &colpoint); + static bool IsSoftLanding(uint8 surf); }; diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index e4f5b01e..77f26a8b 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -5,9 +5,11 @@ #include "DMAudio.h" #include "Record.h" #include "Timer.h" +#include "SpecialFX.h" uint32 CTimer::m_snTimeInMilliseconds; uint32 CTimer::m_snTimeInMillisecondsPauseMode = 1; + uint32 CTimer::m_snTimeInMillisecondsNonClipped; uint32 CTimer::m_snPreviousTimeInMilliseconds; uint32 CTimer::m_FrameCounter; @@ -15,7 +17,7 @@ float CTimer::ms_fTimeScale; float CTimer::ms_fTimeStep; float CTimer::ms_fTimeStepNonClipped; bool CTimer::m_UserPause; -bool CTimer::m_CodePause; +bool CTimer::m_CodePause; #ifdef FIX_BUGS uint32 CTimer::m_LogicalFrameCounter; uint32 CTimer::m_LogicalFramesPassed; @@ -83,9 +85,10 @@ void CTimer::Shutdown(void) { ; } + #ifdef FIX_BUGS void CTimer::Update(void) -{ +{ static double frameTimeLogical = 0.0; static double frameTimeFraction = 0.0; static double frameTimeFractionScaled = 0.0; @@ -103,10 +106,9 @@ void CTimer::Update(void) int32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless _oldPerfCounter = pc; - - // bugfix from VC - double updInCyclesScaled = GetIsPaused() ? updInCycles : updInCycles * ms_fTimeScale; - + + float updInCyclesScaled = GetIsPaused() ? updInCycles : updInCycles * ms_fTimeScale; + frameTime = updInCyclesScaled / (double)_nCyclesPerMS; dblUpdInMs = (double)updInCycles / (double)_nCyclesPerMS; @@ -117,10 +119,9 @@ void CTimer::Update(void) RsTimerType timer = RsTimer(); RsTimerType updInMs = timer - oldPcTimer; - - // bugfix from VC - frameTime = GetIsPaused() ? (double)updInMs : (double)updInMs * ms_fTimeScale; - + + frameTime = (double)updInMs * ms_fTimeScale; + oldPcTimer = timer; dblUpdInMs = (double)updInMs; @@ -129,7 +130,7 @@ void CTimer::Update(void) // count frames as if we're running at 30 fps m_LogicalFramesPassed = 0; frameTimeLogical += dblUpdInMs; - while(frameTimeLogical >= 1000.0 / 30.0) { + while (frameTimeLogical >= 1000.0 / 30.0) { frameTimeLogical -= 1000.0 / 30.0; m_LogicalFramesPassed++; } @@ -139,7 +140,7 @@ void CTimer::Update(void) frameTimeFractionScaled += frameTime; m_snTimeInMillisecondsPauseMode += uint32(frameTimeFraction); - + if ( GetIsPaused() ) ms_fTimeStep = 0.0f; else @@ -151,7 +152,7 @@ void CTimer::Update(void) frameTimeFraction -= uint32(frameTimeFraction); frameTimeFractionScaled -= uint32(frameTimeFractionScaled); - if ( ms_fTimeStep < 0.01f && !GetIsPaused() ) + if ( ms_fTimeStep < 0.01f && !GetIsPaused() && !CSpecialFX::bSnapShotActive) ms_fTimeStep = 0.01f; ms_fTimeStepNonClipped = ms_fTimeStep; @@ -186,10 +187,11 @@ void CTimer::Update(void) int32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless _oldPerfCounter = pc; - - float updInCyclesScaled = updInCycles * ms_fTimeScale; - + + float updInCyclesScaled = GetIsPaused() ? updInCycles : updInCycles * ms_fTimeScale; + double frameTime = updInCyclesScaled / (double)_nCyclesPerMS; + m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime; if ( GetIsPaused() ) @@ -209,11 +211,11 @@ void CTimer::Update(void) RsTimerType updInMs = timer - oldPcTimer; double frameTime = (double)updInMs * ms_fTimeScale; - - oldPcTimer = timer; + oldPcTimer = timer; + m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime; - + if ( GetIsPaused() ) ms_fTimeStep = 0.0f; else @@ -224,7 +226,7 @@ void CTimer::Update(void) } } - if ( ms_fTimeStep < 0.01f && !GetIsPaused() ) + if ( ms_fTimeStep < 0.01f && !GetIsPaused() && !CSpecialFX::bSnapShotActive) ms_fTimeStep = 0.01f; ms_fTimeStepNonClipped = ms_fTimeStep; diff --git a/src/core/User.cpp b/src/core/User.cpp index f906ae44..53196d03 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -1,6 +1,6 @@ #include "common.h" - +#include "GameLogic.h" #include "Hud.h" #include "PlayerPed.h" #include "Replay.h" @@ -32,8 +32,8 @@ void CPlaceName::Process() { CVector pos = CWorld::Players[CWorld::PlayerInFocus].GetPos(); - CZone *navigZone = CTheZones::FindSmallestZonePositionType(&pos, ZONE_NAVIG); - CZone *defaultZone = CTheZones::FindSmallestZonePositionType(&pos, ZONE_DEFAULT); + CZone *navigZone = CTheZones::FindSmallestNavigationZoneForPosition(&pos, false, true); + CZone *defaultZone = CTheZones::FindSmallestNavigationZoneForPosition(&pos, true, false); if (navigZone == nil) m_pZone = nil; if (defaultZone == nil) m_pZone2 = nil; @@ -74,6 +74,14 @@ CPlaceName::Display() CHud::SetZoneName(text); } +void +CPlaceName::ProcessAfterFrontEndShutDown(void) +{ + CHud::m_pLastZoneName = nil; + CHud::m_ZoneState = 0; + m_nAdditionalTimer = 250; +} + CCurrentVehicle::CCurrentVehicle() { Init(); @@ -99,7 +107,7 @@ void CCurrentVehicle::Display() { wchar *text = nil; - if (m_pCurrentVehicle != nil) + if (m_pCurrentVehicle != nil && m_pCurrentVehicle != CGameLogic::pShortCutTaxi) text = TheText.Get(((CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pCurrentVehicle->GetModelIndex()))->m_gameName); CHud::SetVehicleName(text); } diff --git a/src/core/User.h b/src/core/User.h index 153ef57b..dd53a40a 100644 --- a/src/core/User.h +++ b/src/core/User.h @@ -16,6 +16,7 @@ public: void Init(); void Process(); void Display(); + void ProcessAfterFrontEndShutDown(); }; class CCurrentVehicle diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp index 909674d0..65bc84d8 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -10,16 +10,19 @@ #include "CopPed.h" #include "Wanted.h" #include "General.h" +#include "Stats.h" int32 CWanted::MaximumWantedLevel = 6; -int32 CWanted::nMaximumWantedLevel = 6400; +int32 CWanted::nMaximumWantedLevel = 9600; void CWanted::Initialise() { m_nChaos = 0; + m_nMinChaos = 0; m_nLastUpdateTime = 0; m_nLastWantedLevelChange = 0; + m_nLastTimeSuspended = 0; m_CurrentCops = 0; m_MaxCops = 0; m_MaximumLawEnforcerVehicles = 0; @@ -31,6 +34,7 @@ CWanted::Initialise() m_bArmyRequired = false; m_fCrimeSensitivity = 1.0f; m_nWantedLevel = 0; + m_nMinWantedLevel = 0; m_CopsBeatingSuspect = 0; for (int i = 0; i < ARRAY_SIZE(m_pCops); i++) @@ -40,6 +44,12 @@ CWanted::Initialise() } bool +CWanted::AreMiamiViceRequired() +{ + return m_nWantedLevel >= 3; +} + +bool CWanted::AreSwatRequired() { return m_nWantedLevel == 4 || m_bSwatRequired; @@ -69,7 +79,7 @@ CWanted::NumOfHelisRequired() return 1; case 5: case 6: - return 2; + return 1; default: return 0; } @@ -87,22 +97,22 @@ CWanted::SetWantedLevel(int32 level) m_nChaos = 0; break; case 1: - m_nChaos = 60; + m_nChaos = 70; break; case 2: - m_nChaos = 220; + m_nChaos = 200; break; case 3: - m_nChaos = 420; + m_nChaos = 570; break; case 4: - m_nChaos = 820; + m_nChaos = 1220; break; case 5: - m_nChaos = 1620; + m_nChaos = 2420; break; case 6: - m_nChaos = 3220; + m_nChaos = 4820; break; default: break; @@ -113,11 +123,21 @@ CWanted::SetWantedLevel(int32 level) void CWanted::SetWantedLevelNoDrop(int32 level) { + if (m_nWantedLevel < m_nMinWantedLevel) + SetWantedLevel(m_nMinWantedLevel); + if (level > m_nWantedLevel) SetWantedLevel(level); } void +CWanted::CheatWantedLevel(int32 level) +{ + SetWantedLevel(level); + UpdateWantedLevel(); +} + +void CWanted::SetMaximumWantedLevel(int32 level) { switch(level){ @@ -126,27 +146,27 @@ CWanted::SetMaximumWantedLevel(int32 level) MaximumWantedLevel = 0; break; case 1: - nMaximumWantedLevel = 120; + nMaximumWantedLevel = 115; MaximumWantedLevel = 1; break; case 2: - nMaximumWantedLevel = 300; + nMaximumWantedLevel = 365; MaximumWantedLevel = 2; break; case 3: - nMaximumWantedLevel = 600; + nMaximumWantedLevel = 875; MaximumWantedLevel = 3; break; case 4: - nMaximumWantedLevel = 1200; + nMaximumWantedLevel = 1800; MaximumWantedLevel = 4; break; case 5: - nMaximumWantedLevel = 2400; + nMaximumWantedLevel = 3600; MaximumWantedLevel = 5; break; case 6: - nMaximumWantedLevel = 4800; + nMaximumWantedLevel = 7200; MaximumWantedLevel = 6; break; } @@ -161,10 +181,10 @@ CWanted::RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool po void CWanted::RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare) { -#if defined FIX_SIGNIFICANT_BUGS || defined PEDS_REPORT_CRIMES_ON_PHONE - if (!AddCrimeToQ(type, id, coors, true, policeDoesntCare)) +#ifdef FIX_SIGNIFICANT_BUGS + if(!AddCrimeToQ(type, id, coors, true, policeDoesntCare)) #else - if (!AddCrimeToQ(type, id, coors, false, policeDoesntCare)) + if(!AddCrimeToQ(type, id, coors, false, policeDoesntCare)) #endif ReportCrimeNow(type, coors, policeDoesntCare); } @@ -223,9 +243,6 @@ CWanted::ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesnt chaos *= 0.333f; switch(type){ case CRIME_POSSESSION_GUN: -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - m_nChaos += 5.0f*chaos; -#endif break; case CRIME_HIT_PED: m_nChaos += 5.0f*chaos; @@ -272,10 +289,20 @@ CWanted::ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesnt case CRIME_DESTROYED_CESSNA: m_nChaos += 500.0f*chaos; break; + case CRIME_EXPLOSION: + m_nChaos += 25.0f * chaos; + break; + case CRIME_HIT_PED_NASTYWEAPON: + m_nChaos += 35.0f * chaos; + break; + case CRIME_HIT_COP_NASTYWEAPON: + m_nChaos += 100.0f * chaos; + break; default: // Error("Undefined crime type, RegisterCrime, Crime.cpp"); // different file for some reason Error("Undefined crime type, RegisterCrime, Wanted.cpp"); } + m_nChaos = Max(m_nChaos, m_nMinChaos); DMAudio.ReportCrime(type, coors); UpdateWantedLevel(); } @@ -288,47 +315,49 @@ CWanted::UpdateWantedLevel() if (m_nChaos > nMaximumWantedLevel) m_nChaos = nMaximumWantedLevel; - if (m_nChaos >= 0 && m_nChaos < 40) { + if (m_nChaos >= 0 && m_nChaos < 50) { + if (m_nWantedLevel == 1) + ++CStats::WantedStarsEvaded; m_nWantedLevel = 0; m_MaximumLawEnforcerVehicles = 0; m_MaxCops = 0; m_RoadblockDensity = 0; - } - else if (m_nChaos >= 40 && m_nChaos < 200) { + } else if (m_nChaos >= 50 && m_nChaos < 180) { + CStats::WantedStarsAttained += 1 - m_nWantedLevel; m_nWantedLevel = 1; m_MaximumLawEnforcerVehicles = 1; m_MaxCops = 1; m_RoadblockDensity = 0; - } - else if (m_nChaos >= 200 && m_nChaos < 400) { + } else if (m_nChaos >= 180 && m_nChaos < 550) { + CStats::WantedStarsAttained += 2 - m_nWantedLevel; m_nWantedLevel = 2; m_MaximumLawEnforcerVehicles = 2; m_MaxCops = 3; m_RoadblockDensity = 0; - } - else if (m_nChaos >= 400 && m_nChaos < 800) { + } else if (m_nChaos >= 550 && m_nChaos < 1200) { + CStats::WantedStarsAttained += 3 - m_nWantedLevel; m_nWantedLevel = 3; m_MaximumLawEnforcerVehicles = 2; m_MaxCops = 4; - m_RoadblockDensity = 4; - } - else if (m_nChaos >= 800 && m_nChaos < 1600) { + m_RoadblockDensity = 12; + } else if (m_nChaos >= 1200 && m_nChaos < 2400) { + CStats::WantedStarsAttained += 4 - m_nWantedLevel; m_nWantedLevel = 4; m_MaximumLawEnforcerVehicles = 2; m_MaxCops = 6; - m_RoadblockDensity = 8; - } - else if (m_nChaos >= 1600 && m_nChaos < 3200) { + m_RoadblockDensity = 18; + } else if (m_nChaos >= 2400 && m_nChaos < 4800) { + CStats::WantedStarsAttained += 5 - m_nWantedLevel; m_nWantedLevel = 5; m_MaximumLawEnforcerVehicles = 3; m_MaxCops = 8; - m_RoadblockDensity = 10; - } - else if (m_nChaos >= 3200) { + m_RoadblockDensity = 24; + } else if (m_nChaos >= 4800) { + CStats::WantedStarsAttained += 6 - m_nWantedLevel; m_nWantedLevel = 6; m_MaximumLawEnforcerVehicles = 3; m_MaxCops = 10; - m_RoadblockDensity = 12; + m_RoadblockDensity = 30; } if (CurrWantedLevel != m_nWantedLevel) @@ -370,6 +399,10 @@ CWanted::WorkOutPolicePresence(CVector posn, float radius) void CWanted::Update(void) { + if (CTimer::GetTimeInMilliseconds() > m_nLastTimeSuspended + 20000) { + m_nMinChaos = 0; + m_nMinWantedLevel = 0; + } if (CTimer::GetTimeInMilliseconds() - m_nLastUpdateTime > 1000) { if (m_nWantedLevel > 1) { m_nLastUpdateTime = CTimer::GetTimeInMilliseconds(); @@ -447,30 +480,6 @@ CWanted::Reset(void) Initialise(); } -#ifdef PEDS_REPORT_CRIMES_ON_PHONE -bool -CrimeShouldBeReportedOnPhone(eCrimeType crime) -{ - switch (crime) { - case CRIME_POSSESSION_GUN: - case CRIME_HIT_PED: - case CRIME_HIT_COP: - case CRIME_SHOOT_PED: - case CRIME_SHOOT_COP: - case CRIME_STEAL_CAR: - case CRIME_RECKLESS_DRIVING: - case CRIME_RUNOVER_PED: - case CRIME_RUNOVER_COP: - case CRIME_PED_BURNED: - case CRIME_COP_BURNED: - case CRIME_VEHICLE_BURNED: - return true; - default: - return false; - } -} -#endif - void CWanted::UpdateCrimesQ(void) { @@ -478,9 +487,6 @@ CWanted::UpdateCrimesQ(void) CCrimeBeingQd &crime = m_aCrimes[i]; if (crime.m_nType != CRIME_NONE) { -#ifdef PEDS_REPORT_CRIMES_ON_PHONE - if (!CrimeShouldBeReportedOnPhone(crime.m_nType)) -#endif if (CTimer::GetTimeInMilliseconds() > crime.m_nTime + 500 && !crime.m_bReported) { ReportCrimeNow(crime.m_nType, crime.m_vecPosn, crime.m_bPoliceDoesntCare); crime.m_bReported = true; @@ -490,3 +496,15 @@ CWanted::UpdateCrimesQ(void) } } } + +void +CWanted::Suspend(void) +{ + CStats::WantedStarsEvaded += m_nWantedLevel; + m_nMinChaos = m_nChaos; + m_nMinWantedLevel = m_nWantedLevel; + m_nLastTimeSuspended = CTimer::GetTimeInMilliseconds(); + m_nChaos = 0; + m_nWantedLevel = 0; + ResetPolicePursuit(); +} diff --git a/src/core/Wanted.h b/src/core/Wanted.h index 9f08e752..f2da23e3 100644 --- a/src/core/Wanted.h +++ b/src/core/Wanted.h @@ -9,8 +9,10 @@ class CWanted { public: int32 m_nChaos; + int32 m_nMinChaos; int32 m_nLastUpdateTime; uint32 m_nLastWantedLevelChange; + uint32 m_nLastTimeSuspended; float m_fCrimeSensitivity; uint8 m_CurrentCops; uint8 m_MaxCops; @@ -23,6 +25,7 @@ public: uint8 m_bFbiRequired : 1; uint8 m_bArmyRequired : 1; int32 m_nWantedLevel; + int32 m_nMinWantedLevel; CCrimeBeingQd m_aCrimes[16]; CCopPed *m_pCops[10]; @@ -31,6 +34,7 @@ public: public: void Initialise(); + bool AreMiamiViceRequired(); bool AreSwatRequired(); bool AreFbiRequired(); bool AreArmyRequired(); @@ -38,6 +42,7 @@ public: void SetWantedLevel(int32); void SetWantedLevelNoDrop(int32 level); int32 GetWantedLevel() { return m_nWantedLevel; } + void CheatWantedLevel(int32 level); void RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare); void RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare); void ClearQdCrimes(); @@ -49,6 +54,8 @@ public: void UpdateCrimesQ(); void Update(); + void Suspend(); + bool IsIgnored(void) { return m_bIgnoredByCops || m_bIgnoredByEveryone; } static int32 WorkOutPolicePresence(CVector posn, float radius); diff --git a/src/core/World.cpp b/src/core/World.cpp index 6e8314f4..841aab40 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -12,6 +12,7 @@ #include "Messages.h" #include "ModelIndices.h" #include "ParticleObject.h" +#include "Pickups.h" #include "Population.h" #include "ProjectileInfo.h" #include "Record.h" @@ -23,7 +24,6 @@ #include "WaterLevel.h" #include "World.h" - #define OBJECT_REPOSITION_OFFSET_Z 2.0f CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; @@ -44,13 +44,13 @@ bool CWorld::bProcessCutsceneOnly; bool CWorld::bDoingCarCollisions; bool CWorld::bIncludeCarTyres; +bool CWorld::bIncludeBikers; + +CColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS]; void CWorld::Initialise() { -#if GTA_VERSION <= GTA3_PS2_160 - CPools::Initialise(); -#endif pIgnoreEntity = nil; bDoingCarCollisions = false; bSecondShift = false; @@ -59,6 +59,7 @@ CWorld::Initialise() bIncludeDeadPeds = false; bForceProcessControl = false; bIncludeCarTyres = false; + bIncludeBikers = false; } void @@ -151,6 +152,7 @@ CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemov CProjectileInfo::RemoveAllProjectiles(); CShadows::TidyUpShadows(); } + CPickups::RemoveUnnecessaryPickups(pos, radius); } bool @@ -163,7 +165,7 @@ CWorld::CameraToIgnoreThisObject(CEntity *ent) bool CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, - bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) + bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { int x, xstart, xend; int y, ystart, yend; @@ -182,7 +184,7 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi #define LOSARGS \ CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, \ - checkDummies, ignoreSeeThrough, ignoreSomeObjects + checkDummies, ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough if(xstart == xend && ystart == yend) { // Only one sector @@ -264,50 +266,55 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi bool CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, - bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) + bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { float mindist = dist; bool deadPeds = !!bIncludeDeadPeds; + bool bikers = !!bIncludeBikers; bIncludeDeadPeds = false; + bIncludeBikers = false; if(checkBuildings) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); } if(checkVehicles) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); } if(checkPeds) { if(deadPeds) bIncludeDeadPeds = true; + if(bikers) bIncludeBikers = true; ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); bIncludeDeadPeds = false; + bIncludeBikers = false; } if(checkObjects) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, - ignoreSeeThrough, ignoreSomeObjects); + ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough, ignoreSomeObjects); + ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough); } if(checkDummies) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, - ignoreSeeThrough); + ignoreSeeThrough, false, ignoreShootThrough); } bIncludeDeadPeds = deadPeds; + bIncludeBikers = bikers; if(mindist < dist) { dist = mindist; @@ -318,53 +325,63 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin bool CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, - CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects) + CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { bool deadPeds = false; + bool bikers = false; + bool carTyres = false; float mindist = dist; CPtrNode *node; CEntity *e; CColModel *colmodel; - + CColModel tyreCol; + CColSphere tyreSpheres[6]; + CColPoint tyreColPoint; + float tyreDist; + + if(bIncludeCarTyres && list.first && ((CEntity*)list.first->item)->IsVehicle()){ + carTyres = true; + tyreCol.numTriangles = 0; + tyreCol.numBoxes = 0; + tyreCol.numLines = 0; + tyreCol.spheres = tyreSpheres; + tyreCol.numSpheres = ARRAY_SIZE(tyreSpheres); + } if(list.first && bIncludeDeadPeds && ((CEntity *)list.first->item)->IsPed()) deadPeds = true; + if(list.first && bIncludeBikers && ((CEntity *)list.first->item)->IsPed()) bikers = true; for(node = list.first; node; node = node->next) { e = (CEntity *)node->item; - if(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds) && + if(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds || bikers) && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { colmodel = nil; + tyreDist = mindist; e->m_scanCode = GetCurrentScanCode(); if(e->IsPed()) { - if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) { -#ifdef PED_SKIN - if(IsClumpSkinned(e->GetClump())) - colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump()); - else -#endif - if(((CPed *)e)->UseGroundColModel()) - colmodel = &CTempColModels::ms_colModelPedGroundHit; - else -#ifdef ANIMATE_PED_COL_MODEL - colmodel = CPedModelInfo::AnimatePedColModel( - ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) - ->GetHitColModel(), - RpClumpGetFrame(e->GetClump())); -#else - colmodel = - ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) - ->GetHitColModel(); -#endif + if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD || bikers && ((CPed*)e)->InVehicle() && (((CPed*)e)->m_pMyVehicle->IsBike() || ((CPed*)e)->m_pMyVehicle->IsBoat())) { + colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump()); } else colmodel = nil; + } else if(e->bUsesCollision) colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, mindist, - ignoreSeeThrough)) + ignoreSeeThrough, ignoreShootThrough)) entity = e; + if(carTyres && ((CVehicle*)e)->SetUpWheelColModel(&tyreCol) && CCollision::ProcessLineOfSight(line, e->GetMatrix(), tyreCol, tyreColPoint, tyreDist, false, ignoreShootThrough)){ + float dp1 = DotProduct(line.p1 - line.p0, e->GetRight()); + float dp2 = DotProduct(point.point - e->GetPosition(), e->GetRight()); + if(tyreDist < mindist || dp1 < -0.85f && dp2 > 0.0f || dp1 > 0.85f && dp2 < 0.0f){ + mindist = tyreDist; + point = tyreColPoint; + entity = e; + } + } } } + tyreCol.spheres = nil; if(mindist < dist) { dist = mindist; @@ -380,7 +397,11 @@ CWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, C { AdvanceCurrentScanCode(); CVector point2(point1.x, point1.y, z2); - return ProcessVerticalLineSector(*GetSector(GetSectorIndexX(point1.x), GetSectorIndexY(point1.y)), + int secX = GetSectorIndexX(point1.x); + int secY = GetSectorIndexY(point1.y); + secX = Clamp(secX, 0, NUMSECTORS_X-1); + secY = Clamp(secY, 0, NUMSECTORS_Y-1); + return ProcessVerticalLineSector(*GetSector(secX, secY), CColLine(point1, point2), point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly); } @@ -446,7 +467,7 @@ CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CCol colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, mindist, - ignoreSeeThrough, poly)) + ignoreSeeThrough, false, poly)) entity = e; } } @@ -647,7 +668,7 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); - if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough)) + if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough, false)) return false; } } @@ -694,18 +715,10 @@ CWorld::FindObjectsInRange(Const CVector ¢re, float radius, bool ignoreZ, in if(minY <= 0) minY = 0; int maxX = GetSectorIndexX(centre.x + radius); -#ifdef FIX_BUGS if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; -#else - if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; -#endif int maxY = GetSectorIndexY(centre.y + radius); -#ifdef FIX_BUGS if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; -#else - if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; -#endif AdvanceCurrentScanCode(); @@ -782,8 +795,13 @@ CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector &position, float const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); const int32 nStartX = Max(GetSectorIndexX(vecSectorStartPos.x), 0); const int32 nStartY = Max(GetSectorIndexY(vecSectorStartPos.y), 0); +#ifdef FIX_BUGS const int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); +#else + const int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X); + const int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y); +#endif for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = GetSector(x, y); @@ -918,6 +936,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad bool ignoreSomeObjects) { static CColModel OurColModel; + CColSphere sphere; OurColModel.boundingSphere.center.x = 0.0f; OurColModel.boundingSphere.center.y = 0.0f; @@ -930,7 +949,8 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad OurColModel.boundingBox.max.y = radius; OurColModel.boundingBox.max.z = radius; OurColModel.numSpheres = 1; - OurColModel.spheres = &OurColModel.boundingSphere; + sphere.Set(radius, CVector(0.0f, 0.0f, 0.0f)); + OurColModel.spheres = &sphere; OurColModel.numLines = 0; OurColModel.numBoxes = 0; OurColModel.numTriangles = 0; @@ -947,11 +967,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad if(e != entityToIgnore && e->bUsesCollision && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { -#ifdef FIX_BUGS CVector diff = spherePos - e->GetBoundCentre(); -#else - CVector diff = spherePos - e->GetPosition(); -#endif float distance = diff.Magnitude(); if(e->GetBoundRadius() + radius > distance) { @@ -1053,8 +1069,13 @@ CWorld::FindObjectsKindaColliding(const CVector &position, float radius, bool bC const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); const int32 nStartX = Max(GetSectorIndexX(vecSectorStartPos.x), 0); const int32 nStartY = Max(GetSectorIndexY(vecSectorStartPos.y), 0); +#ifdef FIX_BUGS const int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); +#else + const int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X); + const int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y); +#endif for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = GetSector(x, y); @@ -1132,8 +1153,13 @@ CWorld::FindObjectsIntersectingCube(const CVector &vecStartPos, const CVector &v *nIntersecting = 0; const int32 nStartX = Max(GetSectorIndexX(vecStartPos.x), 0); const int32 nStartY = Max(GetSectorIndexY(vecStartPos.y), 0); - const int32 nEndX = Min(GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = Min(GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); +#ifdef FIX_BUGS + const int32 nEndX = Min(GetSectorIndexX(vecStartPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(GetSectorIndexY(vecStartPos.y), NUMSECTORS_Y - 1); +#else + const int32 nEndX = Min(GetSectorIndexX(vecStartPos.x), NUMSECTORS_X); + const int32 nEndY = Min(GetSectorIndexY(vecStartPos.y), NUMSECTORS_Y); +#endif for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = GetSector(x, y); @@ -1203,7 +1229,7 @@ CWorld::FindObjectsIntersectingCubeSectorList(CPtrList &list, const CVector &vec } void -CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, const CMatrix &matrix, +CWorld::FindObjectsIntersectingAngledCollisionBox(const CBox &boundingBox, const CMatrix &matrix, const CVector &position, float fStartX, float fStartY, float fEndX, float fEndY, int16 *nEntitiesFound, int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles, bool bPeds, @@ -1213,8 +1239,13 @@ CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, co *nEntitiesFound = 0; const int32 nStartX = Max(GetSectorIndexX(fStartX), 0); const int32 nStartY = Max(GetSectorIndexY(fStartY), 0); +#ifdef FIX_BUGS const int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X - 1); const int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); +#else + const int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X); + const int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y); +#endif for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = GetSector(x, y); @@ -1263,7 +1294,7 @@ CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, co } void -CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CColBox &boundingBox, +CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CBox &boundingBox, const CMatrix &matrix, const CVector &position, int16 *nEntitiesFound, int16 maxEntitiesToFind, CEntity **aEntities) @@ -1293,8 +1324,13 @@ CWorld::FindMissionEntitiesIntersectingCube(const CVector &vecStartPos, const CV *nIntersecting = 0; const int32 nStartX = Max(GetSectorIndexX(vecStartPos.x), 0); const int32 nStartY = Max(GetSectorIndexY(vecStartPos.y), 0); +#ifdef FIX_BUGS const int32 nEndX = Min(GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = Min(GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); +#else + const int32 nEndX = Min(GetSectorIndexX(vecEndPos.x), NUMSECTORS_X); + const int32 nEndY = Min(GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y); +#endif for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = GetSector(x, y); @@ -1411,8 +1447,13 @@ CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2) float fEndY = y2 + 10.0f; const int32 nStartX = Max(GetSectorIndexX(fStartX), 0); const int32 nStartY = Max(GetSectorIndexY(fStartY), 0); +#ifdef FIX_BUGS const int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X - 1); const int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); +#else + const int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X); + const int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y); +#endif for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = GetSector(x, y); @@ -1543,7 +1584,7 @@ CWorld::RemoveFallenCars(void) CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); if(veh) { if(veh->GetPosition().z < MAP_Z_LOW_LIMIT) { - if(veh->VehicleCreatedBy == MISSION_VEHICLE || veh == FindPlayerVehicle() || + if(veh->VehicleCreatedBy == MISSION_VEHICLE && !veh->bRenderScorched || veh == FindPlayerVehicle() || (veh->pDriver && veh->pDriver->IsPlayer())) { int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR, 999999.9f, false, false); @@ -1595,10 +1636,10 @@ CWorld::ExtinguishAllCarFiresInArea(CVector point, float range) } } -inline void -AddSteamsFromGround(CPtrList& list) +inline void +AddSteamsFromGround(CPtrList& list) { - CPtrNode *pNode = list.first; + CPtrNode* pNode = list.first; while (pNode) { ((CEntity*)pNode->item)->AddSteamsFromGround(nil); pNode = pNode->next; @@ -1700,9 +1741,6 @@ CWorld::ShutDown(void) } } ms_listMovingEntityPtrs.Flush(); -#if GTA_VERSION <= GTA3_PS2_160 - CPools::Shutdown(); -#endif } void @@ -1750,35 +1788,56 @@ void CWorld::RepositionOneObject(CEntity *pEntity) { int16 modelId = pEntity->GetModelIndex(); - if (IsStreetLight(modelId) || IsTreeModel(modelId) || modelId == MI_PARKINGMETER || - modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || modelId == MI_BIN || modelId == MI_POSTBOX1 || - modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || modelId == MI_DUMP1 || - modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || - modelId == MI_PHONESIGN || modelId == MI_TAXISIGN || modelId == MI_FISHSTALL01 || - modelId == MI_FISHSTALL02 || modelId == MI_FISHSTALL03 || modelId == MI_FISHSTALL04 || - modelId == MI_BAGELSTAND2 || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || - modelId == MI_PARKTABLE) { - CVector &position = pEntity->GetMatrix().GetPosition(); - float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; + if (modelId == MI_PARKINGMETER || modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || + modelId == MI_BIN || modelId == MI_POSTBOX1 || modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || + modelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || + modelId == MI_PHONESIGN || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || + modelId == MI_PARKTABLE || modelId == MI_PARKINGMETER2 || modelId == MI_TELPOLE02 || + modelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId) + ) { + CVector& position = pEntity->GetMatrix().GetPosition(); + CColModel* pColModel = pEntity->GetColModel(); + float fBoundingBoxMinZ = pColModel->boundingBox.min.z; + float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; + if (fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z; position.z = FindGroundZFor3DCoord(position.x, position.y, - position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - - fBoundingBoxMinZ; + position.z + fHeight, nil) - + fBoundingBoxMinZ; + pEntity->GetMatrix().UpdateRW(); + pEntity->UpdateRwFrame(); + } else if(IsLightThatNeedsRepositioning(modelId)) { + CVector position = pEntity->GetMatrix().GetPosition(); + CColModel* pColModel = pEntity->GetColModel(); + float fBoundingBoxMinZ = pColModel->boundingBox.min.z; + float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; + if (fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z; + if (pColModel->numBoxes == 1) + position = pEntity->GetMatrix() * CVector( + (pColModel->boxes[0].min.x + pColModel->boxes[0].max.x) / 2, + (pColModel->boxes[0].min.y + pColModel->boxes[0].max.y) / 2, + pColModel->boxes[0].min.z); + else if (pColModel->numSpheres > 0) { + position.z = 1000.0f; + for (int i = 0; i < pColModel->numSpheres; i++) { + if (pColModel->spheres[i].center.z < position.z) + position = pColModel->spheres[i].center; + } + if (position.z < 1000.0f) + position = pEntity->GetMatrix() * position; + } + pEntity->GetMatrix().GetPosition().z = FindGroundZFor3DCoord(position.x, position.y, pEntity->GetMatrix().GetPosition().z + fHeight, nil) - fBoundingBoxMinZ; pEntity->GetMatrix().UpdateRW(); pEntity->UpdateRwFrame(); - } else if(modelId == MI_BUOY) { - float fWaterLevel = 0.0f; + + } + if(modelId == MI_BUOY) { bool bFound = true; const CVector &position = pEntity->GetPosition(); float fGroundZ = FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound); - if(CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, - &fWaterLevel)) { - if(!bFound || fWaterLevel > fGroundZ) { - CColModel *pColModel = pEntity->GetColModel(); - float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; - pEntity->GetMatrix().GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; - } - } + CColModel *pColModel = pEntity->GetColModel(); + float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; + pEntity->GetMatrix().GetPosition().z = 0.2f * fHeight + 6.0f - 0.5f * fHeight; } } @@ -1797,6 +1856,28 @@ CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason) } void +CWorld::SetPedsChoking(float x, float y, float z, float radius, CEntity* reason) +{ + int32 poolSize = CPools::GetPedPool()->GetSize(); + for (int32 i = poolSize - 1; i >= 0; i--) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + // suspicious copypaste + if (pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof && pPed->CharCreatedBy != MISSION_CHAR) { + if (Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius && + Abs(pPed->GetPosition().y - y) < radius) { + if (!pPed->IsPlayer()) + pPed->SetFlee(CVector2D(x, y), 10000); +#ifdef FIX_BUGS + pPed->InflictDamage(reason, WEAPONTYPE_TEARGAS, 1.0f, PEDPIECE_TORSO, 0); +#else + pPed->InflictDamage(nil, WEAPONTYPE_TEARGAS, 1.0f, PEDPIECE_TORSO, 0); +#endif + } + } + } +} + +void CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity *reason) { int32 poolSize = CPools::GetPedPool()->GetSize(); @@ -1848,10 +1929,13 @@ CWorld::Process(void) if(csObj && csObj->m_entryInfoList.first) { if(csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP && RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) { - RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), - csObj->IsObject() - ? CTimer::GetTimeStepNonClippedInSeconds() - : CTimer::GetTimeStepInSeconds()); + if (csObj->IsObject()) + RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), CTimer::GetTimeStepNonClippedInSeconds()); + else { + if (!csObj->bOffscreen) + csObj->bOffscreen = !csObj->GetIsOnScreen(); + RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), CTimer::GetTimeStepInSeconds(), !csObj->bOffscreen); + } } csObj->ProcessControl(); csObj->ProcessCollision(); @@ -1864,16 +1948,15 @@ CWorld::Process(void) } else { for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { CEntity *movingEnt = (CEntity *)node->item; -#ifdef FIX_BUGS // from VC if(!movingEnt->bRemoveFromWorld && movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP && -#else - if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP && -#endif RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) { - RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), - movingEnt->IsObject() - ? CTimer::GetTimeStepNonClippedInSeconds() - : CTimer::GetTimeStepInSeconds()); + if (movingEnt->IsObject()) + RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), CTimer::GetTimeStepNonClippedInSeconds()); + else { + if (!movingEnt->bOffscreen) + movingEnt->bOffscreen = !movingEnt->GetIsOnScreen(); + RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), CTimer::GetTimeStepInSeconds(), !movingEnt->bOffscreen); + } } } for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { @@ -1957,7 +2040,7 @@ CWorld::Process(void) movingEnt->bIsStuck = true; if(movingEnt->GetStatus() == STATUS_PLAYER) { printf("STUCK: Final Step: Player Entity %d Is Stuck\n", movingEnt->GetModelIndex()); - movingEnt->m_vecMoveSpeed *= 0.3f; + movingEnt->m_vecMoveSpeed *= Pow(0.707f, CTimer::GetTimeStep()); movingEnt->ApplyMoveSpeed(); movingEnt->ApplyTurnSpeed(); } @@ -1972,9 +2055,12 @@ CWorld::Process(void) movingPed->EnteringCar()) { CVehicle *movingCar = movingPed->m_pMyVehicle; if(movingCar) { +#ifdef GTA_TRAIN if(movingCar->IsTrain()) { movingPed->SetPedPositionInTrain(); - } else { + } else +#endif + { switch(movingPed->m_nPedState) { case PED_ENTER_CAR: case PED_CARJACK: movingPed->EnterCar(); break; @@ -1995,6 +2081,10 @@ CWorld::Process(void) movingPed->bInVehicle = false; movingPed->QuitEnteringCar(); } + } else if (movingPed->m_attachedTo) { + movingPed->PositionAttachedPed(); + movingPed->GetMatrix().UpdateRW(); + movingPed->UpdateRwFrame(); } } } @@ -2059,7 +2149,7 @@ CWorld::TriggerExplosionSectorList(CPtrList &list, const CVector &position, floa pObject->bHasBeenDamaged) { if(pEntity->IsObject() && modelId != MI_EXPLODINGBARREL && - modelId != MI_PETROLPUMP) + modelId != MI_PETROLPUMP && modelId != MI_PETROLPUMP2) pObject->bHasBeenDamaged = true; } else { CVector pos = pEntity->GetPosition(); @@ -2149,8 +2239,12 @@ CWorld::UseDetonator(CEntity *pEntity) { int32 i = CPools::GetVehiclePool()->GetSize(); while(--i >= 0) { +#ifdef FIX_BUGS + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); +#else CAutomobile *pVehicle = (CAutomobile *)CPools::GetVehiclePool()->GetSlot(i); - if(pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE && +#endif + if(pVehicle && pVehicle->m_bombType == CARBOMB_REMOTE && pVehicle->m_pBombRigger == pEntity) { pVehicle->m_bombType = CARBOMB_NONE; pVehicle->m_nBombTimer = 500; @@ -2159,4 +2253,60 @@ CWorld::UseDetonator(CEntity *pEntity) pVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity); } } + CProjectileInfo::RemoveDetonatorProjectiles(); +} + +bool +CWorld::IsWanderPathClear(CVector const& point1, CVector const& point2, float distance, int maxSteps) +{ + if (Abs(point1.z - point2.z) > distance) + return false; + if (!GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false)) + return false; + CVector vecBetween = point2 - point1; + uint32 nSteps = Max(vecBetween.Magnitude(), maxSteps); + if (nSteps == 0) + return true; + vecBetween.Normalise(); + uint32 step = 1; + for (step = 1; step < nSteps; step++) { + CVector posThisStep = point1 + vecBetween * step; + float level; + if (!CWaterLevel::GetWaterLevel(posThisStep, &level, false)) + continue; + posThisStep.z = level; + AdvanceCurrentScanCode(); + + CVector vecCheckedPos(posThisStep.x, posThisStep.y, Max(point1.z, point2.z)); + CColPoint colpoint; + CEntity* entity; + if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)), + CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil)) + return false; + } + + CVector posThisStep = point1; + AdvanceCurrentScanCode(); + CVector vecCheckedPos(posThisStep.x, posThisStep.y, point1.z - 5.0f); + + CColPoint colpoint; + CEntity* entity; + if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)), + CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil)) + return false; + + float heightNextStep = colpoint.point.z + 0.5f; + for (step = 1; step < nSteps; step++) { + CVector posThisStep = point1 + vecBetween * step; + posThisStep.z = heightNextStep; + AdvanceCurrentScanCode(); + CVector vecCheckedPos(posThisStep.x, posThisStep.y, heightNextStep - 2.0f); + if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)), + CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil)) + return false; + if (Abs(colpoint.point.z - heightNextStep) > 1.0f) + return false; + heightNextStep = colpoint.point.z + 0.5f; + } + return true; } diff --git a/src/core/World.h b/src/core/World.h index 3d553752..81eb5d4c 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -5,19 +5,19 @@ #include "PlayerInfo.h" #include "Collision.h" -/* Sectors span from -2000 to 2000 in x and y. - * With 100x100 sectors, each is 40x40 units. */ +/* Sectors span from -2400 to 1600 in x and -2000 to 2000 y. + * With 80x80 sectors, each is 50x50 units. */ -#define SECTOR_SIZE_X (40.0f) -#define SECTOR_SIZE_Y (40.0f) +#define SECTOR_SIZE_X (50.0f) +#define SECTOR_SIZE_Y (50.0f) -#define NUMSECTORS_X (100) -#define NUMSECTORS_Y (100) +#define NUMSECTORS_X (80) +#define NUMSECTORS_Y (80) #define WORLD_SIZE_X (NUMSECTORS_X * SECTOR_SIZE_X) #define WORLD_SIZE_Y (NUMSECTORS_Y * SECTOR_SIZE_Y) -#define WORLD_MIN_X (-2000.0f) +#define WORLD_MIN_X (-2400.0f) #define WORLD_MIN_Y (-2000.0f) #define WORLD_MAX_X (WORLD_MIN_X + WORLD_SIZE_X) @@ -67,11 +67,13 @@ public: static bool bProcessCutsceneOnly; static bool bDoingCarCollisions; static bool bIncludeCarTyres; + static bool bIncludeBikers; + static CColPoint m_aTempColPts[MAX_COLLISION_POINTS]; static void Remove(CEntity *entity); static void Add(CEntity *entity); - static CSector *GetSector(int x, int y) { return &ms_aSectors[y][x]; } + static CSector *GetSector(int x, int y) { if (x > NUMSECTORS_X - 1 || y > NUMSECTORS_Y - 1) return &ms_aSectors[0][0]; return &ms_aSectors[y][x]; } static CPtrList &GetBigBuildingList(eLevelName i) { return ms_bigBuildingsList[i]; } static CPtrList &GetMovingEntityList(void) { return ms_listMovingEntityPtrs; } static uint16 GetCurrentScanCode(void) { return ms_nCurrentScanCode; } @@ -86,9 +88,9 @@ public: static bool CameraToIgnoreThisObject(CEntity *ent); - static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false); - static bool ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false); - static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects = false); + static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false, bool ignoreShootThrough = false); + static bool ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough); + static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough); static bool ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly); static bool ProcessVerticalLineSector(CSector §or, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly); static bool ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly); @@ -110,8 +112,8 @@ public: static void FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities); static void FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies); static void FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities); - static void FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool); - static void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities); + static void FindObjectsIntersectingAngledCollisionBox(const CBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool); + static void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities); static void FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects); static void FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList); @@ -121,6 +123,8 @@ public: static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY); static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2); + static bool IsWanderPathClear(CVector const&, CVector const&, float, int); + static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); } static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); } static int GetSectorIndexX(float f) { return (int)GetSectorX(f); } @@ -136,6 +140,7 @@ public: static void SetAllCarsCanBeDamaged(bool); static void ExtinguishAllCarFiresInArea(CVector, float); static void SetCarsOnFire(float x, float y, float z, float radius, CEntity* reason); + static void SetPedsChoking(float x, float y, float z, float radius, CEntity* reason); static void SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason); static void Initialise(); @@ -149,7 +154,23 @@ public: static void TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); static void TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); static void UseDetonator(CEntity *pEntity); + + // NB: following functions are unused (TODO?) + static void CastShadow(float, float, float, float); + static void CastShadowSectorList(CPtrList&, float, float, float, float); + static void FindLowestZForCoord(float, float); + static void CheckBlockListIntegrity(void); + static void ProcessVerticalLineSectorList_FillGlobeColPoints(CPtrList&, const CColLine&, CEntity*&, bool, CStoredCollPoly*); + static void ProcessVerticalLineSector_FillGlobeColPoints(CSector&, const CColLine&, CEntity*&, bool, bool, bool, bool, bool, bool, CStoredCollPoly*); + static void ProcessVerticalLine_FillGlobeColPoints(const CVector&, float, CEntity*&, bool, bool, bool, bool, bool, bool, CStoredCollPoly*); + static void PrintCarChanges(void); + static void TestForBuildingsOnTopOfEachOther(CPtrList&); + static void TestForBuildingsOnTopOfEachOther(void); + static void TestForUnusedModels(CPtrList&, int*); + static void TestForUnusedModels(void); + static void HandleCollisionZoneChange(eLevelName, eLevelName); + static void DoZoneTestForChaser(class CPhysical*); + static void FindPlayerSlotWithPedPointer(void*); }; extern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; - diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index 5a76e5ed..db3577ad 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -1,6 +1,5 @@ #include "common.h" -#include "General.h" #include "Building.h" #include "Treadable.h" #include "Train.h" @@ -12,242 +11,23 @@ #include "ZoneCull.h" #include "Zones.h" -#include "Debug.h" -#include "Renderer.h" - -int32 CCullZones::NumCullZones; -CCullZone CCullZones::aZones[NUMCULLZONES]; int32 CCullZones::NumAttributeZones; CAttributeZone CCullZones::aAttributeZones[NUMATTRIBZONES]; -uint16 CCullZones::aIndices[NUMZONEINDICES]; -int16 CCullZones::aPointersToBigBuildingsForBuildings[NUMBUILDINGS]; -int16 CCullZones::aPointersToBigBuildingsForTreadables[NUMTREADABLES]; int32 CCullZones::CurrentWantedLevelDrop_Player; int32 CCullZones::CurrentFlags_Camera; int32 CCullZones::CurrentFlags_Player; -int32 CCullZones::OldCullZone; -int32 CCullZones::EntityIndicesUsed; bool CCullZones::bCurrentSubwayIsInvisible; -bool CCullZones::bCullZonesDisabled; - -#define NUMUNCOMPRESSED (6000) -#define NUMTEMPINDICES (140000) +bool CCullZones::bAtBeachForAudio; void CCullZones::Init(void) { - int i; - NumAttributeZones = 0; CurrentWantedLevelDrop_Player = 0; CurrentFlags_Camera = 0; CurrentFlags_Player = 0; bCurrentSubwayIsInvisible = false; - NumCullZones = 0; - OldCullZone = -1; - EntityIndicesUsed = 0; - - for(i = 0; i < NUMBUILDINGS; i++) - aPointersToBigBuildingsForBuildings[i] = -1; - for(i = 0; i < NUMTREADABLES; i++) - aPointersToBigBuildingsForTreadables[i] = -1; -} - - -uint16* pTempArrayIndices; -int TempEntityIndicesUsed; - -void -CCullZones::ResolveVisibilities(void) -{ - int fd; - - CFileMgr::SetDir(""); - fd = CFileMgr::OpenFile("DATA\\cullzone.dat", "rb"); - if(fd > 0){ - CFileMgr::Read(fd, (char*)&NumCullZones, sizeof(NumCullZones)); - CFileMgr::Read(fd, (char*)aZones, sizeof(aZones)); - CFileMgr::Read(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones)); - CFileMgr::Read(fd, (char*)aAttributeZones, sizeof(aAttributeZones)); - CFileMgr::Read(fd, (char*)aIndices, sizeof(aIndices)); - CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings)); - CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); - CFileMgr::CloseFile(fd); - }else{ -#ifndef MASTER - EntityIndicesUsed = 0; - BuildListForBigBuildings(); - pTempArrayIndices = new uint16[NUMTEMPINDICES]; - TempEntityIndicesUsed = 0; - -// if(!LoadTempFile()) // not in final game - { - for (int i = 0; i < NumCullZones; i++) { -//printf("testing zone %d (%d indices)\n", i, TempEntityIndicesUsed); - DoVisibilityTestCullZone(i, true); - } - -// SaveTempFile(); // not in final game - } - - CompressIndicesArray(); - delete[] pTempArrayIndices; - pTempArrayIndices = nil; - - fd = CFileMgr::OpenFileForWriting("data\\cullzone.dat"); - if (fd != 0) { - CFileMgr::Write(fd, (char*)&NumCullZones, sizeof(NumCullZones)); - CFileMgr::Write(fd, (char*)aZones, sizeof(aZones)); - CFileMgr::Write(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones)); - CFileMgr::Write(fd, (char*)&aAttributeZones, sizeof(aAttributeZones)); - CFileMgr::Write(fd, (char*)&aIndices, sizeof(aIndices)); - CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings)); - CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); - CFileMgr::CloseFile(fd); - } -#endif - } -} - -bool -CCullZones::LoadTempFile(void) -{ - int fd = CFileMgr::OpenFile("cullzone.tmp"); - if (fd != 0) { - CFileMgr::Read(fd, (char*)&NumCullZones, sizeof(NumCullZones)); - CFileMgr::Read(fd, (char*)aZones, sizeof(aZones)); - CFileMgr::Read(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones)); - CFileMgr::Read(fd, (char*)&aAttributeZones, sizeof(aAttributeZones)); - CFileMgr::Read(fd, (char*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16)); - CFileMgr::Read(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed)); - CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings)); - CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); - CFileMgr::CloseFile(fd); - return true; - } - return false; -} - -void -CCullZones::SaveTempFile(void) -{ - int fd = CFileMgr::OpenFileForWriting("cullzone.tmp"); - if (fd != 0) { - CFileMgr::Write(fd, (char*)&NumCullZones, sizeof(NumCullZones)); - CFileMgr::Write(fd, (char*)aZones, sizeof(aZones)); - CFileMgr::Write(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones)); - CFileMgr::Write(fd, (char*)&aAttributeZones, sizeof(aAttributeZones)); - CFileMgr::Write(fd, (char*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16)); - CFileMgr::Write(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed)); - CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings)); - CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables)); - CFileMgr::CloseFile(fd); - } -} - - -void -CCullZones::BuildListForBigBuildings() -{ - for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) { - CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); - if (building == nil || !building->bIsBIGBuilding) continue; - CSimpleModelInfo *nonlod = ((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->GetRelatedModel(); - if (nonlod == nil) continue; - - for (int j = CPools::GetBuildingPool()->GetSize()-1; j >= 0; j--) { - CBuilding *building2 = CPools::GetBuildingPool()->GetSlot(j); - if (building2 == nil || building2->bIsBIGBuilding) continue; - if (CModelInfo::GetModelInfo(building2->GetModelIndex()) == nonlod) { - if ((building2->GetPosition() - building->GetPosition()).Magnitude() < 5.0f) { - aPointersToBigBuildingsForBuildings[j] = i; - } - } - } - - for (int j = CPools::GetTreadablePool()->GetSize()-1; j >= 0; j--) { - CTreadable *treadable = CPools::GetTreadablePool()->GetSlot(j); - if (treadable == nil || treadable->bIsBIGBuilding) continue; - if (CModelInfo::GetModelInfo(treadable->GetModelIndex()) == nonlod) { - if ((treadable->GetPosition() - building->GetPosition()).Magnitude() < 5.0f) { - aPointersToBigBuildingsForTreadables[j] = i; - } - } - } - } -} - -void -CCullZones::DoVisibilityTestCullZone(int zoneId, bool findIndices) -{ - aZones[zoneId].m_groupIndexCount[0] = 0; - aZones[zoneId].m_groupIndexCount[1] = 0; - aZones[zoneId].m_groupIndexCount[2] = 0; - aZones[zoneId].m_indexStart = TempEntityIndicesUsed; - aZones[zoneId].FindTestPoints(); - - if (!findIndices) return; - - for (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) { - CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); - if (building != nil && !building->bIsBIGBuilding && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForBuildings[i] != -1)) { - CBuilding *LODbuilding = nil; - if (aPointersToBigBuildingsForBuildings[i] != -1) - LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]); - - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) { - assert(TempEntityIndicesUsed < NUMTEMPINDICES); - pTempArrayIndices[TempEntityIndicesUsed++] = i; - aZones[zoneId].m_groupIndexCount[0]++; - } - } - } - - for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) { - CBuilding* building = CPools::GetTreadablePool()->GetSlot(i); - if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) { - CBuilding *LODbuilding = nil; - if (aPointersToBigBuildingsForTreadables[i] != -1) - LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); - - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, LODbuilding)) { - assert(TempEntityIndicesUsed < NUMTEMPINDICES); - pTempArrayIndices[TempEntityIndicesUsed++] = i; - aZones[zoneId].m_groupIndexCount[1]++; - } - } - } - - for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) { - CBuilding *building = CPools::GetTreadablePool()->GetSlot(i); - if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < SQR(200.0f)) { - int start = aZones[zoneId].m_groupIndexCount[0] + aZones[zoneId].m_indexStart; - int end = aZones[zoneId].m_groupIndexCount[1] + start; - - bool alreadyAdded = false; - - for (int k = start; k < end; k++) { -#ifdef FIX_BUGS - if (pTempArrayIndices[k] == i) -#else - if (aIndices[k] == i) -#endif - alreadyAdded = true; - } - - if (!alreadyAdded) { - CBuilding *LODbuilding = nil; - if (aPointersToBigBuildingsForTreadables[i] != -1) - LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) { - assert(TempEntityIndicesUsed < NUMTEMPINDICES); - pTempArrayIndices[TempEntityIndicesUsed++] = i; - aZones[zoneId].m_groupIndexCount[2]++; - } - } - } - } } void @@ -255,14 +35,10 @@ CCullZones::Update(void) { bool invisible; - if(bCullZonesDisabled) - return; - switch(CTimer::GetFrameCounter() & 7){ case 0: case 4: - /* Update Cull zone */ - ForceCullZoneCoors(TheCamera.GetGameCamPosition()); + UpdateAtBeachForAudio(); break; case 2: @@ -283,31 +59,30 @@ CCullZones::Update(void) } } -void -CCullZones::ForceCullZoneCoors(CVector coors) +// TODO? put somewhere else? +bool +IsPointWithinArbitraryArea(float px, float py, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { - int32 z; - z = FindCullZoneForCoors(coors); - if(z != OldCullZone){ - if(OldCullZone >= 0) - aZones[OldCullZone].DoStuffLeavingZone(); - if(z >= 0) - aZones[z].DoStuffEnteringZone(); - OldCullZone = z; - } + if((px-x1)*(x2-x1) - (py-y1)*(y2-y1) < 0.0f) return false; + if((px-x2)*(x3-x2) - (py-y2)*(y3-y2) < 0.0f) return false; + if((px-x3)*(x4-x3) - (py-y3)*(y4-y3) < 0.0f) return false; + if((px-x4)*(x1-x4) - (py-y4)*(y1-y4) < 0.0f) return false; + return true; } -int32 -CCullZones::FindCullZoneForCoors(CVector coors) +void +CCullZones::UpdateAtBeachForAudio(void) { - int i; + bAtBeachForAudio = IsPointWithinArbitraryArea(TheCamera.GetPosition().x, TheCamera.GetPosition().y, + 400.0f, -1644.4f, + 751.9f, 1267.8f, + 971.9f, 1216.2f, + 840.0f, -1744.0f); +} - for(i = 0; i < NumCullZones; i++) - if(coors.x >= aZones[i].minx && coors.x <= aZones[i].maxx && - coors.y >= aZones[i].miny && coors.y <= aZones[i].maxy && - coors.z >= aZones[i].minz && coors.z <= aZones[i].maxz) - return i; - return -1; +void +CCullZones::ForceCullZoneCoors(CVector coors) +{ } int32 @@ -382,1208 +157,16 @@ CCullZones::AddCullZone(CVector const &position, float minz, float maxz, uint16 flag, int16 wantedLevel) { - CCullZone *cull; CAttributeZone *attrib; - CVector v; - if((flag & ATTRZONE_NOTCULLZONE) == 0){ - cull = &aZones[NumCullZones++]; - v = position; - // reposition start point to the start/end of the - // alley next to the big building in the industrial district. - // probably isn't analyzed correctly otherwise?s - if((v-CVector(1032.14f, -624.255f, 24.93f)).Magnitude() < 1.0f) - v = CVector(1061.7f, -613.0f, 19.0f); - if((v-CVector(1029.48f, -495.757f, 21.98f)).Magnitude() < 1.0f) - v = CVector(1061.4f, -506.0f, 18.5f); - cull->position.x = Clamp(v.x, minx, maxx); - cull->position.y = Clamp(v.y, miny, maxy); - cull->position.z = Clamp(v.z, minz, maxz); - cull->minx = minx; - cull->maxx = maxx; - cull->miny = miny; - cull->maxy = maxy; - cull->minz = minz; - cull->maxz = maxz; - cull->m_groupIndexCount[0] = 0; - cull->m_groupIndexCount[1] = 0; - cull->m_groupIndexCount[2] = 0; - cull->m_indexStart = 0; - } - if(flag & ~ATTRZONE_NOTCULLZONE){ - attrib = &aAttributeZones[NumAttributeZones++]; - attrib->minx = minx; - attrib->maxx = maxx; - attrib->miny = miny; - attrib->maxy = maxy; - attrib->minz = minz; - attrib->maxz = maxz; - attrib->attributes = flag; - attrib->wantedLevel = wantedLevel; - } -} - -uint16 *pExtraArrayIndices; - -void -CCullZones::CompressIndicesArray() -{ - uint16 set[3]; - - // These are used to hold the compressed groups in sets of 3 - int numExtraIndices = 0; - pExtraArrayIndices = new uint16[NUMTEMPINDICES]; - - for(int numOccurrences = 6; numOccurrences > 1; numOccurrences--){ - if(NumCullZones == 0) - break; - -//printf("checking occurrences %d\n", numOccurrences); - int attempt = 0; - while(attempt < 10000){ - for(;;){ - attempt++; - - int zone = CGeneral::GetRandomNumber() % NumCullZones; - int group = CGeneral::GetRandomNumber() % 3; - if(!PickRandomSetForGroup(zone, group, set)) - break; - if(!DoWeHaveMoreThanXOccurencesOfSet(numOccurrences, set)) - break; - - // add this set - attempt = 1; - int setId = numExtraIndices + NUMUNCOMPRESSED; - pExtraArrayIndices[numExtraIndices++] = set[0]; - pExtraArrayIndices[numExtraIndices++] = set[1]; - pExtraArrayIndices[numExtraIndices++] = set[2]; - ReplaceSetForAllGroups(set, setId); - } - } - } - - TidyUpAndMergeLists(pExtraArrayIndices, numExtraIndices); - - delete[] pExtraArrayIndices; -} - -// Get three random indices for this group of a zone -bool -CCullZones::PickRandomSetForGroup(int32 zone, int32 group, uint16 *set) -{ - int32 start; - int32 size; - - aZones[zone].GetGroupStartAndSize(group, start, size); - if(size <= 0) - return false; - - int numIndices = 0; - for(int i = 0; i < size; i++) - if(pTempArrayIndices[start + i] != 0xFFFF) - numIndices++; - if(numIndices < 3) - return false; - - int first = CGeneral::GetRandomNumber() % (numIndices-2); - - numIndices = 0; - int n = 0; - for(int i = 0; i < size; i++) - if(pTempArrayIndices[start + i] != 0xFFFF){ - if(n++ < first) continue; - - set[numIndices++] = pTempArrayIndices[start + i]; - if(numIndices == 3) - break; - } - return true; -} - -bool -CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set) -{ - int32 curCount; - int32 start; - int32 size; - - curCount = 0; - for (int i = 0; i < NumCullZones; i++) { - for (int group = 0; group < 3; group++) { - aZones[i].GetGroupStartAndSize(group, start, size); - if(size <= 0) continue; - - // check if the set is a subset of the group - int n = 0; - for (int j = 0; j < size; j++) { - for (int k = 0; k < 3; k++) { - if (pTempArrayIndices[start+j] == set[k]) - n++; - } - } - // yes it is - if(n == 3){ - curCount++; - // check if we have seen this set often enough - if(curCount >= count) - return true; - } - } - } - return false; -} - -void -CCullZones::ReplaceSetForAllGroups(uint16 *set, uint16 setid) -{ - int32 start; - int32 size; - - for(int i = 0; i < NumCullZones; i++) - for(int group = 0; group < 3; group++){ - aZones[i].GetGroupStartAndSize(group, start, size); - if(size <= 0) continue; - - // check if the set is a subset of the group - int n = 0; - for(int j = 0; j < size; j++){ - for(int k = 0; k < 3; k++){ - if(pTempArrayIndices[start+j] == set[k]) - n++; - } - } - - // yes it is, so replace it - if(n == 3){ - bool insertedSet = false; - for(int j = 0; j < size; j++){ - for(int k = 0; k < 3; k++){ - // replace first element by set, invalidate others - if(pTempArrayIndices[start+j] == set[k]){ - if(!insertedSet) - pTempArrayIndices[start+j] = setid; - else - pTempArrayIndices[start+j] = 0xFFFF; - insertedSet = true; - } - } - } - } - } -} - -void -CCullZones::TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices) -{ - int numTempIndices = 0; - for(int i = 0; i < TempEntityIndicesUsed; i++) - if(pTempArrayIndices[i] != 0xFFFF) - numTempIndices++; - - // Fix up zone ranges such that there are no holes - for(int i = 0; i < NumCullZones; i++){ - int j; - int start = 0; - for(j = 0; j < aZones[i].m_indexStart; j++) - if(pTempArrayIndices[j] != 0xFFFF) - start++; - - aZones[i].m_indexStart = start; - aZones[i].m_numBuildings = 0; - aZones[i].m_numTreadablesPlus10m = 0; - aZones[i].m_numTreadables = 0; - - for(int k = 0; k < aZones[i].m_groupIndexCount[0]; k++) - if(pTempArrayIndices[j++] != 0xFFFF) - aZones[i].m_numBuildings++; - for(int k = 0; k < aZones[i].m_groupIndexCount[1]; k++) - if(pTempArrayIndices[j++] != 0xFFFF) - aZones[i].m_numTreadablesPlus10m++; - for(int k = 0; k < aZones[i].m_groupIndexCount[2]; k++) - if(pTempArrayIndices[j++] != 0xFFFF) - aZones[i].m_numTreadables++; - } - - // Now copy the actually used indices - EntityIndicesUsed = 0; - for(int i = 0; i < TempEntityIndicesUsed; i++) - if(pTempArrayIndices[i] != 0xFFFF){ - assert(EntityIndicesUsed < NUMZONEINDICES); - if(pTempArrayIndices[i] < NUMUNCOMPRESSED) - aIndices[EntityIndicesUsed++] = pTempArrayIndices[i]; - else - aIndices[EntityIndicesUsed++] = pTempArrayIndices[i] + numTempIndices; - } - for(int i = 0; i < numExtraIndices; i++) - if(extraIndices[i] != 0xFFFF){ - assert(EntityIndicesUsed < NUMZONEINDICES); - if(extraIndices[i] < NUMUNCOMPRESSED) - aIndices[EntityIndicesUsed++] = extraIndices[i]; - else - aIndices[EntityIndicesUsed++] = extraIndices[i] + numTempIndices; - } -} - - - -void -CCullZone::DoStuffLeavingZone(void) -{ - int i; - - for(i = 0; i < m_numBuildings; i++) - DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]); - for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables ; i++) - DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[m_indexStart + i]); -} - -void -CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i) -{ - int16 bb; - int j; - - - if(i < NUMUNCOMPRESSED){ - CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false; - bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; - }else{ - i -= NUMUNCOMPRESSED; - for(j = 0; j < 3; j++) - DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i) -{ - int16 bb; - int j; - - if(i < NUMUNCOMPRESSED){ - CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false; - CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false; - bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; - }else{ - i -= NUMUNCOMPRESSED; - for(j = 0; j < 3; j++) - DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffEnteringZone(void) -{ - int i; - - for(i = 0; i < m_numBuildings; i++) - DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]); - for(; i < m_numBuildings + m_numTreadablesPlus10m; i++) - DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[m_indexStart + i]); - for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables; i++) - DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[m_indexStart + i]); -} - -void -CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i) -{ - int16 bb; - int j; - - if(i < NUMUNCOMPRESSED){ - CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true; - bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; - }else{ - i -= NUMUNCOMPRESSED; - for(j = 0; j < 3; j++) - DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i) -{ - int16 bb; - int j; - - if(i < NUMUNCOMPRESSED){ - CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true; - CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true; - bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; - }else{ - i -= NUMUNCOMPRESSED; - for(j = 0; j < 3; j++) - DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i) -{ - int16 bb; - int j; - - if(i < NUMUNCOMPRESSED){ - CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true; - bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; - }else{ - i -= NUMUNCOMPRESSED; - for(j = 0; j < 3; j++) - DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[i+j]); - } -} - -float -CCullZone::CalcDistToCullZoneSquared(float x, float y) -{ - float rx, ry; - - if (x < minx) rx = sq(x - minx); - else if (x > maxx) rx = sq(x - maxx); - else rx = 0.0f; - - if (y < miny) ry = sq(y - miny); - else if (y > maxy) ry = sq(y - maxy); - else ry = 0.0f; - - return rx + ry; -} - -bool -CCullZone::TestLine(CVector vec1, CVector vec2) -{ - CColPoint colPoint; - CEntity *entity; - - if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false)) - return true; - if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false)) - return true; - return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false); -} - -bool -CCullZone::DoThoroughLineTest(CVector start, CVector end, CEntity *testEntity) -{ - CColPoint colPoint; - CEntity *entity; - - if(CWorld::ProcessLineOfSight(start, end, colPoint, entity, true, false, false, false, false, true, false) && - testEntity != entity) - return false; - - CVector side; -#ifdef FIX_BUGS - if(start.x != end.x || start.y != end.y) -#else - if(start.x != end.x && start.y != end.y) -#endif - side = CVector(0.0f, 0.0f, 1.0f); - else - side = CVector(1.0f, 0.0f, 0.0f); - CVector up = CrossProduct(side, end - start); - side = CrossProduct(up, end - start); - side.Normalise(); - up.Normalise(); - side *= 0.1f; - up *= 0.1f; - - if(CWorld::ProcessLineOfSight(start+side, end+side, colPoint, entity, true, false, false, false, false, true, false) && - testEntity != entity) - return false; - if(CWorld::ProcessLineOfSight(start-side, end-side, colPoint, entity, true, false, false, false, false, true, false) && - testEntity != entity) - return false; - if(CWorld::ProcessLineOfSight(start+up, end+up, colPoint, entity, true, false, false, false, false, true, false) && - testEntity != entity) - return false; - if(CWorld::ProcessLineOfSight(start-up, end-up, colPoint, entity, true, false, false, false, false, true, false) && - testEntity != entity) - return false; - return true; -} - -bool -CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel) -{ - const CVector &pos = entity->GetPosition(); - - CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex()); - float distToZone = CalcDistToCullZone(pos.x, pos.y); - float lodDist; - if (minfo->m_noFade) - lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE; - else - lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE + FADE_DISTANCE; - - if (lodDist > distToZone) return true; - if (!checkLevel) return false; - CVector tempPos(minx, miny, minz); - return CTheZones::GetLevelFromPosition(&pos) == CTheZones::GetLevelFromPosition(&tempPos); -} - -bool -CCullZone::PointFallsWithinZone(CVector pos, float radius) -{ - if(minx - radius > pos.x || - maxx + radius < pos.x || - miny - radius > pos.y || - maxy + radius < pos.y || - minz - radius > pos.z || - maxz + radius < pos.z) - return false; - return true; -} - - -CVector ExtraFudgePointsCoors[] = { - CVector(978.0f, -394.0f, 18.0f), - CVector(1189.7f, -414.6f, 27.0f), - CVector(978.8f, -391.0f, 19.0f), - CVector(1199.0f, -502.3f, 28.0f), - CVector(1037.0f, -391.9f, 18.4f), - CVector(1140.0f, -608.7f, 16.0f), - CVector(1051.0f, -26.0f, 11.0f), - CVector(951.5f, -345.1f, 12.0f), - CVector(958.2f, -394.6f, 16.0f), - CVector(1036.5f, -390.0f, 15.2f), - CVector(960.6f, -390.5f, 20.9f), - CVector(1061.0f, -640.6f, 16.3f), - CVector(1034.5f, -388.96f, 14.78f), - CVector(1038.4f, -13.98f, 12.2f), - CVector(1047.2f, -16.7f, 10.6f), - CVector(1257.9f, -333.3f, 40.0f), - CVector(885.6f, -424.9f, 17.0f), - CVector(1127.5f, -795.8f, 17.7f), - CVector(1133.0f, -716.0f, 19.0f), - CVector(1125.0f, -694.0f, 18.5f), - CVector(1125.0f, -670.0f, 16.3f), - CVector(1051.6f, 36.3f, 17.9f), - CVector(1054.6f, -11.4f, 15.0f), - CVector(1058.9f, -278.0f, 15.0f), - CVector(1059.4f, -261.0f, 10.9f), - CVector(1051.5f, -638.5f, 16.5f), - CVector(1058.2f, -643.4f, 15.5f), - CVector(1058.2f, -643.4f, 18.0f), - CVector(826.0f, -260.0f, 7.0f), - CVector(826.0f, -260.0f, 11.0f), - CVector(833.0f, -603.6f, 16.4f), - CVector(833.0f, -603.6f, 20.0f), - CVector(1002.0f, -318.5f, 10.5f), - CVector(998.0f, -318.0f, 9.8f), - CVector(1127.0f, -183.0f, 18.1f), - CVector(1123.0f, -331.5f, 23.8f), - CVector(1123.8f, -429.0f, 24.0f), - CVector(1197.0f, -30.0f, 13.7f), - CVector(1117.5f, -230.0f, 17.3f), - CVector(1117.5f, -230.0f, 20.0f), - CVector(1120.0f, -281.6f, 21.5f), - CVector(1120.0f, -281.6f, 24.0f), - CVector(1084.5f, -1022.7f, 17.0f), - CVector(1071.5f, 5.4f, 4.6f), - CVector(1177.2f, -215.7f, 27.6f), - CVector(841.6f, -460.0f, 19.7f), - CVector(874.8f, -456.6f, 16.6f), - CVector(918.3f, -451.8f, 17.8f), - CVector(844.0f, -495.7f, 16.7f), - CVector(842.0f, -493.4f, 21.0f), - CVector(1433.5f, -774.4f, 16.9f), - CVector(1051.0f, -205.0f, 7.5f), - CVector(885.5f, -425.6f, 15.6f), - CVector(182.6f, -470.4f, 27.8f), - CVector(132.5f, -930.2f, 29.0f), - CVector(124.7f, -904.0f, 28.0f), - CVector(-50.0f, -686.0f, 22.0f), - CVector(-49.1f, -694.5f, 22.5f), - CVector(1063.8f, -404.45f, 16.2f), - CVector(1062.2f, -405.5f, 17.0f) -}; -int32 NumTestPoints; -int32 aTestPointsX[100]; -int32 aTestPointsY[100]; -int32 aTestPointsZ[100]; -CVector aTestPoints[100]; -int32 ElementsX, ElementsY, ElementsZ; -float StepX, StepY, StepZ; -int32 Memsize; -uint8 *pMem; -#define MEM(x, y, z) pMem[((x)*ElementsY + (y))*ElementsZ + (z)] -#define FLAG_FREE 1 -#define FLAG_PROCESSED 2 - -int32 MinValX, MaxValX; -int32 MinValY, MaxValY; -int32 MinValZ, MaxValZ; -int32 Point1, Point2; -int32 NewPointX, NewPointY, NewPointZ; - - -void -CCullZone::FindTestPoints() -{ - static int CZNumber; - - NumTestPoints = 0; - ElementsX = (maxx-minx) < 1.0f ? 2 : (maxx-minx)+1.0f; - ElementsY = (maxy-miny) < 1.0f ? 2 : (maxy-miny)+1.0f; - ElementsZ = (maxz-minz) < 1.0f ? 2 : (maxz-minz)+1.0f; - if(ElementsX > 32) ElementsX = 32; - if(ElementsY > 32) ElementsY = 32; - if(ElementsZ > 32) ElementsZ = 32; - Memsize = ElementsX * ElementsY * ElementsZ; - StepX = (maxx-minx)/(ElementsX-1); - StepY = (maxy-miny)/(ElementsY-1); - StepZ = (maxz-minz)/(ElementsZ-1); - - pMem = new uint8[Memsize]; - memset(pMem, 0, Memsize); - - // indices of center - int x = ElementsX * (position.x-minx)/(maxx-minx); - x = Clamp(x, 0, ElementsX-1); - int y = ElementsY * (position.y-miny)/(maxy-miny); - y = Clamp(y, 0, ElementsY-1); - int z = ElementsZ * (position.z-minz)/(maxz-minz); - z = Clamp(z, 0, ElementsZ-1); - - // Mark which test points inside the zone are not occupied by buildings. - // To do this, mark the start point as free and do a food fill. - - // NB: we just assume the start position is free here! - MEM(x, y, z) |= FLAG_FREE; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - NumTestPoints++; - - bool notDoneYet; - do{ - notDoneYet = false; - for(x = 0; x < ElementsX; x++){ - for(y = 0; y < ElementsY; y++){ - for(z = 0; z < ElementsZ; z++){ - if(!(MEM(x, y, z) & FLAG_FREE) || MEM(x, y, z) & FLAG_PROCESSED) - continue; - - float pX = x*StepX + minx; - float pY = y*StepY + miny; - float pZ = z*StepZ + minz; - - if(x > 0 && !(MEM(x-1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) && - !TestLine(CVector(pX, pY, pZ), CVector(pX-StepX, pY, pZ))) - MEM(x-1, y, z) |= FLAG_FREE; - if(x < ElementsX-1 && !(MEM(x+1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) && - !TestLine(CVector(pX, pY, pZ), CVector(pX+StepX, pY, pZ))) - MEM(x+1, y, z) |= FLAG_FREE; - - if(y > 0 && !(MEM(x, y-1, z) & (FLAG_FREE | FLAG_PROCESSED)) && - !TestLine(CVector(pX, pY, pZ), CVector(pX, pY-StepY, pZ))) - MEM(x, y-1, z) |= FLAG_FREE; - if(y < ElementsY-1 && !(MEM(x, y+1, z) & (FLAG_FREE | FLAG_PROCESSED)) && - !TestLine(CVector(pX, pY, pZ), CVector(pX, pY+StepY, pZ))) - MEM(x, y+1, z) |= FLAG_FREE; - - if(z > 0 && !(MEM(x, y, z-1) & (FLAG_FREE | FLAG_PROCESSED)) && - !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ-StepZ))) - MEM(x, y, z-1) |= FLAG_FREE; - if(z < ElementsZ-1 && !(MEM(x, y, z+1) & (FLAG_FREE | FLAG_PROCESSED)) && - !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ+StepZ))) - MEM(x, y, z+1) |= FLAG_FREE; - - notDoneYet = true; - MEM(x, y, z) |= FLAG_PROCESSED; - } - } - } - }while(notDoneYet); - - bool done; - - // Find bound planes of free space - - // increase x, bounds in y and z - x = 0; - do{ - done = false; - int minA = 10000; - int minB = 10000; - int maxA = -10000; - int maxB = -10000; - for(y = 0; y < ElementsY; y++) - for(z = 0; z < ElementsZ; z++) - if(MEM(x, y, z) & FLAG_FREE){ - if(y + z < minA){ - minA = y + z; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - } - if(y + z > maxA){ - maxA = y + z; - aTestPointsX[NumTestPoints+1] = x; - aTestPointsY[NumTestPoints+1] = y; - aTestPointsZ[NumTestPoints+1] = z; - } - if(y - z < minB){ - minB = y - z; - aTestPointsX[NumTestPoints+2] = x; - aTestPointsY[NumTestPoints+2] = y; - aTestPointsZ[NumTestPoints+2] = z; - } - if(y - z > maxB){ - maxB = y - z; - aTestPointsX[NumTestPoints+3] = x; - aTestPointsY[NumTestPoints+3] = y; - aTestPointsZ[NumTestPoints+3] = z; - } - done = true; - } - x++; - }while(!done); - NumTestPoints += 4; - - // decrease x, bounds in y and z - x = ElementsX-1; - do{ - done = false; - int minA = 10000; - int minB = 10000; - int maxA = -10000; - int maxB = -10000; - for(y = 0; y < ElementsY; y++) - for(z = 0; z < ElementsZ; z++) - if(MEM(x, y, z) & FLAG_FREE){ - if(y + z < minA){ - minA = y + z; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - } - if(y + z > maxA){ - maxA = y + z; - aTestPointsX[NumTestPoints+1] = x; - aTestPointsY[NumTestPoints+1] = y; - aTestPointsZ[NumTestPoints+1] = z; - } - if(y - z < minB){ - minB = y - z; - aTestPointsX[NumTestPoints+2] = x; - aTestPointsY[NumTestPoints+2] = y; - aTestPointsZ[NumTestPoints+2] = z; - } - if(y - z > maxB){ - maxB = y - z; - aTestPointsX[NumTestPoints+3] = x; - aTestPointsY[NumTestPoints+3] = y; - aTestPointsZ[NumTestPoints+3] = z; - } - done = true; - } - x--; - }while(!done); - NumTestPoints += 4; - - // increase y, bounds in x and z - y = 0; - do{ - done = false; - int minA = 10000; - int minB = 10000; - int maxA = -10000; - int maxB = -10000; - for(x = 0; x < ElementsX; x++) - for(z = 0; z < ElementsZ; z++) - if(MEM(x, y, z) & FLAG_FREE){ - if(x + z < minA){ - minA = x + z; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - } - if(x + z > maxA){ - maxA = x + z; - aTestPointsX[NumTestPoints+1] = x; - aTestPointsY[NumTestPoints+1] = y; - aTestPointsZ[NumTestPoints+1] = z; - } - if(x - z < minB){ - minB = x - z; - aTestPointsX[NumTestPoints+2] = x; - aTestPointsY[NumTestPoints+2] = y; - aTestPointsZ[NumTestPoints+2] = z; - } - if(x - z > maxB){ - maxB = x - z; - aTestPointsX[NumTestPoints+3] = x; - aTestPointsY[NumTestPoints+3] = y; - aTestPointsZ[NumTestPoints+3] = z; - } - done = true; - } - y++; - }while(!done); - NumTestPoints += 4; - - // decrease y, bounds in x and z - y = ElementsY-1; - do{ - done = false; - int minA = 10000; - int minB = 10000; - int maxA = -10000; - int maxB = -10000; - for(x = 0; x < ElementsX; x++) - for(z = 0; z < ElementsZ; z++) - if(MEM(x, y, z) & FLAG_FREE){ - if(x + z < minA){ - minA = x + z; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - } - if(x + z > maxA){ - maxA = x + z; - aTestPointsX[NumTestPoints+1] = x; - aTestPointsY[NumTestPoints+1] = y; - aTestPointsZ[NumTestPoints+1] = z; - } - if(x - z < minB){ - minB = x - z; - aTestPointsX[NumTestPoints+2] = x; - aTestPointsY[NumTestPoints+2] = y; - aTestPointsZ[NumTestPoints+2] = z; - } - if(x - z > maxB){ - maxB = x - z; - aTestPointsX[NumTestPoints+3] = x; - aTestPointsY[NumTestPoints+3] = y; - aTestPointsZ[NumTestPoints+3] = z; - } - done = true; - } - y--; - }while(!done); - NumTestPoints += 4; - - // increase z, bounds in x and y - z = 0; - do{ - done = false; - int minA = 10000; - int minB = 10000; - int maxA = -10000; - int maxB = -10000; - for(x = 0; x < ElementsX; x++) - for(y = 0; y < ElementsY; y++) - if(MEM(x, y, z) & FLAG_FREE){ - if(x + y < minA){ - minA = x + y; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - } - if(x + y > maxA){ - maxA = x + y; - aTestPointsX[NumTestPoints+1] = x; - aTestPointsY[NumTestPoints+1] = y; - aTestPointsZ[NumTestPoints+1] = z; - } - if(x - y < minB){ - minB = x - y; - aTestPointsX[NumTestPoints+2] = x; - aTestPointsY[NumTestPoints+2] = y; - aTestPointsZ[NumTestPoints+2] = z; - } - if(x - y > maxB){ - maxB = x - y; - aTestPointsX[NumTestPoints+3] = x; - aTestPointsY[NumTestPoints+3] = y; - aTestPointsZ[NumTestPoints+3] = z; - } - done = true; - } - z++; - }while(!done); - NumTestPoints += 4; - - // decrease z, bounds in x and y - z = ElementsZ-1; - do{ - done = false; - int minA = 10000; - int minB = 10000; - int maxA = -10000; - int maxB = -10000; - for(x = 0; x < ElementsX; x++) - for(y = 0; y < ElementsY; y++) - if(MEM(x, y, z) & FLAG_FREE){ - if(x + y < minA){ - minA = x + y; - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - } - if(x + y > maxA){ - maxA = x + y; - aTestPointsX[NumTestPoints+1] = x; - aTestPointsY[NumTestPoints+1] = y; - aTestPointsZ[NumTestPoints+1] = z; - } - if(x - y < minB){ - minB = x - y; - aTestPointsX[NumTestPoints+2] = x; - aTestPointsY[NumTestPoints+2] = y; - aTestPointsZ[NumTestPoints+2] = z; - } - if(x - y > maxB){ - maxB = x - y; - aTestPointsX[NumTestPoints+3] = x; - aTestPointsY[NumTestPoints+3] = y; - aTestPointsZ[NumTestPoints+3] = z; - } - done = true; - } - z--; - }while(!done); - NumTestPoints += 4; - - // divide the axis aligned bounding planes into 4 and place some test points - - // x = 0 plane - MinValY = 999999; - MinValZ = 999999; - MaxValY = 0; - MaxValZ = 0; - for(y = 0; y < ElementsY; y++) - for(z = 0; z < ElementsZ; z++) - if(MEM(0, y, z) & FLAG_FREE){ - if(y < MinValY) MinValY = y; - if(z < MinValZ) MinValZ = z; - if(y > MaxValY) MaxValY = y; - if(z > MaxValZ) MaxValZ = z; - } - // pick 4 points in the found bounds and add new test points - if(MaxValY != 0 && MaxValZ != 0) - for(Point1 = 0; Point1 < 2; Point1++) - for(Point2 = 0; Point2 < 2; Point2++){ - NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; - NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; - if(MEM(0, NewPointY, NewPointZ) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = 0; - aTestPointsY[NumTestPoints] = NewPointY; - aTestPointsZ[NumTestPoints] = NewPointZ; - NumTestPoints++; - } - } - - // x = ElementsX-1 plane - MinValY = 999999; - MinValZ = 999999; - MaxValY = 0; - MaxValZ = 0; - for(y = 0; y < ElementsY; y++) - for(z = 0; z < ElementsZ; z++) - if(MEM(ElementsX-1, y, z) & FLAG_FREE){ - if(y < MinValY) MinValY = y; - if(z < MinValZ) MinValZ = z; - if(y > MaxValY) MaxValY = y; - if(z > MaxValZ) MaxValZ = z; - } - // pick 4 points in the found bounds and add new test points - if(MaxValY != 0 && MaxValZ != 0) - for(Point1 = 0; Point1 < 2; Point1++) - for(Point2 = 0; Point2 < 2; Point2++){ - NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; - NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; - if(MEM(ElementsX-1, NewPointY, NewPointZ) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = ElementsX-1; - aTestPointsY[NumTestPoints] = NewPointY; - aTestPointsZ[NumTestPoints] = NewPointZ; - NumTestPoints++; - } - } - - // y = 0 plane - MinValX = 999999; - MinValZ = 999999; - MaxValX = 0; - MaxValZ = 0; - for(x = 0; x < ElementsX; x++) - for(z = 0; z < ElementsZ; z++) - if(MEM(x, 0, z) & FLAG_FREE){ - if(x < MinValX) MinValX = x; - if(z < MinValZ) MinValZ = z; - if(x > MaxValX) MaxValX = x; - if(z > MaxValZ) MaxValZ = z; - } - // pick 4 points in the found bounds and add new test points - if(MaxValX != 0 && MaxValZ != 0) - for(Point1 = 0; Point1 < 2; Point1++) - for(Point2 = 0; Point2 < 2; Point2++){ - NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; - NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; - if(MEM(NewPointX, 0, NewPointZ) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = NewPointX; - aTestPointsY[NumTestPoints] = 0; - aTestPointsZ[NumTestPoints] = NewPointZ; - NumTestPoints++; - } - } - - // y = ElementsY-1 plane - MinValX = 999999; - MinValZ = 999999; - MaxValX = 0; - MaxValZ = 0; - for(x = 0; x < ElementsX; x++) - for(z = 0; z < ElementsZ; z++) - if(MEM(x, ElementsY-1, z) & FLAG_FREE){ - if(x < MinValX) MinValX = x; - if(z < MinValZ) MinValZ = z; - if(x > MaxValX) MaxValX = x; - if(z > MaxValZ) MaxValZ = z; - } - // pick 4 points in the found bounds and add new test points - if(MaxValX != 0 && MaxValZ != 0) - for(Point1 = 0; Point1 < 2; Point1++) - for(Point2 = 0; Point2 < 2; Point2++){ - NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; - NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ; - if(MEM(NewPointX, ElementsY-1, NewPointZ) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = NewPointX; - aTestPointsY[NumTestPoints] = ElementsY-1; - aTestPointsZ[NumTestPoints] = NewPointZ; - NumTestPoints++; - } - } - - // z = 0 plane - MinValX = 999999; - MinValY = 999999; - MaxValX = 0; - MaxValY = 0; - for(x = 0; x < ElementsX; x++) - for(y = 0; y < ElementsY; y++) - if(MEM(x, y, 0) & FLAG_FREE){ - if(x < MinValX) MinValX = x; - if(y < MinValY) MinValY = y; - if(x > MaxValX) MaxValX = x; - if(y > MaxValY) MaxValY = y; - } - // pick 4 points in the found bounds and add new test points - if(MaxValX != 0 && MaxValY != 0) - for(Point1 = 0; Point1 < 2; Point1++) - for(Point2 = 0; Point2 < 2; Point2++){ - NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; - NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; - if(MEM(NewPointX, NewPointY, 0) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = NewPointX; - aTestPointsY[NumTestPoints] = NewPointY; - aTestPointsZ[NumTestPoints] = 0; - NumTestPoints++; - } - } - - // z = ElementsZ-1 plane - MinValX = 999999; - MinValY = 999999; - MaxValX = 0; - MaxValY = 0; - for(x = 0; x < ElementsX; x++) - for(y = 0; y < ElementsY; y++) - if(MEM(x, y, ElementsZ-1) & FLAG_FREE){ - if(x < MinValX) MinValX = x; - if(y < MinValY) MinValY = y; - if(x > MaxValX) MaxValX = x; - if(y > MaxValY) MaxValY = y; - } - // pick 4 points in the found bounds and add new test points - if(MaxValX != 0 && MaxValY != 0) - for(Point1 = 0; Point1 < 2; Point1++) - for(Point2 = 0; Point2 < 2; Point2++){ - NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX; - NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY; - if(MEM(NewPointX, NewPointY, ElementsZ-1) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = NewPointX; - aTestPointsY[NumTestPoints] = NewPointY; - aTestPointsZ[NumTestPoints] = ElementsZ-1; - NumTestPoints++; - } - } - - // add some hardcoded test points - for(int i = 0; i < ARRAY_SIZE(ExtraFudgePointsCoors); i++) - if(PointFallsWithinZone(ExtraFudgePointsCoors[i], 0.0f)){ - x = ElementsX * (ExtraFudgePointsCoors[i].x-minx)/(maxx-minx); - y = ElementsY * (ExtraFudgePointsCoors[i].y-miny)/(maxy-miny); - z = ElementsZ * (ExtraFudgePointsCoors[i].z-minz)/(maxz-minz); - if(MEM(x, y, z) & FLAG_FREE){ - aTestPointsX[NumTestPoints] = x; - aTestPointsY[NumTestPoints] = y; - aTestPointsZ[NumTestPoints] = z; - NumTestPoints++; - } - } - - // remove duplicate points - for(int i = 0; i < NumTestPoints; i++) - for(int j = i+1; j < NumTestPoints; j++) - if(aTestPointsX[j] == aTestPointsX[i] && - aTestPointsY[j] == aTestPointsY[i] && - aTestPointsZ[j] == aTestPointsZ[i]){ - // get rid of [j] - for(int k = j; k < NumTestPoints-1; k++){ - aTestPointsX[k] = aTestPointsX[k+1]; - aTestPointsY[k] = aTestPointsY[k+1]; - aTestPointsZ[k] = aTestPointsZ[k+1]; - } - NumTestPoints--; - } - - // convert points to floating point - for(int i = 0; i < NumTestPoints; i++){ - aTestPoints[i].x = aTestPointsX[i]*StepX + minx; - aTestPoints[i].y = aTestPointsY[i]*StepY + miny; - aTestPoints[i].z = aTestPointsZ[i]*StepZ + minz; - } - - CZNumber++; - - delete[] pMem; - pMem = nil; -} - -bool -CCullZone::TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity) -{ - CColModel *colmodel = entity->GetColModel(); - float boundMaxX = colmodel->boundingBox.max.x; - float boundMaxY = colmodel->boundingBox.max.y; - float boundMaxZ = colmodel->boundingBox.max.z; - float boundMinX = colmodel->boundingBox.min.x; - float boundMinY = colmodel->boundingBox.min.y; - float boundMinZ = colmodel->boundingBox.min.z; - if(LODentity){ - colmodel = LODentity->GetColModel(); - boundMaxX = Max(boundMaxX, colmodel->boundingBox.max.x); - boundMaxY = Max(boundMaxY, colmodel->boundingBox.max.y); - boundMaxZ = Max(boundMaxZ, colmodel->boundingBox.max.z); - boundMinX = Min(boundMinX, colmodel->boundingBox.min.x); - boundMinY = Min(boundMinY, colmodel->boundingBox.min.y); - boundMinZ = Min(boundMinZ, colmodel->boundingBox.min.z); - } - - if(boundMaxZ-boundMinZ + extraDist < 0.5f) - boundMaxZ = boundMinZ + 0.5f; - else - boundMaxZ += extraDist; - - CVector vecMin = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMinZ); - CVector vecMaxX = entity->GetMatrix() * CVector(boundMaxX, boundMinY, boundMinZ); - CVector vecMaxY = entity->GetMatrix() * CVector(boundMinX, boundMaxY, boundMinZ); - CVector vecMaxZ = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMaxZ); - CVector dirx = vecMaxX - vecMin; - CVector diry = vecMaxY - vecMin; - CVector dirz = vecMaxZ - vecMin; - - // If building intersects zone at all, it's visible - int x, y, z; - for(x = 0; x < 9; x++){ - CVector posX = vecMin + x/8.0f*dirx; - for(y = 0; y < 9; y++){ - CVector posY = posX + y/8.0f*diry; - for(z = 0; z < 9; z++){ - CVector posZ = posY + z/8.0f*dirz; - if(PointFallsWithinZone(posZ, 2.0f)) - return true; - } - } - } - - float distToZone = CalcDistToCullZone(entity->GetPosition().x, entity->GetPosition().y)/15.0f; - distToZone = Max(distToZone, 7.0f); - int numX = (boundMaxX - boundMinX)/distToZone + 2.0f; - int numY = (boundMaxY - boundMinY)/distToZone + 2.0f; - int numZ = (boundMaxZ - boundMinZ)/distToZone + 2.0f; - - float stepX = 1.0f/(numX-1); - float stepY = 1.0f/(numY-1); - float stepZ = 1.0f/(numZ-1); - float midX = (boundMaxX + boundMinX)/2.0f; - float midY = (boundMaxY + boundMinY)/2.0f; - float midZ = (boundMaxZ + boundMinZ)/2.0f; - - // check both xy planes - for(int i = 0; i < NumTestPoints; i++){ - CVector testPoint = aTestPoints[i]; - CVector mid = entity->GetMatrix() * CVector(midX, midY, midZ); - mid.z += 0.1f; - if(DoThoroughLineTest(testPoint, mid, entity)) - return true; - - CVector ray = entity->GetPosition() - testPoint; - - float dotX = DotProduct(ray, dirx); - float dotY = DotProduct(ray, diry); - float dotZ = DotProduct(ray, dirz); - - for(x = 0; x < numX; x++){ - CVector pMinZ = vecMin + x*stepX*dirx; - CVector pMaxZ = vecMin + x*stepX*dirx + dirz; - for(y = 0; y < numY; y++) - if(dotZ > 0.0f){ - if(DoThoroughLineTest(testPoint, pMinZ + y*stepY*diry, entity)) - return true; - }else{ - if(DoThoroughLineTest(testPoint, pMaxZ + y*stepY*diry, entity)) - return true; - } - } - - for(x = 0; x < numX; x++){ - CVector pMinY = vecMin + x*stepX*dirx; - CVector pMaxY = vecMin + x*stepX*dirx + diry; - for(z = 1; z < numZ-1; z++) // edge cases already handled - if(dotY > 0.0f){ - if(DoThoroughLineTest(testPoint, pMinY + z*stepZ*dirz, entity)) - return true; - }else{ - if(DoThoroughLineTest(testPoint, pMaxY + z*stepZ*dirz, entity)) - return true; - } - } - - for(y = 1; y < numY-1; y++){ // edge cases already handled - CVector pMinX = vecMin + y*stepY*diry; - CVector pMaxX = vecMin + y*stepY*diry + dirx; - for(z = 1; z < numZ-1; z++) // edge cases already handled - if(dotX > 0.0f){ - if(DoThoroughLineTest(testPoint, pMinX + z*stepZ*dirz, entity)) - return true; - }else{ - if(DoThoroughLineTest(testPoint, pMaxX + z*stepZ*dirz, entity)) - return true; - } - } - } - - return false; + assert(NumAttributeZones < NUMATTRIBZONES); + attrib = &aAttributeZones[NumAttributeZones++]; + attrib->minx = minx; + attrib->maxx = maxx; + attrib->miny = miny; + attrib->maxy = maxy; + attrib->minz = minz; + attrib->maxz = maxz; + attrib->attributes = flag; + attrib->wantedLevel = wantedLevel; } diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h index 10742ffb..d7780caf 100644 --- a/src/core/ZoneCull.h +++ b/src/core/ZoneCull.h @@ -1,62 +1,5 @@ class CEntity; -class CCullZone -{ -public: - CVector position; - float minx; - float maxx; - float miny; - float maxy; - float minz; - float maxz; - - int32 m_indexStart; - int16 m_groupIndexCount[3]; // only useful during resolution stage - int16 m_numBuildings; - int16 m_numTreadablesPlus10m; - int16 m_numTreadables; - - void DoStuffLeavingZone(void); - static void DoStuffLeavingZone_OneBuilding(uint16 i); - static void DoStuffLeavingZone_OneTreadableBoth(uint16 i); - void DoStuffEnteringZone(void); - static void DoStuffEnteringZone_OneBuilding(uint16 i); - static void DoStuffEnteringZone_OneTreadablePlus10m(uint16 i); - static void DoStuffEnteringZone_OneTreadable(uint16 i); - - - static bool TestLine(CVector vec1, CVector vec2); - static bool DoThoroughLineTest(CVector vec1, CVector vec2, CEntity *testEntity); - float CalcDistToCullZoneSquared(float x, float y); - float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); }; - bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel); - bool PointFallsWithinZone(CVector pos, float radius); - bool TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity); - void FindTestPoints(); - - void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) { - switch (groupid) { - case 0: - default: - // buildings - start = m_indexStart; - size = m_groupIndexCount[0]; - break; - case 1: - // treadables + 10m - start = m_groupIndexCount[0] + m_indexStart; - size = m_groupIndexCount[1]; - break; - case 2: - // treadables - start = m_groupIndexCount[0] + m_groupIndexCount[1] + m_indexStart; - size = m_groupIndexCount[2]; - break; - } - } -}; - enum eZoneAttribs { ATTRZONE_CAMCLOSEIN = 1, @@ -67,16 +10,19 @@ enum eZoneAttribs ATTRZONE_NOTCULLZONE = 0x20, ATTRZONE_DOINEEDCOLLISION = 0x40, ATTRZONE_SUBWAYVISIBLE = 0x80, + ATTRZONE_POLICEABANDONCARS = 0x100, + ATTRZONE_ROOMFORAUDIO = 0x200, + ATTRZONE_WATERFUDGE = 0x400, }; struct CAttributeZone { - float minx; - float maxx; - float miny; - float maxy; - float minz; - float maxz; + int16 minx; + int16 maxx; + int16 miny; + int16 maxy; + int16 minz; + int16 maxz; int16 attributes; int16 wantedLevel; }; @@ -84,27 +30,19 @@ struct CAttributeZone class CCullZones { public: - static int32 NumCullZones; - static CCullZone aZones[NUMCULLZONES]; static int32 NumAttributeZones; static CAttributeZone aAttributeZones[NUMATTRIBZONES]; - static uint16 aIndices[NUMZONEINDICES]; - static int16 aPointersToBigBuildingsForBuildings[NUMBUILDINGS]; - static int16 aPointersToBigBuildingsForTreadables[NUMTREADABLES]; static int32 CurrentWantedLevelDrop_Player; static int32 CurrentFlags_Camera; static int32 CurrentFlags_Player; - static int32 OldCullZone; - static int32 EntityIndicesUsed; static bool bCurrentSubwayIsInvisible; - static bool bCullZonesDisabled; + static bool bAtBeachForAudio; static void Init(void); - static void ResolveVisibilities(void); static void Update(void); + static void UpdateAtBeachForAudio(void); static void ForceCullZoneCoors(CVector coors); - static int32 FindCullZoneForCoors(CVector coors); static int32 FindAttributesForCoors(CVector coors, int32 *wantedLevel); static CAttributeZone *FindZoneWithStairsAttributeForPlayer(void); static void MarkSubwayAsInvisible(bool visible); @@ -120,18 +58,8 @@ public: static bool DoINeedToLoadCollision(void) { return (CurrentFlags_Player & ATTRZONE_DOINEEDCOLLISION) != 0; } static bool PlayerNoRain(void) { return (CurrentFlags_Player & ATTRZONE_NORAIN) != 0; } static bool CamNoRain(void) { return (CurrentFlags_Camera & ATTRZONE_NORAIN) != 0; } + static bool PoliceAbandonCars(void) { return (CurrentFlags_Camera & ATTRZONE_POLICEABANDONCARS) != 0; } + static bool InRoomForAudio(void) { return (CurrentFlags_Camera & ATTRZONE_ROOMFORAUDIO) != 0; } + static bool WaterFudge(void) { return (CurrentFlags_Camera & ATTRZONE_WATERFUDGE) != 0; } static int32 GetWantedLevelDrop(void) { return CurrentWantedLevelDrop_Player; } - - static void BuildListForBigBuildings(); - static void DoVisibilityTestCullZone(int zoneId, bool doIt); - static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set); - - static void CompressIndicesArray(); - static bool PickRandomSetForGroup(int32 zone, int32 group, uint16 *set); - static void ReplaceSetForAllGroups(uint16 *set, uint16 setid); - static void TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices); - - // debug - static bool LoadTempFile(void); - static void SaveTempFile(void); }; diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 82fbc047..93eca199 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -10,51 +10,22 @@ #include "Timer.h" #include "SaveBuf.h" -#ifdef COMPATIBLE_SAVES -#define ZONEARRAY_SAVE_SIZE 0xAF0 -#define MAPZONEARRAY_SAVE_SIZE 0x578 -#else -#define ZONEARRAY_SAVE_SIZE sizeof(ZoneArray) -#define MAPZONEARRAY_SAVE_SIZE sizeof(MapZoneArray) -#endif - eLevelName CTheZones::m_CurrLevel; -CZone *CTheZones::m_pPlayersZone; int16 CTheZones::FindIndex; uint16 CTheZones::NumberOfAudioZones; int16 CTheZones::AudioZoneArray[NUMAUDIOZONES]; uint16 CTheZones::TotalNumberOfMapZones; -uint16 CTheZones::TotalNumberOfZones; -CZone CTheZones::ZoneArray[NUMZONES]; +uint16 CTheZones::TotalNumberOfInfoZones; +uint16 CTheZones::TotalNumberOfNavigationZones; +CZone CTheZones::InfoZoneArray[NUMINFOZONES]; CZone CTheZones::MapZoneArray[NUMMAPZONES]; +CZone CTheZones::NavigationZoneArray[NUMNAVIGZONES]; uint16 CTheZones::TotalNumberOfZoneInfos; -CZoneInfo CTheZones::ZoneInfoArray[2*NUMZONES]; - -#define SWAPF(a, b) { float t; t = a; a = b; b = t; } +CZoneInfo CTheZones::ZoneInfoArray[2*NUMINFOZONES]; -inline bool IsNormalZone(int type) { return type == ZONE_DEFAULT || type == ZONE_NAVIG || type == ZONE_INFO; } -static void -CheckZoneInfo(CZoneInfo *info) -{ - assert(info->carThreshold[0] >= 0); - assert(info->carThreshold[0] <= info->carThreshold[1]); - assert(info->carThreshold[1] <= info->carThreshold[2]); - assert(info->carThreshold[2] <= info->carThreshold[3]); - assert(info->carThreshold[3] <= info->carThreshold[4]); - assert(info->carThreshold[4] <= info->carThreshold[5]); - assert(info->carThreshold[5] <= info->copThreshold); - assert(info->copThreshold <= info->gangThreshold[0]); - assert(info->gangThreshold[0] <= info->gangThreshold[1]); - assert(info->gangThreshold[1] <= info->gangThreshold[2]); - assert(info->gangThreshold[2] <= info->gangThreshold[3]); - assert(info->gangThreshold[3] <= info->gangThreshold[4]); - assert(info->gangThreshold[4] <= info->gangThreshold[5]); - assert(info->gangThreshold[5] <= info->gangThreshold[6]); - assert(info->gangThreshold[6] <= info->gangThreshold[7]); - assert(info->gangThreshold[7] <= info->gangThreshold[8]); -} +#define SWAPF(a, b) { float t; t = a; a = b; b = t; } wchar* CZone::GetTranslatedName(void) @@ -65,66 +36,89 @@ CZone::GetTranslatedName(void) void CTheZones::Init(void) { - int i; + int i, j; for(i = 0; i < NUMAUDIOZONES; i++) AudioZoneArray[i] = -1; NumberOfAudioZones = 0; - for(i = 0; i < NUMZONES; i++) - memset(&ZoneArray[i], 0, sizeof(CZone)); - - CZoneInfo *zonei; - int x = 1000/6; - for(i = 0; i < 2*NUMZONES; i++){ - zonei = &ZoneInfoArray[i]; - zonei->carDensity = 10; - zonei->carThreshold[0] = x; - zonei->carThreshold[1] = zonei->carThreshold[0] + x; - zonei->carThreshold[2] = zonei->carThreshold[1] + x; - zonei->carThreshold[3] = zonei->carThreshold[2] + x; - zonei->carThreshold[4] = zonei->carThreshold[3]; - zonei->carThreshold[5] = zonei->carThreshold[4]; - zonei->copThreshold = zonei->carThreshold[5] + x; - zonei->gangThreshold[0] = zonei->copThreshold; - zonei->gangThreshold[1] = zonei->gangThreshold[0]; - zonei->gangThreshold[2] = zonei->gangThreshold[1]; - zonei->gangThreshold[3] = zonei->gangThreshold[2]; - zonei->gangThreshold[4] = zonei->gangThreshold[3]; - zonei->gangThreshold[5] = zonei->gangThreshold[4]; - zonei->gangThreshold[6] = zonei->gangThreshold[5]; - zonei->gangThreshold[7] = zonei->gangThreshold[6]; - zonei->gangThreshold[8] = zonei->gangThreshold[7]; - CheckZoneInfo(zonei); + for(i = 0; i < NUMNAVIGZONES; i++) + memset(&NavigationZoneArray[i], 0, sizeof(CZone)); + + for(i = 0; i < NUMINFOZONES; i++) + memset(&InfoZoneArray[i], 0, sizeof(CZone)); + + int x = 1000/9; + for(i = 0; i < 2*NUMINFOZONES; i++){ + // Cars + + ZoneInfoArray[i].carDensity = 10; + ZoneInfoArray[i].carThreshold[0] = x; + ZoneInfoArray[i].carThreshold[1] = ZoneInfoArray[i].carThreshold[0] + x; + ZoneInfoArray[i].carThreshold[2] = ZoneInfoArray[i].carThreshold[1] + x; + ZoneInfoArray[i].carThreshold[3] = ZoneInfoArray[i].carThreshold[2] + x; + ZoneInfoArray[i].carThreshold[4] = ZoneInfoArray[i].carThreshold[3] + x; + ZoneInfoArray[i].carThreshold[5] = ZoneInfoArray[i].carThreshold[4] + x; + ZoneInfoArray[i].carThreshold[6] = ZoneInfoArray[i].carThreshold[5] + x; + ZoneInfoArray[i].carThreshold[7] = ZoneInfoArray[i].carThreshold[6] + x; + ZoneInfoArray[i].carThreshold[8] = 1000; + + ZoneInfoArray[i].boatThreshold[0] = 500; + ZoneInfoArray[i].boatThreshold[1] = 1000; + + // What's going on here? this looks more like density + ZoneInfoArray[i].copThreshold = 50; + for(j = 0; j < NUM_GANGS; j++) + ZoneInfoArray[i].gangThreshold[j] = ZoneInfoArray[i].copThreshold; + + // Peds + + ZoneInfoArray[i].pedDensity = 12; + + // What's going on here? this looks more like density + ZoneInfoArray[i].copPedThreshold = 50; + for(j = 0; j < NUM_GANGS; j++) + ZoneInfoArray[i].gangPedThreshold[j] = ZoneInfoArray[i].copPedThreshold; + + ZoneInfoArray[i].pedGroup = 0; } TotalNumberOfZoneInfos = 1; // why 1? - TotalNumberOfZones = 1; + TotalNumberOfNavigationZones = 1; + TotalNumberOfInfoZones = 1; + + strcpy(InfoZoneArray[0].name, "CITYINF"); + InfoZoneArray[0].minx = -2400.0f; + InfoZoneArray[0].miny = -2000.0f; + InfoZoneArray[0].minz = -500.0f; + InfoZoneArray[0].maxx = 1600.0f; + InfoZoneArray[0].maxy = 2000.0f; + InfoZoneArray[0].maxz = 500.0f; + InfoZoneArray[0].level = LEVEL_GENERIC; + InfoZoneArray[0].type = ZONE_INFO; + + strcpy(NavigationZoneArray[0].name, "VICE_C"); + NavigationZoneArray[0].minx = -2400.0f; + NavigationZoneArray[0].miny = -2000.0f; + NavigationZoneArray[0].minz = -500.0f; + NavigationZoneArray[0].maxx = 1600.0f; + NavigationZoneArray[0].maxy = 2000.0f; + NavigationZoneArray[0].maxz = 500.0f; + NavigationZoneArray[0].level = LEVEL_GENERIC; + NavigationZoneArray[0].type = ZONE_DEFAULT; m_CurrLevel = LEVEL_GENERIC; - m_pPlayersZone = &ZoneArray[0]; - - strcpy(ZoneArray[0].name, "CITYZON"); - ZoneArray[0].minx = -4000.0f; - ZoneArray[0].miny = -4000.0f; - ZoneArray[0].minz = -500.0f; - ZoneArray[0].maxx = 4000.0f; - ZoneArray[0].maxy = 4000.0f; - ZoneArray[0].maxz = 500.0f; - ZoneArray[0].level = LEVEL_GENERIC; for(i = 0; i < NUMMAPZONES; i++){ memset(&MapZoneArray[i], 0, sizeof(CZone)); MapZoneArray[i].type = ZONE_MAPZONE; } - TotalNumberOfMapZones = 1; - strcpy(MapZoneArray[0].name, "THEMAP"); - MapZoneArray[0].minx = -4000.0f; - MapZoneArray[0].miny = -4000.0f; + MapZoneArray[0].minx = -2400.0f; + MapZoneArray[0].miny = -2000.0f; MapZoneArray[0].minz = -500.0f; - MapZoneArray[0].maxx = 4000.0f; - MapZoneArray[0].maxy = 4000.0f; + MapZoneArray[0].maxx = 1600.0f; + MapZoneArray[0].maxy = 2000.0f; MapZoneArray[0].maxz = 500.0f; MapZoneArray[0].level = LEVEL_GENERIC; } @@ -138,7 +132,6 @@ CTheZones::Update(void) #endif CVector pos; pos = FindPlayerCoors(); - m_pPlayersZone = FindSmallestZonePosition(&pos); m_CurrLevel = GetLevelFromPosition(&pos); } @@ -148,8 +141,8 @@ CTheZones::CreateZone(char *name, eZoneType type, float maxx, float maxy, float maxz, eLevelName level) { + char tmpname[24]; char *p; - char tmpname[8]; if(minx > maxx) SWAPF(minx, maxx); if(miny > maxy) SWAPF(miny, maxy); @@ -158,62 +151,81 @@ CTheZones::CreateZone(char *name, eZoneType type, // make upper case for(p = name; *p; p++) if(islower(*p)) *p = toupper(*p); - // add zone strncpy(tmpname, name, 7); tmpname[7] = '\0'; - strcpy(ZoneArray[TotalNumberOfZones].name, tmpname); - ZoneArray[TotalNumberOfZones].type = type; - ZoneArray[TotalNumberOfZones].minx = minx; - ZoneArray[TotalNumberOfZones].miny = miny; - ZoneArray[TotalNumberOfZones].minz = minz; - ZoneArray[TotalNumberOfZones].maxx = maxx; - ZoneArray[TotalNumberOfZones].maxy = maxy; - ZoneArray[TotalNumberOfZones].maxz = maxz; - ZoneArray[TotalNumberOfZones].level = level; - if(IsNormalZone(type)){ - ZoneArray[TotalNumberOfZones].zoneinfoDay = TotalNumberOfZoneInfos++; - ZoneArray[TotalNumberOfZones].zoneinfoNight = TotalNumberOfZoneInfos++; - } - TotalNumberOfZones++; -} - -void -CTheZones::CreateMapZone(char *name, eZoneType type, - float minx, float miny, float minz, - float maxx, float maxy, float maxz, - eLevelName level) -{ - CZone *zone; - char *p; - - if(minx > maxx) SWAPF(minx, maxx); - if(miny > maxy) SWAPF(miny, maxy); - if(minz > maxz) SWAPF(minz, maxz); - - // make upper case - for(p = name; *p; p++) if(islower(*p)) *p = toupper(*p); // add zone - zone = &MapZoneArray[TotalNumberOfMapZones++]; - strncpy(zone->name, name, 7); - zone->name[7] = '\0'; - zone->type = type; - zone->minx = minx; - zone->miny = miny; - zone->minz = minz; - zone->maxx = maxx; - zone->maxy = maxy; - zone->maxz = maxz; - zone->level = level; + switch(type){ + case ZONE_DEFAULT: + case ZONE_NAVIG: + assert(TotalNumberOfNavigationZones < NUMNAVIGZONES); + strcpy(NavigationZoneArray[TotalNumberOfNavigationZones].name, tmpname); + NavigationZoneArray[TotalNumberOfNavigationZones].type = type; + NavigationZoneArray[TotalNumberOfNavigationZones].minx = minx; + NavigationZoneArray[TotalNumberOfNavigationZones].miny = miny; + NavigationZoneArray[TotalNumberOfNavigationZones].minz = minz; + NavigationZoneArray[TotalNumberOfNavigationZones].maxx = maxx; + NavigationZoneArray[TotalNumberOfNavigationZones].maxy = maxy; + NavigationZoneArray[TotalNumberOfNavigationZones].maxz = maxz; + NavigationZoneArray[TotalNumberOfNavigationZones].level = level; + TotalNumberOfNavigationZones++; + break; + case ZONE_INFO: + assert(TotalNumberOfInfoZones < NUMINFOZONES); + strcpy(InfoZoneArray[TotalNumberOfInfoZones].name, tmpname); + InfoZoneArray[TotalNumberOfInfoZones].type = type; + InfoZoneArray[TotalNumberOfInfoZones].minx = minx; + InfoZoneArray[TotalNumberOfInfoZones].miny = miny; + InfoZoneArray[TotalNumberOfInfoZones].minz = minz; + InfoZoneArray[TotalNumberOfInfoZones].maxx = maxx; + InfoZoneArray[TotalNumberOfInfoZones].maxy = maxy; + InfoZoneArray[TotalNumberOfInfoZones].maxz = maxz; + InfoZoneArray[TotalNumberOfInfoZones].level = level; + InfoZoneArray[TotalNumberOfInfoZones].zoneinfoDay = TotalNumberOfZoneInfos++; + InfoZoneArray[TotalNumberOfInfoZones].zoneinfoNight = TotalNumberOfZoneInfos++; + TotalNumberOfInfoZones++; + break; + case ZONE_MAPZONE: + assert(TotalNumberOfMapZones < NUMMAPZONES); + strcpy(MapZoneArray[TotalNumberOfMapZones].name, tmpname); + MapZoneArray[TotalNumberOfMapZones].type = type; + MapZoneArray[TotalNumberOfMapZones].minx = minx; + MapZoneArray[TotalNumberOfMapZones].miny = miny; + MapZoneArray[TotalNumberOfMapZones].minz = minz; + MapZoneArray[TotalNumberOfMapZones].maxx = maxx; + MapZoneArray[TotalNumberOfMapZones].maxy = maxy; + MapZoneArray[TotalNumberOfMapZones].maxz = maxz; + MapZoneArray[TotalNumberOfMapZones].level = level; + TotalNumberOfMapZones++; + break; + } } void CTheZones::PostZoneCreation(void) { int i; - for(i = 1; i < TotalNumberOfZones; i++) - InsertZoneIntoZoneHierarchy(&ZoneArray[i]); + for(i = 1; i < TotalNumberOfNavigationZones; i++) + InsertZoneIntoZoneHierarchy(&NavigationZoneArray[i]); InitialiseAudioZoneArray(); +#ifndef MASTER + CheckZonesForOverlap(); +#endif +} + +void +CTheZones::CheckZonesForOverlap(void) +{ + int i, j; + char str[116]; + + for(i = 1; i < TotalNumberOfInfoZones; i++){ + ZoneIsEntirelyContainedWithinOtherZone(&InfoZoneArray[i], &InfoZoneArray[0]); + + for(j = 1; j < TotalNumberOfInfoZones; j++) + if(i != j && ZoneIsEntirelyContainedWithinOtherZone(&InfoZoneArray[i], &InfoZoneArray[j])) + sprintf(str, "Info zone %s contains %s\n", InfoZoneArray[j].name, InfoZoneArray[i].name); + } } void @@ -222,7 +234,7 @@ CTheZones::InsertZoneIntoZoneHierarchy(CZone *zone) zone->child = nil; zone->parent = nil; zone->next = nil; - InsertZoneIntoZoneHierRecursive(zone, &ZoneArray[0]); + InsertZoneIntoZoneHierRecursive(zone, &NavigationZoneArray[0]); } bool @@ -314,34 +326,32 @@ CTheZones::GetLevelFromPosition(CVector const *v) } CZone* -CTheZones::FindSmallestZonePosition(const CVector *v) +CTheZones::FindInformationZoneForPosition(const CVector *v) { - CZone *best = &ZoneArray[0]; - // zone to test next - CZone *zone = ZoneArray[0].child; - while(zone) - // if in zone, descent into children - if(PointLiesWithinZone(v, zone)){ - best = zone; - zone = zone->child; - // otherwise try next zone - }else - zone = zone->next; - return best; + int i; +// char tmp[116]; +// if(!PointLiesWithinZone(v, &InfoZoneArray[0])) +// sprintf(tmp, "x = %.3f y= %.3f z = %.3f\n", v.x, v.y, v.z); + for(i = 1; i < TotalNumberOfInfoZones; i++) + if(PointLiesWithinZone(v, &InfoZoneArray[i])) + return &InfoZoneArray[i]; + return &InfoZoneArray[0]; } CZone* -CTheZones::FindSmallestZonePositionType(const CVector *v, eZoneType type) +CTheZones::FindSmallestNavigationZoneForPosition(const CVector *v, bool findDefault, bool findNavig) { CZone *best = nil; - if(ZoneArray[0].type == type) - best = &ZoneArray[0]; + if(findDefault && NavigationZoneArray[0].type == ZONE_DEFAULT || + findNavig && NavigationZoneArray[0].type == ZONE_NAVIG) + best = &NavigationZoneArray[0]; // zone to test next - CZone *zone = ZoneArray[0].child; + CZone *zone = NavigationZoneArray[0].child; while(zone) // if in zone, descent into children if(PointLiesWithinZone(v, zone)){ - if(zone->type == type) + if(findDefault && zone->type == ZONE_DEFAULT || + findNavig && zone->type == ZONE_NAVIG) best = zone; zone = zone->child; // otherwise try next zone @@ -350,35 +360,62 @@ CTheZones::FindSmallestZonePositionType(const CVector *v, eZoneType type) return best; } -CZone* -CTheZones::FindSmallestZonePositionILN(const CVector *v) +int16 +CTheZones::FindZoneByLabelAndReturnIndex(char *name, eZoneType type) { - CZone *best = nil; - if(IsNormalZone(ZoneArray[0].type)) - best = &ZoneArray[0]; - // zone to test next - CZone *zone = ZoneArray[0].child; - while(zone) - // if in zone, descent into children - if(PointLiesWithinZone(v, zone)){ - if(IsNormalZone(zone->type)) - best = zone; - zone = zone->child; - // otherwise try next zone - }else - zone = zone->next; - return best; + char str[8]; + memset(str, 0, 8); + strncpy(str, name, 8); + switch(type){ + case ZONE_DEFAULT: + case ZONE_NAVIG: + for(FindIndex = 0; FindIndex < TotalNumberOfNavigationZones; FindIndex++) + if(strcmp(GetNavigationZone(FindIndex)->name, name) == 0) + return FindIndex; + break; + + case ZONE_INFO: + for(FindIndex = 0; FindIndex < TotalNumberOfInfoZones; FindIndex++) + if(strcmp(GetInfoZone(FindIndex)->name, name) == 0) + return FindIndex; + break; + + case ZONE_MAPZONE: + for(FindIndex = 0; FindIndex < TotalNumberOfMapZones; FindIndex++) + if(strcmp(GetMapZone(FindIndex)->name, name) == 0) + return FindIndex; + break; + } + return -1; } int16 -CTheZones::FindZoneByLabelAndReturnIndex(Const char *name) +CTheZones::FindNextZoneByLabelAndReturnIndex(char *name, eZoneType type) { char str[8]; + ++FindIndex; memset(str, 0, 8); strncpy(str, name, 8); - for(FindIndex = 0; FindIndex < TotalNumberOfZones; FindIndex++) - if(strcmp(GetZone(FindIndex)->name, name) == 0) - return FindIndex; + switch(type){ + case ZONE_DEFAULT: + case ZONE_NAVIG: + for(; FindIndex < TotalNumberOfNavigationZones; FindIndex++) + if(strcmp(GetNavigationZone(FindIndex)->name, name) == 0) + return FindIndex; + break; + + case ZONE_INFO: + for(; FindIndex < TotalNumberOfInfoZones; FindIndex++) + if(strcmp(GetInfoZone(FindIndex)->name, name) == 0) + return FindIndex; + break; + + case ZONE_MAPZONE: + for(; FindIndex < TotalNumberOfMapZones; FindIndex++) + if(strcmp(GetMapZone(FindIndex)->name, name) == 0) + return FindIndex; + break; + } return -1; } @@ -386,7 +423,7 @@ CZoneInfo* CTheZones::GetZoneInfo(const CVector *v, uint8 day) { CZone *zone; - zone = FindSmallestZonePositionILN(v); + zone = FindInformationZoneForPosition(v); if(zone == nil) return &ZoneInfoArray[0]; return &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight]; @@ -397,6 +434,7 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info) { CZoneInfo *day, *night; float d, n; + int i; day = GetZoneInfo(pos, 1); night = GetZoneInfo(pos, 0); @@ -415,110 +453,78 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info) assert(d >= 0.0f && d <= 1.0f); n = 1.0f - d; } +#ifdef FIX_BUGS info->carDensity = day->carDensity * d + night->carDensity * n; - info->carThreshold[0] = day->carThreshold[0] * d + night->carThreshold[0] * n; - info->carThreshold[1] = day->carThreshold[1] * d + night->carThreshold[1] * n; - info->carThreshold[2] = day->carThreshold[2] * d + night->carThreshold[2] * n; - info->carThreshold[3] = day->carThreshold[3] * d + night->carThreshold[3] * n; - info->carThreshold[4] = day->carThreshold[4] * d + night->carThreshold[4] * n; - info->carThreshold[5] = day->carThreshold[5] * d + night->carThreshold[5] * n; - info->copThreshold = day->copThreshold * d + night->copThreshold * n; - info->gangThreshold[0] = day->gangThreshold[0] * d + night->gangThreshold[0] * n; - info->gangThreshold[1] = day->gangThreshold[1] * d + night->gangThreshold[1] * n; - info->gangThreshold[2] = day->gangThreshold[2] * d + night->gangThreshold[2] * n; - info->gangThreshold[3] = day->gangThreshold[3] * d + night->gangThreshold[3] * n; - info->gangThreshold[4] = day->gangThreshold[4] * d + night->gangThreshold[4] * n; - info->gangThreshold[5] = day->gangThreshold[5] * d + night->gangThreshold[5] * n; - info->gangThreshold[6] = day->gangThreshold[6] * d + night->gangThreshold[6] * n; - info->gangThreshold[7] = day->gangThreshold[7] * d + night->gangThreshold[7] * n; - info->gangThreshold[8] = day->gangThreshold[8] * d + night->gangThreshold[8] * n; + for(i = 0; i < ARRAY_SIZE(info->carThreshold); i++) + info->carThreshold[i] = day->carThreshold[i] * d + night->carThreshold[i] * n; + for(i = 0; i < ARRAY_SIZE(info->boatThreshold); i++) + info->boatThreshold[i] = day->boatThreshold[i] * d + night->boatThreshold[i] * n; + for(i = 0; i < ARRAY_SIZE(info->gangThreshold); i++) + info->gangThreshold[i] = day->gangThreshold[i] * d + night->gangThreshold[i] * n; + info->copThreshold = day->copThreshold * d + night->copThreshold * n; info->pedDensity = day->pedDensity * d + night->pedDensity * n; - info->copDensity = day->copDensity * d + night->copDensity * n; - info->gangDensity[0] = day->gangDensity[0] * d + night->gangDensity[0] * n; - info->gangDensity[1] = day->gangDensity[1] * d + night->gangDensity[1] * n; - info->gangDensity[2] = day->gangDensity[2] * d + night->gangDensity[2] * n; - info->gangDensity[3] = day->gangDensity[3] * d + night->gangDensity[3] * n; - info->gangDensity[4] = day->gangDensity[4] * d + night->gangDensity[4] * n; - info->gangDensity[5] = day->gangDensity[5] * d + night->gangDensity[5] * n; - info->gangDensity[6] = day->gangDensity[6] * d + night->gangDensity[6] * n; - info->gangDensity[7] = day->gangDensity[7] * d + night->gangDensity[7] * n; - info->gangDensity[8] = day->gangDensity[8] * d + night->gangDensity[8] * n; + info->copPedThreshold = day->copPedThreshold * d + night->copPedThreshold * n; + for(i = 0; i < ARRAY_SIZE(info->gangPedThreshold); i++) + info->gangPedThreshold[i] = day->gangPedThreshold[i] * d + night->gangPedThreshold[i] * n; +#else + // This is a complete mess. + info->carDensity = day->carDensity * n + night->carDensity * d; + for(i = 0; i < ARRAY_SIZE(info->carThreshold); i++) + info->carThreshold[i] = night->carThreshold[i] * d + night->carThreshold[i] * n; + for(i = 0; i < ARRAY_SIZE(info->boatThreshold); i++) + info->boatThreshold[i] = night->boatThreshold[i] * d + night->boatThreshold[i] * n; + for(i = 0; i < ARRAY_SIZE(info->gangThreshold); i++) + info->gangThreshold[i] = night->gangThreshold[i] * d + night->gangThreshold[i] * n; + + info->copThreshold = night->copThreshold * d + night->copThreshold * n; + info->pedDensity = night->pedDensity * d + night->pedDensity * n; + info->copPedThreshold = night->copPedThreshold * d + night->copPedThreshold * n; + for(i = 0; i < ARRAY_SIZE(info->gangPedThreshold); i++) + info->gangPedThreshold[i] = night->gangPedThreshold[i] * d + night->gangPedThreshold[i] * n; +#endif } if(CClock::GetIsTimeInRange(5, 19)) info->pedGroup = day->pedGroup; else info->pedGroup = night->pedGroup; - - CheckZoneInfo(info); } void CTheZones::SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity, - int16 gang0Num, int16 gang1Num, int16 gang2Num, - int16 gang3Num, int16 gang4Num, int16 gang5Num, - int16 gang6Num, int16 gang7Num, int16 gang8Num, - int16 copNum, - int16 car0Num, int16 car1Num, int16 car2Num, - int16 car3Num, int16 car4Num, int16 car5Num) + int16 copCarDensity, const int16 *gangCarDensities) { CZone *zone; CZoneInfo *info; - zone = GetZone(zoneid); + zone = GetInfoZone(zoneid); info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight]; - CheckZoneInfo(info); - - if(carDensity != -1) info->carDensity = carDensity; - int16 oldCar1Num = info->carThreshold[1] - info->carThreshold[0]; - int16 oldCar2Num = info->carThreshold[2] - info->carThreshold[1]; - int16 oldCar3Num = info->carThreshold[3] - info->carThreshold[2]; - int16 oldCar4Num = info->carThreshold[4] - info->carThreshold[3]; - int16 oldCar5Num = info->carThreshold[5] - info->carThreshold[4]; - int16 oldCopNum = info->copThreshold - info->carThreshold[5]; - int16 oldGang0Num = info->gangThreshold[0] - info->copThreshold; - int16 oldGang1Num = info->gangThreshold[1] - info->gangThreshold[0]; - int16 oldGang2Num = info->gangThreshold[2] - info->gangThreshold[1]; - int16 oldGang3Num = info->gangThreshold[3] - info->gangThreshold[2]; - int16 oldGang4Num = info->gangThreshold[4] - info->gangThreshold[3]; - int16 oldGang5Num = info->gangThreshold[5] - info->gangThreshold[4]; - int16 oldGang6Num = info->gangThreshold[6] - info->gangThreshold[5]; - int16 oldGang7Num = info->gangThreshold[7] - info->gangThreshold[6]; - int16 oldGang8Num = info->gangThreshold[8] - info->gangThreshold[7]; - - if(car0Num != -1) info->carThreshold[0] = car0Num; - if(car1Num != -1) info->carThreshold[1] = info->carThreshold[0] + car1Num; - else info->carThreshold[1] = info->carThreshold[0] + oldCar1Num; - if(car2Num != -1) info->carThreshold[2] = info->carThreshold[1] + car2Num; - else info->carThreshold[2] = info->carThreshold[1] + oldCar2Num; - if(car3Num != -1) info->carThreshold[3] = info->carThreshold[2] + car3Num; - else info->carThreshold[3] = info->carThreshold[2] + oldCar3Num; - if(car4Num != -1) info->carThreshold[4] = info->carThreshold[3] + car4Num; - else info->carThreshold[4] = info->carThreshold[3] + oldCar4Num; - if(car5Num != -1) info->carThreshold[5] = info->carThreshold[4] + car5Num; - else info->carThreshold[5] = info->carThreshold[4] + oldCar5Num; - if(copNum != -1) info->copThreshold = info->carThreshold[5] + copNum; - else info->copThreshold = info->carThreshold[5] + oldCopNum; - if(gang0Num != -1) info->gangThreshold[0] = info->copThreshold + gang0Num; - else info->gangThreshold[0] = info->copThreshold + oldGang0Num; - if(gang1Num != -1) info->gangThreshold[1] = info->gangThreshold[0] + gang1Num; - else info->gangThreshold[1] = info->gangThreshold[0] + oldGang1Num; - if(gang2Num != -1) info->gangThreshold[2] = info->gangThreshold[1] + gang2Num; - else info->gangThreshold[2] = info->gangThreshold[1] + oldGang2Num; - if(gang3Num != -1) info->gangThreshold[3] = info->gangThreshold[2] + gang3Num; - else info->gangThreshold[3] = info->gangThreshold[2] + oldGang3Num; - if(gang4Num != -1) info->gangThreshold[4] = info->gangThreshold[3] + gang4Num; - else info->gangThreshold[4] = info->gangThreshold[3] + oldGang4Num; - if(gang5Num != -1) info->gangThreshold[5] = info->gangThreshold[4] + gang5Num; - else info->gangThreshold[5] = info->gangThreshold[4] + oldGang5Num; - if(gang6Num != -1) info->gangThreshold[6] = info->gangThreshold[5] + gang6Num; - else info->gangThreshold[6] = info->gangThreshold[5] + oldGang6Num; - if(gang7Num != -1) info->gangThreshold[7] = info->gangThreshold[6] + gang7Num; - else info->gangThreshold[7] = info->gangThreshold[6] + oldGang7Num; - if(gang8Num != -1) info->gangThreshold[8] = info->gangThreshold[7] + gang8Num; - else info->gangThreshold[8] = info->gangThreshold[7] + oldGang8Num; - - CheckZoneInfo(info); + info->carDensity = carDensity; + info->copThreshold = copCarDensity; + info->gangThreshold[0] = gangCarDensities[0] + copCarDensity; + info->gangThreshold[1] = gangCarDensities[1] + info->gangThreshold[0]; + info->gangThreshold[2] = gangCarDensities[2] + info->gangThreshold[1]; + info->gangThreshold[3] = gangCarDensities[3] + info->gangThreshold[2]; + info->gangThreshold[4] = gangCarDensities[4] + info->gangThreshold[3]; + info->gangThreshold[5] = gangCarDensities[5] + info->gangThreshold[4]; + info->gangThreshold[6] = gangCarDensities[6] + info->gangThreshold[5]; + info->gangThreshold[7] = gangCarDensities[7] + info->gangThreshold[6]; + info->gangThreshold[8] = gangCarDensities[8] + info->gangThreshold[7]; +} + +void CTheZones::SetZoneCivilianCarInfo(uint16 zoneid, uint8 day, + const int16* carDensities, const int16* boatDensities) +{ + CZone* zone; + CZoneInfo* info; + zone = GetInfoZone(zoneid); + info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight]; + info->carThreshold[0] = carDensities[0]; + for (int i = 1; i < CCarCtrl::NUM_CAR_CLASSES; i++) + info->carThreshold[i] = carDensities[i] + info->carThreshold[i-1]; + info->boatThreshold[0] = boatDensities[0]; + for (int i = 1; i < CCarCtrl::NUM_BOAT_CLASSES; i++) + info->boatThreshold[i] = boatDensities[i] + info->boatThreshold[i - 1]; } void @@ -529,46 +535,55 @@ CTheZones::SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity, { CZone *zone; CZoneInfo *info; - zone = GetZone(zoneid); + zone = GetInfoZone(zoneid); info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight]; - if(pedDensity != -1) info->pedDensity = pedDensity; - if(copDensity != -1) info->copDensity = copDensity; - if(gang0Density != -1) info->gangDensity[0] = gang0Density; - if(gang1Density != -1) info->gangDensity[1] = gang1Density; - if(gang2Density != -1) info->gangDensity[2] = gang2Density; - if(gang3Density != -1) info->gangDensity[3] = gang3Density; - if(gang4Density != -1) info->gangDensity[4] = gang4Density; - if(gang5Density != -1) info->gangDensity[5] = gang5Density; - if(gang6Density != -1) info->gangDensity[6] = gang6Density; - if(gang7Density != -1) info->gangDensity[7] = gang7Density; - if(gang8Density != -1) info->gangDensity[8] = gang8Density; + info->pedDensity = pedDensity; + info->copPedThreshold = copDensity; + info->gangPedThreshold[0] = gang0Density; + info->gangPedThreshold[1] = gang1Density; + info->gangPedThreshold[2] = gang2Density; + info->gangPedThreshold[3] = gang3Density; + info->gangPedThreshold[4] = gang4Density; + info->gangPedThreshold[5] = gang5Density; + info->gangPedThreshold[6] = gang6Density; + info->gangPedThreshold[7] = gang7Density; + info->gangPedThreshold[8] = gang8Density; + + info->gangPedThreshold[0] += info->copPedThreshold; + info->gangPedThreshold[1] += info->gangPedThreshold[0]; + info->gangPedThreshold[2] += info->gangPedThreshold[1]; + info->gangPedThreshold[3] += info->gangPedThreshold[2]; + info->gangPedThreshold[4] += info->gangPedThreshold[3]; + info->gangPedThreshold[5] += info->gangPedThreshold[4]; + info->gangPedThreshold[6] += info->gangPedThreshold[5]; + info->gangPedThreshold[7] += info->gangPedThreshold[6]; + info->gangPedThreshold[8] += info->gangPedThreshold[7]; } +// unused void CTheZones::SetCarDensity(uint16 zoneid, uint8 day, uint16 cardensity) { CZone *zone; - zone = GetZone(zoneid); - if(IsNormalZone(zone->type)) - ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].carDensity = cardensity; + zone = GetInfoZone(zoneid); + ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].carDensity = cardensity; } +// unused void CTheZones::SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity) { CZone *zone; - zone = GetZone(zoneid); - if(IsNormalZone(zone->type)) - ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedDensity = peddensity; + zone = GetInfoZone(zoneid); + ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedDensity = peddensity; } void CTheZones::SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup) { CZone *zone; - zone = GetZone(zoneid); - if(IsNormalZone(zone->type)) - ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedGroup = pedgroup; + zone = GetInfoZone(zoneid); + ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedGroup = pedgroup; } int16 @@ -582,18 +597,6 @@ CTheZones::FindAudioZone(CVector *pos) return -1; } -eLevelName -CTheZones::FindZoneForPoint(const CVector &pos) -{ - if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("IND_ZON")))) - return LEVEL_INDUSTRIAL; - if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("COM_ZON")))) - return LEVEL_COMMERCIAL; - if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("SUB_ZON")))) - return LEVEL_SUBURBAN; - return LEVEL_GENERIC; -} - void CTheZones::AddZoneToAudioZoneArray(CZone *zone) { @@ -604,9 +607,10 @@ CTheZones::AddZoneToAudioZoneArray(CZone *zone) /* This is a bit stupid */ z = -1; - for(i = 0; i < NUMZONES; i++) - if(&ZoneArray[i] == zone) + for(i = 0; i < NUMNAVIGZONES; i++) + if(&NavigationZoneArray[i] == zone) z = i; + assert(NumberOfAudioZones < NUMAUDIOZONES); AudioZoneArray[NumberOfAudioZones++] = z; } @@ -617,7 +621,7 @@ CTheZones::InitialiseAudioZoneArray(void) CZone *zone; gonext = false; - zone = &ZoneArray[0]; + zone = &NavigationZoneArray[0]; // Go deep first, // set gonext when backing up a level to visit the next child while(zone) @@ -641,175 +645,113 @@ CTheZones::InitialiseAudioZoneArray(void) } } -#ifdef COMPATIBLE_SAVES -static inline void -SaveOneZone(CZone &zone, uint8 *&buffer) -{ - memcpy(buffer, zone.name, sizeof(zone.name)); - SkipSaveBuf(buffer, sizeof(zone.name)); - WriteSaveBuf(buffer, zone.minx); - WriteSaveBuf(buffer, zone.miny); - WriteSaveBuf(buffer, zone.minz); - WriteSaveBuf(buffer, zone.maxx); - WriteSaveBuf(buffer, zone.maxy); - WriteSaveBuf(buffer, zone.maxz); - WriteSaveBuf(buffer, zone.type); - WriteSaveBuf(buffer, zone.level); - WriteSaveBuf(buffer, zone.zoneinfoDay); - WriteSaveBuf(buffer, zone.zoneinfoNight); - WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.child)); - WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.parent)); - WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.next)); -} -#endif - void CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) { INITSAVEBUF int i; +#define CZONE_SAVE_SIZE (sizeof(char)*8+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(eZoneType)+sizeof(eLevelName)+sizeof(int16)+sizeof(int16)+sizeof(int32)+sizeof(int32)+sizeof(int32)) + *size = SAVE_HEADER_SIZE - + sizeof(int32) // GetIndexForZonePointer + sizeof(m_CurrLevel) + sizeof(FindIndex) + sizeof(int16) // padding - + ZONEARRAY_SAVE_SIZE + sizeof(ZoneInfoArray) - + sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos) - + MAPZONEARRAY_SAVE_SIZE + sizeof(AudioZoneArray) + + CZONE_SAVE_SIZE * ARRAY_SIZE(NavigationZoneArray) + CZONE_SAVE_SIZE * ARRAY_SIZE(InfoZoneArray) + sizeof(ZoneInfoArray) + + sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos) + + sizeof(int16) // padding + + CZONE_SAVE_SIZE * ARRAY_SIZE(MapZoneArray) + sizeof(AudioZoneArray) + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); +#undef CZONE_SAVE_SIZE - WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); + uint32 length = 0; + WriteSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); - WriteSaveBuf(buffer, (int32)GetIndexForZonePointer(m_pPlayersZone)); - WriteSaveBuf(buffer, m_CurrLevel); - WriteSaveBuf(buffer, FindIndex); - WriteSaveBuf(buffer, (int16)0); // padding + WriteSaveBuf(buffer, length, m_CurrLevel); + WriteSaveBuf(buffer, length, FindIndex); + WriteSaveBuf(buffer, length, (int16)0); // padding - for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ -#ifdef COMPATIBLE_SAVES - SaveOneZone(ZoneArray[i], buffer); -#else - CZone *zone = WriteSaveBuf(buffer, ZoneArray[i]); - zone->child = (CZone*)GetIndexForZonePointer(ZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(ZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(ZoneArray[i].next); -#endif - } + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++) + SaveOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG); - for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) - WriteSaveBuf(buffer, ZoneInfoArray[i]); + for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++) + SaveOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO); - WriteSaveBuf(buffer, TotalNumberOfZones); - WriteSaveBuf(buffer, TotalNumberOfZoneInfos); + for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) + WriteSaveBuf(buffer, length, ZoneInfoArray[i]); - for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { -#ifndef COMPATIBLE_SAVES - CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); -#endif + WriteSaveBuf(buffer, length, TotalNumberOfNavigationZones); + WriteSaveBuf(buffer, length, TotalNumberOfInfoZones); + WriteSaveBuf(buffer, length, TotalNumberOfZoneInfos); + WriteSaveBuf(buffer, length, (int16)0); // padding - /* - The call of GetIndexForZonePointer is wrong, as it is - meant for a different array, but the game doesn't brake - if those fields are nil. Let's make sure they are. - */ - assert(MapZoneArray[i].child == nil); - assert(MapZoneArray[i].parent == nil); - assert(MapZoneArray[i].next == nil); -#ifndef COMPATIBLE_SAVES - zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next); -#else - SaveOneZone(MapZoneArray[i], buffer); -#endif - } + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) + SaveOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE); for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) - WriteSaveBuf(buffer, AudioZoneArray[i]); + WriteSaveBuf(buffer, length, AudioZoneArray[i]); - WriteSaveBuf(buffer, TotalNumberOfMapZones); - WriteSaveBuf(buffer, NumberOfAudioZones); + WriteSaveBuf(buffer, length, TotalNumberOfMapZones); + WriteSaveBuf(buffer, length, NumberOfAudioZones); VALIDATESAVEBUF(*size) } -#ifdef COMPATIBLE_SAVES -static inline void -LoadOneZone(CZone &zone, uint8 *&buffer) +void +CTheZones::SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType) { - memcpy(zone.name, buffer, sizeof(zone.name)); - SkipSaveBuf(buffer, sizeof(zone.name)); - ReadSaveBuf(&zone.minx, buffer); - ReadSaveBuf(&zone.miny, buffer); - ReadSaveBuf(&zone.minz, buffer); - ReadSaveBuf(&zone.maxx, buffer); - ReadSaveBuf(&zone.maxy, buffer); - ReadSaveBuf(&zone.maxz, buffer); - ReadSaveBuf(&zone.type, buffer); - ReadSaveBuf(&zone.level, buffer); - ReadSaveBuf(&zone.zoneinfoDay, buffer); - ReadSaveBuf(&zone.zoneinfoNight, buffer); - int32 tmp; - ReadSaveBuf(&tmp, buffer); - zone.child = CTheZones::GetPointerForZoneIndex(tmp); - ReadSaveBuf(&tmp, buffer); - zone.parent = CTheZones::GetPointerForZoneIndex(tmp); - ReadSaveBuf(&tmp, buffer); - zone.next = CTheZones::GetPointerForZoneIndex(tmp); + WriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[0]); + WriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[4]); + + WriteSaveBuf(*buffer, *length, zone->minx); + WriteSaveBuf(*buffer, *length, zone->miny); + WriteSaveBuf(*buffer, *length, zone->minz); + WriteSaveBuf(*buffer, *length, zone->maxx); + WriteSaveBuf(*buffer, *length, zone->maxy); + WriteSaveBuf(*buffer, *length, zone->maxz); + + WriteSaveBuf(*buffer, *length, zone->type); + WriteSaveBuf(*buffer, *length, zone->level); + WriteSaveBuf(*buffer, *length, zone->zoneinfoDay); + WriteSaveBuf(*buffer, *length, zone->zoneinfoNight); + + int32 zoneId; + zoneId = GetIndexForNavigationZonePointer(zone->child); + WriteSaveBuf(*buffer, *length, zoneId); + zoneId = GetIndexForNavigationZonePointer(zone->parent); + WriteSaveBuf(*buffer, *length, zoneId); + zoneId = GetIndexForNavigationZonePointer(zone->next); + WriteSaveBuf(*buffer, *length, zoneId); } -#endif void CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { INITSAVEBUF - int32 i; + int i; - CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); + uint32 length = 0; + CheckSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); - ReadSaveBuf(&i, buffer); - m_pPlayersZone = GetPointerForZoneIndex(i); ReadSaveBuf(&m_CurrLevel, buffer); ReadSaveBuf(&FindIndex, buffer); SkipSaveBuf(buffer, 2); - for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ -#ifdef COMPATIBLE_SAVES - LoadOneZone(ZoneArray[i], buffer); -#else - ReadSaveBuf(&ZoneArray[i], buffer); + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++) + LoadOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG); - ZoneArray[i].child = GetPointerForZoneIndex((uintptr)ZoneArray[i].child); - ZoneArray[i].parent = GetPointerForZoneIndex((uintptr)ZoneArray[i].parent); - ZoneArray[i].next = GetPointerForZoneIndex((uintptr)ZoneArray[i].next); -#endif - } + for (i = 0; i < ARRAY_SIZE(InfoZoneArray); i++) + LoadOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO); for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) ReadSaveBuf(&ZoneInfoArray[i], buffer); - ReadSaveBuf(&TotalNumberOfZones, buffer); + ReadSaveBuf(&TotalNumberOfNavigationZones, buffer); + ReadSaveBuf(&TotalNumberOfInfoZones, buffer); ReadSaveBuf(&TotalNumberOfZoneInfos, buffer); + SkipSaveBuf(buffer, 2); - for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ -#ifdef COMPATIBLE_SAVES - LoadOneZone(MapZoneArray[i], buffer); -#else - ReadSaveBuf(&MapZoneArray[i], buffer); - - /* - The call of GetPointerForZoneIndex is wrong, as it is - meant for a different array, but the game doesn't brake - if save data stored is -1. - */ - MapZoneArray[i].child = GetPointerForZoneIndex((uintptr)MapZoneArray[i].child); - MapZoneArray[i].parent = GetPointerForZoneIndex((uintptr)MapZoneArray[i].parent); - MapZoneArray[i].next = GetPointerForZoneIndex((uintptr)MapZoneArray[i].next); -#endif - assert(MapZoneArray[i].child == nil); - assert(MapZoneArray[i].parent == nil); - assert(MapZoneArray[i].next == nil); - } + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) + LoadOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE); for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) ReadSaveBuf(&AudioZoneArray[i], buffer); @@ -819,3 +761,40 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) VALIDATESAVEBUF(size) } + +void +CTheZones::LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType) +{ +#ifdef THIS_IS_STUPID + uint32 part1, part2; + ReadSaveBuf(&part1, *buffer, *length); + ReadSaveBuf(&part2, *buffer, *length); + + *(uint64 *)&zone->name[0] = (uint64)part2; + *(uint64 *)&zone->name[0] <<= 32; + *(uint64 *)&zone->name[0] |= (uint64)part1; +#else + for(int i = 0; i < sizeof(zone->name); i++) + ReadSaveBuf(&zone->name[i], *buffer, *length); +#endif + + ReadSaveBuf(&zone->minx, *buffer, *length); + ReadSaveBuf(&zone->miny, *buffer, *length); + ReadSaveBuf(&zone->minz, *buffer, *length); + ReadSaveBuf(&zone->maxx, *buffer, *length); + ReadSaveBuf(&zone->maxy, *buffer, *length); + ReadSaveBuf(&zone->maxz, *buffer, *length); + + ReadSaveBuf(&zone->type, *buffer, *length); + ReadSaveBuf(&zone->level, *buffer, *length); + ReadSaveBuf(&zone->zoneinfoDay, *buffer, *length); + ReadSaveBuf(&zone->zoneinfoNight, *buffer, *length); + + int32 zoneId; + ReadSaveBuf(&zoneId, *buffer, *length); + zone->child = GetPointerForNavigationZoneIndex(zoneId); + ReadSaveBuf(&zoneId, *buffer, *length); + zone->parent = GetPointerForNavigationZoneIndex(zoneId); + ReadSaveBuf(&zoneId, *buffer, *length); + zone->next = GetPointerForNavigationZoneIndex(zoneId); +}
\ No newline at end of file diff --git a/src/core/Zones.h b/src/core/Zones.h index aa0466e8..2316eeef 100644 --- a/src/core/Zones.h +++ b/src/core/Zones.h @@ -2,6 +2,7 @@ #include "Game.h" #include "Gangs.h" +#include "CarCtrl.h" enum eZoneType { @@ -37,31 +38,33 @@ class CZoneInfo public: // Car data int16 carDensity; - int16 carThreshold[6]; - int16 copThreshold; + int16 carThreshold[CCarCtrl::NUM_CAR_CLASSES]; + int16 boatThreshold[CCarCtrl::NUM_BOAT_CLASSES]; int16 gangThreshold[NUM_GANGS]; + int16 copThreshold; // Ped data uint16 pedDensity; - uint16 copDensity; - uint16 gangDensity[NUM_GANGS]; + uint16 gangPedThreshold[NUM_GANGS]; + uint16 copPedThreshold; uint16 pedGroup; }; class CTheZones { - static CZone *m_pPlayersZone; static int16 FindIndex; static uint16 NumberOfAudioZones; static int16 AudioZoneArray[NUMAUDIOZONES]; static uint16 TotalNumberOfMapZones; - static uint16 TotalNumberOfZones; - static CZone ZoneArray[NUMZONES]; + static uint16 TotalNumberOfInfoZones; + static uint16 TotalNumberOfNavigationZones; + static CZone InfoZoneArray[NUMINFOZONES]; static CZone MapZoneArray[NUMMAPZONES]; + static CZone NavigationZoneArray[NUMNAVIGZONES]; static uint16 TotalNumberOfZoneInfos; - static CZoneInfo ZoneInfoArray[2*NUMZONES]; + static CZoneInfo ZoneInfoArray[2*NUMINFOZONES]; public: static eLevelName m_CurrLevel; @@ -71,31 +74,27 @@ public: float minx, float miny, float minz, float maxx, float maxy, float maxz, eLevelName level); - static void CreateMapZone(char *name, eZoneType type, - float minx, float miny, float minz, - float maxx, float maxy, float maxz, - eLevelName level); - static CZone *GetZone(uint16 i) { return &ZoneArray[i]; } - static CZone *GetAudioZone(uint16 i) { return &ZoneArray[AudioZoneArray[i]]; } + static CZone *GetInfoZone(uint16 i) { return &InfoZoneArray[i]; } + static CZone *GetNavigationZone(uint16 i) { return &NavigationZoneArray[i]; } + static CZone *GetMapZone(uint16 i) { return &MapZoneArray[i]; } + static CZone *GetAudioZone(uint16 i) { return &NavigationZoneArray[AudioZoneArray[i]]; } static void PostZoneCreation(void); + static void CheckZonesForOverlap(void); static void InsertZoneIntoZoneHierarchy(CZone *zone); static bool InsertZoneIntoZoneHierRecursive(CZone *z1, CZone *z2); static bool ZoneIsEntirelyContainedWithinOtherZone(CZone *z1, CZone *z2); static bool PointLiesWithinZone(const CVector *v, CZone *zone); static eLevelName GetLevelFromPosition(const CVector *v); - static CZone *FindSmallestZonePosition(const CVector *v); - static CZone *FindSmallestZonePositionType(const CVector *v, eZoneType type); - static CZone *FindSmallestZonePositionILN(const CVector *v); - static int16 FindZoneByLabelAndReturnIndex(Const char *name); + static CZone *FindInformationZoneForPosition(const CVector *v); + static CZone *FindSmallestNavigationZoneForPosition(const CVector *v, bool findDefault, bool findNavig); + static int16 FindZoneByLabelAndReturnIndex(char *name, eZoneType type); + static int16 FindNextZoneByLabelAndReturnIndex(char *name, eZoneType type); static CZoneInfo *GetZoneInfo(const CVector *v, uint8 day); static void GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info); static void SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity, - int16 gang0Num, int16 gang1Num, int16 gang2Num, - int16 gang3Num, int16 gang4Num, int16 gang5Num, - int16 gang6Num, int16 gang7Num, int16 gang8Num, - int16 copNum, - int16 car0Num, int16 car1Num, int16 car2Num, - int16 car3Num, int16 car4Num, int16 car5Num); + int16 copCarDensity, const int16 *gangCarDensities /*[NUMGANGS]*/); + static void SetZoneCivilianCarInfo(uint16 zoneid, uint8 day, + const int16* carDensities, const int16* boatDensities); static void SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity, int16 gang0Density, int16 gang1Density, int16 gang2Density, int16 gang3Density, int16 gang4Density, int16 gang5Density, int16 gang6Density, int16 gang7Density, @@ -104,11 +103,12 @@ public: static void SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity); static void SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup); static int16 FindAudioZone(CVector *pos); - static eLevelName FindZoneForPoint(const CVector &pos); - static CZone *GetPointerForZoneIndex(ssize_t i) { return i == -1 ? nil : &ZoneArray[i]; } - static ssize_t GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - ZoneArray; } + static CZone *GetPointerForNavigationZoneIndex(ssize_t i) { return i == -1 ? nil : &NavigationZoneArray[i]; } + static ssize_t GetIndexForNavigationZonePointer(CZone *zone) { return zone == nil ? -1 : zone - NavigationZoneArray; } static void AddZoneToAudioZoneArray(CZone *zone); static void InitialiseAudioZoneArray(void); static void SaveAllZones(uint8 *buffer, uint32 *length); + static void SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType); static void LoadAllZones(uint8 *buffer, uint32 length); + static void LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType); }; diff --git a/src/core/common.h b/src/core/common.h index da162762..9d3bca67 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -116,10 +116,8 @@ typedef ptrdiff_t ssize_t; #include "config.h" -#ifdef PED_SKIN #include <rphanim.h> #include <rpskin.h> -#endif #ifdef __GNUC__ #define TYPEALIGN(n) __attribute__ ((aligned (n))) @@ -148,7 +146,7 @@ inline uint32 ldb(uint32 p, uint32 s, uint32 w) #include "skeleton.h" #include "Draw.h" -#if defined(PROPER_SCALING) || defined(PS2_HUD) +#if defined(PROPER_SCALING) #ifdef FORCE_PC_SCALING #define DEFAULT_SCREEN_WIDTH (640) #define DEFAULT_SCREEN_HEIGHT (448) @@ -286,12 +284,15 @@ public: #if (defined(_MSC_VER)) extern int strcasecmp(const char *str1, const char *str2); +extern int strncasecmp(const char *str1, const char *str2, size_t len); #endif extern wchar *AllocUnicode(const char*src); #define Clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v)) +#define Clamp2(v, center, radius) ((v) < (center) ? Max(v, center - radius) : Min(v, center + radius)) + inline float sq(float x) { return x*x; } #define SQR(x) ((x) * (x)) @@ -393,3 +394,4 @@ template<int s, int t> struct check_size { #define STR(x) STRINGIFY(x) #define CONCAT_(x,y) x##y #define CONCAT(x,y) CONCAT_(x,y) + diff --git a/src/core/config.h b/src/core/config.h index 21a8b738..73b77560 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,82 +1,82 @@ #pragma once -// disables (most) stuff that wasn't in original gta3.exe +// disables (most) stuff that wasn't in original gta-vc.exe #ifdef __MWERKS__ #define VANILLA_DEFINES #endif enum Config { - NUMPLAYERS = 1, // 4 on PS2 + NUMPLAYERS = 1, - NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC) + NUMCDIMAGES = 6, // gta3.img duplicates (not used on PC) MAX_CDIMAGES = 8, // additional cdimages MAX_CDCHANNELS = 5, - MODELINFOSIZE = 5500, // 3150 on PS2 -#ifdef VANILLA_DEFINES - TXDSTORESIZE = 850, -#else - TXDSTORESIZE = 1024, // for Xbox map -#endif - EXTRADIRSIZE = 128, + MODELINFOSIZE = 6500, // 4900 on PS2 + TXDSTORESIZE = 1385, + COLSTORESIZE = 31, + EXTRADIRSIZE = 256, CUTSCENEDIRSIZE = 512, - SIMPLEMODELSIZE = 5000, // 2910 on PS2 - MLOMODELSIZE = 1, - MLOINSTANCESIZE = 1, - TIMEMODELSIZE = 30, + SIMPLEMODELSIZE = 3885, + TIMEMODELSIZE = 385, CLUMPMODELSIZE = 5, - PEDMODELSIZE = 90, - VEHICLEMODELSIZE = 120, // 70 on PS2 - XTRACOMPSMODELSIZE = 2, - TWODFXSIZE = 2000, // 1210 on PS2 + WEAPONMODELSIZE = 37, + PEDMODELSIZE = 130, + VEHICLEMODELSIZE = 110, + TWODFXSIZE = 1210, MAXVEHICLESLOADED = 50, // 70 on mobile - NUMOBJECTINFO = 168, // object.dat + NUMOBJECTINFO = 210, // Pool sizes - NUMPTRNODES = 30000, // 26000 on PS2 - NUMENTRYINFOS = 5400, // 3200 on PS2 - NUMPEDS = 140, // 90 on PS2 - NUMVEHICLES = 110, // 70 on PS2 - NUMBUILDINGS = 5500, // 4915 on PS2 - NUMTREADABLES = 1214, - NUMOBJECTS = 450, - NUMDUMMIES = 2802, // 2368 on PS2 - NUMAUDIOSCRIPTOBJECTS = 256, - NUMCUTSCENEOBJECTS = 50, - - NUMANIMBLOCKS = 2, - NUMANIMATIONS = 250, - - NUMTEMPOBJECTS = 30, + NUMPTRNODES = 50000, + NUMENTRYINFOS = 3200, + NUMPEDS = 140, + NUMVEHICLES = 110, + NUMBUILDINGS = 7000, + NUMTREADABLES = 1, + NUMOBJECTS = 460, + NUMDUMMIES = 2340, + NUMAUDIOSCRIPTOBJECTS = 192, + NUMCOLMODELS = 4400, + NUMCUTSCENEOBJECTS = 50, // not a pool in VC + + NUMANIMBLOCKS = 35, + NUMANIMATIONS = 450, + + NUMTEMPOBJECTS = 40, // Path data - NUM_PATHNODES = 4930, - NUM_CARPATHLINKS = 2076, + NUM_PATHNODES = 9650, + NUM_CARPATHLINKS = 3500, NUM_MAPOBJECTS = 1250, - NUM_PATHCONNECTIONS = 10260, + NUM_PATHCONNECTIONS = 20400, // Link list lengths NUMALPHALIST = 20, - NUMALPHAENTITYLIST = 150, - NUMCOLCACHELINKS = 200, + NUMBOATALPHALIST = 20, + NUMALPHAENTITYLIST = 200, + NUMALPHAUNTERWATERENTITYLIST = 30, + NUMCOLCACHELINKS = 50, NUMREFERENCES = 800, // Zones - NUMAUDIOZONES = 36, - NUMZONES = 50, - NUMMAPZONES = 25, + NUMAUDIOZONES = 14, + NUMINFOZONES = 169, + NUMMAPZONES = 39, + NUMNAVIGZONES = 20, // Cull zones - NUMCULLZONES = 512, - NUMATTRIBZONES = 288, - NUMZONEINDICES = 55000, + NUMATTRIBZONES = 704, + + NUMOCCLUSIONVOLUMES = 350, + NUMACTIVEOCCLUDERS = 48, PATHNODESIZE = 4500, - NUMWEATHERS = 4, + NUMWEATHERS = 7, NUMHOURS = 24, NUMEXTRADIRECTIONALS = 4, @@ -92,8 +92,9 @@ enum Config { NUMMBLURSTREAKS = 4, NUMSKIDMARKS = 32, - NUMONSCREENTIMERENTRIES = 1, - NUMRADARBLIPS = 32, + NUMONSCREENCLOCKS = 1, + NUMONSCREENCOUNTERS = 3, + NUMRADARBLIPS = 75, NUMGENERALPICKUPS = 320, NUMSCRIPTEDPICKUPS = 16, NUMPICKUPS = NUMGENERALPICKUPS + NUMSCRIPTEDPICKUPS, @@ -101,7 +102,7 @@ enum Config { NUMPACMANPICKUPS = 256, NUMEVENTS = 64, - NUM_CARGENS = 160, + NUM_CARGENS = 185, NUM_PATH_NODES_IN_AUTOPILOT = 8, @@ -116,11 +117,13 @@ enum Config { NUMPEDROUTES = 200, NUMPHONES = 50, - NUMPEDGROUPS = 31, - NUMMODELSPERPEDGROUP = 8, + NUMPEDGROUPS = 67, + NUMMODELSPERPEDGROUP = 16, + MAXZONEPEDSLOADED = 8, NUMSHOTINFOS = 100, - NUMROADBLOCKS = 600, + NUMROADBLOCKS = 300, + NUM_SCRIPT_ROADBLOCKS = 16, NUMVISIBLEENTITIES = 2000, NUMINVISIBLEENTITIES = 150, @@ -130,16 +133,21 @@ enum Config { NUM_PED_COMMENTS_SLOTS = 20, NUM_SOUNDS_SAMPLES_BANKS = 2, - NUM_AUDIOENTITIES = 200, + NUM_AUDIOENTITIES = 250, - NUM_AUDIO_REFLECTIONS = 5, + NUM_AUDIO_REFLECTIONS = 8, NUM_SCRIPT_MAX_ENTITIES = 40, - NUM_GARAGE_STORED_CARS = 6, + NUM_GARAGE_STORED_CARS = 4, NUM_CRANES = 8, + NUM_ESCALATORS = 22, + NUM_WATER_CREATURES = 8, NUM_EXPLOSIONS = 48, + + NUM_SETPIECES = 96, + NUM_SHORTCUT_START_POINTS = 16 }; // We don't expect to compile for PS2 or Xbox @@ -149,28 +157,34 @@ enum Config { //#define GTA_XBOX // Version defines -#define GTA3_PS2_140 300 -#define GTA3_PS2_160 301 -#define GTA3_PC_10 310 -#define GTA3_PC_11 311 -#define GTA3_PC_STEAM 312 +#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 GTA3_PC_11 +#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 USE_CUSTOM_ALLOCATOR # define VU_COLLISION -# define ANIM_COMPRESSION # 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 +#elif defined GTA_MOBILE +# define MISSION_REPLAY +# define SIMPLER_MISSIONS #endif // This is enabled for all released games. @@ -203,7 +217,6 @@ enum Config { #define MASTER //#define USE_MY_DOCUMENTS #define THIS_IS_STUPID -#define PC_PARTICLE #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 @@ -221,7 +234,6 @@ enum Config { // If you disable this then game will fetch version from peds.col, as R* did while in development. //#define USE_OUR_VERSIONING // enabled from buildfiles by default #endif -//#define DRAW_MENU_VERSION_TEXT // Memory allocation and compression // #define USE_CUSTOM_ALLOCATOR // use CMemoryHeap for allocation. use with care, not finished yet @@ -259,7 +271,7 @@ enum Config { #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 COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible, and keeps saves compatible between platforms, needs to be enabled on 64bit builds! +#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 @@ -274,19 +286,17 @@ enum Config { #define ASCII_STRCMP // use faster ascii str comparisons -#if !defined _WIN32 || defined __MINGW32__ +#if !defined _WIN32 || defined __MINGW32__ #undef ASCII_STRCMP #endif // Just debug menu entries #ifdef DEBUGMENU +#define RELOADABLES // some debug menu options to reload TXD files #define MISSION_SWITCHER // from debug menu #endif // Rendering/display -//#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering -//# define HARDCODED_MODEL_FLAGS // sets the flags enabled above from hardcoded model names. - // NB: keep this enabled unless your map IDEs have these flags baked in #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios #define PROPER_SCALING // use original DEFAULT_SCREEN_WIDTH/DEFAULT_SCREEN_HEIGHT from PS2 instead of PC(R* changed HEIGHT here to make radar look better, but broke other hud elements aspect ratio). #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) @@ -294,10 +304,6 @@ enum Config { #define PS2_ALPHA_TEST // emulate ps2 alpha test #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number #define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time -#ifdef DISABLE_LOADING_SCREEN -// enable the PC splash -#undef RANDOMSPLASH -#endif #define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync #define ANISOTROPIC_FILTERING // set all textures to max anisotropic filtering //#define USE_TEXTURE_POOL @@ -314,9 +320,12 @@ enum Config { #undef SCREEN_DROPLETS // we need the backbuffer for this effect #endif -// Particle -//#define PC_PARTICLE -//#define PS2_ALTERNATIVE_CARSPLASH // unused on PS2 +// Water & Particle +#undef PC_WATER +#define WATER_CHEATS + +//#define USE_CUTSCENE_SHADOW_FOR_PED // requires COMPATIBLE_SAVES +//#define DISABLE_CUTSCENE_SHADOWS // Pad #if !defined(RW_GL3) && defined(_WIN32) @@ -327,45 +336,39 @@ enum Config { #endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define KANGAROO_CHEAT -#define ALLCARSHELI_CHEAT -#define ALT_DODO_CHEAT +#define RESTORE_ALLCARSHELI_CHEAT +#define BETTER_ALLCARSAREDODO_CHEAT +#define WALLCLIMB_CHEAT #define REGISTER_START_BUTTON #define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls #define BUTTON_ICONS // use textures to show controller buttons // Hud, frontend and radar -//#define PS2_HUD -#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. -// #define BETA_SLIDING_TEXT -#define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC -#define FIX_RADAR // use radar size from early version before R* broke it -// #define XBOX_SUBTITLES // the infamous outlines -#define RADIO_OFF_TEXT #define PC_MENU +#define FIX_RADAR // use radar size from early version before R* broke it +#define RADIO_OFF_TEXT // Won't work without FIX_BUGS #ifndef PC_MENU # define PS2_MENU //# define PS2_MENU_USEALLPAGEICONS #else - +# define MAP_ENHANCEMENTS // Adding waypoint and better mouse support # ifdef XINPUT # define GAMEPAD_MENU // Add gamepad menu # endif - -# define SCROLLABLE_STATS_PAGE // only draggable by mouse atm # define TRIANGLE_BACK_BUTTON //# define CIRCLE_BACK_BUTTON -//# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. -//# define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box +#define LEGACY_MENU_OPTIONS // i.e. frame sync(vsync) +#define MUCH_SHORTER_OUTRO_SCREEN +// #define XBOX_MESSAGE_SCREEN // Blue background, no "saved successfully press OK" screen etc. # define CUSTOM_FRONTEND_OPTIONS # ifdef CUSTOM_FRONTEND_OPTIONS -# define MENU_MAP // VC-like menu map. Won't appear if you don't have our menu.txd # define GRAPHICS_MENU_OPTIONS // otherwise Display settings will be scrollable # define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU # define CUTSCENE_BORDERS_SWITCH # define MULTISAMPLING // adds MSAA option -# define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC +# define INVERT_LOOK_FOR_PAD // enable the hidden option # define PED_CAR_DENSITY_SLIDERS # endif #endif @@ -374,10 +377,17 @@ enum Config { #define USE_DEBUG_SCRIPT_LOADER // Loads main.scm by default. Hold R for main_freeroam.scm and D for main_d.scm #define USE_MEASUREMENTS_IN_METERS // makes game use meters instead of feet in script #define USE_PRECISE_MEASUREMENT_CONVERTION // makes game convert feet to meeters more precisely +#define SUPPORT_JAPANESE_SCRIPT +//#define SUPPORT_XBOX_SCRIPT +#define SUPPORT_MOBILE_SCRIPT +#if (defined SUPPORT_XBOX_SCRIPT && defined SUPPORT_MOBILE_SCRIPT) +static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually exclusive"); +#endif #ifdef PC_MENU -# define MISSION_REPLAY // mobile feature +#define MISSION_REPLAY // mobile feature +//#define SIMPLER_MISSIONS // apply simplifications from mobile +#define USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT #endif -//#define SIMPLIER_MISSIONS // apply simplifications from mobile #define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log @@ -394,45 +404,43 @@ enum Config { #undef USE_BASIC_SCRIPT_DEBUG_OUTPUT #endif +#ifndef MISSION_REPLAY +#undef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT +#endif + // Replay //#define DONT_FIX_REPLAY_BUGS // keeps various bugs in CReplay, some of which are fairly cool! //#define USE_BETA_REPLAY_MODE // adds another replay mode, a few seconds slomo (caution: buggy!) // Vehicles #define EXPLODING_AIRTRAIN // can blow up jumbo jet with rocket launcher -//#define REMOVE_TREADABLE_PATHFIND +#define CPLANE_ROTORS // make the rotors of the NPC police heli rotate // Pickups //#define MONEY_MESSAGES #define CAMERA_PICKUP // Peds -#define PED_SKIN // support for skinned geometry on peds, requires COMPATIBLE_SAVES -#define ANIMATE_PED_COL_MODEL -// #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle -// #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward #define CANCELLABLE_CAR_ENTER -//#define PEDS_REPORT_CRIMES_ON_PHONE // requires COMPATIBLE_SAVES // Camera -//#define PS2_CAM_TRANSITION // old way of transitioning between cam modes #define IMPROVED_CAMERA // Better Debug cam, and maybe more in the future #define FREE_CAM // Rotating cam // Audio -#define RADIO_SCROLL_TO_PREV_STATION -#define AUDIO_CACHE -#define PS2_AUDIO_CHANNELS // increases the maximum number of audio channels to PS2 value of 44 (PC has 28 originally) +#define RADIO_SCROLL_TO_PREV_STATION // Won't work without FIX_BUGS +#define AUDIO_CACHE // cache sound lengths to speed up the cold boot +#define PS2_AUDIO_CHANNELS // increases the maximum number of audio channels to PS2 value of 43 (PC has 28 originally) #define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds) //#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder #define AUDIO_OAL_USE_MPG123 // use mpg123 to support mp3 files -#define PAUSE_RADIO_IN_FRONTEND // pause radio when game is paused #define MULTITHREADED_AUDIO // for streams. requires C++11 or later +#define PAUSE_RADIO_IN_FRONTEND // pause radio when game is paused #ifdef AUDIO_OPUS #define AUDIO_OAL_USE_OPUS // enable support of opus files -#define OPUS_AUDIO_PATHS // changes audio paths to opus paths (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled) -#define OPUS_SFX // enable if your sfx.raw is encoded with opus (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled) +//#define OPUS_AUDIO_PATHS // (not supported on VC yet) changes audio paths to opus paths (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled) +//#define OPUS_SFX // enable if your sfx.raw is encoded with opus (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled) #ifndef AUDIO_OAL_USE_OPUS #undef OPUS_AUDIO_PATHS @@ -454,15 +462,11 @@ enum Config { #undef NO_ISLAND_LOADING #undef PS2_AUDIO_CHANNELS #undef EXTENDED_OFFSCREEN_DESPAWN_RANGE - #define PC_PARTICLE - #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial - #define VC_RAIN_NERF // Reduces number of rain particles #endif // if these defines are enabled saves are not vanilla compatible without COMPATIBLE_SAVES #ifndef COMPATIBLE_SAVES -#undef PED_SKIN -#undef PEDS_REPORT_CRIMES_ON_PHONE +#undef USE_CUTSCENE_SHADOW_FOR_PED #endif -#endif // VANILLA_DEFINES +#endif // VANILLA_DEFINES
\ No newline at end of file diff --git a/src/core/main.cpp b/src/core/main.cpp index 2a0a77ca..e84c6eeb 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -65,13 +65,16 @@ #include "timebars.h" #include "GenericGameStorage.h" #include "MemoryCard.h" +#include "MemoryHeap.h" #include "SceneEdit.h" #include "debugmenu.h" #include "Clock.h" +#include "Occlusion.h" +#include "Ropes.h" #include "postfx.h" #include "custompipes.h" #include "screendroplets.h" -#include "MemoryHeap.h" +#include "VarConsole.h" #ifdef USE_OUR_VERSIONING #include "GitSHA1.h" #endif @@ -105,11 +108,7 @@ RwRGBA gColourTop; bool gameAlreadyInitialised; float NumberOfChunksLoaded; -#ifdef GTA_PS2 -#define TOTALNUMCHUNKS 48.0f -#else -#define TOTALNUMCHUNKS 73.0f -#endif +#define TOTALNUMCHUNKS 95.0f bool g_SlowMode = false; char version_name[64]; @@ -127,7 +126,7 @@ void DebugMenuPopulate(void); bool gbPrintMemoryUsage; #endif -#ifdef PS2_MENU +#ifdef GTA_PS2 #define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad #define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad #else @@ -137,11 +136,18 @@ bool gbPrintMemoryUsage; #ifdef NEW_RENDERER bool gbNewRenderer; +#endif +#ifdef FIX_BUGS +// need to clear stencil for mblur fx. no idea why it works in the original game +// also for clearing out water rects in new renderer #define CLEARMODE (rwCAMERACLEARZ | rwCAMERACLEARSTENCIL) #else #define CLEARMODE (rwCAMERACLEARZ) #endif +bool bDisplayNumOfAtomicsRendered = false; +bool bDisplayPosn = false; + #ifdef __MWERKS__ void debug(char *fmt, ...) @@ -201,20 +207,14 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR CRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha); CRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha); -#ifndef ASPECT_RATIO_SCALE - CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, (CMenuManager::m_PrefsUseWideScreen ? 16.f / 9.f : 4.f / 3.f)); -#else + CDraw::CalculateAspectRatio(); CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); -#endif CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &TopColor.rwRGBA, CLEARMODE); if(!RsCameraBeginUpdate(Scene.camera)) return false; -#ifdef FIX_BUGS - CSprite2d::SetRecipNearClip(); -#endif CSprite2d::InitPerFrame(); if(Alpha != 0) @@ -226,11 +226,8 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha) { -#ifndef ASPECT_RATIO_SCALE - CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, (CMenuManager::m_PrefsUseWideScreen ? 16.f/9.f : 4.f/3.f)); -#else + CDraw::CalculateAspectRatio(); CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); -#endif CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, CLEARMODE); @@ -287,13 +284,13 @@ DoFade(void) } } - if(CDraw::FadeValue != 0 || CMenuManager::m_PrefsBrightness < 256){ + if(CDraw::FadeValue != 0 || FrontEndMenuManager.m_PrefsBrightness < 256){ CSprite2d *splash = LoadSplash(nil); CRGBA fadeColor; CRect rect; int fadeValue = CDraw::FadeValue; - float brightness = Min(CMenuManager::m_PrefsBrightness, 256); + float brightness = Min(FrontEndMenuManager.m_PrefsBrightness, 256); if(brightness <= 50) brightness = 50; if(FrontEndMenuManager.m_bMenuActive) @@ -318,31 +315,11 @@ DoFade(void) fadeColor.a = alpha; } - if(TheCamera.m_WideScreenOn -#ifdef CUTSCENE_BORDERS_SWITCH - && CMenuManager::m_PrefsCutsceneBorders -#endif - ){ - // what's this? - float y = SCREEN_HEIGHT/2 * TheCamera.m_ScreenReductionPercentage/100.0f; - rect.left = 0.0f; - rect.right = SCREEN_WIDTH; -#ifdef FIX_BUGS - rect.top = y - SCREEN_SCALE_Y(8.0f); - rect.bottom = SCREEN_HEIGHT - y - SCREEN_SCALE_Y(8.0f); -#else - rect.top = y - 8.0f; - rect.bottom = SCREEN_HEIGHT - y - 8.0f; -#endif // FIX_BUGS - }else{ - rect.left = 0.0f; - rect.right = SCREEN_WIDTH; - rect.top = 0.0f; - rect.bottom = SCREEN_HEIGHT; - } + TheCamera.GetScreenRect(rect); CSprite2d::DrawRect(rect, fadeColor); if(CDraw::FadeValue != 0 && TheCamera.m_FadeTargetIsSplashScreen){ + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); fadeColor.r = 255; fadeColor.g = 255; fadeColor.b = 255; @@ -425,7 +402,12 @@ PluginAttach(void) return FALSE; } - +#ifndef LIBRW + if (!RtAnimInitialize()) + { + return FALSE; + } +#endif if( !RpHAnimPluginAttach() ) { printf("Couldn't attach RpHAnim plugin\n"); @@ -471,19 +453,21 @@ PluginAttach(void) } #ifdef GTA_PS2 -#define NUM_PREALLOC_ATOMICS 3245 -#define NUM_PREALLOC_CLUMPS 101 -#define NUM_PREALLOC_FRAMES 2821 -#define NUM_PREALLOC_GEOMETRIES 1404 -#define NUM_PREALLOC_TEXDICTS 106 -#define NUM_PREALLOC_TEXTURES 1900 -#define NUM_PREALLOC_MATERIALS 3300 +#define NUM_PREALLOC_ATOMICS 1800 +#define NUM_PREALLOC_CLUMPS 80 +#define NUM_PREALLOC_FRAMES 2600 +#define NUM_PREALLOC_GEOMETRIES 850 +#define NUM_PREALLOC_TEXDICTS 121 +#define NUM_PREALLOC_TEXTURES 1700 +#define NUM_PREALLOC_MATERIALS 2600 bool preAlloc; void PreAllocateRwObjects(void) { int i; + + PUSH_MEMID(MEMID_PRE_ALLOC); void **tmp = new void*[0x8000]; preAlloc = true; @@ -524,20 +508,31 @@ PreAllocateRwObjects(void) delete[] tmp; preAlloc = false; + POP_MEMID(); } #endif static RwBool Initialise3D(void *param) { + PUSH_MEMID(MEMID_RENDER); + +#ifndef MASTER + VarConsole.Add("Display number of atomics rendered", &bDisplayNumOfAtomicsRendered, true); + VarConsole.Add("Display posn and framerate", &bDisplayPosn, true); +#endif + if (RsRwInitialize(param)) { + POP_MEMID(); + #ifdef DEBUGMENU DebugMenuInit(); DebugMenuPopulate(); #endif // !DEBUGMENU return CGame::InitialiseRenderWare(); } + POP_MEMID(); return (FALSE); } @@ -609,16 +604,16 @@ GetRandomSplashScreen(void) int index; static int index2 = 0; static char splashName[128]; - static int splashIndex[24] = { - 25, 22, 4, 13, - 1, 21, 14, 16, - 10, 12, 5, 9, - 11, 18, 3, 2, - 19, 23, 7, 17, - 15, 6, 8, 20 + static int splashIndex[12] = { + 1, 2, + 3, 4, + 5, 11, + 6, 8, + 9, 10, + 7, 12 }; - index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)]; + index = splashIndex[2*index2 + CGeneral::GetRandomNumberInRange(0, 2)]; index2++; if(index2 == 6) index2 = 0; @@ -656,10 +651,7 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) #endif #ifndef RANDOMSPLASH - if(CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) - splashscreen = "mainsc2"; - else - splashscreen = "mainsc1"; + splashscreen = "LOADSC0"; #endif splash = LoadSplash(splashscreen); @@ -669,12 +661,7 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) return; #endif -#ifndef GTA_PS2 - if(DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)) -#else - DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); -#endif - { + if(DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)){ CSprite2d::SetRecipNearClip(); CSprite2d::InitPerFrame(); CFont::InitPerFrame(); @@ -685,37 +672,51 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) if(str1){ NumberOfChunksLoaded += 1; +#ifndef RANDOMSPLASH float hpos = SCREEN_SCALE_X(40); - float length = SCREEN_WIDTH - SCREEN_SCALE_X(100); - float vpos = SCREEN_HEIGHT - SCREEN_SCALE_Y(13); - float height = SCREEN_SCALE_Y(7); - CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(40, 53, 68, 255)); + float length = SCREEN_WIDTH - SCREEN_SCALE_X(80); + float top = SCREEN_HEIGHT - SCREEN_SCALE_Y(14); + float bottom = top + SCREEN_SCALE_Y(5); +#else + float hpos = SCREEN_STRETCH_X(40); + float length = SCREEN_STRETCH_X(440); + // this is rather weird + float top = SCREEN_STRETCH_Y(407.4f - 7.0f/3.0f); + float bottom = SCREEN_STRETCH_Y(407.4f + 7.0f/3.0f); +#endif + + CSprite2d::DrawRect(CRect(hpos-1.0f, top-1.0f, hpos+length+1.0f, bottom+1.0f), CRGBA(40, 53, 68, 255)); + + CSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(155, 50, 125, 255)); length *= NumberOfChunksLoaded/TOTALNUMCHUNKS; - CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(81, 106, 137, 255)); + CSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(255, 150, 225, 255)); // this is done by the game but is unused + CFont::SetBackgroundOff(); CFont::SetScale(SCREEN_SCALE_X(2), SCREEN_SCALE_Y(2)); CFont::SetPropOn(); CFont::SetRightJustifyOn(); + CFont::SetDropShadowPosition(1); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_HEADING); #ifdef CHATTYSPLASH // my attempt static wchar tmpstr[80]; float yscale = SCREEN_SCALE_Y(0.9f); - vpos -= 45*yscale; + top -= 45*yscale; CFont::SetScale(SCREEN_SCALE_X(0.75f), yscale); CFont::SetPropOn(); CFont::SetRightJustifyOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::SetColor(CRGBA(255, 255, 255, 255)); AsciiToUnicode(str1, tmpstr); - CFont::PrintString(hpos, vpos, tmpstr); - vpos += 22*yscale; + CFont::PrintString(hpos, top, tmpstr); + top += 22*yscale; if (str2) { AsciiToUnicode(str2, tmpstr); - CFont::PrintString(hpos, vpos, tmpstr); + CFont::PrintString(hpos, top, tmpstr); } #endif } @@ -729,83 +730,19 @@ void LoadingIslandScreen(const char *levelName) { CSprite2d *splash; - wchar *name; - char str[100]; - wchar wstr[80]; - CRGBA col; splash = LoadSplash(nil); - name = TheText.Get(levelName); - -#ifndef GTA_PS2 if(!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)) return; -#else - DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); -#endif CSprite2d::SetRecipNearClip(); CSprite2d::InitPerFrame(); CFont::InitPerFrame(); DefinedState(); - col = CRGBA(255, 255, 255, 255); + CRGBA col = CRGBA(255, 255, 255, 255); + CRGBA col2 = CRGBA(0, 0, 0, 255); + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), col2); splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), col, col, col, col); - CFont::SetBackgroundOff(); -#ifdef FIX_BUGS - CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); -#else - CFont::SetScale(1.5f, 1.5f); -#endif - CFont::SetPropOn(); - CFont::SetRightJustifyOn(); -#ifdef FIX_BUGS - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(150.0f)); -#else - CFont::SetRightJustifyWrap(150.0f); -#endif - CFont::SetFontStyle(FONT_HEADING); - sprintf(str, "WELCOME TO"); - AsciiToUnicode(str, wstr); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::SetDropShadowPosition(3); - CFont::SetColor(CRGBA(243, 237, 71, 255)); -#if !defined(PS2_HUD) && defined(GTA_PC) - CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); -#endif - -#ifdef PS2_HUD - #ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(140.0f), TheText.Get("WELCOME")); - #else - CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_HEIGHT - 140, TheText.Get("WELCOME")); - #endif -#else - #ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(110.0f), TheText.Get("WELCOME")); - #else - CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_SCALE_FROM_BOTTOM(110.0f), TheText.Get("WELCOME")); - #endif -#endif - TextCopy(wstr, name); - TheText.UpperCase(wstr); - CFont::SetColor(CRGBA(243, 237, 71, 255)); -#if !defined(PS2_HUD) && defined(GTA_PC) - CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); -#endif - -#ifdef PS2_HUD - #ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(110.0f), wstr); - #else - CFont::PrintString(SCREEN_WIDTH-20, SCREEN_HEIGHT - 110, wstr); - #endif -#else - #ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(80.0f), wstr); - #else - CFont::PrintString(SCREEN_WIDTH-20, SCREEN_SCALE_FROM_BOTTOM(80.0f), wstr); - #endif -#endif CFont::DrawFonts(); DoRWStuffEndOfFrame(); } @@ -838,7 +775,7 @@ ProcessSlowMode(void) do { - if ( CPad::GetPad(1)->GetLeftShoulder1JustDown() || CPad::GetPad(1)->GetRightShoulder1() ) + if ( CPad::GetPad(1)->GetSelectJustDown() || CPad::GetPad(1)->GetStart() ) break; if ( stop ) @@ -852,10 +789,7 @@ ProcessSlowMode(void) RwCameraBeginUpdate(Scene.camera); RwCameraEndUpdate(Scene.camera); - if ( CPad::GetPad(1)->GetLeftShoulder1JustDown() || CPad::GetPad(1)->GetRightShoulder1() ) - break; - - } while (!CPad::GetPad(1)->GetRightShoulder1()); + } while (!CPad::GetPad(1)->GetSelectJustDown() && !CPad::GetPad(1)->GetStart()); CPad::GetPad(0)->OldState.LeftStickX = lX; @@ -909,22 +843,32 @@ int32 FrameSamples; #ifndef MASTER struct tZonePrint { - char name[12]; - CRect rect; + char name[11]; + char area[5]; + CRect rect; }; tZonePrint ZonePrint[] = { - { "suburban", CRect(-1639.4f, 1014.3f, -226.23f, -1347.9f) }, - { "comntop", CRect(-223.52f, 203.62f, 616.79f, -413.6f) }, - { "comnbtm", CRect(-227.24f, -413.6f, 620.51f, -911.84f) }, - { "comse", CRect( 200.35f, -911.84f, 620.51f, -1737.3f) }, - { "comsw", CRect(-223.52f, -911.84f, 200.35f, -1737.3f) }, - { "industsw", CRect( 744.05f, -473.0f, 1067.5f, -1331.5f) }, - { "industne", CRect( 1067.5f, 282.19f, 1915.3f, -473.0f) }, - { "industnw", CRect( 744.05f, 324.95f, 1067.5f, -473.0f) }, - { "industse", CRect( 1070.3f, -473.0f, 1918.1f, -1331.5f) }, - { "no zone", CRect( 0.0f, 0.0f, 0.0f, 0.0f) } + { "DOWNTOWN", "GM", CRect(-1500.0f, 1500.0f, -300.0f, 980.0f)}, + { "DOWNTOWS", "KB", CRect(-1200.0f, 980.0f, -300.0f, 435.0f)}, + { "GOLF", "NT", CRect(-300.0f, 660.0f, 320.0f, -255.0f)}, + { "LITTLEHA", "AG", CRect(-1250.0f, -310.0f, -746.0f, -926.0f)}, + { "HAITI", "CJ", CRect(-1355.0f, 30.0f, -637.0f, -304.0f)}, + { "HAITIN", "SM", CRect(-1355.0f, 435.0f, -637.0f, 30.0f)}, + { "DOCKS", "AW", CRect(-1122.0f, -926.0f, -609.0f, -1575.0f)}, + { "AIRPORT", "NT", CRect(-2000.0f, 200.0f, -871.0f, -2000.0f)}, + { "STARISL", "CJ", CRect(-724.0f, -320.0f, -40.0f, -380.0f)}, + { "CENT.ISLA", "NT", CRect(-163.0f, 1260.0f, 120.0f, 830.0f)}, + { "MALL", "AW", CRect( 300.0f, 1266.0f, 483.0f, 995.0f)}, + { "MANSION", "KB", CRect(-724.0f, -500.0f, -40.0f, -670.0f)}, + { "NBEACH", "AS", CRect( 120.0f, 1340.0f, 900.0f, 600.0f)}, + { "NBEACHBT", "AS", CRect( 200.0f, 680.0f, 660.0f, -50.0f)}, + { "NBEACHW", "AS", CRect(-93.0f, 80.0f, 410.0f, -680.0f)}, + { "OCEANDRV", "AC", CRect( 200.0f, -964.0f, 955.0f, -1797.0f)}, + { "OCEANDN", "WS", CRect( 400.0f, 50.0f, 955.0f, -964.0f)}, + { "WASHINGTN", "AC", CRect(-320.0f, -487.0f, 500.0f, -1200.0f)}, + { "WASHINBTM", "AC", CRect(-255.0f, -1200.0f, 500.0f, -1690.0f)} }; void @@ -973,7 +917,7 @@ return; CFont::PrintString(24.0f, y, gUString); y += 12.0f; - sprintf(gString, "Render List: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDERLIST), gMainHeap.GetMemoryUsed(MEMID_RENDERLIST)); + sprintf(gString, "PreAlloc: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_PRE_ALLOC), gMainHeap.GetMemoryUsed(MEMID_PRE_ALLOC)); AsciiToUnicode(gString, gUString); CFont::PrintString(24.0f, y, gUString); y += 12.0f; @@ -998,11 +942,31 @@ return; CFont::PrintString(24.0f, y, gUString); y += 12.0f; + sprintf(gString, "Streamed LODs: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_LODS), gMainHeap.GetMemoryUsed(MEMID_STREAM_LODS)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + sprintf(gString, "Streamed Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_TEXUTRES), gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES)); AsciiToUnicode(gString, gUString); CFont::PrintString(24.0f, y, gUString); y += 12.0f; + sprintf(gString, "Streamed Collision: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_COLLISION), gMainHeap.GetMemoryUsed(MEMID_STREAM_COLLISION)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Streamed Animation: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_STREAM_ANIMATION)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + + sprintf(gString, "Ped Attr: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_PED_ATTR), gMainHeap.GetMemoryUsed(MEMID_PED_ATTR)); + AsciiToUnicode(gString, gUString); + CFont::PrintString(24.0f, y, gUString); + y += 12.0f; + sprintf(gString, "Animation: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_ANIMATION)); AsciiToUnicode(gString, gUString); CFont::PrintString(24.0f, y, gUString); @@ -1032,11 +996,6 @@ return; AsciiToUnicode(gString, gUString); CFont::PrintString(24.0f, y, gUString); y += 12.0f; - - sprintf(gString, "Frontend: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_FRONTEND), gMainHeap.GetMemoryUsed(MEMID_FRONTEND)); - AsciiToUnicode(gString, gUString); - CFont::PrintString(24.0f, y, gUString); - y += 12.0f; #endif y = 132.0f; @@ -1093,13 +1052,13 @@ return; void DisplayGameDebugText() { - static bool bDisplayPosn = false; - static bool bDisplayRate = false; + static bool bDisplayCheatStr = false; // custom + #ifndef FINAL { SETTWEAKPATH("Debug"); TWEAKBOOL(bDisplayPosn); - TWEAKBOOL(bDisplayRate); + TWEAKBOOL(bDisplayCheatStr); } if(gbPrintMemoryUsage) @@ -1160,18 +1119,14 @@ DisplayGameDebugText() CFont::SetPropOn(); CFont::SetBackgroundOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::SetCentreOff(); CFont::SetRightJustifyOff(); CFont::SetWrapx(SCREEN_WIDTH); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); CFont::SetColor(CRGBA(255, 108, 0, 255)); -#ifdef FIX_BUGS CFont::PrintString(SCREEN_SCALE_X(10.0f), SCREEN_SCALE_Y(10.0f), ver); -#else - CFont::PrintString(10.0f, 10.0f, ver); -#endif } #endif // #ifdef DRAW_GAME_VERSION_TEXT @@ -1183,7 +1138,7 @@ DisplayGameDebugText() PreviousTimeInMillisecondsPauseMode = CTimer::GetTimeInMillisecondsPauseMode(); FramesPerSecond = FrameSamples / FramesPerSecondCounter; #else - FramesPerSecondCounter += 1000.0f / CTimer::GetTimeStepNonClippedInMilliseconds(); + FramesPerSecondCounter += 1000.0f / CTimer::GetTimeStepNonClippedInMilliseconds(); FramesPerSecond = FramesPerSecondCounter / FrameSamples; #endif @@ -1192,23 +1147,8 @@ DisplayGameDebugText() FramesPerSecondCounter = 0.0f; FrameSamples = 0; } - - if ( !TheCamera.WorldViewerBeingUsed - && CPad::GetPad(1)->GetSquare() - && CPad::GetPad(1)->GetTriangle() - && CPad::GetPad(1)->GetLeftShoulder2JustDown() ) - { - bDisplayPosn = !bDisplayPosn; - } - if ( CPad::GetPad(1)->GetSquare() - && CPad::GetPad(1)->GetTriangle() - && CPad::GetPad(1)->GetRightShoulder2JustDown() ) - { - bDisplayRate = !bDisplayRate; - } - - if ( bDisplayPosn || bDisplayRate ) + if ( bDisplayPosn ) { CVector pos = FindPlayerCoors(); int32 ZoneId = ARRAY_SIZE(ZonePrint)-1; // no zone @@ -1225,44 +1165,48 @@ DisplayGameDebugText() } //NOTE: fps should be 30, but its 29 due to different fp2int conversion - if ( bDisplayRate ) - sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, F-%d, %s", pos.x, pos.y, pos.z, (int32)FramesPerSecond, ZonePrint[ZoneId].name); - else - sprintf(str, "X:%5.1f, Y:%5.1f, Z:%5.1f, %s", pos.x, pos.y, pos.z, ZonePrint[ZoneId].name); - + sprintf(str, "X:%4.0f Y:%4.0f Z:%4.0f F-%d %s-%s", pos.x, pos.y, pos.z, (int32)FramesPerSecond, + ZonePrint[ZoneId].name, ZonePrint[ZoneId].area); + AsciiToUnicode(str, ustr); - CFont::SetPropOff(); + CFont::SetPropOn(); CFont::SetBackgroundOff(); -#ifdef FIX_BUGS - CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(1.5f)); -#else - CFont::SetScale(0.7f, 1.5f); -#endif + CFont::SetScale(SCREEN_SCALE_X(0.6f), SCREEN_SCALE_Y(0.8f)); CFont::SetCentreOff(); CFont::SetRightJustifyOff(); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); -#ifdef FIX_BUGS CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); -#else - CFont::SetWrapx(DEFAULT_SCREEN_WIDTH); -#endif - CFont::SetFontStyle(FONT_HEADING); - + CFont::SetFontStyle(FONT_STANDARD); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetDropShadowPosition(2); CFont::SetColor(CRGBA(0, 0, 0, 255)); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_X(40.0f+2.0f), SCREEN_SCALE_Y(40.0f+2.0f), ustr); -#else - CFont::PrintString(40.0f+2.0f, 40.0f+2.0f, ustr); -#endif + CFont::PrintString(41.0f, 41.0f, ustr); - CFont::SetColor(CRGBA(255, 108, 0, 255)); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), ustr); -#else + CFont::SetColor(CRGBA(205, 205, 0, 255)); CFont::PrintString(40.0f, 40.0f, ustr); -#endif + } + + // custom + if (bDisplayCheatStr) + { + sprintf(str, "%s", CPad::KeyBoardCheatString); + AsciiToUnicode(str, ustr); + + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(0.6f), SCREEN_SCALE_Y(0.8f)); + CFont::SetCentreOn(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetFontStyle(FONT_STANDARD); + + CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.5f)+2.f, SCREEN_SCALE_FROM_BOTTOM(20.0f)+2.f, ustr); + + CFont::SetColor(CRGBA(255, 150, 225, 255)); + CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.5f), SCREEN_SCALE_FROM_BOTTOM(20.0f), ustr); } } #endif @@ -1270,7 +1214,7 @@ DisplayGameDebugText() #ifdef NEW_RENDERER bool gbRenderRoads = true; bool gbRenderEverythingBarRoads = true; -//bool gbRenderFadingInUnderwaterEntities = true; +bool gbRenderFadingInUnderwaterEntities = true; bool gbRenderFadingInEntities = true; bool gbRenderWater = true; bool gbRenderBoats = true; @@ -1287,8 +1231,8 @@ MattRenderScene(void) // CMattRenderer::ResetRenderStates /// CRenderer::ClearForFrame(); // before ConstructRenderList // CClock::CalcEnvMapTimeMultiplicator -if(gbRenderWater) - CRenderer::RenderWater(); // actually CMattRenderer::RenderWater + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); + CWaterLevel::RenderWater(); // actually CMattRenderer::RenderWater // CClock::ms_EnvMapTimeMultiplicator = 1.0f; // cWorldStream::ClearDynamics /// CRenderer::ConstructRenderList(); // before PreRender @@ -1304,10 +1248,14 @@ if(gbRenderRoads) CRenderer::RenderPeds(); + // not sure where to put these since LCS has no underwater entities if(gbRenderBoats) CRenderer::RenderBoats(); -//if(gbRenderFadingInUnderwaterEntities) -// CRenderer::RenderFadingInUnderwaterEntities(); +if(gbRenderFadingInUnderwaterEntities) + CRenderer::RenderFadingInUnderwaterEntities(); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); +if(gbRenderWater) + CRenderer::RenderTransparentWater(); if(gbRenderEverythingBarRoads) CRenderer::RenderEverythingBarRoads(); @@ -1375,11 +1323,13 @@ if(gbRenderFadingInEntities) CGlass::Render(); // CMattRenderer::ResetRenderStates DefinedState(); + CCoronas::RenderSunReflection(); CWeather::RenderRainStreaks(); // CWeather::AddSnow CWaterCannons::Render(); CAntennas::Render(); CSpecialFX::Render(); + CRopes::Render(); CCoronas::Render(); CParticle::Render(); CPacManPickups::Render(); @@ -1405,16 +1355,17 @@ RenderScene(void) DoRWRenderHorizon(); CRenderer::RenderRoads(); CCoronas::RenderReflections(); - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); CRenderer::RenderEverythingBarRoads(); - CRenderer::RenderBoats(); - DefinedState(); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); CWaterLevel::RenderWater(); + CRenderer::RenderBoats(); + CRenderer::RenderFadingInUnderwaterEntities(); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); + CWaterLevel::RenderTransparentWater(); CRenderer::RenderFadingInEntities(); -#ifndef SQUEEZE_PERFORMANCE - CRenderer::RenderVehiclesButNotBoats(); -#endif + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); CWeather::RenderRainStreaks(); + CCoronas::RenderSunReflection(); POP_RENDERGROUP(); } @@ -1446,6 +1397,7 @@ RenderEffects(void) CGlass::Render(); CWaterCannons::Render(); CSpecialFX::Render(); + CRopes::Render(); CShadows::RenderStaticShadows(); CShadows::RenderStoredShadows(); CSkidmarks::Render(); @@ -1492,11 +1444,12 @@ Render2dStuff(void) if(cammode == CCam::MODE_SNIPER || cammode == CCam::MODE_SNIPER_RUNABOUT || cammode == CCam::MODE_ROCKETLAUNCHER || - cammode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) + cammode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || + cammode == CCam::MODE_CAMERA) firstPersonWeapon = true; // Draw black border for sniper and rocket launcher - if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){ + if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_LASERSCOPE) && firstPersonWeapon){ CRGBA black(0, 0, 0, 255); // top and bottom strips @@ -1520,12 +1473,17 @@ Render2dStuff(void) else #endif CHud::Draw(); + + CSpecialFX::Render2DFXs(); CUserDisplay::OnscnTimer.ProcessForDisplay(); CMessages::Display(); CDarkel::DrawMessages(); CGarages::PrintMessages(); CPad::PrintErrorMessage(); CFont::DrawFonts(); +#ifndef MASTER + COcclusion::Render(); +#endif #ifdef DEBUGMENU DebugMenuRender(); @@ -1539,11 +1497,13 @@ RenderMenus(void) if (FrontEndMenuManager.m_bMenuActive) { PUSH_RENDERGROUP("RenderMenus"); - PUSH_MEMID(MEMID_FRONTEND); FrontEndMenuManager.DrawFrontEnd(); - POP_MEMID(); POP_RENDERGROUP(); } +#ifndef MASTER + else + VarConsole.Check(); +#endif } void @@ -1554,18 +1514,18 @@ Render2dStuffAfterFade(void) DisplayGameDebugText(); #endif +#ifdef MOBILE_IMPROVEMENTS + if (CDraw::FadeValue != 0) +#endif CHud::DrawAfterFade(); CFont::DrawFonts(); + CCredits::Render(); POP_RENDERGROUP(); } void Idle(void *arg) { -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif - CTimer::Update(); tbInit(); @@ -1573,32 +1533,6 @@ Idle(void *arg) CSprite2d::InitPerFrame(); CFont::InitPerFrame(); - // We're basically merging FrontendIdle and Idle (just like TheGame on PS2) -#ifdef PS2_SAVE_DIALOG - // Only exists on PC FrontendIdle, probably some PS2 bug fix - if (FrontEndMenuManager.m_bMenuActive) - CSprite2d::SetRecipNearClip(); - - if (FrontEndMenuManager.m_bGameNotLoaded) { - CPad::UpdatePads(); - FrontEndMenuManager.Process(); - } else { - PUSH_MEMID(MEMID_GAME_PROCESS); - CPointLights::InitPerFrame(); - tbStartTimer(0, "CGame::Process"); - CGame::Process(); - tbEndTimer("CGame::Process"); - POP_MEMID(); - - tbStartTimer(0, "DMAudio.Service"); - DMAudio.Service(); - tbEndTimer("DMAudio.Service"); - } - - if (RsGlobal.quit) - return; -#else - PUSH_MEMID(MEMID_GAME_PROCESS); CPointLights::InitPerFrame(); @@ -1610,7 +1544,6 @@ Idle(void *arg) tbStartTimer(0, "DMAudio.Service"); DMAudio.Service(); tbEndTimer("DMAudio.Service"); -#endif if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){ WANT_TO_LOAD = false; @@ -1630,21 +1563,20 @@ Idle(void *arg) PUSH_MEMID(MEMID_RENDER); - if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) && - TheCamera.GetScreenFadeStatus() != FADE_2) + if(!FrontEndMenuManager.m_bMenuActive && TheCamera.GetScreenFadeStatus() != FADE_2) { -#if defined(GTA_PC) && !defined(RW_GL3) && defined(FIX_BUGS) // This is from SA, but it's nice for windowed mode - if (!FrontEndMenuManager.m_bRenderGameInMenu) { - RwV2d pos; - pos.x = SCREEN_WIDTH / 2.0f; - pos.y = SCREEN_HEIGHT / 2.0f; - RsMouseSetPos(&pos); - } +#if defined(GTA_PC) && !defined(RW_GL3) + RwV2d pos; + pos.x = SCREEN_WIDTH / 2.0f; + pos.y = SCREEN_HEIGHT / 2.0f; + RsMouseSetPos(&pos); #endif - PUSH_MEMID(MEMID_RENDERLIST); tbStartTimer(0, "CnstrRenderList"); +#ifdef PC_WATER + CWaterLevel::PreCalcWaterGeometry(); +#endif #ifdef NEW_RENDERER if(gbNewRenderer){ CWorld::AdvanceCurrentScanCode(); // don't think this is even necessary @@ -1657,7 +1589,6 @@ Idle(void *arg) tbStartTimer(0, "PreRender"); CRenderer::PreRender(); tbEndTimer("PreRender"); - POP_MEMID(); #ifdef FIX_BUGS RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this @@ -1712,6 +1643,7 @@ Idle(void *arg) Render2dStuff(); tbEndTimer("Render2dStuff"); }else{ + CDraw::CalculateAspectRatio(); #ifdef ASPECT_RATIO_SCALE CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); #else @@ -1723,10 +1655,6 @@ Idle(void *arg) goto popret; } -#ifdef PS2_SAVE_DIALOG - if (FrontEndMenuManager.m_bMenuActive) - DefinedState(); -#endif tbStartTimer(0, "RenderMenus"); RenderMenus(); tbEndTimer("RenderMenus"); @@ -1743,9 +1671,10 @@ Idle(void *arg) tbStartTimer(0, "Render2dStuff-Fade"); Render2dStuffAfterFade(); tbEndTimer("Render2dStuff-Fade"); - - CCredits::Render(); - + // CCredits::Render(); // They added it to function above and also forgot it here +#ifdef XBOX_MESSAGE_SCREEN + FrontEndMenuManager.DrawOverlays(); +#endif if (gbShowTimebars) tbDisplay(); @@ -1764,10 +1693,7 @@ popret: POP_MEMID(); // MEMID_RENDER void FrontendIdle(void) { -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif - + CDraw::CalculateAspectRatio(); CTimer::Update(); CSprite2d::SetRecipNearClip(); // this should be on InitialiseRenderWare according to PS2 asm. seems like a bug fix CSprite2d::InitPerFrame(); @@ -1778,11 +1704,7 @@ FrontendIdle(void) if(RsGlobal.quit) return; -#ifdef ASPECT_RATIO_SCALE CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); -#else - CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO); -#endif CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, CLEARMODE); if(!RsCameraBeginUpdate(Scene.camera)) @@ -1790,9 +1712,12 @@ FrontendIdle(void) DefinedState(); // seems redundant, but breaks resolution change. RenderMenus(); +#ifdef XBOX_MESSAGE_SCREEN + FrontEndMenuManager.DrawOverlays(); +#endif DoFade(); Render2dStuffAfterFade(); -// CFont::DrawFonts(); // redundant + CFont::DrawFonts(); DoRWStuffEndOfFrame(); } @@ -1800,7 +1725,7 @@ void InitialiseGame(void) { LoadingScreen(nil, nil, "loadsc0"); - CGame::Initialise("DATA\\GTA3.DAT"); + CGame::Initialise("DATA\\GTA_VC.DAT"); } RsEventStatus @@ -1863,11 +1788,7 @@ AppEventHandler(RsEvent event, void *param) case rsFRONTENDIDLE: { -#ifdef PS2_SAVE_DIALOG - Idle((void*)1); -#else FrontendIdle(); -#endif return rsEVENTPROCESSED; } @@ -1893,20 +1814,20 @@ TheModelViewer(void) #if (defined(GTA_PS2) || defined(GTA_XBOX)) //TODO #else - // This is III Mobile code. III Xbox code run it like main function, which is impossible to implement on PC's state machine implementation. - // Also we want 2D things initialized in here to print animation ids etc., our additions for that marked with X -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); // X -#endif + // This is not original. Because; + // 1- We want 2D things to be initalized, whereas original AnimViewer doesn't use them. my additions marked with X + // 2- VC Mobile code run it like main function(as opposed to III and LCS), so it has it's own loop inside it, but our func. already called in a loop. + + CDraw::CalculateAspectRatio(); // X CAnimViewer::Update(); - CTimer::Update(); SetLightsWithTimeOfDayColour(Scene.world); CRenderer::ConstructRenderList(); - DoRWStuffStartOfFrame(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(), + DoRWStuffStartOfFrame(CTimeCycle::GetSkyTopRed()*0.5f, CTimeCycle::GetSkyTopGreen()*0.5f, CTimeCycle::GetSkyTopBlue()*0.5f, CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), 255); + CSprite2d::SetRecipNearClip(); // X CSprite2d::InitPerFrame(); // X CFont::InitPerFrame(); // X DefinedState(); @@ -1914,6 +1835,7 @@ TheModelViewer(void) CAnimViewer::Render(); Render2dStuff(); // X DoRWStuffEndOfFrame(); + CTimer::Update(); #endif } #endif @@ -1928,17 +1850,14 @@ void TheGame(void) CTimer::Initialise(); -#if GTA_VERSION <= GTA3_PS2_160 - CGame::Initialise(); -#else CGame::Initialise("DATA\\GTA3.DAT"); -#endif Const char *splash = GetRandomSplashScreen(); // inlined here LoadingScreen("Starting Game", NULL, splash); #ifdef GTA_PS2 + // TODO(MIAMI): not checked yet if ( TheMemoryCard.CheckCardInserted(CARD_ONE) == CMemoryCard::NO_ERR_SUCCESS && TheMemoryCard.ChangeDirectory(CARD_ONE, TheMemoryCard.Cards[CARD_ONE].dir) && TheMemoryCard.FindMostRecentFileName(CARD_ONE, TheMemoryCard.MostRecentFile) == true @@ -1947,9 +1866,9 @@ void TheGame(void) strcpy(TheMemoryCard.LoadFileName, TheMemoryCard.MostRecentFile); TheMemoryCard.b_FoundRecentSavedGameWantToLoad = true; - if (CMenuManager::m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad()) + if (FrontEndMenuManager.m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad()) { - CMenuManager::m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad(); + FrontEndMenuManager.m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad(); TheText.Unload(); TheText.Load(); } @@ -1962,7 +1881,7 @@ void TheGame(void) while (true) { - if (WANT_TO_LOAD) + if (FOUND_GAME_TO_LOAD) { Const char *splash1 = GetLevelSplashScreen(CGame::currLevel); LoadSplash(splash1); @@ -1998,13 +1917,12 @@ void TheGame(void) PUSH_MEMID(MEMID_RENDER); + CRenderer::ConstructRenderList(); + if ((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true) && TheCamera.GetScreenFadeStatus() != FADE_2 ) { - - PUSH_MEMID(MEMID_RENDERLIST); - CRenderer::ConstructRenderList(); CRenderer::PreRender(); - POP_MEMID(); + // TODO(MIAMI): something ps2all specific #ifdef FIX_BUGS // This has to be done BEFORE RwCameraBeginUpdate @@ -2035,11 +1953,7 @@ void TheGame(void) } else { -#ifdef ASPECT_RATIO_SCALE - CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); -#else - CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO); -#endif + CameraSize(Scene.camera, NULL, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); CVisibilityPlugins::SetRenderWareCamera(Scene.camera); RwCameraClear(Scene.camera, &gColourTop, CLEARMODE); RsCameraBeginUpdate(Scene.camera); @@ -2102,10 +2016,6 @@ void TheGame(void) void SystemInit() { -#ifdef __MWERKS__ - mwInit(); -#endif - #ifdef USE_CUSTOM_ALLOCATOR InitMemoryMgr(); #endif @@ -2115,7 +2025,7 @@ void SystemInit() char path[256]; - sprintf(path, "cdrom0:\\%s%s;1", "SYSTEM\\", "IOPRP23.IMG"); + sprintf(path, "cdrom0:\\%s%s;1", "SYSTEM\\", "IOPRP241.IMG"); sceSifInitRpc(0); @@ -2129,11 +2039,7 @@ void SystemInit() CFileMgr::InitCdSystem(); sceFsReset(); -#endif - CFileMgr::Initialise(); - -#ifdef GTA_PS2 CFileMgr::InitCd(); char modulepath[256]; @@ -2167,6 +2073,16 @@ void SystemInit() strcat(modulepath, "SYSTEM\\"); strcat(modulepath, "MCSERV.IRX"); LoadModule(modulepath); + + strcpy(modulepath, "cdrom0:\\"); + strcat(modulepath, "SYSTEM\\"); + strcat(modulepath, "CDSTREAM.IRX"); + LoadModule(modulepath); + + strcpy(modulepath, "cdrom0:\\"); + strcat(modulepath, "SYSTEM\\"); + strcat(modulepath, "SAMPMAN2.IRX"); + LoadModule(modulepath); #endif @@ -2193,30 +2109,31 @@ void SystemInit() CGame::frenchGame = false; CGame::germanGame = false; CGame::nastyGame = true; - CMenuManager::m_PrefsAllowNastyGame = true; + FrontEndMenuManager.m_PrefsAllowNastyGame = true; #ifdef GTA_PS2 + // TODO(MIAMI): this code probably went elsewhere? int32 lang = sceScfGetLanguage(); if ( lang == SCE_ITALIAN_LANGUAGE ) - CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_ITALIAN; else if ( lang == SCE_SPANISH_LANGUAGE ) - CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_SPANISH; else if ( lang == SCE_GERMAN_LANGUAGE ) { CGame::germanGame = true; CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; - CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_GERMAN; } else if ( lang == SCE_FRENCH_LANGUAGE ) { CGame::frenchGame = true; CGame::nastyGame = false; - CMenuManager::m_PrefsAllowNastyGame = false; - CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH; + FrontEndMenuManager.m_PrefsAllowNastyGame = false; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_FRENCH; } else - CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN; + FrontEndMenuManager.m_PrefsLanguage = LANGUAGE_AMERICAN; FrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame(); #else @@ -2242,43 +2159,35 @@ extern "C" void WaitVBlank(void) while(startFrame == frameCount); } -void GameInit() +void GameInit(bool onlyRW) { - if ( !gameAlreadyInitialised ) + if(onlyRW) { #ifdef GTA_PS2 - char path[256]; - - strcpy(path, "cdrom0:\\"); - strcat(path, "SYSTEM\\"); - strcat(path, "CDSTREAM.IRX"); - LoadModule(path); - - strcpy(path, "cdrom0:\\"); - strcat(path, "SYSTEM\\"); - strcat(path, "SAMPMAN.IRX"); - LoadModule(path); - - strcpy(path, "cdrom0:\\"); - strcat(path, "SYSTEM\\"); - strcat(path, "MUSICSTR.IRX"); - LoadModule(path); + Initialise3D(nil); +#else + Initialise3D(nil); //TODO: window parameter #endif - CdStreamInit(MAX_CDCHANNELS); - + gameAlreadyInitialised = true; + } + else + { + if ( !gameAlreadyInitialised ) #ifdef GTA_PS2 - Initialise3D(); //no params + Initialise3D(nil); #else - //TODO + Initialise3D(nil); //TODO: window parameter #endif - + } + #ifdef GTA_PS2 char *files[] = { "\\ANIM\\CUTS.IMG;1", "\\ANIM\\CUTS.DIR;1", "\\ANIM\\PED.IFP;1", - "\\MODELS\\FRONTEND.TXD;1", + "\\MODELS\\FRONTEN1.TXD;1", + "\\MODELS\\FRONTEN2.TXD;1", "\\MODELS\\FONTS.TXD;1", "\\MODELS\\HUD.TXD;1", "\\MODELS\\PARTICLE.TXD;1", @@ -2295,6 +2204,96 @@ void GameInit() #else "\\TEXT\\AMERICAN.GXT;1", #endif + "\\MODELS\\COLL\\GENERIC.COL;1", + "\\MODELS\\COLL\\VEHICLES.COL;1", + "\\MODELS\\COLL\\PEDS.COL;1", + "\\MODELS\\COLL\\WEAPONS.COL;1", + "\\MODELS\\GENERIC\\AIR_VLO.DFF;1", + "\\MODELS\\GENERIC\\WHEELS.DFF;1", + "\\MODELS\\GENERIC\\ARROW.DFF;1", + "\\MODELS\\GENERIC\\ZONECYLB.DFF;1", + "\\DATA\\HANDLING.CFG;1", + "\\DATA\\SURFACE.DAT;1", + "\\DATA\\PEDSTATS.DAT;1", + "\\DATA\\TIMECYC.DAT;1", + "\\DATA\\PARTICLE.CFG;1", + "\\DATA\\DEFAULT.DAT;1", + "\\DATA\\DEFAULT.IDE;1", + "\\DATA\\GTA_VC.DAT;1", + "\\DATA\\OBJECT.DAT;1", + "\\DATA\\MAP.ZON;1", + "\\DATA\\NAVIG.ZON;1", + "\\DATA\\INFO.ZON;1", + "\\DATA\\WATERPRO.DAT;1", + "\\DATA\\MAIN.SCM;1", + "\\DATA\\CARCOLS.DAT;1", + "\\DATA\\PED.DAT;1", + "\\DATA\\FISTFITE.DAT;1", + "\\DATA\\WEAPON.DAT;1", + "\\DATA\\PEDGRP.DAT;1", + "\\DATA\\PATHS\\FLIGHT.DAT;1", + "\\DATA\\PATHS\\FLIGHT2.DAT;1", + "\\DATA\\PATHS\\FLIGHT3.DAT;1", + "\\DATA\\PATHS\\SPATH0.DAT;1", + "\\DATA\\MAPS\\LITTLEHA\\LITTLEHA.IDE;1", + "\\DATA\\MAPS\\DOWNTOWN\\DOWNTOWN.IDE;1", + "\\DATA\\MAPS\\DOWNTOWS\\DOWNTOWS.IDE;1", + "\\DATA\\MAPS\\DOCKS\\DOCKS.IDE;1", + "\\DATA\\MAPS\\WASHINTN\\WASHINTN.IDE;1", + "\\DATA\\MAPS\\WASHINTS\\WASHINTS.IDE;1", + "\\DATA\\MAPS\\OCEANDRV\\OCEANDRV.IDE;1", + "\\DATA\\MAPS\\OCEANDN\\OCEANDN.IDE;1", + "\\DATA\\MAPS\\GOLF\\GOLF.IDE;1", + "\\DATA\\MAPS\\BRIDGE\\BRIDGE.IDE;1", + "\\DATA\\MAPS\\STARISL\\STARISL.IDE;1", + "\\DATA\\MAPS\\NBEACHBT\\NBEACHBT.IDE;1", + "\\DATA\\MAPS\\NBEACHW\\NBEACHW.IDE;1", + "\\DATA\\MAPS\\NBEACH\\NBEACH.IDE;1", + "\\DATA\\MAPS\\BANK\\BANK.IDE;1", + "\\DATA\\MAPS\\MALL\\MALL.IDE;1", + "\\DATA\\MAPS\\YACHT\\YACHT.IDE;1", + "\\DATA\\MAPS\\CISLAND\\CISLAND.IDE;1", + "\\DATA\\MAPS\\CLUB\\CLUB.IDE;1", + "\\DATA\\MAPS\\HOTEL\\HOTEL.IDE;1", + "\\DATA\\MAPS\\LAWYERS\\LAWYERS.IDE;1", + "\\DATA\\MAPS\\STRIPCLB\\STRIPCLB.IDE;1", + "\\DATA\\MAPS\\AIRPORT\\AIRPORT.IDE;1", + "\\DATA\\MAPS\\HAITI\\HAITI.IDE;1", + "\\DATA\\MAPS\\HAITIN\\HAITIN.IDE;1", + "\\DATA\\MAPS\\CONCERTH\\CONCERTH.IDE;1", + "\\DATA\\MAPS\\MANSION\\MANSION.IDE;1", + "\\DATA\\MAPS\\ISLANDSF\\ISLANDSF.IDE;1", + "\\DATA\\MAPS\\LITTLEHA\\LITTLEHA.IPL;1", + "\\DATA\\MAPS\\DOWNTOWN\\DOWNTOWN.IPL;1", + "\\DATA\\MAPS\\DOWNTOWS\\DOWNTOWS.IPL;1", + "\\DATA\\MAPS\\DOCKS\\DOCKS.IPL;1", + "\\DATA\\MAPS\\WASHINTN\\WASHINTN.IPL;1", + "\\DATA\\MAPS\\WASHINTS\\WASHINTS.IPL;1", + "\\DATA\\MAPS\\OCEANDRV\\OCEANDRV.IPL;1", + "\\DATA\\MAPS\\OCEANDN\\OCEANDN.IPL;1", + "\\DATA\\MAPS\\GOLF\\GOLF.IPL;1", + "\\DATA\\MAPS\\BRIDGE\\BRIDGE.IPL;1", + "\\DATA\\MAPS\\STARISL\\STARISL.IPL;1", + "\\DATA\\MAPS\\NBEACHBT\\NBEACHBT.IPL;1", + "\\DATA\\MAPS\\NBEACH\\NBEACH.IPL;1", + "\\DATA\\MAPS\\NBEACHW\\NBEACHW.IPL;1", + "\\DATA\\MAPS\\CISLAND\\CISLAND.IPL;1", + "\\DATA\\MAPS\\AIRPORT\\AIRPORT.IPL;1", + "\\DATA\\MAPS\\HAITI\\HAITI.IPL;1", + "\\DATA\\MAPS\\HAITIN\\HAITIN.IPL;1", + "\\DATA\\MAPS\\ISLANDSF\\ISLANDSF.IPL;1", + "\\DATA\\MAPS\\BANK\\BANK.IPL;1", + "\\DATA\\MAPS\\MALL\\MALL.IPL;1", + "\\DATA\\MAPS\\YACHT\\YACHT.IPL;1", + "\\DATA\\MAPS\\CLUB\\CLUB.IPL;1", + "\\DATA\\MAPS\\HOTEL\\HOTEL.IPL;1", + "\\DATA\\MAPS\\LAWYERS\\LAWYERS.IPL;1", + "\\DATA\\MAPS\\STRIPCLB\\STRIPCLB.IPL;1", + "\\DATA\\MAPS\\CONCERTH\\CONCERTH.IPL;1", + "\\DATA\\MAPS\\MANSION\\MANSION.IPL;1", + "\\DATA\\MAPS\\GENERIC.IDE;1", + "\\DATA\\OCCLU.IPL;1", + "\\DATA\\MAPS\\PATHS.IPL;1", "\\TXD\\LOADSC0.TXD;1", "\\TXD\\LOADSC1.TXD;1", "\\TXD\\LOADSC2.TXD;1", @@ -2309,90 +2308,17 @@ void GameInit() "\\TXD\\LOADSC11.TXD;1", "\\TXD\\LOADSC12.TXD;1", "\\TXD\\LOADSC13.TXD;1", - "\\TXD\\LOADSC14.TXD;1", - "\\TXD\\LOADSC15.TXD;1", - "\\TXD\\LOADSC16.TXD;1", - "\\TXD\\LOADSC17.TXD;1", - "\\TXD\\LOADSC18.TXD;1", - "\\TXD\\LOADSC19.TXD;1", - "\\TXD\\LOADSC20.TXD;1", - "\\TXD\\LOADSC21.TXD;1", - "\\TXD\\LOADSC22.TXD;1", - "\\TXD\\LOADSC23.TXD;1", - "\\TXD\\LOADSC24.TXD;1", - "\\TXD\\LOADSC25.TXD;1", - "\\TXD\\NEWS.TXD;1", - "\\MODELS\\COLL\\GENERIC.COL;1", - "\\MODELS\\COLL\\INDUST.COL;1", - "\\MODELS\\COLL\\COMMER.COL;1", - "\\MODELS\\COLL\\SUBURB.COL;1", - "\\MODELS\\COLL\\WEAPONS.COL;1", - "\\MODELS\\COLL\\VEHICLES.COL;1", - "\\MODELS\\COLL\\PEDS.COL;1", - "\\MODELS\\GENERIC\\AIR_VLO.DFF;1", - "\\MODELS\\GENERIC\\WEAPONS.DFF;1", - "\\MODELS\\GENERIC\\WHEELS.DFF;1", - "\\MODELS\\GENERIC\\LOPLYGUY.DFF;1", - "\\MODELS\\GENERIC\\ARROW.DFF;1", - "\\MODELS\\GENERIC\\ZONECYLB.DFF;1", - "\\DATA\\MAPS\\COMNTOP.IPL;1", - "\\DATA\\MAPS\\COMNBTM.IPL;1", - "\\DATA\\MAPS\\COMSE.IPL;1", - "\\DATA\\MAPS\\COMSW.IPL;1", - "\\DATA\\MAPS\\CULL.IPL;1", - "\\DATA\\MAPS\\INDUSTNE.IPL;1", - "\\DATA\\MAPS\\INDUSTNW.IPL;1", - "\\DATA\\MAPS\\INDUSTSE.IPL;1", - "\\DATA\\MAPS\\INDUSTSW.IPL;1", - "\\DATA\\MAPS\\SUBURBNE.IPL;1", - "\\DATA\\MAPS\\SUBURBSW.IPL;1", - "\\DATA\\MAPS\\OVERVIEW.IPL;1", - "\\DATA\\MAPS\\PROPS.IPL;1", - "\\DATA\\MAPS\\GTA3.IDE;1", - "\\DATA\\PATHS\\FLIGHT.DAT;1", - "\\DATA\\PATHS\\FLIGHT2.DAT;1", - "\\DATA\\PATHS\\FLIGHT3.DAT;1", - "\\DATA\\PATHS\\FLIGHT4.DAT;1", - "\\DATA\\PATHS\\TRACKS.DAT;1", - "\\DATA\\PATHS\\TRACKS2.DAT;1", - "\\DATA\\PATHS\\CHASE0.DAT;1", - "\\DATA\\PATHS\\CHASE1.DAT;1", - "\\DATA\\PATHS\\CHASE2.DAT;1", - "\\DATA\\PATHS\\CHASE3.DAT;1", - "\\DATA\\PATHS\\CHASE4.DAT;1", - "\\DATA\\PATHS\\CHASE5.DAT;1", - "\\DATA\\PATHS\\CHASE6.DAT;1", - "\\DATA\\PATHS\\CHASE7.DAT;1", - "\\DATA\\PATHS\\CHASE10.DAT;1", - "\\DATA\\PATHS\\CHASE11.DAT;1", - "\\DATA\\PATHS\\CHASE14.DAT;1", - "\\DATA\\PATHS\\CHASE16.DAT;1", - "\\DATA\\PATHS\\CHASE18.DAT;1", - "\\DATA\\PATHS\\CHASE19.DAT;1" + "\\TXD\\SPLASH1.TXD;1" }; for ( int32 i = 0; i < ARRAY_SIZE(files); i++ ) SkyRegisterFileOnCd([i]); #endif - CreateDebugFont(); - #ifdef GTA_PS2 AddIntcHandler(INTC_VBLANK_S, VBlankCounter, 0); #endif - CameraSize(Scene.camera, NULL, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO); - - CSprite2d::SetRecipNearClip(); - CTxdStore::Initialise(); - - PUSH_MEMID(MEMID_TEXTURES); - CFont::Initialise(); - CHud::Initialise(); - POP_MEMID(); - - ValidateVersion(); - #ifdef GTA_PS2 sceCdCLOCK rtc; sceCdReadClock(&rtc); @@ -2404,10 +2330,13 @@ void GameInit() //TODO: mysrand(); #endif - gameAlreadyInitialised = true; + // gameAlreadyInitialised = true; // why is this gone? } } +int32 SkipAllMPEGs; +int32 gMemoryStickLoadOK; + void PlayIntroMPEGs() { #ifdef GTA_PS2 @@ -2416,17 +2345,33 @@ void PlayIntroMPEGs() InitMPEGPlayer(); + float skipTime; // wrong type, should be int #ifdef GTA_PAL - PlayMPEG("cdrom0:\\MOVIES\\DMAPAL.PSS;1", false); - - if (CGame::frenchGame || CGame::germanGame) - PlayMPEG("cdrom0:\\MOVIES\\INTROPAF.PSS;1", true); + if(gMemoryStickLoadOK) + skipTime = 2500000; else - PlayMPEG("cdrom0:\\MOVIES\\INTROPAL.PSS;1", true); + skipTime = 5300000; + + if(!SkipAllMPEGs) + PlayMPEG("cdrom0:\\MOVIES\\VCPAL.PSS;1", false, unk); + + if(!SkipAllMPEGs){ + SkipAllMPEGs = true; + PlayMPEG("cdrom0:\\MOVIES\\VICEPAL.PSS;1", true, 0); + } #else - PlayMPEG("cdrom0:\\MOVIES\\DMANTSC.PSS;1", false); + if(gMemoryStickLoadOK) + skipTime = 2750000; + else + skipTime = 5500000; + + if(!SkipAllMPEGs) + PlayMPEG("cdrom0:\\MOVIES\\VCNTSC.PSS;1", false, unk); - PlayMPEG("cdrom0:\\MOVIES\\INTRNTSC.PSS;1", true); + if(!SkipAllMPEGs){ + SkipAllMPEGs = true; + PlayMPEG("cdrom0:\\MOVIES\\VICE.PSS;1", true, 0); + } #endif ShutdownMPEGPlayer(); @@ -2446,13 +2391,16 @@ main(int argc, char *argv[]) #endif SystemInit(); - + + if(RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR) + return 0; + #ifdef GTA_PS2 int32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE); if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT ) { - GameInit(); + GameInit(true); TheText.Unload(); TheText.Load(); @@ -2460,24 +2408,24 @@ main(int argc, char *argv[]) CFont::Initialise(); FrontEndMenuManager.DrawMemoryCardStartUpMenus(); - }else if(r == CMemoryCard::ERR_OPENNOENTRY || r == CMemoryCard::ERR_NONE){ - // eh? - } + }else if(r == CMemoryCard::ERR_OPENNOENTRY) + gMemoryStickLoadOK = false; + else if(r == CMemoryCard::ERR_NONE) + gMemoryStickLoadOK = true; #endif PlayIntroMPEGs(); - GameInit(); + GameInit(false); + + frameCount = 0; + while(frameCount < 100); + + CGame::InitialiseOnceAfterRW(); - if ( CGame::frenchGame || CGame::germanGame ) - LoadingScreen(NULL, version_name, "loadsc24"); - else - LoadingScreen(NULL, version_name, "loadsc0"); - - DMAudio.Initialise(); - TheGame(); - + +#if 0 // maybe ifndef FINAL or MASTER? CGame::ShutDown(); RwEngineStop(); @@ -2487,7 +2435,7 @@ main(int argc, char *argv[]) #ifdef __MWERKS__ mwExit(); // metrowerks shutdown #endif - +#endif return 0; } #endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index b7d89363..b0183408 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -10,18 +10,20 @@ #endif #endif #include "Renderer.h" +#include "Occlusion.h" #include "Credits.h" #include "Camera.h" #include "Weather.h" +#include "Timecycle.h" #include "Clock.h" #include "World.h" #include "Vehicle.h" #include "ModelIndices.h" #include "Streaming.h" -#include "PathFind.h" #include "Boat.h" #include "Heli.h" #include "Automobile.h" +#include "Bike.h" #include "Console.h" #include "Debug.h" #include "Hud.h" @@ -34,6 +36,7 @@ #include "WaterLevel.h" #include "main.h" #include "Script.h" +#include "MBlur.h" #include "postfx.h" #include "custompipes.h" #include "MemoryHeap.h" @@ -54,6 +57,8 @@ #include <stdarg.h> #endif +#include <list> + #ifdef RWLIBS extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList); #endif @@ -88,6 +93,8 @@ mysrand(unsigned int seed) #ifdef CUSTOM_FRONTEND_OPTIONS #include "frontendoption.h" + + #ifdef MORE_LANGUAGES void LangPolSelect(int8 action) { @@ -125,8 +132,8 @@ CustomFrontendOptionsPopulate(void) { // Most of custom options are done statically in MenuScreensCustom.cpp, we add them here only if they're dependent to extra files - // These work only if we have neo folder int fd; + // These work only if we have neo folder, so they're dynamically added #ifdef EXTENDED_PIPELINES const char *vehPipelineNames[] = { "FED_MFX", "FED_NEO" }; const char *off_on[] = { "FEM_OFF", "FEM_ON" }; @@ -134,49 +141,52 @@ CustomFrontendOptionsPopulate(void) if (fd) { #ifdef GRAPHICS_MENU_OPTIONS FrontendOptionSetCursor(MENUPAGE_GRAPHICS_SETTINGS, -3, false); - FrontendOptionAddSelect("FED_VPL", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, "Graphics", "VehiclePipeline"); - FrontendOptionAddSelect("FED_PRM", off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, "Graphics", "NeoRimLight"); - FrontendOptionAddSelect("FED_WLM", off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, "Graphics", "NeoLightMaps"); - FrontendOptionAddSelect("FED_RGL", off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, "Graphics", "NeoRoadGloss"); + FrontendOptionAddSelect("FED_VPL", 0, 0, MENUALIGN_LEFT, vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, "Graphics", "VehiclePipeline"); + FrontendOptionAddSelect("FED_PRM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, "Graphics", "NeoRimLight"); + FrontendOptionAddSelect("FED_WLM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, "Graphics", "NeoLightMaps"); + FrontendOptionAddSelect("FED_RGL", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, "Graphics", "NeoRoadGloss"); #else FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3, false); - FrontendOptionAddSelect("FED_VPL", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, "Graphics", "VehiclePipeline"); - FrontendOptionAddSelect("FED_PRM", off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, "Graphics", "NeoRimLight"); - FrontendOptionAddSelect("FED_WLM", off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, "Graphics", "NeoLightMaps"); - FrontendOptionAddSelect("FED_RGL", off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, "Graphics", "NeoRoadGloss"); + FrontendOptionAddSelect("FED_VPL", 0, 0, MENUALIGN_LEFT, vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, "Graphics", "VehiclePipeline"); + FrontendOptionAddSelect("FED_PRM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, "Graphics", "NeoRimLight"); + FrontendOptionAddSelect("FED_WLM", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, "Graphics", "NeoLightMaps"); + FrontendOptionAddSelect("FED_RGL", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, "Graphics", "NeoRoadGloss"); #endif CFileMgr::CloseFile(fd); } #endif - // Add outsourced language translations, if files are found #ifdef MORE_LANGUAGES int fd2; FrontendOptionSetCursor(MENUPAGE_LANGUAGE_SETTINGS, 5, false); - if (fd = CFileMgr::OpenFile("text/polish.gxt","r")) { - if (fd2 = CFileMgr::OpenFile("models/fonts_p.txd","r")) { - FrontendOptionAddDynamic("FEL_POL", nil, nil, LangPolSelect, nil, nil); +#if 0 + if (fd = CFileMgr::OpenFile("text/polish.gxt")) { + if (fd2 = CFileMgr::OpenFile("models/fonts_p.txd")) { + FrontendOptionAddDynamic("FEL_POL", 0, 0, MENUALIGN_CENTER, nil, nil, LangPolSelect, nil, nil); CFileMgr::CloseFile(fd2); } CFileMgr::CloseFile(fd); } +#endif - if (fd = CFileMgr::OpenFile("text/russian.gxt","r")) { - if (fd2 = CFileMgr::OpenFile("models/fonts_r.txd","r")) { - FrontendOptionAddDynamic("FEL_RUS", nil, nil, LangRusSelect, nil, nil); + if (fd = CFileMgr::OpenFile("text/russian.gxt")) { + if (fd2 = CFileMgr::OpenFile("models/fonts_r.txd")) { + FrontendOptionAddDynamic("FEL_RUS", 0, 0, MENUALIGN_CENTER, nil, nil, LangRusSelect, nil, nil); CFileMgr::CloseFile(fd2); } CFileMgr::CloseFile(fd); } - if (fd = CFileMgr::OpenFile("text/japanese.gxt","r")) { - if (fd2 = CFileMgr::OpenFile("models/fonts_j.txd","r")) { - FrontendOptionAddDynamic("FEL_JAP", nil, nil, LangJapSelect, nil, nil); +#if 0 + if (fd = CFileMgr::OpenFile("text/japanese.gxt")) { + if (fd2 = CFileMgr::OpenFile("models/fonts_j.txd")) { + FrontendOptionAddDynamic("FEL_JAP", 0, 0, MENUALIGN_CENTER, nil, nil, LangJapSelect, nil, nil); CFileMgr::CloseFile(fd2); } CFileMgr::CloseFile(fd); } #endif +#endif } #endif @@ -185,7 +195,7 @@ CustomFrontendOptionsPopulate(void) #define MINI_CASE_SENSITIVE #include "ini.h" -mINI::INIFile ini("re3.ini"); +mINI::INIFile ini("reVC.ini"); mINI::INIStructure cfg; bool ReadIniIfExists(const char *cat, const char *key, uint32 *out) @@ -306,14 +316,14 @@ void StoreIni(const char *cat, const char *key, char *val, int size) } const char *iniControllerActions[] = { "PED_FIREWEAPON", "PED_CYCLE_WEAPON_RIGHT", "PED_CYCLE_WEAPON_LEFT", "GO_FORWARD", "GO_BACK", "GO_LEFT", "GO_RIGHT", "PED_SNIPER_ZOOM_IN", - "PED_SNIPER_ZOOM_OUT", "VEHICLE_ENTER_EXIT", "CAMERA_CHANGE_VIEW_ALL_SITUATIONS", "PED_JUMPING", "PED_SPRINT", "PED_LOOKBEHIND", + "PED_SNIPER_ZOOM_OUT", "VEHICLE_ENTER_EXIT", "CAMERA_CHANGE_VIEW_ALL_SITUATIONS", "PED_JUMPING", "PED_SPRINT", "PED_LOOKBEHIND", "PED_DUCK", "PED_ANSWER_PHONE", #ifdef BIND_VEHICLE_FIREWEAPON "VEHICLE_FIREWEAPON", #endif "VEHICLE_ACCELERATE", "VEHICLE_BRAKE", "VEHICLE_CHANGE_RADIO_STATION", "VEHICLE_HORN", "TOGGLE_SUBMISSIONS", "VEHICLE_HANDBRAKE", "PED_1RST_PERSON_LOOK_LEFT", "PED_1RST_PERSON_LOOK_RIGHT", "VEHICLE_LOOKLEFT", "VEHICLE_LOOKRIGHT", "VEHICLE_LOOKBEHIND", "VEHICLE_TURRETLEFT", "VEHICLE_TURRETRIGHT", "VEHICLE_TURRETUP", "VEHICLE_TURRETDOWN", "PED_CYCLE_TARGET_LEFT", "PED_CYCLE_TARGET_RIGHT", "PED_CENTER_CAMERA_BEHIND_PLAYER", "PED_LOCK_TARGET", "NETWORK_TALK", "PED_1RST_PERSON_LOOK_UP", "PED_1RST_PERSON_LOOK_DOWN", - "_CONTROLLERACTION_36", "TOGGLE_DPAD", "SWITCH_DEBUG_CAM_ON", "TAKE_SCREEN_SHOT", "SHOW_MOUSE_POINTER_TOGGLE" }; + "_CONTROLLERACTION_36", "TOGGLE_DPAD", "SWITCH_DEBUG_CAM_ON", "TAKE_SCREEN_SHOT", "SHOW_MOUSE_POINTER_TOGGLE", "UNKNOWN_ACTION" }; const char *iniControllerTypes[] = { "kbd:", "2ndKbd:", "mouse:", "joy:" }; @@ -413,7 +423,7 @@ void LoadINIControllerSettings() } } } - + ControlsManager.SetControllerKeyAssociatedWithAction((e_ControllerAction)i, contKey, (eControllerType)contType); } } @@ -424,7 +434,7 @@ void SaveINIControllerSettings() { for (int32 i = 0; i < MAX_CONTROLLERACTIONS; i++) { char value[128] = { '\0' }; - + // upper limit should've been GetNumOfSettingsForAction(i), but sadly even R* doesn't use it's own system correctly, and there are gaps between orders. for (int32 j = SETORDER_1; j < MAX_SETORDERS; j++){ @@ -485,13 +495,13 @@ bool LoadINISettings() ReadIniIfExists("Graphics", "VideoMode", &FrontEndMenuManager.m_nDisplayVideoMode); #endif ReadIniIfExists("Controller", "HeadBob1stPerson", &TheCamera.m_bHeadBob); - ReadIniIfExists("Controller", "VerticalMouseSens", &TheCamera.m_fMouseAccelVertical); ReadIniIfExists("Controller", "HorizantalMouseSens", &TheCamera.m_fMouseAccelHorzntl); ReadIniIfExists("Controller", "InvertMouseVertically", &MousePointerStateHelper.bInvertVertically); ReadIniIfExists("Controller", "DisableMouseSteering", &CVehicle::m_bDisableMouseSteering); ReadIniIfExists("Controller", "Vibration", &FrontEndMenuManager.m_PrefsUseVibration); ReadIniIfExists("Audio", "SfxVolume", &FrontEndMenuManager.m_PrefsSfxVolume); ReadIniIfExists("Audio", "MusicVolume", &FrontEndMenuManager.m_PrefsMusicVolume); + ReadIniIfExists("Audio", "MP3BoostVolume", &FrontEndMenuManager.m_PrefsMP3BoostVolume); ReadIniIfExists("Audio", "Radio", &FrontEndMenuManager.m_PrefsRadioStation); ReadIniIfExists("Audio", "SpeakerType", &FrontEndMenuManager.m_PrefsSpeakers); ReadIniIfExists("Audio", "Provider", &FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); @@ -500,12 +510,17 @@ bool LoadINISettings() ReadIniIfExists("Display", "DrawDistance", &FrontEndMenuManager.m_PrefsLOD); ReadIniIfExists("Display", "Subtitles", &FrontEndMenuManager.m_PrefsShowSubtitles); ReadIniIfExists("Graphics", "AspectRatio", &FrontEndMenuManager.m_PrefsUseWideScreen); - ReadIniIfExists("Graphics", "VSync", &FrontEndMenuManager.m_PrefsVsyncDisp); ReadIniIfExists("Graphics", "FrameLimiter", &FrontEndMenuManager.m_PrefsFrameLimiter); +#ifdef LEGACY_MENU_OPTIONS + ReadIniIfExists("Graphics", "VSync", &FrontEndMenuManager.m_PrefsVsyncDisp); ReadIniIfExists("Graphics", "Trails", &CMBlur::BlurOn); +#endif ReadIniIfExists("General", "SkinFile", FrontEndMenuManager.m_PrefsSkinFile, 256); ReadIniIfExists("Controller", "Method", &FrontEndMenuManager.m_ControlMethod); ReadIniIfExists("General", "Language", &FrontEndMenuManager.m_PrefsLanguage); + ReadIniIfExists("Display", "ShowHud", &FrontEndMenuManager.m_PrefsShowHud); + ReadIniIfExists("Display", "RadarMode", &FrontEndMenuManager.m_PrefsRadarMode); + ReadIniIfExists("Display", "ShowLegends", &FrontEndMenuManager.m_PrefsShowLegends); #ifdef EXTENDED_COLOURFILTER ReadIniIfExists("CustomPipesValues", "PostFXIntensity", &CPostFX::Intensity); @@ -517,6 +532,7 @@ bool LoadINISettings() ReadIniIfExists("CustomPipesValues", "LightmapMult", &CustomPipes::LightmapMult); ReadIniIfExists("CustomPipesValues", "GlossMult", &CustomPipes::GlossMult); #endif + ReadIniIfExists("Rendering", "BackfaceCulling", &gBackfaceCulling); #ifdef NEW_RENDERER ReadIniIfExists("Rendering", "NewRenderer", &gbNewRenderer); #endif @@ -567,6 +583,7 @@ bool LoadINISettings() // Fetched in above block, but needs evaluation #ifdef PED_CAR_DENSITY_SLIDERS CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * CIniFile::PedNumberMultiplier; + CPopulation::MaxNumberOfPedsInUseInterior = DEFAULT_MAX_NUMBER_OF_PEDS_INTERIOR * CIniFile::PedNumberMultiplier; CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS * CIniFile::CarNumberMultiplier; #endif @@ -585,13 +602,13 @@ void SaveINISettings() StoreIni("Graphics", "VideoMode", FrontEndMenuManager.m_nDisplayVideoMode); #endif StoreIni("Controller", "HeadBob1stPerson", TheCamera.m_bHeadBob); - StoreIni("Controller", "VerticalMouseSens", TheCamera.m_fMouseAccelVertical); StoreIni("Controller", "HorizantalMouseSens", TheCamera.m_fMouseAccelHorzntl); StoreIni("Controller", "InvertMouseVertically", MousePointerStateHelper.bInvertVertically); StoreIni("Controller", "DisableMouseSteering", CVehicle::m_bDisableMouseSteering); StoreIni("Controller", "Vibration", FrontEndMenuManager.m_PrefsUseVibration); StoreIni("Audio", "SfxVolume", FrontEndMenuManager.m_PrefsSfxVolume); StoreIni("Audio", "MusicVolume", FrontEndMenuManager.m_PrefsMusicVolume); + StoreIni("Audio", "MP3BoostVolume", FrontEndMenuManager.m_PrefsMP3BoostVolume); StoreIni("Audio", "Radio", FrontEndMenuManager.m_PrefsRadioStation); StoreIni("Audio", "SpeakerType", FrontEndMenuManager.m_PrefsSpeakers); StoreIni("Audio", "Provider", FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); @@ -600,12 +617,17 @@ void SaveINISettings() StoreIni("Display", "DrawDistance", FrontEndMenuManager.m_PrefsLOD); StoreIni("Display", "Subtitles", FrontEndMenuManager.m_PrefsShowSubtitles); StoreIni("Graphics", "AspectRatio", FrontEndMenuManager.m_PrefsUseWideScreen); +#ifdef LEGACY_MENU_OPTIONS StoreIni("Graphics", "VSync", FrontEndMenuManager.m_PrefsVsyncDisp); - StoreIni("Graphics", "FrameLimiter", FrontEndMenuManager.m_PrefsFrameLimiter); StoreIni("Graphics", "Trails", CMBlur::BlurOn); +#endif + StoreIni("Graphics", "FrameLimiter", FrontEndMenuManager.m_PrefsFrameLimiter); StoreIni("General", "SkinFile", FrontEndMenuManager.m_PrefsSkinFile, 256); StoreIni("Controller", "Method", FrontEndMenuManager.m_ControlMethod); StoreIni("General", "Language", FrontEndMenuManager.m_PrefsLanguage); + StoreIni("Display", "ShowHud", FrontEndMenuManager.m_PrefsShowHud); + StoreIni("Display", "RadarMode", FrontEndMenuManager.m_PrefsRadarMode); + StoreIni("Display", "ShowLegends", FrontEndMenuManager.m_PrefsShowLegends); #ifdef EXTENDED_COLOURFILTER StoreIni("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity); @@ -617,6 +639,7 @@ void SaveINISettings() StoreIni("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult); StoreIni("CustomPipesValues", "GlossMult", CustomPipes::GlossMult); #endif + StoreIni("Rendering", "BackfaceCulling", gBackfaceCulling); #ifdef NEW_RENDERER StoreIni("Rendering", "NewRenderer", gbNewRenderer); #endif @@ -658,11 +681,12 @@ void SaveINISettings() #endif - #ifdef DEBUGMENU -void WeaponCheat(); +void WeaponCheat1(); +void WeaponCheat2(); +void WeaponCheat3(); void HealthCheat(); -void TankCheat(); +void VehicleCheat(int model); void BlowUpCarsCheat(); void ChangePlayerCheat(); void MayhemCheat(); @@ -682,7 +706,8 @@ void FastWeatherCheat(); void OnlyRenderWheelsCheat(); void ChittyChittyBangBangCheat(); void StrongGripCheat(); -void NastyLimbsCheat(); +void SpecialCarCheats(); +void PickUpChicksCheat(); DebugMenuEntry *carCol1; DebugMenuEntry *carCol2; @@ -705,6 +730,8 @@ SpawnCar(int id) CVehicle *v; if(CModelInfo::IsBoatModel(id)) v = new CBoat(id, RANDOM_VEHICLE); + else if(CModelInfo::IsBikeModel(id)) + v = new CBike(id, RANDOM_VEHICLE); else v = new CAutomobile(id, RANDOM_VEHICLE); @@ -734,13 +761,15 @@ FixCar(void) if(veh == nil) return; veh->m_fHealth = 1000.0f; - if(!veh->IsCar()) - return; - ((CAutomobile*)veh)->Damage.SetEngineStatus(0); - ((CAutomobile*)veh)->Fix(); + if(veh->IsCar()){ + ((CAutomobile*)veh)->Damage.SetEngineStatus(0); + ((CAutomobile*)veh)->Fix(); + }else if(veh->IsBike()){ + ((CBike*)veh)->Fix(); + } } -#ifdef MENU_MAP +#ifdef MAP_ENHANCEMENTS static void TeleportToWaypoint(void) { @@ -795,20 +824,20 @@ SwitchToMission(void) } #endif -#ifdef USE_CUSTOM_ALLOCATOR -static void ParseHeap(void) { gMainHeap.ParseHeap(); } -#endif - static const char *carnames[] = { - "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony", - "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer", - "securica", "banshee", "predator", "bus", "rhino", "barracks", "train", "chopper", "dodo", "coach", "cabbie", "stallion", "rumpo", "rcbandit", - "bellyup", "mrwongs", "mafia", "yardie", "yakuza", "diablos", "columb", "hoods", "airtrain", "deaddodo", "speeder", "reefer", "panlant", "flatbed", - "yankee", "escape", "borgnine", "toyz", "ghost", + "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "rio", "firetruk", "trash", "stretch", "manana", + "infernus", "voodoo", "pony", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "washing", + "bobcat", "mrwhoop", "bfinject", "hunter", "police", "enforcer", "securica", "banshee", "predator", "bus", + "rhino", "barracks", "cuban", "chopper", "angel", "coach", "cabbie", "stallion", "rumpo", "rcbandit", "romero", + "packer", "sentxs", "admiral", "squalo", "seaspar", "pizzaboy", "gangbur", "airtrain", "deaddodo", "speeder", + "reefer", "tropic", "flatbed", "yankee", "caddy", "zebra", "topfun", "skimmer", "pcj600", "faggio", "freeway", + "rcbaron", "rcraider", "glendale", "oceanic", "sanchez", "sparrow", "patriot", "lovefist", "coastg", "dinghy", + "hermes", "sabre", "sabretur", "pheonix", "walton", "regina", "comet", "deluxo", "burrito", "spand", "marquis", + "baggage", "kaufman", "maverick", "vcnmav", "rancher", "fbiranch", "virgo", "greenwoo", "jetmax", "hotring", + "sandking", "blistac", "polmav", "boxville", "benson", "mesa", "rcgoblin", "hotrina", "hotrinb", + "bloodra", "bloodrb", "vicechee" }; -//#include <list> - static CTweakVar** TweakVarsList; static int TweakVarsListSize = -1; static bool bAddTweakVarsNow = false; @@ -866,11 +895,37 @@ TWEAKSWITCH(CWeather::NewWeatherType, 0, 3, wt, NULL); */ void +switchWeather(void) +{ + CWeather::StreamAfterRainTimer = 0; +} + +void DebugMenuPopulate(void) { if(1){ static const char *weathers[] = { - "Sunny", "Cloudy", "Rainy", "Foggy" + "Sunny", "Cloudy", "Rainy", "Foggy", "Extrasunny", "Stormy" + }; + static const char *extracols[] = { + "1 - Malibu club", + "2 - Strib club", + "3 - Hotel", + "4 - Bank", + "5 - Police HQ", + "6 - Mall", + "7 - Rifle Range", + "8 - Mansion", + "9 - Dirt ring", + "10 - Blood ring", + "11 - Hot ring", + "12 - Concert hall", + "13 - Auntie Poulets", + "14 - Intro at docks", + "15 - Biker bar", + "16 - Intro cafe", + "17 - Studio", + "18", "19", "20", "21", "22", "23", "24" }; DebugMenuEntry *e; e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil); @@ -878,19 +933,22 @@ DebugMenuPopulate(void) e = DebugMenuAddVar("Time & Weather", "Current Minute", &CClock::GetMinutesRef(), [](){ CWeather::InterpolationValue = CClock::GetMinutes()/60.0f; }, 1, 0, 59, nil); DebugMenuEntrySetWrap(e, true); - e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 3, weathers); + e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, switchWeather, 1, 0, 5, weathers); DebugMenuEntrySetWrap(e, true); - e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers); + e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, switchWeather, 1, 0, 5, weathers); DebugMenuEntrySetWrap(e, true); - DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f); + DebugMenuAddVarBool32("Time & Weather", "Extracolours On", &CTimeCycle::m_bExtraColourOn, nil); + DebugMenuAddVar("Time & Weather", "Extracolour", &CTimeCycle::m_ExtraColour, nil, 1, 0, 23, extracols); DebugMenuAddVar("Time & Weather", "Time scale", (float*)&CTimer::GetTimeScale(), nil, 0.1f, 0.0f, 10.0f); - DebugMenuAddCmd("Cheats", "Weapons", WeaponCheat); + DebugMenuAddCmd("Cheats", "Weapon set 1", WeaponCheat1); + DebugMenuAddCmd("Cheats", "Weapon set 2", WeaponCheat2); + DebugMenuAddCmd("Cheats", "Weapon set 3", WeaponCheat3); DebugMenuAddCmd("Cheats", "Money", MoneyCheat); DebugMenuAddCmd("Cheats", "Health", HealthCheat); DebugMenuAddCmd("Cheats", "Wanted level up", WantedLevelUpCheat); DebugMenuAddCmd("Cheats", "Wanted level down", WantedLevelDownCheat); - DebugMenuAddCmd("Cheats", "Tank", TankCheat); + DebugMenuAddCmd("Cheats", "Tank", []() { VehicleCheat(MI_TAXI); }); DebugMenuAddCmd("Cheats", "Blow up cars", BlowUpCarsCheat); DebugMenuAddCmd("Cheats", "Change player", ChangePlayerCheat); DebugMenuAddCmd("Cheats", "Mayhem", MayhemCheat); @@ -907,17 +965,16 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Cheats", "Only render wheels", OnlyRenderWheelsCheat); DebugMenuAddCmd("Cheats", "Chitty chitty bang bang", ChittyChittyBangBangCheat); DebugMenuAddCmd("Cheats", "Strong grip", StrongGripCheat); - DebugMenuAddCmd("Cheats", "Nasty limbs", NastyLimbsCheat); + DebugMenuAddCmd("Cheats", "Special car", SpecialCarCheats); + DebugMenuAddCmd("Cheats", "Pickup chicks", PickUpChicksCheat); static int spawnCarId = MI_LANDSTAL; - e = DebugMenuAddVar("Spawn", "Spawn Car ID", &spawnCarId, nil, 1, MI_LANDSTAL, MI_GHOST, carnames); + e = DebugMenuAddVar("Spawn", "Spawn Car ID", &spawnCarId, nil, 1, MI_LANDSTAL, MI_VICECHEE, carnames); DebugMenuEntrySetWrap(e, true); DebugMenuAddCmd("Spawn", "Spawn Car", [](){ - if(spawnCarId == MI_TRAIN || - spawnCarId == MI_CHOPPER || + if(spawnCarId == MI_CHOPPER || spawnCarId == MI_AIRTRAIN || - spawnCarId == MI_DEADDODO || - spawnCarId == MI_ESCAPE) + spawnCarId == MI_DEADDODO) return; SpawnCar(spawnCarId); }); @@ -927,22 +984,33 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Spawn", "Spawn Stinger", [](){ SpawnCar(MI_STINGER); }); DebugMenuAddCmd("Spawn", "Spawn Infernus", [](){ SpawnCar(MI_INFERNUS); }); DebugMenuAddCmd("Spawn", "Spawn Cheetah", [](){ SpawnCar(MI_CHEETAH); }); + DebugMenuAddCmd("Spawn", "Spawn Phoenix", [](){ SpawnCar(MI_PHEONIX); }); + DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); }); DebugMenuAddCmd("Spawn", "Spawn Esperanto", [](){ SpawnCar(MI_ESPERANT); }); DebugMenuAddCmd("Spawn", "Spawn Stallion", [](){ SpawnCar(MI_STALLION); }); - DebugMenuAddCmd("Spawn", "Spawn Kuruma", [](){ SpawnCar(MI_KURUMA); }); + DebugMenuAddCmd("Spawn", "Spawn Admiral", [](){ SpawnCar(MI_ADMIRAL); }); + DebugMenuAddCmd("Spawn", "Spawn Washington", [](){ SpawnCar(MI_WASHING); }); DebugMenuAddCmd("Spawn", "Spawn Taxi", [](){ SpawnCar(MI_TAXI); }); DebugMenuAddCmd("Spawn", "Spawn Police", [](){ SpawnCar(MI_POLICE); }); DebugMenuAddCmd("Spawn", "Spawn Enforcer", [](){ SpawnCar(MI_ENFORCER); }); - DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); }); - DebugMenuAddCmd("Spawn", "Spawn Yakuza", [](){ SpawnCar(MI_YAKUZA); }); - DebugMenuAddCmd("Spawn", "Spawn Yardie", [](){ SpawnCar(MI_YARDIE); }); - DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); }); + DebugMenuAddCmd("Spawn", "Spawn Cuban", [](){ SpawnCar(MI_CUBAN); }); + DebugMenuAddCmd("Spawn", "Spawn Voodoo", [](){ SpawnCar(MI_VOODOO); }); + DebugMenuAddCmd("Spawn", "Spawn BF injection", [](){ SpawnCar(MI_BFINJECT); }); + DebugMenuAddCmd("Spawn", "Spawn Maverick", [](){ SpawnCar(MI_MAVERICK); }); + DebugMenuAddCmd("Spawn", "Spawn VCN Maverick", [](){ SpawnCar(MI_VCNMAV); }); + DebugMenuAddCmd("Spawn", "Spawn Sparrow", [](){ SpawnCar(MI_SPARROW); }); + DebugMenuAddCmd("Spawn", "Spawn Sea Sparrow", [](){ SpawnCar(MI_SEASPAR); }); + DebugMenuAddCmd("Spawn", "Spawn Hunter", [](){ SpawnCar(MI_HUNTER); }); DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); }); DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); }); + DebugMenuAddCmd("Spawn", "Spawn PCJ 600", [](){ SpawnCar(MI_PCJ600); }); + DebugMenuAddCmd("Spawn", "Spawn Faggio", [](){ SpawnCar(MI_FAGGIO); }); + DebugMenuAddCmd("Spawn", "Spawn Freeway", [](){ SpawnCar(MI_FREEWAY); }); + DebugMenuAddCmd("Spawn", "Spawn Squalo", [](){ SpawnCar(MI_SQUALO); }); + DebugMenuAddCmd("Spawn", "Spawn Skimmer", [](){ SpawnCar(MI_SKIMMER); }); DebugMenuAddVarBool8("Render", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil); - #ifdef PROPER_SCALING DebugMenuAddVarBool8("Render", "Proper Scaling", &CDraw::ms_bProperScaling, nil); #endif @@ -952,6 +1020,7 @@ DebugMenuPopulate(void) #ifdef FIX_SPRITES DebugMenuAddVarBool8("Render", "Fix Sprites", &CDraw::ms_bFixSprites, nil); #endif + DebugMenuAddVarBool8("Render", "Backface Culling", &gBackfaceCulling, nil); DebugMenuAddVarBool8("Render", "PS2 Alpha test Emu", &gPS2alphaTest, nil); DebugMenuAddVarBool8("Render", "Frame limiter", &FrontEndMenuManager.m_PrefsFrameLimiter, nil); DebugMenuAddVarBool8("Render", "VSynch", &FrontEndMenuManager.m_PrefsVsync, nil); @@ -960,7 +1029,7 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Render", "New Renderer", &gbNewRenderer, nil); extern bool gbRenderRoads; extern bool gbRenderEverythingBarRoads; -//extern bool gbRenderFadingInUnderwaterEntities; +extern bool gbRenderFadingInUnderwaterEntities; extern bool gbRenderFadingInEntities; extern bool gbRenderWater; extern bool gbRenderBoats; @@ -970,7 +1039,7 @@ extern bool gbRenderWorld1; extern bool gbRenderWorld2; DebugMenuAddVarBool8("Debug Render", "gbRenderRoads", &gbRenderRoads, nil); DebugMenuAddVarBool8("Debug Render", "gbRenderEverythingBarRoads", &gbRenderEverythingBarRoads, nil); -// DebugMenuAddVarBool8("Debug Render", "gbRenderFadingInUnderwaterEntities", &gbRenderFadingInUnderwaterEntities, nil); + DebugMenuAddVarBool8("Debug Render", "gbRenderFadingInUnderwaterEntities", &gbRenderFadingInUnderwaterEntities, nil); DebugMenuAddVarBool8("Debug Render", "gbRenderFadingInEntities", &gbRenderFadingInEntities, nil); DebugMenuAddVarBool8("Debug Render", "gbRenderWater", &gbRenderWater, nil); DebugMenuAddVarBool8("Debug Render", "gbRenderBoats", &gbRenderBoats, nil); @@ -985,8 +1054,13 @@ extern bool gbRenderWorld2; e = DebugMenuAddVar("Render", "Colourfilter", &CPostFX::EffectSwitch, nil, 1, CPostFX::POSTFX_OFF, CPostFX::POSTFX_MOBILE, filternames); DebugMenuEntrySetWrap(e, true); DebugMenuAddVar("Render", "Intensity", &CPostFX::Intensity, nil, 0.05f, 0, 10.0f); + DebugMenuAddVarBool8("Render", "Blur", &CPostFX::BlurOn, nil); DebugMenuAddVarBool8("Render", "Motion Blur", &CPostFX::MotionBlurOn, nil); #endif + DebugMenuAddVar("Render", "Drunkness", &CMBlur::Drunkness, nil, 0.05f, 0, 1.0f); +#ifndef MASTER + DebugMenuAddVarBool8("Render", "Occlusion debug", &bDispayOccDebugStuff, nil); +#endif #ifdef LIBRW DebugMenuAddVarBool32("Render", "MatFX env map apply light", &rw::MatFX::envMapApplyLight, nil); DebugMenuAddVarBool32("Render", "MatFX env map flip U", &rw::MatFX::envMapFlipU, nil); @@ -1009,8 +1083,6 @@ extern bool gbRenderWorld2; DebugMenuAddVarBool8("Debug Render", "Show Ped Paths", &gbShowPedPaths, nil); DebugMenuAddVarBool8("Debug Render", "Show Car Paths", &gbShowCarPaths, nil); DebugMenuAddVarBool8("Debug Render", "Show Car Path Links", &gbShowCarPathsLinks, nil); - DebugMenuAddVarBool8("Debug Render", "Show Ped Road Groups", &gbShowPedRoadGroups, nil); - DebugMenuAddVarBool8("Debug Render", "Show Car Road Groups", &gbShowCarRoadGroups, nil); DebugMenuAddVarBool8("Debug Render", "Show Collision Lines", &gbShowCollisionLines, nil); DebugMenuAddVarBool8("Debug Render", "Show Collision Polys", &gbShowCollisionPolys, nil); DebugMenuAddVarBool8("Debug Render", "Don't render Buildings", &gbDontRenderBuildings, nil); @@ -1019,7 +1091,7 @@ extern bool gbRenderWorld2; DebugMenuAddVarBool8("Debug Render", "Don't render Vehicles", &gbDontRenderVehicles, nil); DebugMenuAddVarBool8("Debug Render", "Don't render Objects", &gbDontRenderObjects, nil); DebugMenuAddVarBool8("Debug Render", "Don't Render Water", &gbDontRenderWater, nil); - + #ifdef DRAW_GAME_VERSION_TEXT DebugMenuAddVarBool8("Debug", "Version Text", &gbDrawVersionText, nil); @@ -1035,8 +1107,6 @@ extern bool gbRenderWorld2; DebugMenuAddCmd("Debug", "Parse Heap", ParseHeap); #endif #endif - DebugMenuAddVarBool8("Debug", "Show cullzone debug stuff", &gbShowCullZoneDebugStuff, nil); - DebugMenuAddVarBool8("Debug", "Disable zone cull", &gbDisableZoneCull, nil); DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil); #ifdef GTA_SCENE_EDIT @@ -1045,7 +1115,12 @@ extern bool gbRenderWorld2; //DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); //DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); -#ifdef MENU_MAP +#ifdef RELOADABLES +// maybe put it back if we have more to reload +// DebugMenuAddCmd("Reload", "HUD.TXD", CHud::ReloadTXD); +#endif + +#ifdef MAP_ENHANCEMENTS DebugMenuAddCmd("Game", "Teleport to map waypoint", TeleportToWaypoint); #endif DebugMenuAddCmd("Game", "Fix Car", FixCar); @@ -1053,32 +1128,34 @@ extern bool gbRenderWorld2; DebugMenuAddCmd("Game", "Switch car collision", SwitchCarCollision); DebugMenuAddCmd("Game", "Toggle Comedy Controls", ToggleComedy); - DebugMenuAddVarBool8("Game", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); #ifdef MISSION_SWITCHER DebugMenuEntry *missionEntry; static const char* missions[] = { - "Intro Movie", "Hospital Info Scene", "Police Station Info Scene", - "RC Diablo Destruction", "RC Mafia Massacre", "RC Rumpo Rampage", "RC Casino Calamity", - "Patriot Playground", "A Ride In The Park", "Gripped!", "Multistorey Mayhem", - "Paramedic", "Firefighter", "Vigilante", "Taxi Driver", - "The Crook", "The Thieves", "The Wife", "Her Lover", - "Give Me Liberty and Luigi's Girls", "Don't Spank My Bitch Up", "Drive Misty For Me", "Pump-Action Pimp", "The Fuzz Ball", - "Mike Lips Last Lunch", "Farewell 'Chunky' Lee Chong", "Van Heist", "Cipriani's Chauffeur", "Dead Skunk In The Trunk", "The Getaway", - "Taking Out The Laundry", "The Pick-Up", "Salvatore's Called A Meeting", "Triads And Tribulations", "Blow Fish", "Chaperone", "Cutting The Grass", - "Bomb Da Base: Act I", "Bomb Da Base: Act II", "Last Requests", "Turismo", "I Scream, You Scream", "Trial By Fire", "Big'N'Veiny", "Sayonara Salvatore", - "Under Surveillance", "Paparazzi Purge", "Payday For Ray", "Two-Faced Tanner", "Kanbu Bust-Out", "Grand Theft Auto", "Deal Steal", "Shima", "Smack Down", - "Silence The Sneak", "Arms Shortage", "Evidence Dash", "Gone Fishing", "Plaster Blaster", "Marked Man", - "Liberator", "Waka-Gashira Wipeout!", "A Drop In The Ocean", "Bling-Bling Scramble", "Uzi Rider", "Gangcar Round-Up", "Kingdom Come", - "Grand Theft Aero", "Escort Service", "Decoy", "Love's Disappearance", "Bait", "Espresso-2-Go!", "S.A.M.", - "Uzi Money", "Toyminator", "Rigged To Blow", "Bullion Run", "Rumble", "The Exchange" + "Initial", "Intro", "An Old Friend", "The Party", "Back Alley Brawl", "Jury Fury", "Riot", + "Treacherous Swine", "Mall Shootout", "Guardian Angels", "Sir, Yes Sir!", "All Hands On Deck!", + "The Chase", "Phnom Penh '86", "The Fastest Boat", "Supply & Demand", "Rub Out", "Death Row", + "Four Iron", "Demolition Man", "Two Bit Hit", "No Escape?", "The Shootist", "The Driver", + "The Job", "Gun Runner", "Boomshine Saigon", "Recruitment Drive", "Dildo Dodo", "Martha's Mug Shot", + "G-spotlight", "Shakedown", "Bar Brawl", "Cop Land", "Spilling the Beans", "Hit the Courier", + "Printworks Buy", "Sunshine Autos", "Interglobal Films Buy", "Cherry Popper Icecreams Buy", + "Kaufman Cabs Buy", "Malibu Club Buy", "The Boatyard Buy", "Pole Position Club Buy", "El Swanko Casa Buy", + "Links View Apartment Buy", "Hyman Condo Buy", "Ocean Heighs Aprt. Buy", "1102 Washington Street Buy", + "Vice Point Buy", "Skumole Shack Buy", "Cap the Collector", "Keep your Friends Close...", + "Alloy Wheels of Steel", "Messing with the Man", "Hog Tied", "Stunt Boat Challenge", "Cannon Fodder", + "Naval Engagement", "Trojan Voodoo", "Juju Scramble", "Bombs Away!", "Dirty Lickin's", "Love Juice", + "Psycho Killer", "Publicity Tour", "Weapon Range", "Road Kill", "Waste the Wife", "Autocide", + "Check Out at the Check In", "Loose Ends", "V.I.P.", "Friendly Rivalry", "Cabmaggedon", "TAXI DRIVER", + "PARAMEDIC", "FIREFIGHTER", "VIGILANTE", "HOTRING", "BLOODRING", "DIRTRING", "Sunshine Autos Races", + "Distribution", "Downtown Chopper Checkpoint", "Ocean Beach Chopper Checkpoint", "Vice Point Chopper Checkpoint", + "Little Haiti Chopper Checkpoint", "Trial by Dirt", "Test Track", "PCJ Playground", "Cone Crazy", + "PIZZA BOY", "RC Raider Pickup", "RC Bandit Race", "RC Baron Race", "Checkpoint Charlie" }; missionEntry = DebugMenuAddVar("Game", "Select mission", &nextMissionToSwitch, nil, 1, 0, ARRAY_SIZE(missions) - 1, missions); DebugMenuEntrySetWrap(missionEntry, true); DebugMenuAddCmd("Game", "Start selected mission ", SwitchToMission); #endif - extern bool PrintDebugCode; extern int16 DebugCamMode; DebugMenuAddVarBool8("Cam", "Use mouse Cam", &CCamera::m_bUseMouse3rdPerson, nil); @@ -1088,9 +1165,6 @@ extern bool gbRenderWorld2; DebugMenuAddVarBool8("Cam", "Print Debug Code", &PrintDebugCode, nil); DebugMenuAddVar("Cam", "Cam Mode", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil); DebugMenuAddCmd("Cam", "Normal", []() { DebugCamMode = 0; }); - // DebugMenuAddCmd("Cam", "Follow Ped With Bind", []() { DebugCamMode = CCam::MODE_FOLLOW_PED_WITH_BIND; }); - // DebugMenuAddCmd("Cam", "Reaction", []() { DebugCamMode = CCam::MODE_REACTION; }); - // DebugMenuAddCmd("Cam", "Chris", []() { DebugCamMode = CCam::MODE_CHRIS; }); DebugMenuAddCmd("Cam", "Reset Statics", ResetCamStatics); CTweakVars::AddDBG("Debug"); @@ -1133,7 +1207,7 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con strcat_s(re3_buff, re3_buffsize, "(Press Retry to debug the application)"); - nCode = ::MessageBoxA(nil, re3_buff, "RE3 Assertion Failed!", + nCode = ::MessageBoxA(nil, re3_buff, "REVC Assertion Failed!", MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); if (nCode == IDABORT) @@ -1154,7 +1228,7 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con abort(); #else // TODO - printf("\nRE3 ASSERT FAILED\n\tFile: %s\n\tLine: %d\n\tFunction: %s\n\tExpression: %s\n",filename,lineno,func,expr); + printf("\nREVC ASSERT FAILED\n\tFile: %s\n\tLine: %d\n\tFunction: %s\n\tExpression: %s\n",filename,lineno,func,expr); assert(false); #endif } @@ -1208,14 +1282,14 @@ void re3_usererror(const char *format, ...) vsprintf_s(re3_buff, re3_buffsize, format, va); va_end(va); - ::MessageBoxA(nil, re3_buff, "RE3 Error!", + ::MessageBoxA(nil, re3_buff, "REVC Error!", MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); raise(SIGABRT); _exit(3); #else vsprintf(re3_buff, format, va); - printf("\nRE3 Error!\n\t%s\n",re3_buff); + printf("\nREVC Error!\n\t%s\n",re3_buff); assert(false); #endif } diff --git a/src/core/templates.h b/src/core/templates.h index 545dac39..7bc85ee6 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -41,11 +41,11 @@ class CPool int32 m_allocPtr; public: - CPool(int32 size){ + CPool(int32 size, const char *name){ m_entries = (U*)new uint8[sizeof(U)*size]; m_flags = new uint8[size]; m_size = size; - m_allocPtr = 0; + m_allocPtr = -1; for(int i = 0; i < size; i++){ SetId(i, 0); SetIsFree(i, true); @@ -74,7 +74,6 @@ public: else m_flags[i] &= ~POOLFLAG_ISFREE; } - ~CPool() { Flush(); } @@ -142,21 +141,22 @@ public: return m_flags[handle>>8] == (handle & 0xFF) ? (T*)&m_entries[handle >> 8] : nil; } - int32 GetIndex(T *entry){ + int32 GetIndex(T* entry) { int i = GetJustIndex_NoFreeAssert(entry); return m_flags[i] + (i<<8); } - int32 GetJustIndex(T *entry){ + int32 GetJustIndex(T* entry) { int index = GetJustIndex_NoFreeAssert(entry); + assert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required assert(!GetIsFree(index)); return index; } - int32 GetJustIndex_NoFreeAssert(T* entry){ + int32 GetJustIndex_NoFreeAssert(T* entry) { int index = ((U*)entry - m_entries); - assert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required + // Please don't add unsafe assert here, because at least one func. use this to check if entity is ped or vehicle. return index; } - int32 GetNoOfUsedSpaces(void) const{ + int32 GetNoOfUsedSpaces(void) const { int i; int n = 0; for(i = 0; i < m_size; i++) @@ -186,6 +186,7 @@ public: memcpy(entries, m_entries, sizeof(U)*m_size); debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ } + int32 GetNoOfFreeSpaces() const { return GetSize() - GetNoOfUsedSpaces(); } }; template<typename T> diff --git a/src/core/timebars.cpp b/src/core/timebars.cpp index 94051b25..169fef8c 100644 --- a/src/core/timebars.cpp +++ b/src/core/timebars.cpp @@ -92,7 +92,7 @@ void tbDisplay() CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); CFont::SetRightJustifyOff(); CFont::SetPropOn(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); sprintf(temp, "FPS: %.2f", Diag_GetFPS()); AsciiToUnicode(temp, wtemp); CFont::SetColor(CRGBA(255, 255, 255, 255)); |